From 075d3831ffae63f128bcaabf9fc5e70ade41ad33 Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Tue, 21 Sep 2021 21:00:21 +0200 Subject: chore: separated out all tweak panels --- components/BehaviorPanel.tsx | 148 ++++++++++++++++++++++++ components/CitationsPanel.tsx | 102 +++++++++++++++++ components/ColorMenu.tsx | 71 ++++++++++++ components/ColorsPanel.tsx | 237 +++++++++++++++++++++++++++++++++++++++ components/DropDownMenu.tsx | 28 +++++ components/EnableSection.tsx | 31 +++++ components/FilterPanel.tsx | 171 ++++++++++++++++++++++++++++ components/HighlightingPanel.tsx | 116 +++++++++++++++++++ components/InfoTooltip.tsx | 17 +++ components/LabelsPanel.tsx | 139 +++++++++++++++++++++++ components/NodesNLinksPanel.tsx | 131 ++++++++++++++++++++++ components/PhysicsPanel.tsx | 143 +++++++++++++++++++++++ components/SliderWithInfo.tsx | 48 ++++++++ components/TagColorPanel.tsx | 138 +++++++++++++++++++++++ components/TagPanel.tsx | 59 ++++++++++ components/VisualsPanel.tsx | 117 +++++++++++++++++++ components/tweaks.tsx | 212 ++-------------------------------- 17 files changed, 1705 insertions(+), 203 deletions(-) create mode 100644 components/BehaviorPanel.tsx create mode 100644 components/CitationsPanel.tsx create mode 100644 components/ColorMenu.tsx create mode 100644 components/ColorsPanel.tsx create mode 100644 components/DropDownMenu.tsx create mode 100644 components/EnableSection.tsx create mode 100644 components/FilterPanel.tsx create mode 100644 components/HighlightingPanel.tsx create mode 100644 components/InfoTooltip.tsx create mode 100644 components/LabelsPanel.tsx create mode 100644 components/NodesNLinksPanel.tsx create mode 100644 components/PhysicsPanel.tsx create mode 100644 components/SliderWithInfo.tsx create mode 100644 components/TagColorPanel.tsx create mode 100644 components/TagPanel.tsx create mode 100644 components/VisualsPanel.tsx diff --git a/components/BehaviorPanel.tsx b/components/BehaviorPanel.tsx new file mode 100644 index 0000000..09558af --- /dev/null +++ b/components/BehaviorPanel.tsx @@ -0,0 +1,148 @@ +import { ChevronDownIcon } from '@chakra-ui/icons' +import { + Button, + Flex, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + StackDivider, + VStack, + Text, +} from '@chakra-ui/react' +import React from 'react' +import { initialBehavior, initialMouse } from './config' +import { InfoTooltip } from './InfoTooltip' +import { SliderWithInfo } from './SliderWithInfo' + +export interface BehaviorPanelProps { + behavior: typeof initialBehavior + setBehavior: any + mouse: typeof initialMouse + setMouse: any +} +export const BehaviorPanel = (props: BehaviorPanelProps) => { + const { behavior, setBehavior, mouse, setMouse } = props + return ( + } + align="stretch" + paddingLeft={7} + color="gray.800" + > + + + Expand Node + + + + } colorScheme="" color="black"> + + {mouse.local ? mouse.local[0]!.toUpperCase() + mouse.local!.slice(1) : 'Never'} + + + + {' '} + + setMouse({ ...mouse, local: '' })}>Never + setMouse({ ...mouse, local: 'click' })}>Click + setMouse({ ...mouse, local: 'double' })}> + Double Click + + setMouse({ ...mouse, local: 'right' })}> + Right Click + + + + + + + Open in Emacs + + } colorScheme="" color="black"> + + {mouse.follow ? mouse.follow[0]!.toUpperCase() + mouse.follow!.slice(1) : 'Never'} + + + + {' '} + + setMouse({ ...mouse, follow: '' })}>Never + setMouse({ ...mouse, follow: 'click' })}>Click + setMouse({ ...mouse, follow: 'double' })}> + Double Click + + setMouse({ ...mouse, follow: 'right' })}> + Right Click + + + + + + + Follow Emacs by... + + } colorScheme="" color="black"> + {behavior.follow[0].toUpperCase() + behavior.follow.slice(1)} + + + {' '} + + setBehavior({ ...behavior, follow: 'color' })}> + Just coloring the currently opened node + + setBehavior({ ...behavior, follow: 'local' })}> + Opening the local graph + + setBehavior({ ...behavior, follow: 'zoom' })}> + Zooming to the current node + + + + + + + + Local graph + + + + } colorScheme="" color="black"> + {behavior.localSame === 'add' ? 'Add' : 'Replace'} + + + {' '} + + setBehavior({ ...behavior, localSame: 'replace' })}> + Open that nodes graph + + setBehavior({ ...behavior, localSame: 'add' })}> + Add node to local graph + + + + + + setBehavior({ ...behavior, zoomSpeed: value })} + /> + setBehavior({ ...behavior, zoomPadding: value })} + infoText="How much to zoom out to accomodate all nodes when changing the view." + /> + + ) +} diff --git a/components/CitationsPanel.tsx b/components/CitationsPanel.tsx new file mode 100644 index 0000000..c34b0df --- /dev/null +++ b/components/CitationsPanel.tsx @@ -0,0 +1,102 @@ +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 CitationsPanelProps { + visuals: typeof initialVisuals + setVisuals: any +} +export const CitationsPanel = (props: CitationsPanelProps) => { + const { visuals, setVisuals } = props + return ( + } + align="stretch" + color="gray.800" + > + + setVisuals({ ...visuals, citeDashes: !visuals.citeDashes })} + > + setVisuals({ ...visuals, citeDashLength: value * 10 })} + /> + setVisuals({ ...visuals, citeGapLength: value * 5 })} + /> + + + + + setVisuals({ ...visuals, refDashes: !visuals.refDashes })} + > + setVisuals({ ...visuals, refDashLength: value * 10 })} + /> + setVisuals({ ...visuals, refGapLength: value * 5 })} + /> + + + + + + + ) +} diff --git a/components/ColorMenu.tsx b/components/ColorMenu.tsx new file mode 100644 index 0000000..1bbf087 --- /dev/null +++ b/components/ColorMenu.tsx @@ -0,0 +1,71 @@ +import { ChevronDownIcon } from '@chakra-ui/icons' +import { + Text, + Box, + Button, + Flex, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, +} 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 +} + +export const ColorMenu = (props: ColorMenuProps) => { + const { label, colorList, value, visValue, setVisuals } = props + + const clickCallback = useCallback( + (color) => + setVisuals((curr: typeof initialVisuals) => { + return { + ...curr, + [value]: color, + } + }), + [], + ) + return ( + + {label} + + }> + {} + + + {' '} + + clickCallback('')} + justifyContent="space-between" + alignItems="center" + display="flex" + > + + + {colorList.map((color: string) => ( + clickCallback(color)} + justifyContent="space-between" + alignItems="center" + display="flex" + > + + + ))} + + + + + ) +} diff --git a/components/ColorsPanel.tsx b/components/ColorsPanel.tsx new file mode 100644 index 0000000..6846a93 --- /dev/null +++ b/components/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 ( + } + align="stretch" + color="gray.800" + > + + + Nodes + + } + 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), + }) + }} + /> + + + } + size="sm" + variant="ghost" + onClick={() => { + const arr = visuals.nodeColorScheme ?? [] + setVisualsCallback({ + ...visuals, + nodeColorScheme: [...arr.slice(1, arr.length), arr[0]], + }) + }} + /> + + + } + > + + {visuals.nodeColorScheme.map((color) => ( + + ))} + + + + {' '} + + { + if (!colors.length) { + return + } + setVisualsCallback({ ...visuals, nodeColorScheme: colors }) + }} + > + {colorList.map((color) => ( + c === color)} + value={color} + isDisabled={ + visuals.nodeColorScheme.length === 1 && visuals.nodeColorScheme[0] === color + } + > + + + + + ))} + + + + + + + Links + + }> + + {visuals.linkColorScheme ? ( + + ) : ( + + {visuals.nodeColorScheme.map((color) => ( + + ))} + + )} + + + + {' '} + + setVisualsCallback({ ...visuals, linkColorScheme: '' })} + justifyContent="space-between" + alignItems="center" + display="flex" + > + + {visuals.nodeColorScheme.map((color) => ( + + ))} + + + {colorList.map((color) => ( + + setVisualsCallback({ + ...visuals, + linkColorScheme: color, + }) + } + justifyContent="space-between" + alignItems="center" + display="flex" + > + + + ))} + + + + + + Accent + + }> + {} + + + {' '} + + {colorList.map((color) => ( + setHighlightColor(color)} + justifyContent="space-between" + alignItems="center" + display="flex" + > + + + ))} + + + + + + + + + + + ) +} diff --git a/components/DropDownMenu.tsx b/components/DropDownMenu.tsx new file mode 100644 index 0000000..fbd854b --- /dev/null +++ b/components/DropDownMenu.tsx @@ -0,0 +1,28 @@ +import { ChevronDownIcon } from '@chakra-ui/icons' +import { Button, Menu, MenuButton, MenuItem, MenuList, Portal } from '@chakra-ui/react' +import React from 'react' + +export interface DropDownMenuProps { + textArray: string[] + onClickArray: (() => void)[] + displayValue: string +} + +export const DropDownMenu = (props: DropDownMenuProps) => { + const { textArray, onClickArray, displayValue } = props + return ( + + }> + {displayValue} + + + {' '} + + {textArray.map((option, i) => { + ; {option} + })} + + + + ) +} diff --git a/components/EnableSection.tsx b/components/EnableSection.tsx new file mode 100644 index 0000000..b7981b3 --- /dev/null +++ b/components/EnableSection.tsx @@ -0,0 +1,31 @@ +import { Text, Box, Collapse, Switch } from '@chakra-ui/react' +import React from 'react' +import { InfoTooltip } from './InfoTooltip' + +export interface EnableSectionProps { + label: string + value: boolean | number + onChange: () => void + infoText?: string + children: React.ReactNode +} + +export const EnableSection = (props: EnableSectionProps) => { + const { value, onChange, label, infoText, children } = props + return ( + + + + {label} + {infoText && } + + + + + + {children} + + + + ) +} diff --git a/components/FilterPanel.tsx b/components/FilterPanel.tsx new file mode 100644 index 0000000..871c3d6 --- /dev/null +++ b/components/FilterPanel.tsx @@ -0,0 +1,171 @@ +import { ChevronDownIcon } from '@chakra-ui/icons' +import { + Text, + Box, + Button, + Flex, + Menu, + MenuButton, + StackDivider, + VStack, + Portal, + MenuList, + MenuItem, + Switch, + Accordion, + AccordionItem, + AccordionButton, + AccordionIcon, + AccordionPanel, +} from '@chakra-ui/react' +import React from 'react' +import { TagPanel } from './TagPanel' +import { initialFilter, TagColors } from './config' +import { TagColorPanel } from './TagColorPanel' + +export interface FilterPanelProps { + filter: typeof initialFilter + setFilter: any + tagColors: TagColors + setTagColors: any + highlightColor: string + colorList: string[] + tags: string[] +} + +const FilterPanel = (props: FilterPanelProps) => { + const { filter, setFilter, tagColors, setTagColors, highlightColor, colorList, tags } = props + return ( + + } + align="stretch" + paddingLeft={7} + color="gray.800" + > + + Link children to... + + } colorScheme="" color="black"> + {(() => { + switch (filter.parent) { + case 'parent': + return File + case 'heading': + return Heading + default: + return Nothing + } + })()} + + + {' '} + + + setFilter((curr: typeof initialFilter) => ({ ...curr, parent: '' })) + } + > + Nothing + + + setFilter((curr: typeof initialFilter) => ({ + ...curr, + parent: 'parent', + })) + } + > + Parent file node + + + setFilter((curr: typeof initialFilter) => ({ + ...curr, + parent: 'heading', + })) + } + > + Next highest heading node + + + + + + + Orphans + { + setFilter((curr: typeof initialFilter) => { + return { ...curr, orphans: !curr.orphans } + }) + }} + isChecked={filter.orphans} + > + + + Citations without note files + { + setFilter({ ...filter, filelessCites: !filter.filelessCites }) + }} + isChecked={filter.filelessCites} + > + + + Non-existant nodes + { + setTagColors({ ...tagColors, bad: 'white' }) + setFilter({ ...filter, bad: !filter.bad }) + }} + isChecked={filter.bad} + > + + + + + + Tag filters + + + + + + + + + + Tag Colors + + + + + + + + + ) +} + +export default FilterPanel diff --git a/components/HighlightingPanel.tsx b/components/HighlightingPanel.tsx new file mode 100644 index 0000000..b3900e2 --- /dev/null +++ b/components/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 ( + } + align="stretch" + color="gray.800" + > + + + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlight: !visuals.highlight, + })) + } + value={visuals.highlight} + > + } + align="stretch" + paddingLeft={0} + > + + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlightLinkSize: value, + })) + } + /> + + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlightNodeSize: value, + })) + } + /> + + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlightFade: value, + })) + } + /> + { + setVisuals((visuals: typeof initialVisuals) => ({ + ...visuals, + highlightAnim: !visuals.highlightAnim, + })) + }} + value={visuals.highlightAnim} + > + + 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} + /> + + + + + + + ) +} diff --git a/components/InfoTooltip.tsx b/components/InfoTooltip.tsx new file mode 100644 index 0000000..02c2fad --- /dev/null +++ b/components/InfoTooltip.tsx @@ -0,0 +1,17 @@ +import { InfoOutlineIcon } from '@chakra-ui/icons' +import { Box, Tooltip } from '@chakra-ui/react' +import React from 'react' + +export interface InfoTooltipProps { + infoText?: string | boolean +} +export const InfoTooltip = (props: InfoTooltipProps) => { + const { infoText } = props + return ( + + + + + + ) +} diff --git a/components/LabelsPanel.tsx b/components/LabelsPanel.tsx new file mode 100644 index 0000000..eb7dc34 --- /dev/null +++ b/components/LabelsPanel.tsx @@ -0,0 +1,139 @@ +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 ( + } + align="stretch" + color="gray.800" + > + + + Show labels + + }> + {!visuals.labels ? 'Never' : visuals.labels < 2 ? 'On Highlight' : 'Always'} + + + {' '} + + setVisuals({ ...visuals, labels: 0 })}>Never + setVisuals({ ...visuals, labels: 1 })}> + On Highlight + + setVisuals({ ...visuals, labels: 2 })}>Always + setVisuals({ ...visuals, labels: 3 })}> + Always (even in 3D) + + + + + + } + align="stretch" + paddingLeft={2} + color="gray.800" + > + setVisuals({ ...visuals, labelFontSize: value })} + /> + setVisuals({ ...visuals, labelLength: value })} + /> + setVisuals({ ...visuals, labelWordWrap: value })} + /> + setVisuals({ ...visuals, labelLineSpace: value })} + /> + + + + + { + console.log(visuals.labelBackgroundOpacity) + setVisuals({ ...visuals, labelBackgroundOpacity: value }) + }} + min={0} + max={1} + step={0.01} + /> + + + 1} animateOpacity> + + setVisuals({ ...visuals, labelScale: value / 5 })} + /> + + + + + + ) +} diff --git a/components/NodesNLinksPanel.tsx b/components/NodesNLinksPanel.tsx new file mode 100644 index 0000000..f19a3e2 --- /dev/null +++ b/components/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 ( + } + align="stretch" + color="gray.800" + > + + setVisuals({ ...visuals, nodeRel: value })} + /> + setVisuals({ ...visuals, nodeSizeLinks: value })} + /> + + setVisuals((prev: typeof initialVisuals) => ({ + ...prev, + nodeZoomSize: value, + })) + } + /> + {threeDim && ( + <> + setVisuals({ ...visuals, nodeOpacity: value })} + /> + setVisuals({ ...visuals, nodeResolution: value })} + /> + + )} + setVisuals({ ...visuals, linkWidth: value })} + /> + {threeDim && ( + setVisuals({ ...visuals, linkOpacity: value })} + /> + )} + setVisuals({ ...visuals, arrows: !visuals.arrows })} + > + setVisuals({ ...visuals, arrowsLength: 10 * value })} + /> + setVisuals({ ...visuals, arrowsPos: value })} + /> + + + setVisuals({ ...visuals, particles: !visuals.particles })} + > + setVisuals({ ...visuals, particlesNumber: value })} + /> + setVisuals({ ...visuals, particlesWidth: value })} + /> + + + + ) +} diff --git a/components/PhysicsPanel.tsx b/components/PhysicsPanel.tsx new file mode 100644 index 0000000..1bdfaa0 --- /dev/null +++ b/components/PhysicsPanel.tsx @@ -0,0 +1,143 @@ +import { + Text, + Accordion, + AccordionButton, + AccordionIcon, + AccordionItem, + AccordionPanel, + Box, + Flex, + StackDivider, + Switch, + VStack, +} from '@chakra-ui/react' +import React, { useCallback } from 'react' +import { initialPhysics } from './config' +import { EnableSection } from './EnableSection' +import { SliderWithInfo } from './SliderWithInfo' + +export interface PhysicsPanelProps { + physics: typeof initialPhysics + setPhysics: any +} + +export const PhysicsPanel = (props: PhysicsPanelProps) => { + const { physics, setPhysics } = props + const setPhysicsCallback = useCallback((val: number, phys: string, scale: number) => { + setPhysics((curr: typeof initialPhysics) => { + return { ...curr, [phys]: val / scale } + }) + }, []) + return ( + + } + align="stretch" + paddingLeft={7} + color="gray.800" + > + setPhysics({ ...physics, gravityOn: !physics.gravityOn })} + > + + Also in local + { + setPhysics((curr: typeof initialPhysics) => { + return { ...curr, gravityLocal: !curr.gravityLocal } + }) + }} + isChecked={physics.gravityLocal} + > + + setPhysicsCallback(v, 'gravity', 10)} + /> + + setPhysicsCallback(v, 'charge', -1 / 100)} + label="Repulsive Force" + /> + setPhysics({ ...physics, collision: !physics.collision })} + > + setPhysicsCallback(v, 'collisionStrength', 1 / 5)} + label="Collision Radius" + infoText="Easy with this one, high values can lead to a real jiggly mess" + /> + + setPhysicsCallback(v, 'linkStrength', 5)} + label="Link Force" + /> + setPhysicsCallback(v, 'linkIts', 1)} + min={0} + max={6} + step={1} + infoText="How many links down the line the physics of a single node affects (Slow)" + /> + setPhysicsCallback(v, 'velocityDecay', 10)} + /> + + + + + + Advanced + + + + } + align="stretch" + paddingLeft={3} + color="gray.800" + > + setPhysicsCallback(v, 'alphaDecay', 50)} + /> + setPhysics({ ...physics, centering: !physics.centering })} + infoText="Keeps the nodes in the center of the viewport. If disabled you can drag the nodes anywhere you want." + > + setPhysicsCallback(v, 'centeringStrength', 1)} + /> + + + + + + + + ) +} diff --git a/components/SliderWithInfo.tsx b/components/SliderWithInfo.tsx new file mode 100644 index 0000000..d4f0372 --- /dev/null +++ b/components/SliderWithInfo.tsx @@ -0,0 +1,48 @@ +import { + Text, + Box, + Slider, + SliderFilledTrack, + SliderThumb, + SliderTrack, + Tooltip, +} from '@chakra-ui/react' +import React, { useContext } from 'react' +import { ThemeContext } from '../util/themecontext' +import { InfoTooltip } from './InfoTooltip' + +export interface SliderWithInfoProps { + min?: number + max?: number + step?: number + value: number + onChange: (arg0: number) => void + label: string + infoText?: string +} +export const SliderWithInfo = ({ + min = 0, + max = 10, + step = 0.1, + value = 1, + ...rest +}: SliderWithInfoProps) => { + const { onChange, label, infoText } = rest + const { highlightColor } = useContext(ThemeContext) + return ( + + + {label} + {infoText && } + + + + + + + + + + + ) +} diff --git a/components/TagColorPanel.tsx b/components/TagColorPanel.tsx new file mode 100644 index 0000000..f9a9815 --- /dev/null +++ b/components/TagColorPanel.tsx @@ -0,0 +1,138 @@ +import { DeleteIcon } from '@chakra-ui/icons' +import { + Text, + Box, + Flex, + IconButton, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + StackDivider, + VStack, + Button, +} from '@chakra-ui/react' +import { CUIAutoComplete } from 'chakra-ui-autocomplete' +import React, { useState } from 'react' +import { TagColors } from './config' + +export interface TagColorPanelProps { + tags: string[] + highlightColor: string + colorList: string[] + tagColors: TagColors + setTagColors: any +} +export const TagColorPanel = (props: TagColorPanelProps) => { + const { colorList, tagColors, setTagColors, highlightColor, tags } = props + const tagArray = tags.map((tag) => { + return { value: tag, label: tag } + }) + + const [selectedItems, setSelectedItems] = useState( + Object.keys(tagColors).map((tag) => { + return { value: tag, label: tag } + }), + ) + + return ( + + { + if (changes.selectedItems) { + setSelectedItems(Array.from(new Set(changes.selectedItems))) + setTagColors( + Object.fromEntries( + Array.from(new Set(changes.selectedItems)).map((item) => { + return [item.label, tagColors[item.label] ?? 'gray.600'] + }), + ), + ) + } + }} + listItemStyleProps={{ overflow: 'hidden' }} + highlightItemBg="gray.400" + toggleButtonStyleProps={{ variant: 'outline' }} + inputStyleProps={{ + focusBorderColor: highlightColor, + color: 'gray.800', + borderColor: 'gray.600', + }} + tagStyleProps={{ + display: 'none', + rounded: 'full', + bg: highlightColor, + height: 8, + paddingLeft: 4, + fontWeight: 'bold', + }} + hideToggleButton + itemRenderer={(selected) => selected.label} + /> + } + align="stretch" + color="gray.800" + > + {Object.keys(tagColors).map((tag) => { + return ( + + + {tag} + + + + {} + + + {' '} + + {colorList.map((color: string) => ( + + setTagColors({ + ...tagColors, + [tag]: color, + }) + } + justifyContent="space-between" + alignItems="center" + display="flex" + > + + + ))} + + + + } + onClick={() => { + setTagColors( + Object.fromEntries( + Array.from(new Set(selectedItems)).map((item) => { + return [item.label, tagColors[item.label] ?? 'gray.600'] + }), + ), + ) + setSelectedItems(selectedItems.filter((item) => item.value !== tag)) + }} + /> + + ) + })} + + + ) +} diff --git a/components/TagPanel.tsx b/components/TagPanel.tsx new file mode 100644 index 0000000..545102b --- /dev/null +++ b/components/TagPanel.tsx @@ -0,0 +1,59 @@ +import { CUIAutoComplete } from 'chakra-ui-autocomplete' +import React, { useState } from 'react' +import { initialFilter } from './config' + +export interface TagPanelProps { + tags: string[] + filter: typeof initialFilter + setFilter: any + highlightColor: string + mode: string +} + +export const TagPanel = (props: TagPanelProps) => { + const { filter, setFilter, tags, highlightColor, mode } = props + const tagArray = tags.map((tag) => { + return { value: tag, label: tag } + }) + + const currentTags = mode === 'blacklist' ? 'tagsBlacklist' : 'tagsWhitelist' + const [selectedItems, setSelectedItems] = useState( + filter[currentTags].map((tag) => { + return { value: tag, label: tag } + }), + ) + + return ( + null} + disableCreateItem={true} + selectedItems={selectedItems} + onSelectedItemsChange={(changes) => { + if (changes.selectedItems) { + setSelectedItems(changes.selectedItems) + setFilter({ ...filter, [currentTags]: changes.selectedItems.map((item) => item.value) }) + } + }} + listItemStyleProps={{ overflow: 'hidden' }} + highlightItemBg="gray.400" + toggleButtonStyleProps={{ variant: 'outline' }} + inputStyleProps={{ + focusBorderColor: highlightColor, + color: 'gray.800', + borderColor: 'gray.600', + }} + tagStyleProps={{ + rounded: 'full', + bg: highlightColor, + height: 8, + paddingLeft: 4, + fontWeight: 'bold', + }} + hideToggleButton + itemRenderer={(selected) => selected.label} + /> + ) +} diff --git a/components/VisualsPanel.tsx b/components/VisualsPanel.tsx new file mode 100644 index 0000000..1b6fceb --- /dev/null +++ b/components/VisualsPanel.tsx @@ -0,0 +1,117 @@ +import { ArrowRightIcon, ChevronDownIcon } from '@chakra-ui/icons' +import { + Text, + Accordion, + AccordionButton, + AccordionItem, + Box, + Flex, + IconButton, + Menu, + MenuButton, + MenuItemOption, + MenuList, + MenuOptionGroup, + Portal, + Tooltip, + VStack, + AccordionIcon, + AccordionPanel, + MenuItem, + Collapse, + StackDivider, + Button, +} from '@chakra-ui/react' +import React, { useCallback } from 'react' +import { ColorMenu } from './ColorMenu' +import { EnableSection } from './EnableSection' +import { SliderWithInfo } from './SliderWithInfo' +import { HighlightingPanel } from './HighlightingPanel' +import { ColorsPanel } from './ColorsPanel' +import { colorList, initialVisuals } from './config' +import { NodesNLinksPanel } from './NodesNLinksPanel' +import { LabelsPanel } from './LabelsPanel' +import { CitationsPanel } from './CitationsPanel' + +export interface VisualsPanelProps { + visuals: typeof initialVisuals + setVisuals: any + highlightColor: string + setHighlightColor: any + threeDim: boolean +} + +export const VisualsPanel = (props: VisualsPanelProps) => { + const { visuals, setVisuals, highlightColor, setHighlightColor, threeDim } = props + const setVisualsCallback = useCallback((val) => setVisuals(val), []) + return ( + + + + + + Colors + + + + + + + + + + + Nodes & Links + + + + + + + + + + + Labels + + + + + + + + + + + Highlighting + + + + + + + + + + + Citations + + + + + + + + + + ) +} diff --git a/components/tweaks.tsx b/components/tweaks.tsx index 1a7e72c..a78c7f4 100644 --- a/components/tweaks.tsx +++ b/components/tweaks.tsx @@ -1,11 +1,4 @@ -import { - CloseIcon, - RepeatClockIcon, - ChevronDownIcon, - SettingsIcon, - RepeatIcon, - ArrowRightIcon, -} from '@chakra-ui/icons' +import { CloseIcon, RepeatClockIcon, SettingsIcon } from '@chakra-ui/icons' import { Accordion, AccordionButton, @@ -14,26 +7,12 @@ import { AccordionPanel, Box, Button, - Flex, IconButton, - Menu, - MenuButton, - MenuItem, - MenuList, - MenuOptionGroup, - MenuItemOption, - Select, - StackDivider, - Switch, - Text, Tooltip, - VStack, Heading, - Collapse, - Portal, } from '@chakra-ui/react' -import React, { useContext, useCallback } from 'react' +import React, { useContext } from 'react' import Scrollbars from 'react-custom-scrollbars-2' import { initialPhysics, @@ -46,15 +25,12 @@ import { } from './config' import FilterPanel from './FilterPanel' -import { ColorMenu } from './ColorMenu' import { ThemeContext } from '../util/themecontext' import { usePersistantState } from '../util/persistant-state' -import { SliderWithInfo } from './SliderWithInfo' -import { EnableSection } from './EnableSection' -import { InfoTooltip } from './InfoTooltip' import { PhysicsPanel } from './PhysicsPanel' import { VisualsPanel } from './VisualsPanel' +import { BehaviorPanel } from './BehaviorPanel' export interface TweakProps { physics: typeof initialPhysics @@ -226,157 +202,12 @@ export const Tweaks = (props: TweakProps) => { Behavior - } - align="stretch" - paddingLeft={7} - color="gray.800" - > - - - Expand Node - - - - } - colorScheme="" - color="black" - > - - {mouse.local - ? mouse.local[0]!.toUpperCase() + mouse.local!.slice(1) - : 'Never'} - - - - {' '} - - setMouse({ ...mouse, local: '' })}>Never - setMouse({ ...mouse, local: 'click' })}> - Click - - setMouse({ ...mouse, local: 'double' })}> - Double Click - - setMouse({ ...mouse, local: 'right' })}> - Right Click - - - - - - - Open in Emacs - - } - colorScheme="" - color="black" - > - - {mouse.follow - ? mouse.follow[0]!.toUpperCase() + mouse.follow!.slice(1) - : 'Never'} - - - - {' '} - - setMouse({ ...mouse, follow: '' })}> - Never - - setMouse({ ...mouse, follow: 'click' })}> - Click - - setMouse({ ...mouse, follow: 'double' })}> - Double Click - - setMouse({ ...mouse, follow: 'right' })}> - Right Click - - - - - - - Follow Emacs by... - - } - colorScheme="" - color="black" - > - {behavior.follow[0].toUpperCase() + behavior.follow.slice(1)} - - - {' '} - - setBehavior({ ...behavior, follow: 'color' })}> - Just coloring the currently opened node - - setBehavior({ ...behavior, follow: 'local' })}> - Opening the local graph - - setBehavior({ ...behavior, follow: 'zoom' })}> - Zooming to the current node - - - - - - - - Local graph - - - - } - colorScheme="" - color="black" - > - {behavior.localSame === 'add' ? 'Add' : 'Replace'} - - - {' '} - - setBehavior({ ...behavior, localSame: 'replace' })} - > - Open that nodes graph - - setBehavior({ ...behavior, localSame: 'add' })}> - Add node to local graph - - - - - - setBehavior({ ...behavior, zoomSpeed: value })} - /> - setBehavior({ ...behavior, zoomPadding: value })} - infoText="How much to zoom out to accomodate all nodes when changing the view." - /> - + @@ -384,28 +215,3 @@ export const Tweaks = (props: TweakProps) => { ) } - -export interface DropDownMenuProps { - textArray: string[] - onClickArray: (() => void)[] - displayValue: string -} - -export const DropDownMenu = (props: DropDownMenuProps) => { - const { textArray, onClickArray, displayValue } = props - return ( - - }> - {displayValue} - - - {' '} - - {textArray.map((option, i) => { - ; {option} - })} - - - - ) -} -- cgit v1.2.3