132 lines
3.6 KiB
TypeScript
132 lines
3.6 KiB
TypeScript
import type { LucideIcon } from 'lucide-react'
|
|
import type { ReactElement } from 'react'
|
|
import type { BlockKind, BlockView, KindIconName } from './types'
|
|
import {
|
|
Activity,
|
|
Atom,
|
|
Box,
|
|
Braces,
|
|
CalendarClock,
|
|
Code,
|
|
Copy,
|
|
CornerDownLeft,
|
|
CornerDownRight,
|
|
Database,
|
|
Globe,
|
|
Import,
|
|
Layers,
|
|
ListOrdered,
|
|
Lock,
|
|
MessageSquareText,
|
|
MousePointerClick,
|
|
Network,
|
|
Package,
|
|
Play,
|
|
Repeat,
|
|
ServerCog,
|
|
Shield,
|
|
ShieldAlert,
|
|
ShieldCheck,
|
|
Signpost,
|
|
SlidersHorizontal,
|
|
Split,
|
|
SquareFunction,
|
|
SquareTerminal,
|
|
Tag,
|
|
Terminal,
|
|
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,
|
|
}
|
|
|
|
/**
|
|
* 内置种类的图标:块左边只画图标,名字是悬停提示。
|
|
* 同一类语义共用一个颜色(codeReader.css 的 --cr-kind-*:常量 / 变量 / 字段都是数据,尝试 / 捕获都是异常处理),图标区分具体是哪种。
|
|
*/
|
|
export const KIND_ICONS: Record<BlockKind, KindIconName> = {
|
|
import: 'import',
|
|
function: 'square-function',
|
|
class: 'box',
|
|
type: 'braces',
|
|
enum: 'list-ordered',
|
|
exception: 'triangle-alert',
|
|
field: 'tag',
|
|
const: 'lock',
|
|
variable: 'variable',
|
|
if: 'split',
|
|
else: 'corner-down-right',
|
|
loop: 'repeat',
|
|
try: 'shield',
|
|
catch: 'shield-alert',
|
|
finally: 'shield-check',
|
|
return: 'corner-down-left',
|
|
statement: 'code',
|
|
comment: 'message-square-text',
|
|
interpreter: 'terminal',
|
|
options: 'sliders-horizontal',
|
|
case: 'signpost',
|
|
command: 'square-terminal',
|
|
pipeline: 'square-terminal',
|
|
directive: 'terminal',
|
|
stage: 'layers',
|
|
run: 'square-terminal',
|
|
copy: 'copy',
|
|
setting: 'sliders-horizontal',
|
|
label: 'tag',
|
|
health: 'activity',
|
|
start: 'play',
|
|
}
|
|
|
|
/**
|
|
* 块左边的种类:只画图标,和一行字等高(20px 的框、16px 的图形),颜色是种类色(--kind)。图标是库规则给的(badge.icon),
|
|
* 没有就是内置种类的(KIND_ICONS,没带 badge 的块 kind 是 BlockKind);名字(翻译插件给种类起的,库规则的种类是规则给的)
|
|
* 写在悬停提示(data-tooltip,见 components/ui/tooltip.tsx)和读屏念的 aria-label 里。
|
|
*/
|
|
export function KindIcon({ block, name }: { block: Pick<BlockView, 'kind' | 'badge'>, name: string }): ReactElement {
|
|
const Icon = KIND_ICON_COMPONENTS[block.badge?.icon ?? KIND_ICONS[block.kind as BlockKind]]
|
|
return (
|
|
<span className="cr-kind flex size-5 shrink-0 items-center justify-center" role="img" data-tooltip={name} aria-label={name}>
|
|
<Icon size={16} strokeWidth={2.2} aria-hidden />
|
|
</span>
|
|
)
|
|
}
|