✨ feat(vscode): 代码阅读页面画链式调用卡片:竖轨道、小链、收起的闭包和合成的表

链的各步排在值下面的竖轨道上,方法一列对齐、轨道线是函数色淡到 35%;实参是链的缩进成空心点小链,注释挂在步骤下;收起的闭包是能点的小框,点开那一步才画挂着的子块(折叠 id 记在属性行下面);跳到定义、查找、高度估算、只看改动都算上链里的字和步骤下的子块
This commit is contained in:
cruldra committed 2026-10-15 21:05:07 +11:00
1 parent ee595f3da9
commit 1956879aa1
13 files changed
+531 -47

No files matched your search

@@ -5,7 +5,9 @@ import type { Highlight, OccurrenceStyle } from './occurrences'
import type { Placement } from './placement'
import type { ReadableStore } from './store'
import type { GroupStyle, Inline, Segment, SegmentGroup, ShownName } from './types'
import { ChevronDown, ChevronRight } from 'lucide-react'
import { createContext, memo, useContext, useState } from 'react'
import { ChainFoldContext } from './chainFold'
import { sameShownName, shownName } from './displayNames'
import { KIND_ICON_COMPONENTS } from './kindIcons'
import { isCurrent, segmentOccurrence, sourceOf } from './occurrences'
@@ -106,6 +108,7 @@ const GROUP_ICONS: Record<GroupStyle, LucideIcon | undefined> = {
branch: undefined,
tag: undefined,
classes: undefined,
fold: undefined,
}
/** 框自己的颜色,暗色、亮色两个都写在 style 上,CSS 按主题挑一个(见 .cr-group[data-colored])。 */
@@ -120,6 +123,8 @@ function groupColor(group: SegmentGroup): CSSProperties | undefined {
function GroupBox({ group }: { group: SegmentGroup }): ReactElement {
if (group.style === 'classes')
return <ClassesChip group={group} />
if (group.style === 'fold')
return <FoldChip group={group} />
const Icon = GROUP_ICONS[group.style]
return (
<span className="cr-group" data-style={group.style} data-colored={group.color ? '' : undefined} style={groupColor(group)}>
@@ -134,6 +139,33 @@ function GroupBox({ group }: { group: SegmentGroup }): ReactElement {
)
}
/**
* 链式调用卡片里收起来的闭包、async 块(「闭包 |app| · 37 句」):前面一个折叠箭头,点它展开、收起这一步下面挂着的子块
* (开关是所在那一步给的,见 [ChainFoldContext]);不在链的某一步里时只是一个小框。
*/
function FoldChip({ group }: { group: SegmentGroup }): ReactElement {
const fold = useContext(ChainFoldContext)
const Chevron = fold?.open ? ChevronDown : ChevronRight
return (
<button
type="button"
className="cr-group"
data-style="fold"
data-open={fold?.open ? '' : undefined}
aria-expanded={fold?.open ?? false}
aria-label={`${fold?.open ? '收起' : '展开'}${group.label}`}
disabled={!fold}
onClick={fold?.onToggle}
>
<span className="cr-group-head">
<Chevron size={12} strokeWidth={2} aria-hidden />
{group.label}
</span>
<SegmentText segments={group.segments} />
</button>
)
}
/** 收起来的一串类名(「样式 N 个类」):悬停看全部类名,点一下在它下面弹出、盖住后面的字,再点收起。 */
function ClassesChip({ group }: { group: SegmentGroup }): ReactElement {
const [open, setOpen] = useState(false)