mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
85 lines
2.2 KiB
TypeScript
85 lines
2.2 KiB
TypeScript
import * as React from 'react'
|
|
import { cx } from 'utils/cx'
|
|
import { OperatingSystems, os } from 'utils/general'
|
|
import { TreeNode } from 'utils/VisibleNodesGenerator'
|
|
import { getFileIconSrc, getFolderIconSrc } from '../utils/parseIconMapCSV'
|
|
import { Icon } from './Icon'
|
|
|
|
function getIconType(node: TreeNode) {
|
|
switch (node.type) {
|
|
case 'tree':
|
|
return 'folder'
|
|
case 'commit':
|
|
return 'submodule'
|
|
default:
|
|
return node.name.replace(/.*\./, '.')
|
|
}
|
|
}
|
|
|
|
type Props = {
|
|
node: TreeNode
|
|
onClick(node: TreeNode): void
|
|
depth: number
|
|
expanded: boolean
|
|
focused: boolean
|
|
renderActions?(node: TreeNode): React.ReactNode
|
|
style?: React.CSSProperties
|
|
}
|
|
export function Node({ node, depth, expanded, focused, renderActions, style, onClick }: Props) {
|
|
const onClickNode: React.MouseEventHandler = React.useCallback(
|
|
event => {
|
|
if (
|
|
(os === OperatingSystems.macOS && event.metaKey) ||
|
|
(os === OperatingSystems.Windows && event.ctrlKey)
|
|
) {
|
|
// The default behavior, open in new tab
|
|
return
|
|
}
|
|
event.preventDefault()
|
|
|
|
onClick(node)
|
|
},
|
|
[node, onClick],
|
|
)
|
|
|
|
const { name, path } = node
|
|
return (
|
|
<div
|
|
className={cx(`node-item-row`, { focused, disabled: node.accessDenied })}
|
|
style={style}
|
|
title={path}
|
|
>
|
|
<a href={node.url} onClick={onClickNode}>
|
|
<div
|
|
className={cx('node-item', { expanded })}
|
|
style={{ paddingLeft: `${10 + 20 * depth}px` }}
|
|
>
|
|
<div className={'node-item-label'}>
|
|
<NodeItemIcon node={node} open={expanded} />
|
|
<span className={'node-item-name'}>{name}</span>
|
|
</div>
|
|
{renderActions && <div>{renderActions(node)}</div>}
|
|
</div>
|
|
</a>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const NodeItemIcon = React.memo(function NodeItemIcon({
|
|
node,
|
|
open = false,
|
|
}: {
|
|
node: TreeNode
|
|
open?: boolean
|
|
}) {
|
|
const src = React.useMemo(
|
|
() => (node.type === 'tree' ? getFolderIconSrc(node, open) : getFileIconSrc(node)),
|
|
[open],
|
|
)
|
|
return (
|
|
<>
|
|
{node.type !== 'blob' && <Icon type={getIconType(node)} />}
|
|
<img alt={node.name} className={'node-item-icon'} src={src} />
|
|
</>
|
|
)
|
|
})
|