dify/web/app/components/workflow/skill/editor-tabs.tsx
yyh a30fb5909b
feat(skill): implement VS Code-style preview/pinned tab management
- Single-click file in tree opens in preview mode (temporary, replaceable)
- Double-click file opens in pinned mode (permanent)
- Preview tabs display with italic filename
- Editing content auto-converts preview tab to pinned
- Double-clicking preview tab header converts to pinned
- Only one preview tab can exist at a time
2026-01-16 11:20:49 +08:00

66 lines
1.9 KiB
TypeScript

'use client'
import type { FC } from 'react'
import * as React from 'react'
import { cn } from '@/utils/classnames'
import EditorTabItem from './editor-tab-item'
import { useSkillAssetNodeMap } from './hooks/use-skill-asset-tree'
import { useSkillEditorStore, useSkillEditorStoreApi } from './store'
const EditorTabs: FC = () => {
const openTabIds = useSkillEditorStore(s => s.openTabIds)
const activeTabId = useSkillEditorStore(s => s.activeTabId)
const previewTabId = useSkillEditorStore(s => s.previewTabId)
const dirtyContents = useSkillEditorStore(s => s.dirtyContents)
const storeApi = useSkillEditorStoreApi()
const { data: nodeMap } = useSkillAssetNodeMap()
const handleTabClick = (fileId: string) => {
storeApi.getState().activateTab(fileId)
}
const handleTabDoubleClick = (fileId: string) => {
storeApi.getState().pinTab(fileId)
}
const handleTabClose = (fileId: string) => {
storeApi.getState().closeTab(fileId)
storeApi.getState().clearDraftContent(fileId)
}
if (openTabIds.length === 0)
return null
return (
<div
className={cn(
'flex items-center overflow-hidden rounded-t-lg border-b border-components-panel-border-subtle bg-components-panel-bg-alt',
)}
>
{openTabIds.map((fileId) => {
const node = nodeMap?.get(fileId)
const name = node?.name ?? fileId
const isActive = activeTabId === fileId
const isDirty = dirtyContents.has(fileId)
const isPreview = previewTabId === fileId
return (
<EditorTabItem
key={fileId}
fileId={fileId}
name={name}
isActive={isActive}
isDirty={isDirty}
isPreview={isPreview}
onClick={handleTabClick}
onClose={handleTabClose}
onDoubleClick={handleTabDoubleClick}
/>
)
})}
</div>
)
}
export default React.memo(EditorTabs)