import type { CSSProperties, ReactElement } from 'react' import type { BlockView } from './types' import { ChevronDown, ChevronRight, Eye, EyeOff, Pencil } from 'lucide-react' import { Fragment } from 'react' import { cn } from '@/lib/utils' import { CodeEditor } from './CodeEditor' import { PropertyGrid } from './PropertyGrid' import { TextPreview } from './TextPreview' export interface BlockTreeState { version: number editing: ReadonlySet /** 眼下折叠着的块 id、属性行 id 和子行 id(propertyRowId、propertyItemId):用户的选择叠在默认上,见 collapsedIds */ collapsed: ReadonlySet /** 按筛选不画的块(连同子孙),见 applyFilter */ hidden: ReadonlySet /** 本来被筛掉、跳到定义时临时显示的块 */ temporary: ReadonlySet /** 种类标签上写什么:翻译插件给种类起的名字(库规则的种类是规则给的标签),没给就是 id */ kindName: (kind: string) => string /** 刚点了「编辑」、要把光标放进去的块 */ focusId: string | null onFocused: () => void onToggleEdit: (id: string) => void onToggleFold: (id: string) => void } /** 块下面有没有画出来的子块:子块都被筛掉时不留空的一层、不给折叠箭头。 */ function hasShownChildren(block: BlockView, tree: BlockTreeState): boolean { return block.children.some(child => !tree.hidden.has(child.id)) } /** * 块的种类色写在哪:内置种类按 data-kind 取 CSS 里的配色;库规则认领的块(带 badge)按规则给的颜色, * 暗色、亮色两个都写在 style 上,CSS 按主题挑一个(见 [data-badge])。 */ function kindProps(block: BlockView | undefined): { 'data-kind'?: string, 'data-badge'?: '', 'style'?: CSSProperties } { if (!block) return {} if (!block.badge) return { 'data-kind': block.kind } const { dark, light } = block.badge.color return { 'data-kind': block.kind, 'data-badge': '', 'style': { '--kind-dark': dark, '--kind-light': light } as CSSProperties } } /** * 一层代码块:左边一条竖线标出这一层,每块的子块紧跟在它下面、再往右缩进一层。被筛掉的块不画,不留空位,竖线跟着变短。 * owner 是这一层所属的块(顶层没有),悬停它时竖线换成它的种类色。 */ export function BlockLevel({ blocks, owner, tree }: { blocks: BlockView[], owner?: BlockView, tree: BlockTreeState }): ReactElement { return (
{blocks.filter(block => !tree.hidden.has(block.id)).map(block => ( {hasShownChildren(block, tree) && !tree.collapsed.has(block.id) && ( )} ))}
) } /** 预览状态的内容:函数、类、导入、常量、变量块和库规则认领的块是属性表,其余是一行译文,带说明的译文下面接着说明。 */ function BlockPreview({ block, tree }: { block: BlockView, tree: BlockTreeState }): ReactElement { if ('properties' in block) return return ( <> {block.doc && } ) } /** 一块:折叠箭头、种类标签、预览内容或源码、右边的「编辑 / 预览」切换。 */ function BlockCard({ block, tree }: { block: BlockView, tree: BlockTreeState }): ReactElement { const editing = tree.editing.has(block.id) const collapsed = tree.collapsed.has(block.id) const hasChildren = hasShownChildren(block, tree) const Chevron = collapsed ? ChevronRight : ChevronDown return (
{hasChildren ? ( ) : } {tree.kindName(block.kind)}
{editing ? ( tree.onToggleEdit(block.id)} /> ) : }
{tree.temporary.has(block.id) && ( 已被筛选隐藏,临时显示 )}
) }