chore: snapshot workflow migration progress

This commit is contained in:
2026-04-12 11:49:04 +02:00
parent 0cd02513d5
commit 3e810c74a3
163 changed files with 31773 additions and 2752 deletions
@@ -1,14 +1,23 @@
import { useEffect, type ReactNode } from 'react'
import { X } from 'lucide-react'
import { Boxes, Milestone, X } from 'lucide-react'
import type { WorkflowNodeDefinition } from '../../api/workflows'
import type { WorkflowGraphFamily } from './workflowNodeLibrary'
import { WorkflowNodeCatalogBrowser } from './WorkflowNodeCatalogBrowser'
import { WorkflowAuthoringSectionContent } from './WorkflowAuthoringSectionContent'
import {
type WorkflowAuthoringActions,
type WorkflowAuthoringPosition,
} from './workflowAuthoringActions'
import { useWorkflowAuthoringSurface } from './workflowAuthoringSurface'
export const NODE_COMMAND_MENU_WIDTH = 360
interface NodeCommandMenuProps {
definitions: WorkflowNodeDefinition[]
graphFamily: WorkflowGraphFamily
onSelectStep: (step: string) => void
activeSteps?: string[]
actions: WorkflowAuthoringActions
preferredPosition?: WorkflowAuthoringPosition
onClose: () => void
renderIcon: (iconName?: string, size?: number) => ReactNode
}
@@ -16,10 +25,22 @@ interface NodeCommandMenuProps {
export function NodeCommandMenu({
definitions,
graphFamily,
onSelectStep,
activeSteps = [],
actions,
preferredPosition,
onClose,
renderIcon,
}: NodeCommandMenuProps) {
const { activeSection, insertBindings, plan, sections, setActiveSection } =
useWorkflowAuthoringSurface({
definitions,
graphFamily,
activeSteps,
actions,
preferredPosition,
onAfterInsert: onClose,
})
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
@@ -32,14 +53,34 @@ export function NodeCommandMenu({
}, [onClose])
return (
<div className="flex max-h-[70vh] w-[380px] flex-col overflow-hidden rounded-2xl border border-border-default bg-surface shadow-2xl">
<div
className="flex max-h-[calc(100vh-2rem)] flex-col overflow-hidden rounded-2xl border border-border-default bg-surface shadow-2xl"
style={{ width: NODE_COMMAND_MENU_WIDTH }}
>
<div className="border-b border-border-default px-4 py-3">
<div className="flex items-center justify-between gap-3">
<div>
<p className="text-sm font-semibold text-content">Add Workflow Node</p>
<p className="text-sm font-semibold text-content">Workflow Authoring</p>
<p className="text-xs text-content-muted">
Search by label, step, family, or execution mode.
Use complete reference paths, modules, starter steps, or the raw node library directly on the canvas.
</p>
<div className="mt-2 flex flex-wrap items-center gap-1.5 text-[11px] text-content-muted">
<span className="rounded-full border border-border-default bg-surface-hover px-2 py-0.5">
{activeSteps.length} on canvas
</span>
{plan.referenceBundles.length > 0 && (
<span className="inline-flex items-center gap-1 rounded-full border border-border-default bg-surface-hover px-2 py-0.5">
<Milestone size={11} />
{plan.referenceBundles.length} paths
</span>
)}
{plan.moduleBundles.length > 0 && (
<span className="inline-flex items-center gap-1 rounded-full border border-border-default bg-surface-hover px-2 py-0.5">
<Boxes size={11} />
{plan.moduleBundles.length} modules
</span>
)}
</div>
</div>
<button
type="button"
@@ -53,15 +94,42 @@ export function NodeCommandMenu({
</div>
<div className="flex-1 overflow-y-auto px-3 py-3">
<WorkflowNodeCatalogBrowser
definitions={definitions}
graphFamily={graphFamily}
variant="menu"
onSelectStep={onSelectStep}
renderIcon={renderIcon}
searchPlaceholder="Search nodes"
autoFocusSearch
/>
<div className="space-y-3">
<div className="flex flex-wrap gap-2">
{sections.map(section => {
const Icon = section.icon
const isActive = activeSection === section.key
return (
<button
key={section.key}
type="button"
onClick={() => setActiveSection(section.key)}
className={`inline-flex items-center gap-1 rounded-full px-3 py-1.5 text-xs font-medium transition-colors ${
isActive
? 'bg-accent text-white'
: 'border border-border-default bg-surface text-content-secondary hover:bg-surface-hover'
}`}
title={section.helper}
>
<Icon size={12} />
{section.label}
</button>
)
})}
</div>
<WorkflowAuthoringSectionContent
activeSection={activeSection}
definitions={definitions}
graphFamily={graphFamily}
activeSteps={activeSteps}
actions={insertBindings}
renderIcon={renderIcon}
nodesVariant="menu"
searchPlaceholder="Search nodes"
autoFocusSearch
/>
</div>
</div>
</div>
)