mirror of
https://github.com/penxio/penx.git
synced 2026-04-19 03:03:06 -04:00
feat: create TreeView
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import { useState } from 'react'
|
||||
import { Box } from '@fower/react'
|
||||
import { useSelected } from 'slate-react'
|
||||
import { ElementProps } from '@penx/extension-typings'
|
||||
@@ -40,7 +39,7 @@ export const Tag = ({
|
||||
fontNormal
|
||||
py1
|
||||
px1
|
||||
textSM
|
||||
textXS
|
||||
bg--T92={node?.tagColor}
|
||||
bg--T88--hover={node?.tagColor}
|
||||
color={node?.tagColor}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { FavoriteBox } from './FavoriteBox/FavoriteBox'
|
||||
import { RecentlyEdited } from './RecentlyEdited'
|
||||
import { SidebarItem } from './SidebarItem'
|
||||
import { SpacePopover } from './SpacePopover'
|
||||
import { TreeView } from './TreeView'
|
||||
import { UserAvatarModal } from './UserAvatarModal/UserAvatarModal'
|
||||
import { WalletConnectButton } from './WalletConnectButton'
|
||||
|
||||
@@ -88,6 +89,9 @@ export const Sidebar = () => {
|
||||
))}
|
||||
|
||||
<FavoriteBox />
|
||||
|
||||
<TreeView />
|
||||
|
||||
<RecentlyEdited />
|
||||
|
||||
<SidebarItem
|
||||
|
||||
71
packages/app/src/Sidebar/TreeView.tsx
Normal file
71
packages/app/src/Sidebar/TreeView.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { Box } from '@fower/react'
|
||||
import { ChevronDown } from 'lucide-react'
|
||||
import { useNodes } from '@penx/hooks'
|
||||
import { Node } from '@penx/model'
|
||||
import { store } from '@penx/store'
|
||||
|
||||
interface TreeViewItemProps {
|
||||
level: number
|
||||
node: Node
|
||||
}
|
||||
|
||||
function TreeViewItem({ node, level }: TreeViewItemProps) {
|
||||
return (
|
||||
<Box
|
||||
h-32
|
||||
toCenterY
|
||||
cursorPointer
|
||||
rounded
|
||||
bgGray200--hover
|
||||
transitionColors
|
||||
gap1
|
||||
pl={level * 12 + 8}
|
||||
onClick={() => {
|
||||
store.selectNode(node.raw)
|
||||
}}
|
||||
>
|
||||
{node.hasChildren && (
|
||||
<Box inlineFlex gray500>
|
||||
<ChevronDown size={14} />
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{!node.hasChildren && (
|
||||
<Box ml--6 mr-6 inlineFlex bgGray400 square-3 roundedFull></Box>
|
||||
)}
|
||||
|
||||
<Box>{node.title}</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export const TreeView = () => {
|
||||
const { nodes, nodeList } = useNodes()
|
||||
|
||||
function renderNodes(children: string[], level = 0) {
|
||||
return children.map((child, i) => {
|
||||
const node = nodeList.getNode(child)
|
||||
if (!node.children.length) {
|
||||
return <TreeViewItem key={child} node={node} level={level} />
|
||||
}
|
||||
|
||||
return (
|
||||
<Box key={child} py1>
|
||||
<TreeViewItem key={child} node={node} level={level} />
|
||||
<Box>{renderNodes(node.children, level + 1)}</Box>
|
||||
</Box>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (!nodes.length) return null
|
||||
|
||||
return (
|
||||
<Box px3>
|
||||
<Box mb2 fontBold>
|
||||
Tree view
|
||||
</Box>
|
||||
<Box>{renderNodes(nodeList.rootNode?.children || [])}</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -29,6 +29,10 @@ export class Node {
|
||||
return this.raw?.type || ''
|
||||
}
|
||||
|
||||
get hasChildren() {
|
||||
return !!this.children.length
|
||||
}
|
||||
|
||||
get props() {
|
||||
return this.raw.props || {}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,10 @@ export class NodeListService {
|
||||
return this.nodes.filter((node) => node.isTrash)
|
||||
}
|
||||
|
||||
getNode(id: string) {
|
||||
return this.nodeMap.get(id)!
|
||||
}
|
||||
|
||||
getFavorites(ids: string[] = []) {
|
||||
return this.nodes.filter((node) => ids.includes(node.id))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user