✨ feat(vscode): 代码阅读的 React 组件卡片:原子图标,名称后面跟具名导出 / 默认导出 / 客户端组件 / 记忆化 / 转发 ref 小标签,属性表按属性一行(类型取字段、默认值、必填、说明,来自 XxxProps 可点,导入的类型经工作区索引查),"use client" 和组件上的 JSDoc 不再单独成块
This commit is contained in:
1 parent
1a32a51e75
commit
15f3a6600d
14 files changed
+666
-34
No files matched your search
@@ -1,7 +1,7 @@
|
||||
import type { LucideIcon } from 'lucide-react'
|
||||
import type { CSSProperties, ReactElement } from 'react'
|
||||
import type { GroupStyle, Inline, SegmentGroup } from './types'
|
||||
import { useContext } from 'react'
|
||||
import { useContext, useState } from 'react'
|
||||
import { DisplayNameContext, shownName } from './displayNames'
|
||||
import { KIND_ICON_COMPONENTS, KIND_ICONS } from './kindIcons'
|
||||
import { isCurrent, segmentOccurrence, sourceOf } from './occurrences'
|
||||
@@ -42,19 +42,62 @@ export function SegmentText({ segments }: { segments: Inline[] }): ReactElement
|
||||
)
|
||||
}
|
||||
|
||||
/** 框的样式 → 框头图标:遍历同「循环」块的图标;颜色在 codeReader.css 的 .cr-group[data-style] 里。 */
|
||||
const GROUP_ICONS: Record<GroupStyle, LucideIcon> = { iteration: KIND_ICON_COMPONENTS[KIND_ICONS.loop] }
|
||||
/**
|
||||
* 框的样式 → 框头图标:遍历同「循环」块、按条件同「条件」块、不渲染同「返回」块的图标;条件的一支、小标签、类名不带图标。
|
||||
* 颜色在 codeReader.css 的 .cr-group[data-style] 里,框自己给了颜色(color)时用它。
|
||||
*/
|
||||
const GROUP_ICONS: Record<GroupStyle, LucideIcon | undefined> = {
|
||||
iteration: KIND_ICON_COMPONENTS[KIND_ICONS.loop],
|
||||
condition: KIND_ICON_COMPONENTS[KIND_ICONS.if],
|
||||
branch: undefined,
|
||||
skip: KIND_ICON_COMPONENTS[KIND_ICONS.return],
|
||||
tag: undefined,
|
||||
classes: undefined,
|
||||
}
|
||||
|
||||
/** 框起来的一组词:嵌在前后文字里的小框,放不下时整个挪到下一行,比一行还长时在框里换行。 */
|
||||
/** 框自己的颜色,暗色、亮色两个都写在 style 上,CSS 按主题挑一个(见 .cr-group[data-colored])。 */
|
||||
function groupColor(group: SegmentGroup): CSSProperties | undefined {
|
||||
return group.color && { '--group-dark': group.color.dark, '--group-light': group.color.light } as CSSProperties
|
||||
}
|
||||
|
||||
/**
|
||||
* 框起来的一组词:嵌在前后文字里的小框,放不下时整个挪到下一行,比一行还长时在框里换行。框头是图标和 label,只有图标、只有字、都没有都行;
|
||||
* 收起来的类名另见 ClassesChip。
|
||||
*/
|
||||
function GroupBox({ group }: { group: SegmentGroup }): ReactElement {
|
||||
if (group.style === 'classes')
|
||||
return <ClassesChip group={group} />
|
||||
const Icon = GROUP_ICONS[group.style]
|
||||
return (
|
||||
<span className="cr-group" data-style={group.style}>
|
||||
<span className="cr-group-head">
|
||||
<Icon size={12} strokeWidth={2} aria-hidden />
|
||||
{group.label}
|
||||
</span>
|
||||
<span className="cr-group" data-style={group.style} data-colored={group.color ? '' : undefined} style={groupColor(group)}>
|
||||
{(Icon || group.label) && (
|
||||
<span className="cr-group-head" data-bare={group.label ? undefined : ''}>
|
||||
{Icon && <Icon size={12} strokeWidth={2} aria-hidden />}
|
||||
{group.label}
|
||||
</span>
|
||||
)}
|
||||
<SegmentText segments={group.segments} />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
/** 收起来的一串类名(「样式 N 个类」):悬停看全部类名,点一下在它下面弹出、盖住后面的字,再点收起。 */
|
||||
function ClassesChip({ group }: { group: SegmentGroup }): ReactElement {
|
||||
const [open, setOpen] = useState(false)
|
||||
return (
|
||||
<span className="cr-classes">
|
||||
<button
|
||||
type="button"
|
||||
className="cr-group"
|
||||
data-style="classes"
|
||||
data-open={open ? '' : undefined}
|
||||
aria-expanded={open}
|
||||
data-tooltip={open ? undefined : group.detail}
|
||||
onClick={() => setOpen(value => !value)}
|
||||
>
|
||||
<span className="cr-group-head">{group.label}</span>
|
||||
</button>
|
||||
{open && <span className="cr-classes-popup" role="note">{group.detail}</span>}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user