- 组件体的语句不再并进组件卡片,照源码顺序是它的子块;状态、引用、数据源、派生值、副作用、事件处理函数、渲染输出各成一张卡片,回调和函数里的语句是这些卡片下面的子卡片 - 普通变量、提前返回的 if、注释照语言默认的卡片;表格格子里只写名字和位置,去掉「改它的」「来自」格子里单独打开源码的那条路 - 用词改成书面叫法(更新位置、使用位置、计算表达式、依赖项、触发时机、清理函数、绑定事件、样式取决于……),新增 toggle-right、anchor、download、sigma、layout-template 五个种类图标 - 夹具加上 luffy 的 QueuedBubble.tsx、PlanChecklist.tsx,规格的 React 一节照新样子改写
113 lines
3.0 KiB
TypeScript
113 lines
3.0 KiB
TypeScript
import type { LucideIcon } from 'lucide-react'
|
||
import type { CSSProperties, ReactElement } from 'react'
|
||
import type { BlockConcept, KindIconName } from './types'
|
||
import {
|
||
Activity,
|
||
Anchor,
|
||
Atom,
|
||
Box,
|
||
Braces,
|
||
CalendarClock,
|
||
Code,
|
||
Copy,
|
||
CornerDownLeft,
|
||
CornerDownRight,
|
||
Database,
|
||
Download,
|
||
Globe,
|
||
Import,
|
||
Layers,
|
||
LayoutTemplate,
|
||
ListOrdered,
|
||
Lock,
|
||
MessageSquareText,
|
||
MousePointerClick,
|
||
Network,
|
||
Package,
|
||
Play,
|
||
Repeat,
|
||
ServerCog,
|
||
Shield,
|
||
ShieldAlert,
|
||
ShieldCheck,
|
||
Sigma,
|
||
Signpost,
|
||
SlidersHorizontal,
|
||
Split,
|
||
SquareFunction,
|
||
SquareTerminal,
|
||
Tag,
|
||
Terminal,
|
||
ToggleRight,
|
||
TriangleAlert,
|
||
Variable,
|
||
Zap,
|
||
} from 'lucide-react'
|
||
|
||
/** 插件定义的这组种类图标,每个名字一个 lucide 图标(逐个 import,打包只带这些)。 */
|
||
export const KIND_ICON_COMPONENTS: Record<KindIconName, LucideIcon> = {
|
||
'import': Import,
|
||
'square-function': SquareFunction,
|
||
'box': Box,
|
||
'braces': Braces,
|
||
'list-ordered': ListOrdered,
|
||
'triangle-alert': TriangleAlert,
|
||
'tag': Tag,
|
||
'lock': Lock,
|
||
'variable': Variable,
|
||
'split': Split,
|
||
'corner-down-right': CornerDownRight,
|
||
'repeat': Repeat,
|
||
'shield': Shield,
|
||
'shield-alert': ShieldAlert,
|
||
'shield-check': ShieldCheck,
|
||
'corner-down-left': CornerDownLeft,
|
||
'code': Code,
|
||
'message-square-text': MessageSquareText,
|
||
'terminal': Terminal,
|
||
'sliders-horizontal': SlidersHorizontal,
|
||
'signpost': Signpost,
|
||
'square-terminal': SquareTerminal,
|
||
'layers': Layers,
|
||
'copy': Copy,
|
||
'activity': Activity,
|
||
'play': Play,
|
||
'database': Database,
|
||
'package': Package,
|
||
'server-cog': ServerCog,
|
||
'calendar-clock': CalendarClock,
|
||
'globe': Globe,
|
||
'network': Network,
|
||
'atom': Atom,
|
||
'zap': Zap,
|
||
'mouse-pointer-click': MousePointerClick,
|
||
'toggle-right': ToggleRight,
|
||
'anchor': Anchor,
|
||
'download': Download,
|
||
'sigma': Sigma,
|
||
'layout-template': LayoutTemplate,
|
||
}
|
||
|
||
/**
|
||
* 卡片左边的概念图标,横排,各 20px,间距紧。图标名由宿主放进概念列表,这里只按名字画。
|
||
* 没有颜色的是语言的种类,按 id 用 CSS 的种类色;有颜色的只给这个图标上色。
|
||
* 每个图标悬停自己的名字(data-tooltip,见 components/ui/tooltip.tsx);读屏把名字连起来念。
|
||
*/
|
||
export function KindIcon({ concepts }: { concepts: readonly BlockConcept[] }): ReactElement {
|
||
return (
|
||
<span className="flex shrink-0 items-center gap-0.5" role="img" aria-label={concepts.map(concept => concept.label).join(',')}>
|
||
{concepts.map((concept) => {
|
||
const Icon = KIND_ICON_COMPONENTS[concept.icon]
|
||
const tint = concept.color
|
||
? { 'data-badge': '' as const, 'style': { '--kind-dark': concept.color.dark, '--kind-light': concept.color.light } as CSSProperties }
|
||
: { 'data-kind': concept.id }
|
||
return (
|
||
<span key={concept.id} className="cr-kind flex size-5 shrink-0 items-center justify-center" data-tooltip={concept.label} aria-hidden {...tint}>
|
||
<Icon size={16} strokeWidth={2.2} aria-hidden />
|
||
</span>
|
||
)
|
||
})}
|
||
</span>
|
||
)
|
||
}
|