✨ feat(vscode): React 钩子卡片按变量讲,属性表加操作列、调用树能查所有引用
- 钩子调用讲成状态、引用、记忆值、记忆函数、上下文值、过渡、副作用、钩子返回值、钩子调用几种卡片,行照签名表 reactHooks.ts 排,去掉 react.hook - 解构接住时名称一行写出解构,展开是「第几项 | 名称 | 说明」表,每项一个调用树操作;单个名字的按钮在名称一行最右边 - 属性表的行、子行可以带操作(RowAction),表格多一列「操作」,宿主按块记号加序号起键 - 调用树服务按键数次数,新增查所有引用(references):按所在函数分组,去掉定义处和依赖数组里的 - 钩子收的函数参数都收成小框,函数体是卡片子块,直接返回的表达式由 functionBody 排成「返回 …」卡片;小框和卡片折叠箭头同一个开关 - 规则卡片可指定语言种类图标(languageKind)、种类图标悬停字和颜色(KindBadge.tooltip / iconColor)
This commit is contained in:
1 parent
a139341132
commit
86beaac371
38 files changed
+1971
-813
No files matched your search
@@ -1,10 +1,12 @@
|
||||
import type { CSSProperties, ReactElement, ReactNode } from 'react'
|
||||
import type { BlockView, ChainSlot, ChainStep, Inline, ItemDiff, ItemsDiff, KindBadge, PreviewText, PropertyItem, PropertyRow, Removed, RowDiff, RowsDiff, TextDiff } from './types'
|
||||
import type { BlockView, ChainSlot, ChainStep, Inline, ItemDiff, ItemsDiff, KindBadge, PreviewText, PropertyItem, PropertyRow, Removed, RowAction, RowDiff, RowsDiff, TextDiff } from './types'
|
||||
import { ChevronDown, ChevronRight } from 'lucide-react'
|
||||
import { Fragment } from 'react'
|
||||
import { Fragment, useContext } from 'react'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { CallTreeButton } from './BlockTools'
|
||||
import { ChainFoldContext } from './chainFold'
|
||||
import { DiffInline, DiffText } from './DiffText'
|
||||
import { RowActionsContext } from './rowActions'
|
||||
import { inlineText } from './segments'
|
||||
import { SegmentText } from './SegmentText'
|
||||
import { subRowsLayout, tableCells, tableTemplate } from './subRows'
|
||||
@@ -134,6 +136,24 @@ function ItemHead({ id, cell, foldable, folding, find }: { id: string, cell: Pre
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 一行能做的操作([RowAction]),按钮从左往右排:现在都是看调用树([CallTreeButton]),悬停写操作自己的说法,次数、开着没有照卡片给的(见 [RowActionsContext])。
|
||||
* 卡片没给(定义卡片浮窗、删掉的块的旧内容)、操作没有键时不画。
|
||||
*/
|
||||
function RowActionButtons({ actions }: { actions: readonly RowAction[] | undefined }): ReactElement | null {
|
||||
const state = useContext(RowActionsContext)
|
||||
const keyed = state ? (actions ?? []).flatMap(action => action.key === undefined ? [] : [{ action, key: action.key }]) : []
|
||||
if (!state || keyed.length === 0)
|
||||
return null
|
||||
return (
|
||||
<span className="cr-row-actions" role="group" aria-label="操作">
|
||||
{keyed.map(({ action, key }) => (
|
||||
<CallTreeButton key={key} callKey={key} label={action.label} count={state.counts.get(key) ?? 0} open={state.openKey === key} onOpen={() => state.onOpen(key)} />
|
||||
))}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
/** 往右缩进一层、左边一条竖线:一行或一个子行下面的一层子行,列表的一项下面挂的实参表 */
|
||||
function Nested({ children }: { children: ReactNode }): ReactElement {
|
||||
return (
|
||||
@@ -211,6 +231,8 @@ export function PropertyItems({ parentId, items, folding, marks }: { parentId: s
|
||||
* 行带 table(实参的值里跨几行写的调用)时那张表排在它们后面,往右缩一点。一层层往下套。
|
||||
* 标差异时(marks)有加行、删行的表每行第一格前多一个记号位(+ / −,没变的空着),加的行淡绿底,删的行放回原来的位置、淡红底划掉。
|
||||
* 讲某个子块的行(toggles,Rust 实现块的方法表)第一格是按钮,点它在表下面展开那一块,展开时这一行淡淡垫上那一块的种类色。
|
||||
* 有行带操作([PropertyItem.actions])、卡片又给了操作的状态([RowActionsContext])时,最后多一列「操作」,宽度按按钮最多的那一行,
|
||||
* 各行的操作按钮在这一格里从左往右排,没有操作的行空着。
|
||||
*/
|
||||
export function PropertyTable({ parentId, columns, items, marks, folding, toggles }: {
|
||||
parentId: string
|
||||
@@ -224,6 +246,7 @@ export function PropertyTable({ parentId, columns, items, marks, folding, toggle
|
||||
}): ReactElement {
|
||||
// 有加行、删行的表每行第一格前留一个记号位
|
||||
const signed = marks !== undefined && (marks.removed.length > 0 || Object.values(marks.changed).some(mark => mark.added))
|
||||
const operable = useContext(RowActionsContext) !== undefined && items.some(item => (item.actions?.length ?? 0) > 0)
|
||||
/** 一行:删掉的(change 是 del)不带 id,套着的表不再标;toggle 是这一行讲的子块,第一格成了展开它的按钮 */
|
||||
const tableRow = (item: PropertyItem, id: string, change: 'add' | 'del' | undefined, mark: ItemDiff | undefined, toggle?: ItemToggle): ReactElement => {
|
||||
const cells = tableCells(item, columns)
|
||||
@@ -255,6 +278,11 @@ export function PropertyTable({ parentId, columns, items, marks, folding, toggle
|
||||
</div>
|
||||
)
|
||||
: <Fragment key={i}>{cellBox(cell, i, 'cr-table-cell')}</Fragment>)}
|
||||
{operable && (
|
||||
<div className="cr-table-cell cr-table-ops" role="cell">
|
||||
{change !== 'del' && <RowActionButtons actions={item.actions} />}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -262,9 +290,10 @@ export function PropertyTable({ parentId, columns, items, marks, folding, toggle
|
||||
.map(({ value, index }) => <Fragment key={`removed-${index}`}>{tableRow(value, `${parentId}/x${index}`, 'del', undefined)}</Fragment>)
|
||||
return (
|
||||
<div className="pl-[5px]">
|
||||
<div className="cr-table" role="table" style={{ gridTemplateColumns: tableTemplate(columns.length) }}>
|
||||
<div className="cr-table" role="table" style={{ gridTemplateColumns: operable ? `${tableTemplate(columns.length)} max-content` : tableTemplate(columns.length) }}>
|
||||
<div className="cr-table-head" role="row">
|
||||
{columns.map((name, i) => <span key={i} className="cr-table-cell" role="columnheader" data-find={textKey(parentId, `h${i}`)}>{name}</span>)}
|
||||
{operable && <span className="cr-table-cell" role="columnheader">操作</span>}
|
||||
</div>
|
||||
{removed(-1)}
|
||||
{items.map((item, index) => {
|
||||
@@ -283,7 +312,8 @@ export function PropertyTable({ parentId, columns, items, marks, folding, toggle
|
||||
|
||||
/**
|
||||
* 函数、类、枚举、导入、常量、变量块和库规则的卡片的预览:属性名一列对齐,值按词性着色;输入参数、导入项、字典 / 对象的值下面展开子行,
|
||||
* 给了列名的(输入参数、数据表的字段)排成表格,没给的排成列表。
|
||||
* 给了列名的(输入参数、数据表的字段)排成表格,没给的排成列表。一行带操作([PropertyRow.actions],React 卡片只接一个名字时的「名称」一行)时,
|
||||
* 按钮排在这一行最右边(见 [RowActionButtons])。
|
||||
* 标差异时(marks)新加的行淡绿底、左边 +,删掉的行放回原来的位置、淡红底划掉、左边 −,值改了的按旧值 → 新值或逐词标。
|
||||
*/
|
||||
export function PropertyGrid({ blockId, rows, collapsed, onToggleFold, marks, slots, chain }: {
|
||||
@@ -334,14 +364,16 @@ export function PropertyGrid({ blockId, rows, collapsed, onToggleFold, marks, sl
|
||||
</button>
|
||||
)
|
||||
: <span className="cr-prop-label flex h-5 items-center" data-find={textKey(id, 'label')}>{row.label}</span>}
|
||||
{row.chain
|
||||
? (
|
||||
<div className="min-w-0">
|
||||
<RowValue row={row} mark={mark} id={id} />
|
||||
<ChainRail blockId={blockId} row={index} steps={row.chain} folding={folding} slots={chain} />
|
||||
</div>
|
||||
)
|
||||
: <RowValue row={row} mark={mark} id={id} />}
|
||||
<WithActions actions={row.actions}>
|
||||
{row.chain
|
||||
? (
|
||||
<div className="min-w-0">
|
||||
<RowValue row={row} mark={mark} id={id} />
|
||||
<ChainRail blockId={blockId} row={index} steps={row.chain} folding={folding} slots={chain} />
|
||||
</div>
|
||||
)
|
||||
: <RowValue row={row} mark={mark} id={id} />}
|
||||
</WithActions>
|
||||
</div>
|
||||
{!folded && layout === 'table' && <PropertyTable parentId={id} columns={row.columns ?? []} items={row.items ?? []} marks={mark?.items} folding={folding} toggles={toggles} />}
|
||||
{!folded && layout === 'list' && <PropertyItems parentId={id} items={row.items ?? []} folding={folding} marks={mark?.items} />}
|
||||
@@ -354,6 +386,19 @@ export function PropertyGrid({ blockId, rows, collapsed, onToggleFold, marks, sl
|
||||
)
|
||||
}
|
||||
|
||||
/** 属性行的值,这一行带操作、卡片又给了操作的状态时,操作按钮排在值的最右边;不然只有值。 */
|
||||
function WithActions({ actions, children }: { actions: readonly RowAction[] | undefined, children: ReactElement }): ReactElement {
|
||||
const state = useContext(RowActionsContext)
|
||||
if (!state || !actions?.some(action => action.key !== undefined))
|
||||
return children
|
||||
return (
|
||||
<div className="flex min-w-0 items-start gap-2">
|
||||
<div className="min-w-0 flex-1">{children}</div>
|
||||
<RowActionButtons actions={actions} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 一行的值:着色的词或 Markdown(改了的逐截 / 逐词标);跟着说明(PropertyRow.note,输出参数的 `@return`)时说明接在值后面,
|
||||
* 同一行放得下就并排,剩的地方不到 12 个字宽时换到下一行。`id` 是这一行的 id,值和说明按它记上记号(见 [textKey]);删掉的行没有。
|
||||
|
||||
Reference in new issue
Block a user