@pipelex/mthds-ui 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-CCUSQM3E.js → chunk-OMJ6DRXM.js} +1 -1
- package/dist/chunk-OMJ6DRXM.js.map +1 -0
- package/dist/graph/index.d.ts +2 -2
- package/dist/graph/index.js +1 -1
- package/dist/graph/react/index.css +16 -0
- package/dist/graph/react/index.css.map +1 -1
- package/dist/graph/react/index.d.ts +38 -3
- package/dist/graph/react/index.js +356 -168
- package/dist/graph/react/index.js.map +1 -1
- package/dist/graph/react/stuff/StuffViewer.css +23 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{types-bV8F_WoM.d.ts → types--1tl-afL.d.ts} +14 -1
- package/package.json +2 -2
- package/dist/chunk-CCUSQM3E.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/graph/types.ts","../src/graph/graphAnalysis.ts","../src/graph/graphBuilders.ts","../src/graph/elkGraphBuilder.ts","../src/graph/graphLayout.ts","../src/graph/graphControllers.ts","../src/graph/graphConfig.ts"],"sourcesContent":["// ─── Pipe type taxonomy ─────────────────────────────────────────────────────\n// Operators perform work; controllers orchestrate other pipes.\n\nexport type PipeOperatorType =\n | \"PipeLLM\"\n | \"PipeExtract\"\n | \"PipeCompose\"\n | \"PipeImgGen\"\n | \"PipeSearch\"\n | \"PipeFunc\";\n\nexport type PipeControllerType = \"PipeSequence\" | \"PipeParallel\" | \"PipeCondition\" | \"PipeBatch\";\n\nexport type PipeType = PipeOperatorType | PipeControllerType;\n\nexport type PipeStatus = \"succeeded\" | \"failed\" | \"running\" | \"scheduled\" | \"skipped\";\n\n// ─── Node type constants ────────────────────────────────────────────────────\n// Used by graphBuilders and consumed by ReactFlow custom node registration.\n\nexport const NODE_TYPE_PIPE_CARD = \"pipeCard\" as const;\nexport const NODE_TYPE_STUFF = \"default\" as const;\nexport const NODE_TYPE_CONTROLLER = \"controllerGroup\" as const;\n\n// ─── Stuff node ID helpers ──────────────────────────────────────────────────\n// Stuff (data) nodes use a \"stuff_<digest>\" convention throughout the graph.\n\nexport const STUFF_ID_PREFIX = \"stuff_\";\n\nexport function stuffNodeId(digest: string): string {\n return STUFF_ID_PREFIX + digest;\n}\n\nexport function isStuffNodeId(id: string): boolean {\n return id.startsWith(STUFF_ID_PREFIX);\n}\n\nexport function stuffDigestFromId(id: string): string {\n return id.slice(STUFF_ID_PREFIX.length);\n}\n\n// ─── GraphSpec types (from pipelex-agent --view output) ─────────────────────\n\nexport interface GraphSpecNodeIoItem {\n name?: string;\n digest?: string;\n concept?: string;\n content_type?: string;\n preview?: string;\n size?: number;\n data?: unknown;\n data_text?: string;\n data_html?: string;\n extra?: Record<string, unknown>;\n}\n\nexport interface GraphSpecNodeIo {\n inputs?: GraphSpecNodeIoItem[];\n outputs?: GraphSpecNodeIoItem[];\n}\n\nexport type NodeKind =\n | \"pipe_call\"\n | \"controller\"\n | \"operator\"\n | \"input\"\n | \"output\"\n | \"artifact\"\n | \"error\";\n\nexport interface GraphSpecNodeTiming {\n started_at: string;\n ended_at: string;\n duration: number;\n}\n\nexport interface GraphSpecNodeError {\n error_type: string;\n message: string;\n stack?: string;\n}\n\nexport interface GraphSpecNode {\n id: string;\n kind?: NodeKind;\n pipe_code?: string;\n pipe_type?: PipeType;\n description?: string;\n status?: PipeStatus;\n timing?: GraphSpecNodeTiming;\n io?: GraphSpecNodeIo;\n error?: GraphSpecNodeError;\n tags?: Record<string, string>;\n metrics?: Record<string, number>;\n execution_data?: Record<string, unknown>;\n}\n\nexport type GraphSpecEdgeKind =\n | \"contains\"\n | \"data\"\n | \"control\"\n | \"selected_outcome\"\n | \"batch_item\"\n | \"batch_aggregate\"\n | \"parallel_combine\";\n\nexport interface GraphSpecEdge {\n id?: string;\n source: string;\n target: string;\n kind: GraphSpecEdgeKind;\n label?: string;\n source_stuff_digest?: string;\n target_stuff_digest?: string;\n meta?: Record<string, unknown>;\n}\n\n// ─── Concept and Pipe registry types ───────────────────────────────────────\n// Serialized from Python Concept and PipeAbstract instances via model_dump().\n\nexport interface ConceptInfo {\n code: string;\n domain_code: string;\n description: string;\n structure_class_name: string;\n refines: string | null;\n json_schema?: Record<string, unknown>;\n}\n\nexport interface StuffSpecInfo {\n concept: ConceptInfo;\n multiplicity: number | boolean | null;\n}\n\n// ─── Template blueprint (shared by LLM prompts, Search, Compose, ImgGen) ───\n\nexport interface TemplateBlueprint {\n template: string;\n templating_style: string | null;\n category: string;\n extra_context: Record<string, unknown> | null;\n}\n\n// ─── Sub-pipe (used by Sequence, Parallel, Batch) ──────────────────────\n\nexport interface SubPipeSpec {\n pipe_code: string;\n output_name: string | null;\n output_multiplicity: string | number | boolean | null;\n batch_params: { input_list_stuff_name: string; input_item_stuff_name: string } | null;\n}\n\n// ─── PipeAbstract base (common to all pipe types) ──────────────────────\n\nexport interface PipeBlueprintBase {\n type: PipeType;\n pipe_category: \"PipeOperator\" | \"PipeController\";\n code: string;\n domain_code: string;\n description: string;\n inputs: Record<string, StuffSpecInfo>;\n output: StuffSpecInfo;\n}\n\n// ─── Operator blueprints ───────────────────────────────────────────────\n\nexport interface PipeLLMBlueprint extends PipeBlueprintBase {\n type: \"PipeLLM\";\n llm_prompt_spec: {\n templating_style: string | null;\n system_prompt_blueprint: TemplateBlueprint | null;\n prompt_blueprint: TemplateBlueprint | null;\n user_image_references: unknown[] | null;\n user_document_references: unknown[] | null;\n system_image_references: unknown[] | null;\n system_document_references: unknown[] | null;\n };\n llm_choices: { for_text: string | null; for_object: string | null } | null;\n structuring_method: string | null;\n output_multiplicity: string | number | null;\n}\n\nexport interface PipeImgGenBlueprint extends PipeBlueprintBase {\n type: \"PipeImgGen\";\n img_gen_prompt_blueprint: {\n prompt_blueprint: TemplateBlueprint | null;\n negative_prompt_blueprint: TemplateBlueprint | null;\n image_references: unknown[] | null;\n };\n img_gen_choice: string | null;\n aspect_ratio: string | null;\n is_raw: boolean | null;\n seed: number | string | null;\n background: string | null;\n output_format: string | null;\n output_multiplicity: number;\n}\n\n/**\n * A single field in a PipeCompose construct blueprint. Mirrors the\n * `ConstructFieldBlueprint` Pydantic model in pipelex. Exactly one of\n * `fixed_value` / `from_path` / `template` / `nested` is populated, matching\n * the `method` discriminator.\n *\n * - `fixed` → `fixed_value` holds a literal (string, number, bool, list)\n * - `from_var` → `from_path` holds a dotted path into working memory,\n * optionally with a `list_to_dict_keyed_by` modifier\n * - `template` → `template` holds a Jinja2 template string (per-field)\n * - `nested` → `nested` holds a recursive construct blueprint for building\n * nested structured content\n */\nexport interface PipeComposeConstructField {\n method: \"from_var\" | \"fixed\" | \"template\" | \"nested\";\n fixed_value?: unknown;\n from_path?: string | null;\n template?: string | null;\n nested?: PipeComposeConstructBlueprint | null;\n list_to_dict_keyed_by?: string | null;\n}\n\n/**\n * A PipeCompose construct blueprint, parsed from `[pipe.X.construct]` in MTHDS.\n * Mirrors the `ConstructBlueprint` Pydantic model in pipelex.\n */\nexport interface PipeComposeConstructBlueprint {\n fields: Record<string, PipeComposeConstructField>;\n}\n\n/**\n * Per-field record of how each field was built at runtime, emitted by\n * `PipeCompose._run_construct_mode` in pipelex via `execution_data.fields`.\n *\n * - `method` → which composition method was used (mirrors `ConstructFieldMethod`)\n * - `rendered` → present only for `template` fields, holds the Jinja2 output\n *\n * Nested fields record only their method; their sub-fields are not surfaced.\n */\nexport interface FieldResolution {\n method: \"from_var\" | \"fixed\" | \"template\" | \"nested\";\n rendered?: string;\n}\n\nexport interface PipeComposeBlueprint extends PipeBlueprintBase {\n type: \"PipeCompose\";\n /** Legacy monolithic template. Null when construct_blueprint is used instead. */\n template: string | null;\n templating_style: string | null;\n category: string;\n extra_context: Record<string, unknown> | null;\n /** Field-level construct form (e.g. `[pipe.X.construct]` in MTHDS). */\n construct_blueprint: PipeComposeConstructBlueprint | null;\n}\n\nexport interface PipeExtractBlueprint extends PipeBlueprintBase {\n type: \"PipeExtract\";\n extract_choice: string | null;\n should_caption_images: boolean;\n max_page_images: number | null;\n should_include_page_views: boolean;\n page_views_dpi: number | null;\n render_js: boolean | null;\n include_raw_html: boolean | null;\n image_stuff_name: string | null;\n document_stuff_name: string;\n}\n\nexport interface PipeSearchBlueprint extends PipeBlueprintBase {\n type: \"PipeSearch\";\n search_choice: string | null;\n prompt_blueprint: TemplateBlueprint;\n include_images_override: boolean | null;\n max_results_override: number | null;\n from_date: string | null;\n to_date: string | null;\n include_domains: string[] | null;\n exclude_domains: string[] | null;\n is_structured_output: boolean;\n}\n\nexport interface PipeFuncBlueprint extends PipeBlueprintBase {\n type: \"PipeFunc\";\n}\n\n// ─── Controller blueprints ─────────────────────────────────────────────\n\nexport interface PipeSequenceBlueprint extends PipeBlueprintBase {\n type: \"PipeSequence\";\n sequential_sub_pipes: SubPipeSpec[];\n}\n\nexport interface PipeParallelBlueprint extends PipeBlueprintBase {\n type: \"PipeParallel\";\n parallel_sub_pipes: SubPipeSpec[];\n add_each_output: boolean;\n combined_output: string | null;\n}\n\nexport interface PipeConditionBlueprint extends PipeBlueprintBase {\n type: \"PipeCondition\";\n expression: string;\n outcome_map: Record<string, string>;\n default_outcome: string;\n add_alias_from_expression_to: string | null;\n}\n\nexport interface PipeBatchBlueprint extends PipeBlueprintBase {\n type: \"PipeBatch\";\n branch_pipe_code: string;\n batch_params: { input_list_stuff_name: string; input_item_stuff_name: string };\n}\n\nexport type PipeBlueprintUnion =\n | PipeLLMBlueprint\n | PipeImgGenBlueprint\n | PipeComposeBlueprint\n | PipeExtractBlueprint\n | PipeSearchBlueprint\n | PipeFuncBlueprint\n | PipeSequenceBlueprint\n | PipeParallelBlueprint\n | PipeConditionBlueprint\n | PipeBatchBlueprint;\n\n// ─── GraphSpec top-level ───────────────────────────────────────────────────\n\nexport interface GraphSpec {\n graph_id?: string;\n created_at?: string;\n pipeline_ref?: { domain?: string; main_pipe?: string; entrypoint?: string };\n nodes: GraphSpecNode[];\n edges: GraphSpecEdge[];\n meta?: Record<string, unknown>;\n pipe_registry?: Record<string, PipeBlueprintUnion>;\n concept_registry?: Record<string, ConceptInfo>;\n}\n\n// ─── Dataflow analysis result ───────────────────────────────────────────────\n\nexport interface DataflowAnalysis {\n readonly stuffRegistry: Readonly<\n Record<string, { name?: string; concept?: string; contentType?: string }>\n >;\n readonly stuffProducers: Readonly<Record<string, string>>;\n readonly stuffConsumers: Readonly<Record<string, readonly string[]>>;\n readonly controllerNodeIds: ReadonlySet<string>;\n readonly childNodeIds: ReadonlySet<string>;\n readonly containmentTree: Readonly<Record<string, readonly string[]>>;\n}\n\n// ─── Graph configuration ────────────────────────────────────────────────────\n\nexport const GRAPH_DIRECTION = {\n TB: \"TB\",\n BT: \"BT\",\n LR: \"LR\",\n RL: \"RL\",\n} as const;\n\nexport type GraphDirection = (typeof GRAPH_DIRECTION)[keyof typeof GRAPH_DIRECTION];\n\nexport const EDGE_TYPE = {\n /** Bezier curve — ReactFlow v12 renamed this type from \"bezier\" to \"default\". */\n DEFAULT: \"default\",\n STEP: \"step\",\n STRAIGHT: \"straight\",\n SMOOTH_STEP: \"smoothstep\",\n} as const;\n\nexport type EdgeType = (typeof EDGE_TYPE)[keyof typeof EDGE_TYPE];\n\nexport interface GraphConfig {\n direction?: GraphDirection;\n showControllers?: boolean;\n nodesep?: number;\n ranksep?: number;\n edgeType?: EdgeType;\n initialZoom?: number | null;\n panToTop?: boolean;\n paletteColors?: Record<string, string>;\n}\n\n// ─── Label descriptors ──────────────────────────────────────────────────────\n// Plain objects, no React dependency. GraphViewer maps these to React elements.\n\nexport type LabelDescriptor =\n | { kind: \"pipe\"; label: string; isFailed: boolean }\n | { kind: \"stuff\"; label: string; concept: string };\n\n// ─── Pipe card payload ──────────────────────────────────────────────────────\n// Built by graphBuilders, consumed by PipeCardNode in the React layer.\n\nexport interface PipeCardPayload {\n pipeCode: string;\n pipeType: PipeOperatorType;\n description?: string;\n status: PipeStatus;\n inputs: { name: string; concept: string }[];\n outputs: { name: string; concept: string }[];\n /** Layout direction — injected by the layout engine */\n direction?: \"LR\" | \"TB\";\n}\n\n// ─── Graph node data ────────────────────────────────────────────────────────\n// Extends Record<string, unknown> for ReactFlow's Node<T> generic parameter.\n\nexport type StuffRole = \"input\" | \"output\";\n\nexport interface GraphNodeData extends Record<string, unknown> {\n labelDescriptor?: LabelDescriptor;\n label?: unknown;\n nodeData?: GraphSpecNode;\n isPipe: boolean;\n isStuff: boolean;\n isController?: boolean;\n labelText: string;\n pipeCode?: string;\n pipeType?: PipeType;\n pipeCardData?: PipeCardPayload;\n /** For stuff nodes: \"input\" (no producer), \"output\" (no consumer), or undefined (intermediate). */\n stuffRole?: StuffRole;\n /** For stuff nodes: the digest used to build the node ID. */\n stuffDigest?: string;\n}\n\n// ─── Graph node / edge / data ───────────────────────────────────────────────\n\nexport interface GraphNode {\n id: string;\n type: string;\n data: GraphNodeData;\n position: { x: number; y: number };\n style?: Record<string, string | number>;\n sourcePosition?: \"top\" | \"bottom\" | \"left\" | \"right\";\n targetPosition?: \"top\" | \"bottom\" | \"left\" | \"right\";\n parentId?: string;\n extent?: \"parent\";\n selected?: boolean;\n}\n\nexport interface GraphEdge {\n id: string;\n source: string;\n target: string;\n type: string;\n animated?: boolean;\n label?: string;\n labelStyle?: Record<string, string | number>;\n labelBgStyle?: Record<string, string | number>;\n labelBgPadding?: [number, number];\n labelBgBorderRadius?: number;\n style?: Record<string, string | number>;\n markerEnd?: { type: string; color: string };\n _batchEdge?: boolean;\n _crossGroup?: boolean;\n}\n\nexport interface GraphData {\n nodes: GraphNode[];\n edges: GraphEdge[];\n}\n\n// ─── Layout ─────────────────────────────────────────────────────────────────\n\nexport interface LayoutConfig {\n nodesep?: number;\n ranksep?: number;\n}\n\n// Controller padding constants (shared between layout and controller modules)\nexport const CONTROLLER_PADDING_X = 40;\nexport const CONTROLLER_PADDING_TOP = 48;\nexport const CONTROLLER_PADDING_BOTTOM = 20;\n\n// Default marker type string (avoids ReactFlow dependency in pure modules)\nexport const ARROW_CLOSED_MARKER = \"arrowclosed\";\n\n// ─── Node dimension helpers ─────────────────────────────────────────────────\n// Extract dimensions from style. Used by buildControllerNodes.\n// NOT used by getLayoutedElements, which estimates dimensions before styles exist.\n\nexport function nodeWidth(n: GraphNode): number {\n const raw = n.style?.width;\n if (raw == null) return 200;\n const w = typeof raw === \"number\" ? raw : parseFloat(raw);\n return isNaN(w) || w <= 0 ? 200 : w;\n}\n\nexport function nodeHeight(n: GraphNode): number {\n const raw = n.style?.height;\n if (raw != null) {\n const h = typeof raw === \"number\" ? raw : parseFloat(raw);\n if (!isNaN(h) && h > 0) return h;\n }\n return n.data?.isStuff ? 60 : 70;\n}\n","import type { GraphSpec, DataflowAnalysis, PipeBlueprintUnion, ConceptInfo } from \"./types\";\n\nexport function buildDataflowAnalysis(graphspec: GraphSpec | null): DataflowAnalysis | null {\n if (!graphspec) return null;\n\n const stuffRegistry: Record<string, { name?: string; concept?: string; contentType?: string }> =\n {};\n const stuffProducers: Record<string, string> = {};\n const stuffConsumers: Record<string, string[]> = {};\n const containmentTree: Record<string, string[]> = {};\n const childNodeIds = new Set<string>();\n\n // Build containment tree from edges\n for (const edge of graphspec.edges) {\n if (edge.kind === \"contains\") {\n if (!containmentTree[edge.source]) containmentTree[edge.source] = [];\n containmentTree[edge.source].push(edge.target);\n childNodeIds.add(edge.target);\n }\n }\n\n // Controller IDs are nodes that have children\n const controllerNodeIds = new Set<string>(Object.keys(containmentTree));\n\n // Register stuffs from all nodes; track producers/consumers from operators only\n for (const node of graphspec.nodes) {\n const nodeIo = node.io || {};\n const isController = controllerNodeIds.has(node.id);\n\n // Register outputs\n for (const output of nodeIo.outputs || []) {\n if (output.digest && !stuffRegistry[output.digest]) {\n stuffRegistry[output.digest] = {\n name: output.name,\n concept: output.concept,\n contentType: output.content_type,\n };\n }\n if (output.digest && !isController) {\n stuffProducers[output.digest] = node.id;\n }\n }\n\n // Register inputs\n for (const input of nodeIo.inputs || []) {\n if (input.digest && !stuffRegistry[input.digest]) {\n stuffRegistry[input.digest] = {\n name: input.name,\n concept: input.concept,\n contentType: input.content_type,\n };\n }\n if (input.digest && !isController) {\n if (!stuffConsumers[input.digest]) stuffConsumers[input.digest] = [];\n stuffConsumers[input.digest].push(node.id);\n }\n }\n }\n\n return {\n stuffRegistry,\n stuffProducers,\n stuffConsumers,\n controllerNodeIds,\n childNodeIds,\n containmentTree,\n };\n}\n\n/**\n * Build a map from node id -> controller id for all nodes that belong to a controller.\n * Includes both direct children (operators) and stuff nodes assigned to controllers.\n *\n * Stuff nodes are placed at the lowest controller level where they connect producers\n * to consumers. A stuff node produced inside controller C is promoted to C's parent\n * if none of its consumers are inside C (output flows outward).\n */\nexport function buildChildToControllerMap(\n graphspec: GraphSpec,\n analysis: DataflowAnalysis,\n): Record<string, string> {\n const childToController: Record<string, string> = {};\n\n // Direct children from containment tree\n for (const [ctrlId, children] of Object.entries(analysis.containmentTree)) {\n for (const childId of children) {\n childToController[childId] = ctrlId;\n }\n }\n\n // Stuff nodes produced by operators inside controllers\n for (const [digest, producerId] of Object.entries(analysis.stuffProducers)) {\n const stuffId = \"stuff_\" + digest;\n const ctrlId = childToController[producerId];\n if (ctrlId) {\n childToController[stuffId] = ctrlId;\n }\n }\n\n // Stuff produced by controllers themselves -> assign to parent controller\n for (const node of graphspec.nodes) {\n if (!analysis.controllerNodeIds.has(node.id)) continue;\n const parentCtrlId = childToController[node.id];\n if (!parentCtrlId) continue;\n for (const output of node.io?.outputs || []) {\n if (!output.digest) continue;\n const stuffId = \"stuff_\" + output.digest;\n if (!childToController[stuffId]) {\n childToController[stuffId] = parentCtrlId;\n }\n }\n }\n\n // Batch item stuff (fan-out) -> assign to the PipeBatch controller\n for (const edge of graphspec.edges) {\n if (edge.kind === \"batch_item\" && edge.target_stuff_digest) {\n const stuffId = \"stuff_\" + edge.target_stuff_digest;\n // edge.source is the PipeBatch controller node\n if (analysis.controllerNodeIds.has(edge.source)) {\n childToController[stuffId] = edge.source;\n }\n }\n }\n\n // ─── Promote stuff nodes whose consumers are all outside their controller ──\n // Stuff involved in stuff-to-stuff edges (batch/parallel) should not be promoted\n // when they have no operator consumers — they're intermediate batch/parallel data.\n const stuffInStuffEdges = new Set<string>();\n for (const edge of graphspec.edges) {\n if (\n edge.kind === \"batch_item\" ||\n edge.kind === \"batch_aggregate\" ||\n edge.kind === \"parallel_combine\"\n ) {\n if (edge.source_stuff_digest) stuffInStuffEdges.add(edge.source_stuff_digest);\n if (edge.target_stuff_digest) stuffInStuffEdges.add(edge.target_stuff_digest);\n }\n }\n\n const stuffPrefix = \"stuff_\";\n const stuffEntries = Object.keys(childToController).filter((id) => id.startsWith(stuffPrefix));\n\n for (const stuffId of stuffEntries) {\n const digest = stuffId.slice(stuffPrefix.length);\n let assignedCtrl: string | undefined = childToController[stuffId];\n if (!assignedCtrl) continue;\n\n const consumers = analysis.stuffConsumers[digest] || [];\n\n if (consumers.length === 0) {\n // No operator consumers — promote to root only if this is a pure final output\n // (not involved in batch/parallel stuff-to-stuff edges)\n if (!stuffInStuffEdges.has(digest)) {\n delete childToController[stuffId];\n }\n continue;\n }\n\n // Has consumers — promote until we find a level where at least one consumer is inside\n while (assignedCtrl) {\n const ctrl = assignedCtrl;\n const hasConsumerInside = consumers.some((consumerId) =>\n isDescendantOf(consumerId, ctrl, childToController),\n );\n if (hasConsumerInside) break;\n\n const parentCtrl: string | undefined = childToController[assignedCtrl];\n if (parentCtrl) {\n childToController[stuffId] = parentCtrl;\n assignedCtrl = parentCtrl;\n } else {\n delete childToController[stuffId];\n assignedCtrl = undefined;\n }\n }\n }\n\n return childToController;\n}\n\n/** Check if nodeId is a descendant of ancestorCtrlId in the containment hierarchy. */\nfunction isDescendantOf(\n nodeId: string,\n ancestorCtrlId: string,\n childToController: Record<string, string>,\n): boolean {\n let current = childToController[nodeId];\n while (current) {\n if (current === ancestorCtrlId) return true;\n current = childToController[current];\n }\n return false;\n}\n\n// ─── Registry lookup helpers ───────────────────────────────────────────────\n\nexport function getPipeBlueprint(spec: GraphSpec, pipeRef: string): PipeBlueprintUnion | undefined {\n return spec.pipe_registry?.[pipeRef];\n}\n\nexport function getConceptInfo(spec: GraphSpec, conceptRef: string): ConceptInfo | undefined {\n return spec.concept_registry?.[conceptRef];\n}\n\nexport function resolveConceptRef(spec: GraphSpec, codeOrRef: string): ConceptInfo | undefined {\n if (!spec.concept_registry) return undefined;\n // Direct lookup first (e.g., \"test_domain.Summary\")\n const direct = spec.concept_registry[codeOrRef];\n if (direct) return direct;\n // Search by code (e.g., \"Summary\" matches \"test_domain.Summary\")\n for (const info of Object.values(spec.concept_registry)) {\n if (info.code === codeOrRef) return info;\n }\n return undefined;\n}\n","import type {\n GraphSpec,\n DataflowAnalysis,\n GraphNode,\n GraphEdge,\n GraphData,\n PipeOperatorType,\n} from \"./types\";\nimport { ARROW_CLOSED_MARKER, NODE_TYPE_PIPE_CARD, NODE_TYPE_STUFF, stuffNodeId } from \"./types\";\nimport { buildDataflowAnalysis, buildChildToControllerMap } from \"./graphAnalysis\";\n\n/** Fallback description when the GraphSpec node doesn't carry one. */\nfunction defaultDescription(pipeType?: string, pipeCode?: string): string {\n const code = pipeCode || \"this step\";\n const verb: Record<string, string> = {\n PipeLLM: \"Analyze and generate output using\",\n PipeExtract: \"Extract content from\",\n PipeCompose: \"Compose output using\",\n PipeImgGen: \"Generate image for\",\n PipeSearch: \"Search the web for\",\n PipeFunc: \"Process data in\",\n };\n return `${verb[pipeType || \"\"] || \"Execute\"} ${code.replace(/_/g, \" \")}`;\n}\n\nconst STUFF_CHAR_WIDTH_PX = 7;\nconst STUFF_LABEL_PADDING = 48;\nconst MIN_STUFF_WIDTH = 140;\n\n/**\n * Build dataflow graph from GraphSpec. Creates pipe nodes + stuff (data) nodes +\n * producer/consumer edges. Returns label descriptors (not React elements).\n */\nexport function buildDataflowGraph(\n graphspec: GraphSpec,\n analysis: DataflowAnalysis,\n edgeType: string,\n): GraphData {\n const nodes: GraphNode[] = [];\n const edges: GraphEdge[] = [];\n\n // Find participating pipes (those that produce or consume data)\n const participatingPipes = new Set<string>();\n for (const producer of Object.values(analysis.stuffProducers)) {\n participatingPipes.add(producer);\n }\n for (const consumers of Object.values(analysis.stuffConsumers)) {\n for (const consumer of consumers) {\n participatingPipes.add(consumer);\n }\n }\n\n // Create pipe nodes (only those that participate in data flow)\n for (const node of graphspec.nodes) {\n if (!participatingPipes.has(node.id)) continue;\n\n const isFailed = node.status === \"failed\";\n const label = node.pipe_code || node.id.split(\":\").pop() || node.id;\n const inputs = (node.io?.inputs ?? []).map((i) => ({\n name: i.name ?? \"\",\n concept: i.concept ?? \"\",\n }));\n const outputs = (node.io?.outputs ?? []).map((o) => ({\n name: o.name ?? \"\",\n concept: o.concept ?? \"\",\n }));\n\n // Participating pipes are operators (controllers don't produce/consume stuff directly)\n const operatorType: PipeOperatorType = (node.pipe_type as PipeOperatorType) || \"PipeFunc\";\n\n nodes.push({\n id: node.id,\n type: NODE_TYPE_PIPE_CARD,\n data: {\n labelDescriptor: { kind: \"pipe\", label, isFailed },\n nodeData: node,\n isPipe: true,\n isStuff: false,\n labelText: label,\n pipeCode: node.pipe_code || label,\n pipeType: node.pipe_type,\n pipeCardData: {\n pipeCode: node.pipe_code || label,\n pipeType: operatorType,\n description: node.description || defaultDescription(node.pipe_type, node.pipe_code),\n status: node.status || \"scheduled\",\n inputs,\n outputs,\n },\n },\n position: { x: 0, y: 0 },\n });\n }\n\n // Create stuff (data) nodes\n for (const [digest, stuffInfo] of Object.entries(analysis.stuffRegistry)) {\n const stuffId = stuffNodeId(digest);\n const label = stuffInfo.name || \"data\";\n const concept = stuffInfo.concept || \"\";\n const textWidth =\n Math.max(label.length, concept.length) * STUFF_CHAR_WIDTH_PX + STUFF_LABEL_PADDING;\n const stuffWidth = Math.max(MIN_STUFF_WIDTH, textWidth);\n\n // Classify: input (no producer), output (no consumer), or intermediate\n const isInput = !analysis.stuffProducers[digest];\n const isOutput = !isInput && !analysis.stuffConsumers[digest]?.length;\n const stuffRole = isInput ? (\"input\" as const) : isOutput ? (\"output\" as const) : undefined;\n\n const borderColor = isInput\n ? \"var(--color-stuff-input-border, #50FA7B)\"\n : isOutput\n ? \"var(--color-stuff-output-border, #a78bfa)\"\n : \"var(--color-stuff-border)\";\n\n nodes.push({\n id: stuffId,\n type: NODE_TYPE_STUFF,\n data: {\n labelDescriptor: { kind: \"stuff\", label, concept },\n isStuff: true,\n isPipe: false,\n labelText: label,\n stuffRole,\n stuffDigest: digest,\n },\n position: { x: 0, y: 0 },\n style: {\n background: \"var(--color-stuff-bg)\",\n border: `2px solid ${borderColor}`,\n borderRadius: \"999px\",\n padding: \"0\",\n width: stuffWidth + \"px\",\n boxShadow: \"var(--shadow-md)\",\n },\n });\n }\n\n // Create edges: producer -> stuff\n let edgeId = 0;\n for (const [digest, producerNodeId] of Object.entries(analysis.stuffProducers)) {\n const stuffId = stuffNodeId(digest);\n edges.push({\n id: \"edge_\" + edgeId++,\n source: producerNodeId,\n target: stuffId,\n type: edgeType,\n animated: false,\n style: { stroke: \"var(--color-edge)\", strokeWidth: 2 },\n markerEnd: {\n type: ARROW_CLOSED_MARKER,\n color: \"var(--color-edge)\",\n },\n });\n }\n\n // Create edges: stuff -> consumer\n for (const [digest, consumers] of Object.entries(analysis.stuffConsumers)) {\n const stuffId = stuffNodeId(digest);\n for (const consumerNodeId of consumers) {\n edges.push({\n id: \"edge_\" + edgeId++,\n source: stuffId,\n target: consumerNodeId,\n type: edgeType,\n animated: false,\n style: { stroke: \"var(--color-edge)\", strokeWidth: 2 },\n markerEnd: {\n type: ARROW_CLOSED_MARKER,\n color: \"var(--color-edge)\",\n },\n });\n }\n }\n\n // Create PARALLEL_COMBINE edges from GraphSpec\n for (const edge of graphspec.edges) {\n if (edge.kind !== \"parallel_combine\") continue;\n if (!edge.source_stuff_digest || !edge.target_stuff_digest) continue;\n if (\n !analysis.stuffRegistry[edge.source_stuff_digest] ||\n !analysis.stuffRegistry[edge.target_stuff_digest]\n )\n continue;\n const sourceId = stuffNodeId(edge.source_stuff_digest);\n const targetId = stuffNodeId(edge.target_stuff_digest);\n\n edges.push({\n id: edge.id || \"edge_\" + edgeId++,\n source: sourceId,\n target: targetId,\n type: \"smoothstep\",\n animated: false,\n style: {\n stroke: \"var(--color-parallel-combine)\",\n strokeWidth: 2,\n strokeDasharray: \"5,5\",\n },\n markerEnd: {\n type: ARROW_CLOSED_MARKER,\n color: \"var(--color-parallel-combine)\",\n },\n });\n }\n\n // Create BATCH_ITEM and BATCH_AGGREGATE edges (data-centric mode: stuff -> stuff)\n for (const edge of graphspec.edges) {\n if (edge.kind !== \"batch_item\" && edge.kind !== \"batch_aggregate\") continue;\n\n if (!edge.source_stuff_digest || !edge.target_stuff_digest) continue;\n if (\n !analysis.stuffRegistry[edge.source_stuff_digest] ||\n !analysis.stuffRegistry[edge.target_stuff_digest]\n )\n continue;\n const sourceId = stuffNodeId(edge.source_stuff_digest);\n const targetId = stuffNodeId(edge.target_stuff_digest);\n const isBatchItem = edge.kind === \"batch_item\";\n\n edges.push({\n id: edge.id || \"edge_\" + edgeId++,\n source: sourceId,\n target: targetId,\n type: edgeType,\n animated: false,\n _batchEdge: true,\n label: edge.label || \"\",\n labelStyle: {\n fontSize: \"10px\",\n fontFamily: \"var(--font-mono)\",\n fill: isBatchItem ? \"var(--color-batch-item)\" : \"var(--color-batch-aggregate)\",\n },\n labelBgStyle: { fill: \"var(--color-bg)\", fillOpacity: 0.9 },\n style: {\n stroke: isBatchItem ? \"var(--color-batch-item)\" : \"var(--color-batch-aggregate)\",\n strokeWidth: 2,\n strokeDasharray: \"5,5\",\n },\n markerEnd: {\n type: ARROW_CLOSED_MARKER,\n color: isBatchItem ? \"var(--color-batch-item)\" : \"var(--color-batch-aggregate)\",\n },\n });\n }\n\n // Mark edges that cross between different sibling controller groups\n const childToCtrl = buildChildToControllerMap(graphspec, analysis);\n // and assign per-class edge types for better routing\n for (const edge of edges) {\n const srcCtrl = childToCtrl[edge.source] || null;\n const tgtCtrl = childToCtrl[edge.target] || null;\n if (srcCtrl && tgtCtrl && srcCtrl !== tgtCtrl) {\n edge._crossGroup = true;\n // Keep bezier for long-distance cross-group edges (natural curves look better)\n // but visually de-emphasize to reduce spaghetti effect\n edge.style = {\n ...edge.style,\n strokeWidth: 1.5,\n opacity: 0.65,\n };\n }\n }\n\n // Batch edges: keep bezier but visually differentiate\n for (const edge of edges) {\n if (edge._batchEdge) {\n edge.style = {\n ...edge.style,\n opacity: 0.7,\n };\n }\n }\n\n return { nodes, edges };\n}\n\n/**\n * Build graph from GraphSpec using dataflow mode.\n * Returns the built graph data and analysis.\n */\nexport function buildGraph(\n graphspec: GraphSpec | null,\n edgeType: string,\n): { graphData: GraphData; analysis: DataflowAnalysis | null } {\n if (graphspec) {\n const analysis = buildDataflowAnalysis(graphspec);\n if (\n analysis &&\n (Object.keys(analysis.stuffProducers).length > 0 ||\n Object.keys(analysis.stuffConsumers).length > 0)\n ) {\n return { graphData: buildDataflowGraph(graphspec, analysis, edgeType), analysis };\n }\n }\n return { graphData: { nodes: [], edges: [] }, analysis: null };\n}\n","import type { ElkNode, ElkPort, ElkExtendedEdge, LayoutOptions } from \"elkjs/lib/elk-api\";\nimport type {\n GraphNode,\n GraphEdge,\n GraphSpec,\n DataflowAnalysis,\n LayoutConfig,\n GraphDirection,\n} from \"./types\";\nimport {\n NODE_TYPE_PIPE_CARD,\n CONTROLLER_PADDING_X,\n CONTROLLER_PADDING_TOP,\n CONTROLLER_PADDING_BOTTOM,\n} from \"./types\";\nimport { buildChildToControllerMap } from \"./graphAnalysis\";\n\n// ─── Direction mapping ──────────────────────────────────────────────────────\n\nfunction elkDirection(direction: GraphDirection): string {\n switch (direction) {\n case \"LR\":\n return \"RIGHT\";\n case \"RL\":\n return \"LEFT\";\n case \"BT\":\n return \"UP\";\n default:\n return \"DOWN\"; // TB\n }\n}\n\n// ─── Port helpers ───────────────────────────────────────────────────────────\n\nconst INPUT_PORT_SUFFIX = \"_in\";\nconst OUTPUT_PORT_SUFFIX = \"_out\";\n\nexport function inputPortId(nodeId: string): string {\n return nodeId + INPUT_PORT_SUFFIX;\n}\n\nexport function outputPortId(nodeId: string): string {\n return nodeId + OUTPUT_PORT_SUFFIX;\n}\n\nfunction makePorts(nodeId: string, dims: NodeDimensions, direction: GraphDirection): ElkPort[] {\n // Port sides must match the flow direction so ELK computes edge attachment\n // on the same side that ReactFlow renders handles.\n // LR: input=WEST, output=EAST | RL: input=EAST, output=WEST\n // TB: input=NORTH, output=SOUTH | BT: input=SOUTH, output=NORTH\n const portSides: Record<GraphDirection, { inSide: string; outSide: string }> = {\n LR: { inSide: \"WEST\", outSide: \"EAST\" },\n RL: { inSide: \"EAST\", outSide: \"WEST\" },\n TB: { inSide: \"NORTH\", outSide: \"SOUTH\" },\n BT: { inSide: \"SOUTH\", outSide: \"NORTH\" },\n };\n const { inSide, outSide } = portSides[direction];\n\n const isHorizontal = direction === \"LR\" || direction === \"RL\";\n // Pin ports at the exact center of each side so ELK computes layout\n // with the same edge attachment point that ReactFlow will render.\n const inX = isHorizontal ? (direction === \"LR\" ? 0 : dims.width) : dims.width / 2;\n const inY = isHorizontal ? dims.height / 2 : direction === \"TB\" ? 0 : dims.height;\n const outX = isHorizontal ? (direction === \"LR\" ? dims.width : 0) : dims.width / 2;\n const outY = isHorizontal ? dims.height / 2 : direction === \"TB\" ? dims.height : 0;\n\n return [\n {\n id: inputPortId(nodeId),\n x: inX,\n y: inY,\n width: 1,\n height: 1,\n layoutOptions: { \"elk.port.side\": inSide },\n },\n {\n id: outputPortId(nodeId),\n x: outX,\n y: outY,\n width: 1,\n height: 1,\n layoutOptions: { \"elk.port.side\": outSide },\n },\n ];\n}\n\n// ─── Node dimension estimation ──────────────────────────────────────────────\n// ELK needs dimensions upfront to compute layout.\n\ninterface NodeDimensions {\n width: number;\n height: number;\n}\n\n// ─── Pipe card layout constants (keep in sync with graph-core.css) ──────────\n// If you change these, update the matching rules in graph-core.css.\nconst PIPE_CARD_HEIGHT_CAP = 320;\n\n// Horizontal padding (12 + 12 = 24) + vertical padding (12 + 12 = 24)\nconst PIPE_CARD_PADDING_X = 28; // padding-left + padding-right (14 + 14)\nconst PIPE_CARD_PADDING_Y = 24; // padding-top + padding-bottom (12 + 12)\nconst PIPE_CARD_GAP = 8; // gap between flex children (header / description / io sections)\n\n// Header: badge (~20px) + code line with status dot\nconst PIPE_CARD_HEADER_HEIGHT = 22;\n\n// Description: 11.5px font × 1.4 line-height ≈ 16.1px per line\nconst PIPE_CARD_DESC_LINE_HEIGHT = 16;\nconst PIPE_CARD_DESC_MAX_LINES_LR = 3;\n\n// I/O section heights (label + first row of pills)\nconst PIPE_CARD_IO_SECTION_HEIGHT_LR = 38; // stacked: label on top, pills below\nconst PIPE_CARD_IO_SECTION_HEIGHT_TB = 30; // inline: label on left, pills on right\nconst PIPE_CARD_IO_EXTRA_ROW_HEIGHT = 22; // each additional wrapping row of pills\n\n// Pill dimension caps (keep in sync with .pipe-card--tb .pipe-card-io-pill-name/concept max-width)\nconst PIPE_CARD_PILL_NAME_MAX_WIDTH = 140;\nconst PIPE_CARD_PILL_CONCEPT_MAX_WIDTH = 100;\nconst PIPE_CARD_PILL_CHROME_WIDTH = 17; // pill padding (10) + name/concept gap (3) + inter-pill gap (4)\nconst PIPE_CARD_IO_LABEL_WIDTH_TB = 58; // min-width 52 + gap 6\n\n// Character width estimates for Inter font\nconst CHAR_WIDTH_DESC = 5.5; // 11.5px font\nconst CHAR_WIDTH_PILL_NAME = 5.0; // 10px font (pill-name)\nconst CHAR_WIDTH_PILL_CONCEPT = 4.5; // 9px font (pill-concept)\n\nconst MAX_VISIBLE_INPUTS = 4;\n\n/** Estimate how many lines the description will wrap to, given direction + text length. */\nfunction estimateDescriptionLines(\n description: string,\n isHorizontal: boolean,\n cardWidth: number,\n): number {\n if (!description) return 0;\n if (!isHorizontal) return 1; // TB always clamps to 1 line (CSS handles ellipsis)\n const textWidth = cardWidth - PIPE_CARD_PADDING_X;\n const charsPerLine = Math.max(1, Math.floor(textWidth / CHAR_WIDTH_DESC));\n const neededLines = Math.ceil(description.length / charsPerLine);\n return Math.min(PIPE_CARD_DESC_MAX_LINES_LR, Math.max(1, neededLines));\n}\n\n/** Estimate the rendered width of a single pill in TB mode. */\nfunction estimateTbPillWidth(name: string, concept: string): number {\n const nameWidth = Math.min(\n PIPE_CARD_PILL_NAME_MAX_WIDTH,\n Math.ceil(name.length * CHAR_WIDTH_PILL_NAME),\n );\n const conceptWidth = Math.min(\n PIPE_CARD_PILL_CONCEPT_MAX_WIDTH,\n Math.ceil(concept.length * CHAR_WIDTH_PILL_CONCEPT),\n );\n return nameWidth + conceptWidth + PIPE_CARD_PILL_CHROME_WIDTH;\n}\n\n/** Count how many wrapping rows a set of pills will occupy in TB mode.\n * Uses a simple first-fit bin-packing against the available pill area width.\n */\nfunction countTbPillRows(\n pills: readonly { name: string; concept: string }[],\n cardWidth: number,\n): number {\n if (pills.length === 0) return 0;\n const availableWidth = cardWidth - PIPE_CARD_PADDING_X - PIPE_CARD_IO_LABEL_WIDTH_TB;\n let rows = 1;\n let currentRowWidth = 0;\n for (const pill of pills) {\n const pillWidth = estimateTbPillWidth(pill.name, pill.concept);\n if (currentRowWidth === 0) {\n currentRowWidth = pillWidth;\n continue;\n }\n if (currentRowWidth + pillWidth <= availableWidth) {\n currentRowWidth += pillWidth;\n } else {\n rows += 1;\n currentRowWidth = pillWidth;\n }\n }\n return rows;\n}\n\nexport function estimateNodeDimensions(node: GraphNode, isHorizontal: boolean): NodeDimensions {\n const nodeData = node.data || {};\n const isStuff = nodeData.isStuff;\n const labelText = nodeData.labelText || \"\";\n const isPipeCard = node.type === NODE_TYPE_PIPE_CARD;\n\n const pipeCardMinWidth = isHorizontal ? 180 : 280;\n const pipeCardMaxWidth = isHorizontal ? 240 : 400;\n // Stuff nodes are visually aligned with pipe cards — they must never be wider\n // than the pipe card max for the current direction, otherwise the graph looks\n // lopsided (a 400px stuff node next to a 240px pipe card in LR mode).\n const estimatedWidth = Math.max(180, Math.min(pipeCardMaxWidth, labelText.length * 8 + 60));\n\n let width: number;\n if (isStuff) {\n width = Math.max(180, estimatedWidth);\n } else if (isPipeCard && nodeData.pipeCardData) {\n width = pipeCardMaxWidth;\n } else {\n width = Math.max(isPipeCard ? pipeCardMinWidth : 200, estimatedWidth);\n }\n\n let height: number;\n if (isStuff) {\n height = 60;\n } else if (isPipeCard && nodeData.pipeCardData) {\n const pcd = nodeData.pipeCardData;\n const inputs = pcd.inputs ?? [];\n const outputs = pcd.outputs ?? [];\n const description = pcd.description || nodeData.nodeData?.description || \"\";\n\n // Header\n let total = PIPE_CARD_PADDING_Y + PIPE_CARD_HEADER_HEIGHT;\n\n // Description: actual lines needed\n const descLines = estimateDescriptionLines(description, isHorizontal, width);\n if (descLines > 0) {\n total += PIPE_CARD_GAP + descLines * PIPE_CARD_DESC_LINE_HEIGHT;\n }\n\n // Inputs — cap visible to MAX_VISIBLE_INPUTS (rest collapses behind \"+N more\")\n const visibleInputs = inputs.slice(0, MAX_VISIBLE_INPUTS);\n if (visibleInputs.length > 0) {\n total += PIPE_CARD_GAP;\n if (isHorizontal) {\n // LR: one pill per row, always stacked\n total +=\n PIPE_CARD_IO_SECTION_HEIGHT_LR +\n (visibleInputs.length - 1) * PIPE_CARD_IO_EXTRA_ROW_HEIGHT;\n } else {\n // TB: bin-pack pills horizontally, each extra row adds height\n const rows = countTbPillRows(visibleInputs, width);\n total += PIPE_CARD_IO_SECTION_HEIGHT_TB + (rows - 1) * PIPE_CARD_IO_EXTRA_ROW_HEIGHT;\n }\n }\n\n // Outputs — same logic as inputs\n if (outputs.length > 0) {\n total += PIPE_CARD_GAP;\n if (isHorizontal) {\n total +=\n PIPE_CARD_IO_SECTION_HEIGHT_LR + (outputs.length - 1) * PIPE_CARD_IO_EXTRA_ROW_HEIGHT;\n } else {\n const rows = countTbPillRows(outputs, width);\n total += PIPE_CARD_IO_SECTION_HEIGHT_TB + (rows - 1) * PIPE_CARD_IO_EXTRA_ROW_HEIGHT;\n }\n }\n\n height = Math.min(PIPE_CARD_HEIGHT_CAP, total);\n } else {\n height = isPipeCard ? 120 : 70;\n }\n\n return { width, height };\n}\n\n// ─── Controller nesting depth ───────────────────────────────────────────────\n\nfunction computeDepths(\n controllerNodeIds: ReadonlySet<string>,\n containmentTree: Readonly<Record<string, readonly string[]>>,\n): Record<string, number> {\n const depthCache: Record<string, number> = {};\n const visiting = new Set<string>();\n\n function getDepth(ctrlId: string): number {\n if (depthCache[ctrlId] !== undefined) return depthCache[ctrlId];\n if (visiting.has(ctrlId)) return 0;\n visiting.add(ctrlId);\n const children = containmentTree[ctrlId] || [];\n let maxChildDepth = -1;\n for (const childId of children) {\n if (controllerNodeIds.has(childId)) {\n maxChildDepth = Math.max(maxChildDepth, getDepth(childId));\n }\n }\n visiting.delete(ctrlId);\n depthCache[ctrlId] = maxChildDepth + 1;\n return depthCache[ctrlId];\n }\n\n for (const id of controllerNodeIds) getDepth(id);\n return depthCache;\n}\n\n// ─── Leaf node builder ──────────────────────────────────────────────────────\n\nfunction makeLeafNode(nodeId: string, dims: NodeDimensions, direction: GraphDirection): ElkNode {\n return {\n id: nodeId,\n width: dims.width,\n height: dims.height,\n ports: makePorts(nodeId, dims, direction),\n layoutOptions: {\n \"elk.portConstraints\": \"FIXED_POS\",\n },\n };\n}\n\n// ─── Build ELK graph ────────────────────────────────────────────────────────\n\nexport function buildElkGraph(\n nodes: GraphNode[],\n edges: GraphEdge[],\n graphspec: GraphSpec | null,\n analysis: DataflowAnalysis | null,\n direction: GraphDirection,\n layoutConfig?: LayoutConfig,\n): { elkGraph: ElkNode; dimensionMap: Record<string, NodeDimensions> } {\n const isHorizontal = direction === \"LR\" || direction === \"RL\";\n const nodesep = layoutConfig?.nodesep ?? 80;\n const ranksep = layoutConfig?.ranksep ?? 70;\n const elkDir = elkDirection(direction);\n\n const edgeNodeSpacing = \"30\";\n\n const rootLayoutOptions: LayoutOptions = {\n \"elk.algorithm\": \"layered\",\n \"elk.direction\": elkDir,\n \"elk.hierarchyHandling\": \"INCLUDE_CHILDREN\",\n \"elk.spacing.nodeNode\": String(nodesep),\n \"elk.layered.spacing.nodeNodeBetweenLayers\": String(ranksep),\n \"elk.spacing.edgeNode\": edgeNodeSpacing,\n \"elk.spacing.edgeEdge\": \"20\",\n \"elk.layered.spacing.edgeNodeBetweenLayers\": edgeNodeSpacing,\n \"elk.layered.spacing.edgeEdgeBetweenLayers\": \"15\",\n \"elk.layered.nodePlacement.favorStraightEdges\": \"true\",\n };\n\n // Fast path: no hierarchy info → flat layout\n if (!graphspec || !analysis || analysis.controllerNodeIds.size === 0) {\n const dimensionMap: Record<string, NodeDimensions> = {};\n const elkChildren: ElkNode[] = nodes.map((node) => {\n const dims = estimateNodeDimensions(node, isHorizontal);\n dimensionMap[node.id] = dims;\n return makeLeafNode(node.id, dims, direction);\n });\n\n const elkEdges: ElkExtendedEdge[] = edges.map((edge) => ({\n id: edge.id,\n sources: [outputPortId(edge.source)],\n targets: [inputPortId(edge.target)],\n }));\n\n return {\n elkGraph: {\n id: \"root\",\n layoutOptions: rootLayoutOptions,\n children: elkChildren,\n edges: elkEdges,\n },\n dimensionMap,\n };\n }\n\n // Hierarchical layout: build tree from containment analysis\n const childToCtrl = buildChildToControllerMap(graphspec, analysis);\n const depths = computeDepths(analysis.controllerNodeIds, analysis.containmentTree);\n const dimensionMap: Record<string, NodeDimensions> = {};\n\n // Create a map from node ID to its ELK leaf node\n const nodeById = new Map<string, GraphNode>();\n for (const node of nodes) nodeById.set(node.id, node);\n\n // Build controller compound nodes (bottom-up: leaf controllers first)\n const controllerElkNodes: Record<string, ElkNode> = {};\n const controllerIds = Array.from(analysis.controllerNodeIds);\n controllerIds.sort((a, b) => (depths[a] ?? 0) - (depths[b] ?? 0));\n\n for (const ctrlId of controllerIds) {\n const depth = depths[ctrlId] ?? 0;\n const depthScale = 1 + depth * 0.15;\n const padX = Math.round(CONTROLLER_PADDING_X * depthScale);\n const padTop = Math.round(CONTROLLER_PADDING_TOP * depthScale);\n const padBottom = Math.round(CONTROLLER_PADDING_BOTTOM * depthScale);\n\n const ctrlLayoutOptions: LayoutOptions = {\n \"elk.padding\": `[top=${padTop},left=${padX},bottom=${padBottom},right=${padX}]`,\n \"elk.spacing.nodeNode\": String(nodesep),\n \"elk.layered.spacing.nodeNodeBetweenLayers\": String(ranksep),\n \"elk.spacing.edgeNode\": edgeNodeSpacing,\n \"elk.layered.spacing.edgeNodeBetweenLayers\": edgeNodeSpacing,\n };\n\n const children: ElkNode[] = [];\n const directChildren = analysis.containmentTree[ctrlId] || [];\n\n for (const childId of directChildren) {\n if (analysis.controllerNodeIds.has(childId)) {\n // Child is a controller — use its already-built compound node\n const childElk = controllerElkNodes[childId];\n if (childElk) children.push(childElk);\n } else {\n // Child is an operator — create leaf node with ports\n const graphNode = nodeById.get(childId);\n if (graphNode) {\n const dims = estimateNodeDimensions(graphNode, isHorizontal);\n dimensionMap[childId] = dims;\n children.push(makeLeafNode(childId, dims, direction));\n }\n }\n }\n\n // Add stuff nodes that belong to this controller\n for (const node of nodes) {\n if (node.data.isStuff && childToCtrl[node.id] === ctrlId) {\n if (!children.some((c) => c.id === node.id)) {\n const dims = estimateNodeDimensions(node, isHorizontal);\n dimensionMap[node.id] = dims;\n children.push(makeLeafNode(node.id, dims, direction));\n }\n }\n }\n\n controllerElkNodes[ctrlId] = {\n id: ctrlId,\n layoutOptions: ctrlLayoutOptions,\n children,\n };\n }\n\n // Build root children: top-level controllers + loose nodes\n const rootChildren: ElkNode[] = [];\n\n // Add top-level controllers (those not contained by another controller)\n for (const ctrlId of controllerIds) {\n if (!childToCtrl[ctrlId]) {\n const elkNode = controllerElkNodes[ctrlId];\n if (elkNode) rootChildren.push(elkNode);\n }\n }\n\n // Add loose nodes (not inside any controller and not controllers themselves)\n for (const node of nodes) {\n if (!childToCtrl[node.id] && !analysis.controllerNodeIds.has(node.id)) {\n const dims = estimateNodeDimensions(node, isHorizontal);\n dimensionMap[node.id] = dims;\n rootChildren.push(makeLeafNode(node.id, dims, direction));\n }\n }\n\n // All edges at root level — INCLUDE_CHILDREN handles cross-hierarchy routing\n const nodeIdSet = new Set(nodes.map((n) => n.id));\n const elkEdges: ElkExtendedEdge[] = edges\n .filter((e) => nodeIdSet.has(e.source) && nodeIdSet.has(e.target))\n .map((edge) => ({\n id: edge.id,\n sources: [outputPortId(edge.source)],\n targets: [inputPortId(edge.target)],\n }));\n\n return {\n elkGraph: {\n id: \"root\",\n layoutOptions: rootLayoutOptions,\n children: rootChildren,\n edges: elkEdges,\n },\n dimensionMap,\n };\n}\n\n// ─── Extract absolute positions from ELK output ────────────────────────────\n\nexport interface ElkPositionResult {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport function extractAbsolutePositions(elkResult: ElkNode): Record<string, ElkPositionResult> {\n const positions: Record<string, ElkPositionResult> = {};\n\n function walk(node: ElkNode, parentX: number, parentY: number) {\n const absX = parentX + (node.x ?? 0);\n const absY = parentY + (node.y ?? 0);\n\n if (node.id !== \"root\") {\n positions[node.id] = {\n x: absX,\n y: absY,\n width: node.width ?? 0,\n height: node.height ?? 0,\n };\n }\n\n for (const child of node.children ?? []) {\n walk(child, absX, absY);\n }\n }\n\n walk(elkResult, 0, 0);\n return positions;\n}\n","import ELK from \"elkjs/lib/elk.bundled.js\";\nimport type {\n GraphNode,\n GraphEdge,\n GraphSpec,\n DataflowAnalysis,\n LayoutConfig,\n GraphDirection,\n} from \"./types\";\nimport { buildElkGraph, extractAbsolutePositions, estimateNodeDimensions } from \"./elkGraphBuilder\";\nimport type { ElkPositionResult } from \"./elkGraphBuilder\";\n\n// Cache ELK instance at module level to avoid repeated WASM initialization\nlet elkInstance: InstanceType<typeof ELK> | null = null;\nfunction getElk(): InstanceType<typeof ELK> {\n if (!elkInstance) elkInstance = new ELK();\n return elkInstance;\n}\n\nexport interface LayoutResult {\n nodes: GraphNode[];\n edges: GraphEdge[];\n /** ELK-computed positions/sizes for controller compound nodes. */\n controllerPositions: Record<string, ElkPositionResult>;\n}\n\nexport async function getLayoutedElements(\n nodes: GraphNode[],\n edges: GraphEdge[],\n direction: GraphDirection,\n layoutConfig?: LayoutConfig,\n graphspec?: GraphSpec | null,\n analysis?: DataflowAnalysis | null,\n): Promise<LayoutResult> {\n if (nodes.length === 0) return { nodes: [], edges, controllerPositions: {} };\n\n const isHorizontal = direction === \"LR\" || direction === \"RL\";\n\n const { elkGraph, dimensionMap } = buildElkGraph(\n nodes,\n edges,\n graphspec ?? null,\n analysis ?? null,\n direction,\n layoutConfig,\n );\n\n const layoutResult = await getElk().layout(elkGraph);\n const positions = extractAbsolutePositions(layoutResult);\n\n // Extract controller positions from ELK output\n const controllerPositions: Record<string, ElkPositionResult> = {};\n if (analysis) {\n for (const ctrlId of analysis.controllerNodeIds) {\n if (positions[ctrlId]) {\n controllerPositions[ctrlId] = positions[ctrlId];\n }\n }\n }\n\n const result = nodes.map((node) => {\n const pos = positions[node.id];\n const dims = dimensionMap[node.id] ?? estimateNodeDimensions(node, isHorizontal);\n\n const width = dims.width;\n const height = dims.height;\n\n // Inject direction into pipeCardData so the card component can adjust orientation\n const pipeCardData = node.data.pipeCardData;\n const cardDirection = isHorizontal ? (\"LR\" as const) : (\"TB\" as const);\n const updatedPipeCardData = pipeCardData\n ? { ...pipeCardData, direction: cardDirection }\n : undefined;\n\n return {\n ...node,\n data: {\n ...node.data,\n _estimatedWidth: width,\n _estimatedHeight: height,\n pipeCardData: updatedPipeCardData,\n },\n // Lock the ReactFlow node wrapper to the exact dimensions ELK used for layout.\n // This ensures ReactFlow's Handle (centered on the DOM element) matches\n // the port position ELK computed (centered on the estimated dimensions).\n style: {\n ...node.style,\n width: width + \"px\",\n height: height + \"px\",\n },\n position: {\n x: pos ? pos.x : 0,\n y: pos ? pos.y : 0,\n },\n sourcePosition: (isHorizontal\n ? direction === \"LR\"\n ? \"right\"\n : \"left\"\n : direction === \"TB\"\n ? \"bottom\"\n : \"top\") as GraphNode[\"sourcePosition\"],\n targetPosition: (isHorizontal\n ? direction === \"LR\"\n ? \"left\"\n : \"right\"\n : direction === \"TB\"\n ? \"top\"\n : \"bottom\") as GraphNode[\"targetPosition\"],\n };\n });\n\n return { nodes: result, edges, controllerPositions };\n}\n","import type { GraphSpec, DataflowAnalysis, GraphNode, GraphEdge } from \"./types\";\nimport {\n CONTROLLER_PADDING_X,\n CONTROLLER_PADDING_TOP,\n CONTROLLER_PADDING_BOTTOM,\n NODE_TYPE_CONTROLLER,\n nodeWidth,\n nodeHeight,\n isStuffNodeId,\n} from \"./types\";\nimport { buildChildToControllerMap } from \"./graphAnalysis\";\n\n/** Max visible children before a parallel/batch controller auto-collapses. */\nexport const MAX_VISIBLE_CONTROLLER_CHILDREN = 5;\n\n/**\n * Collect all descendant node IDs of a controller (recursive).\n */\nfunction getDescendants(\n controllerId: string,\n containmentTree: Readonly<Record<string, readonly string[]>>,\n controllerNodeIds: ReadonlySet<string>,\n): Set<string> {\n const result = new Set<string>();\n const stack = [controllerId];\n while (stack.length > 0) {\n const id = stack.pop()!;\n for (const childId of containmentTree[id] || []) {\n result.add(childId);\n if (controllerNodeIds.has(childId)) stack.push(childId);\n }\n }\n return result;\n}\n\n/** Position and size for a controller, as computed by the layout engine. */\nexport interface ControllerRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Build controller group nodes that wrap child operators/stuff nodes.\n *\n * When `controllerPositions` is provided (from ELK layout), uses those exact\n * positions/sizes instead of recomputing from child bounding boxes. This ensures\n * controller containers match the layout engine's spacing and edge routing.\n *\n * **Side effect:** mutates `layoutedNodes` entries to set `parentId`, `extent`,\n * and convert positions to parent-relative coordinates.\n */\nexport function buildControllerNodes(\n graphspec: GraphSpec,\n analysis: DataflowAnalysis,\n layoutedNodes: GraphNode[],\n controllerPositions?: Record<string, ControllerRect>,\n): GraphNode[] {\n const nodeById: Record<string, GraphNode> = {};\n for (const n of layoutedNodes) {\n nodeById[n.id] = n;\n }\n\n const controllerInfo: Record<string, GraphSpec[\"nodes\"][number]> = {};\n for (const node of graphspec.nodes) {\n if (analysis.controllerNodeIds.has(node.id)) {\n controllerInfo[node.id] = node;\n }\n }\n\n const depthCache: Record<string, number> = {};\n const depthVisiting = new Set<string>();\n function getDepth(controllerId: string): number {\n if (depthCache[controllerId] !== undefined) return depthCache[controllerId];\n if (depthVisiting.has(controllerId)) {\n throw new Error(\n `Cycle detected in containment tree: controller \"${controllerId}\" is part of a containment cycle`,\n );\n }\n depthVisiting.add(controllerId);\n const children = analysis.containmentTree[controllerId] || [];\n let maxChildDepth = -1;\n for (const childId of children) {\n if (analysis.controllerNodeIds.has(childId)) {\n maxChildDepth = Math.max(maxChildDepth, getDepth(childId));\n }\n }\n depthVisiting.delete(controllerId);\n depthCache[controllerId] = maxChildDepth + 1;\n return depthCache[controllerId];\n }\n\n const childToController = buildChildToControllerMap(graphspec, analysis);\n const controllerStuffChildren: Record<string, string[]> = {};\n for (const [nodeId, ctrlId] of Object.entries(childToController)) {\n if (!isStuffNodeId(nodeId)) continue;\n if (!nodeById[nodeId]) continue;\n if (!controllerStuffChildren[ctrlId]) controllerStuffChildren[ctrlId] = [];\n controllerStuffChildren[ctrlId].push(nodeId);\n }\n\n const controllerIds = Array.from(analysis.controllerNodeIds);\n for (const id of controllerIds) getDepth(id);\n controllerIds.sort((a, b) => depthCache[a] - depthCache[b]);\n\n const controllerNodes: GraphNode[] = [];\n const childToParent: Record<string, string> = {};\n\n for (const controllerId of controllerIds) {\n const directChildren = analysis.containmentTree[controllerId] || [];\n const renderedChildren = directChildren.filter((cid) => nodeById[cid]);\n const stuffChildren = controllerStuffChildren[controllerId] || [];\n const allChildren = [...renderedChildren, ...stuffChildren];\n\n if (allChildren.length === 0) continue;\n\n let groupX: number, groupY: number, groupW: number, groupH: number;\n\n const elkPos = controllerPositions?.[controllerId];\n if (elkPos) {\n // Use ELK's computed position and size — accounts for edge routing and spacing\n groupX = elkPos.x;\n groupY = elkPos.y;\n groupW = elkPos.width;\n groupH = elkPos.height;\n } else {\n // Fallback: compute bounding box from child positions\n let minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n for (const childId of allChildren) {\n const child = nodeById[childId];\n const pos = child.position;\n const w = nodeWidth(child);\n const h = nodeHeight(child);\n minX = Math.min(minX, pos.x);\n minY = Math.min(minY, pos.y);\n maxX = Math.max(maxX, pos.x + w);\n maxY = Math.max(maxY, pos.y + h);\n }\n\n const depth = depthCache[controllerId] ?? 0;\n const depthScale = 1 + depth * 0.15;\n const padX = Math.round(CONTROLLER_PADDING_X * depthScale);\n const padTop = Math.round(CONTROLLER_PADDING_TOP * depthScale);\n const padBottom = Math.round(CONTROLLER_PADDING_BOTTOM * depthScale);\n\n groupX = minX - padX;\n groupY = minY - padTop;\n groupW = maxX - minX + 2 * padX;\n groupH = maxY - minY + padTop + padBottom;\n }\n\n const info = controllerInfo[controllerId] || {};\n const pipeCode = info.pipe_code || controllerId.split(\":\").pop() || controllerId;\n const groupNode: GraphNode = {\n id: controllerId,\n type: NODE_TYPE_CONTROLLER,\n data: {\n label: pipeCode,\n pipeType: info.pipe_type,\n isController: true,\n isPipe: false,\n isStuff: false,\n pipeCode: pipeCode,\n labelText: pipeCode,\n },\n position: { x: groupX, y: groupY },\n style: {\n width: groupW + \"px\",\n height: groupH + \"px\",\n padding: \"0\",\n },\n };\n\n controllerNodes.push(groupNode);\n nodeById[controllerId] = groupNode;\n\n for (const childId of allChildren) {\n childToParent[childId] = controllerId;\n }\n }\n\n // Convert child positions to parent-relative and set parentId\n for (const [childId, parentId] of Object.entries(childToParent)) {\n const child = nodeById[childId];\n const parent = nodeById[parentId];\n if (!child || !parent) continue;\n child.position = {\n x: child.position.x - parent.position.x,\n y: child.position.y - parent.position.y,\n };\n child.parentId = parentId;\n child.extent = \"parent\";\n }\n\n return controllerNodes;\n}\n\n/**\n * Apply controller containers to layouted nodes if showControllers is enabled.\n *\n * When `expandedControllers` is provided, PipeParallel/PipeBatch controllers with\n * more than MAX_VISIBLE_CONTROLLER_CHILDREN children are auto-collapsed unless the\n * controller ID is in the expanded set.\n */\nexport function applyControllers(\n layoutedNodes: GraphNode[],\n layoutedEdges: GraphEdge[],\n graphspec: GraphSpec | null,\n analysis: DataflowAnalysis | null,\n showControllers: boolean,\n expandedControllers?: ReadonlySet<string>,\n onToggleCollapse?: (controllerId: string) => void,\n controllerPositions?: Record<string, ControllerRect>,\n): { nodes: GraphNode[]; edges: GraphEdge[] } {\n if (!showControllers || !analysis || !graphspec) {\n return { nodes: layoutedNodes, edges: layoutedEdges };\n }\n\n // ─── Compute child counts and effective collapse state ─────────────────\n const childCounts: Record<string, number> = {};\n const collapsedSet = new Set<string>();\n\n const controllerTypeMap: Record<string, string> = {};\n for (const node of graphspec.nodes) {\n if (analysis.controllerNodeIds.has(node.id)) {\n controllerTypeMap[node.id] = node.pipe_type || \"\";\n }\n }\n\n for (const ctrlId of analysis.controllerNodeIds) {\n const directChildren = analysis.containmentTree[ctrlId] || [];\n childCounts[ctrlId] = directChildren.length;\n const pipeType = controllerTypeMap[ctrlId] || \"\";\n const isCollapsible = pipeType === \"PipeParallel\" || pipeType === \"PipeBatch\";\n if (\n isCollapsible &&\n directChildren.length > MAX_VISIBLE_CONTROLLER_CHILDREN &&\n !expandedControllers?.has(ctrlId)\n ) {\n collapsedSet.add(ctrlId);\n }\n }\n\n // ─── Filter hidden children for collapsed controllers ──────────────────\n let filteredNodes = layoutedNodes;\n let filteredEdges = layoutedEdges;\n\n if (collapsedSet.size > 0) {\n const hiddenNodes = new Set<string>();\n\n for (const ctrlId of collapsedSet) {\n const directChildren = analysis.containmentTree[ctrlId] || [];\n const toHide = directChildren.slice(MAX_VISIBLE_CONTROLLER_CHILDREN);\n for (const childId of toHide) {\n hiddenNodes.add(childId);\n if (analysis.controllerNodeIds.has(childId)) {\n for (const d of getDescendants(\n childId,\n analysis.containmentTree,\n analysis.controllerNodeIds,\n )) {\n hiddenNodes.add(d);\n }\n }\n }\n }\n\n // Also hide stuff nodes inside collapsed controllers that have no visible\n // pipe connection. We ignore stuff-to-stuff edges (batch_item/batch_aggregate)\n // because those would keep orphaned branch stuff nodes alive.\n const childToCtrl = buildChildToControllerMap(graphspec, analysis);\n for (const node of layoutedNodes) {\n if (!isStuffNodeId(node.id) || hiddenNodes.has(node.id)) continue;\n const ctrlId = childToCtrl[node.id];\n if (!ctrlId || (!collapsedSet.has(ctrlId) && !hiddenNodes.has(ctrlId))) continue;\n const pipeEdges = layoutedEdges.filter((e) => {\n if (e.source !== node.id && e.target !== node.id) return false;\n const other = e.source === node.id ? e.target : e.source;\n return !isStuffNodeId(other); // only pipe connections\n });\n if (\n pipeEdges.length === 0 ||\n pipeEdges.every((e) => {\n const other = e.source === node.id ? e.target : e.source;\n return hiddenNodes.has(other);\n })\n ) {\n hiddenNodes.add(node.id);\n }\n }\n\n filteredNodes = layoutedNodes.filter((n) => !hiddenNodes.has(n.id));\n filteredEdges = layoutedEdges.filter(\n (e) => !hiddenNodes.has(e.source) && !hiddenNodes.has(e.target),\n );\n }\n\n // ─── Build controller group nodes from visible children ────────────────\n const controllerNodes = buildControllerNodes(\n graphspec,\n analysis,\n filteredNodes,\n controllerPositions,\n );\n if (controllerNodes.length === 0) {\n return { nodes: filteredNodes, edges: filteredEdges };\n }\n\n // Inject collapse metadata into controller node data\n for (const cn of controllerNodes) {\n const count = childCounts[cn.id] ?? 0;\n const isCollapsed = collapsedSet.has(cn.id);\n cn.data.childCount = count;\n cn.data.isCollapsed = isCollapsed;\n if (onToggleCollapse) {\n const id = cn.id;\n cn.data.onToggleCollapse = () => onToggleCollapse(id);\n }\n }\n\n const allNodes = [...controllerNodes, ...filteredNodes];\n\n // Sort: ReactFlow requires parent group nodes before their children.\n const nodeMap: Record<string, GraphNode> = {};\n for (const n of allNodes) nodeMap[n.id] = n;\n const depthOf: Record<string, number> = {};\n const depthVisiting = new Set<string>();\n function getContainmentDepth(id: string): number {\n if (depthOf[id] !== undefined) return depthOf[id];\n if (depthVisiting.has(id)) {\n throw new Error(\n `Cycle detected in node parent chain: node \"${id}\" references itself as an ancestor`,\n );\n }\n depthVisiting.add(id);\n const n = nodeMap[id];\n depthOf[id] = n && n.parentId ? 1 + getContainmentDepth(n.parentId) : 0;\n depthVisiting.delete(id);\n return depthOf[id];\n }\n for (const n of allNodes) getContainmentDepth(n.id);\n allNodes.sort((a, b) => depthOf[a.id] - depthOf[b.id]);\n\n return { nodes: allNodes, edges: filteredEdges };\n}\n","import type { GraphConfig } from \"./types\";\nimport { EDGE_TYPE } from \"./types\";\n\nexport const DEFAULT_GRAPH_CONFIG: GraphConfig = {\n direction: \"LR\",\n showControllers: false,\n nodesep: 50,\n ranksep: 100,\n edgeType: EDGE_TYPE.DEFAULT,\n initialZoom: null,\n panToTop: true,\n paletteColors: {\n // Graph node/edge colors\n \"--color-pipe\": \"#ff6b6b\",\n \"--color-pipe-bg\": \"rgba(224,108,117,0.18)\",\n \"--color-pipe-text\": \"#ffffff\",\n \"--color-stuff\": \"#4ECDC4\",\n \"--color-stuff-bg\": \"rgba(78,205,196,0.12)\",\n \"--color-stuff-border\": \"#9ddcfd\",\n \"--color-stuff-text\": \"#98FB98\",\n \"--color-stuff-text-dim\": \"#9ddcfd\",\n \"--color-edge\": \"#FFFACD\",\n \"--color-batch-item\": \"#bd93f9\",\n \"--color-batch-aggregate\": \"#50fa7b\",\n \"--color-parallel-combine\": \"#d6a4ff\",\n \"--color-success\": \"#50FA7B\",\n \"--color-success-bg\": \"rgba(80,250,123,0.15)\",\n \"--color-error\": \"#FF5555\",\n \"--color-error-bg\": \"rgba(255,85,85,0.15)\",\n \"--color-accent\": \"#8BE9FD\",\n \"--color-warning\": \"#FFB86C\",\n // Base theme vars used by graph-core.css\n \"--color-bg\": \"#0a0a0a\",\n \"--color-bg-dots\": \"rgba(255, 255, 255, 0.35)\",\n \"--color-text-muted\": \"#94a3b8\",\n \"--color-controller-text\": \"#94a3b8\",\n \"--font-sans\": '\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n \"--font-mono\": '\"JetBrains Mono\", \"Monaco\", \"Menlo\", monospace',\n \"--shadow-lg\": \"0 8px 24px rgba(0, 0, 0, 0.5)\",\n },\n};\n\nexport function getPaletteColors(): Record<string, string> {\n return DEFAULT_GRAPH_CONFIG.paletteColors || {};\n}\n"],"mappings":"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","names":["_a","_b","dimensionMap","elkEdges","_a","_b"]}
|
package/dist/graph/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as GraphSpec, D as DataflowAnalysis, C as ConceptInfo, j as PipeBlueprintUnion, k as GraphData, b as GraphNode, a as GraphEdge, e as GraphDirection, l as LayoutConfig, d as GraphConfig } from '../types-
|
|
2
|
-
export { A as ARROW_CLOSED_MARKER, m as CONTROLLER_PADDING_BOTTOM, n as CONTROLLER_PADDING_TOP, o as CONTROLLER_PADDING_X, E as EDGE_TYPE, p as EdgeType, q as GRAPH_DIRECTION, G as GraphNodeData, r as GraphSpecEdge, s as GraphSpecEdgeKind, h as GraphSpecNode, t as GraphSpecNodeError, u as GraphSpecNodeIo, i as GraphSpecNodeIoItem, v as GraphSpecNodeTiming, L as LabelDescriptor, N as NODE_TYPE_CONTROLLER, w as NODE_TYPE_PIPE_CARD, x as NODE_TYPE_STUFF, y as NodeKind, z as PipeBatchBlueprint, B as PipeBlueprintBase,
|
|
1
|
+
import { c as GraphSpec, D as DataflowAnalysis, C as ConceptInfo, j as PipeBlueprintUnion, k as GraphData, b as GraphNode, a as GraphEdge, e as GraphDirection, l as LayoutConfig, d as GraphConfig } from '../types--1tl-afL.js';
|
|
2
|
+
export { A as ARROW_CLOSED_MARKER, m as CONTROLLER_PADDING_BOTTOM, n as CONTROLLER_PADDING_TOP, o as CONTROLLER_PADDING_X, E as EDGE_TYPE, p as EdgeType, F as FieldResolution, q as GRAPH_DIRECTION, G as GraphNodeData, r as GraphSpecEdge, s as GraphSpecEdgeKind, h as GraphSpecNode, t as GraphSpecNodeError, u as GraphSpecNodeIo, i as GraphSpecNodeIoItem, v as GraphSpecNodeTiming, L as LabelDescriptor, N as NODE_TYPE_CONTROLLER, w as NODE_TYPE_PIPE_CARD, x as NODE_TYPE_STUFF, y as NodeKind, z as PipeBatchBlueprint, B as PipeBlueprintBase, H as PipeCardPayload, I as PipeComposeBlueprint, J as PipeComposeConstructBlueprint, K as PipeComposeConstructField, M as PipeConditionBlueprint, f as PipeControllerType, O as PipeExtractBlueprint, Q as PipeFuncBlueprint, R as PipeImgGenBlueprint, S as PipeLLMBlueprint, g as PipeOperatorType, T as PipeParallelBlueprint, U as PipeSearchBlueprint, V as PipeSequenceBlueprint, P as PipeStatus, W as PipeType, X as STUFF_ID_PREFIX, Y as StuffRole, Z as StuffSpecInfo, _ as SubPipeSpec, $ as TemplateBlueprint, a0 as isStuffNodeId, a1 as nodeHeight, a2 as nodeWidth, a3 as stuffDigestFromId, a4 as stuffNodeId } from '../types--1tl-afL.js';
|
|
3
3
|
import { ElkNode } from 'elkjs/lib/elk-api';
|
|
4
4
|
|
|
5
5
|
declare function buildDataflowAnalysis(graphspec: GraphSpec | null): DataflowAnalysis | null;
|
package/dist/graph/index.js
CHANGED
|
@@ -186,6 +186,22 @@
|
|
|
186
186
|
background: var(--sv-surface);
|
|
187
187
|
border: 1px solid var(--sv-border);
|
|
188
188
|
}
|
|
189
|
+
button.stuff-viewer-local-file--button {
|
|
190
|
+
width: 100%;
|
|
191
|
+
text-align: left;
|
|
192
|
+
font: inherit;
|
|
193
|
+
color: inherit;
|
|
194
|
+
cursor: pointer;
|
|
195
|
+
transition: background 0.15s ease, border-color 0.15s ease;
|
|
196
|
+
}
|
|
197
|
+
button.stuff-viewer-local-file--button:hover {
|
|
198
|
+
background: var(--sv-surface-hover, var(--sv-surface));
|
|
199
|
+
border-color: var(--sv-accent, var(--sv-border));
|
|
200
|
+
}
|
|
201
|
+
button.stuff-viewer-local-file--button:focus-visible {
|
|
202
|
+
outline: 2px solid var(--sv-accent, var(--sv-border));
|
|
203
|
+
outline-offset: 2px;
|
|
204
|
+
}
|
|
189
205
|
.stuff-viewer-local-file-icon {
|
|
190
206
|
flex-shrink: 0;
|
|
191
207
|
width: 32px;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/graph/react/stuff/StuffViewer.css","../../../src/graph/react/detail/DetailPanel.css","../../../src/graph/react/viewer/GraphToolbar.css"],"sourcesContent":["/* ─── StuffViewer component styles ────────────────────────────────────────── */\n/* Uses CSS custom properties for consumer theming. Defaults match graph-core.css. */\n\n.stuff-viewer {\n --sv-bg: var(--color-bg, #0a0a0a);\n --sv-surface: var(--color-surface, #16213e);\n --sv-surface-hover: var(--color-surface-hover, #1f2b47);\n --sv-border: var(--color-border, #2a3a5a);\n --sv-text: var(--color-text, #e2e8f0);\n --sv-text-muted: var(--color-text-muted, #94a3b8);\n --sv-accent: var(--color-accent, #3b82f6);\n --sv-success: #10b981;\n --sv-success-bg: rgba(16, 185, 129, 0.2);\n --sv-radius: 4px;\n --sv-font-sans: var(\n --font-sans,\n \"Inter\",\n -apple-system,\n BlinkMacSystemFont,\n \"Segoe UI\",\n sans-serif\n );\n --sv-font-mono: var(--font-mono, \"JetBrains Mono\", \"Monaco\", \"Menlo\", monospace);\n\n font-family: var(--sv-font-sans);\n color: var(--sv-text);\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* ─── Header ─────────────────────────────────────────────────────────────── */\n\n.stuff-viewer-header {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 12px 16px 8px;\n border-bottom: 1px solid var(--sv-border);\n flex-shrink: 0;\n}\n\n.stuff-viewer-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--sv-text);\n margin: 0;\n}\n\n.stuff-viewer-subtitle {\n font-size: 12px;\n color: var(--sv-text-muted);\n margin: 0;\n}\n\n/* ─── Toolbar: tabs + action buttons ─────────────────────────────────────── */\n\n.stuff-viewer-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 16px;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.stuff-viewer-tabs {\n display: flex;\n gap: 4px;\n}\n\n.stuff-viewer-tab {\n padding: 5px 10px;\n border-radius: var(--sv-radius);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n background: var(--sv-surface-hover);\n color: var(--sv-text-muted);\n border: none;\n transition:\n background 0.15s,\n color 0.15s;\n}\n\n.stuff-viewer-tab:hover {\n background: var(--sv-border);\n color: var(--sv-text);\n}\n\n.stuff-viewer-tab--active {\n background: var(--sv-accent);\n color: #fff;\n}\n\n/* ─── Action buttons ─────────────────────────────────────────────────────── */\n\n.stuff-viewer-actions {\n display: flex;\n gap: 4px;\n}\n\n.stuff-viewer-action-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: var(--sv-radius);\n cursor: pointer;\n background: var(--sv-surface-hover);\n color: var(--sv-text-muted);\n border: none;\n transition:\n background 0.15s,\n color 0.15s;\n}\n\n.stuff-viewer-action-btn:hover {\n background: var(--sv-border);\n color: var(--sv-text);\n}\n\n.stuff-viewer-action-btn--copied {\n background: var(--sv-success-bg);\n color: var(--sv-success);\n}\n\n.stuff-viewer-action-btn svg {\n width: 14px;\n height: 14px;\n fill: currentColor;\n}\n\n/* ─── Content area ───────────────────────────────────────────────────────── */\n\n.stuff-viewer-content {\n flex: 1;\n overflow: auto;\n padding: 12px 16px 16px;\n min-height: 0;\n}\n\n/* Pre-formatted text (JSON and Pretty tabs) */\n.stuff-viewer-pre {\n font-family: var(--sv-font-mono);\n font-size: 11px;\n line-height: 1.5;\n white-space: pre-wrap;\n word-wrap: break-word;\n margin: 0;\n color: var(--sv-text-muted);\n}\n\n.stuff-viewer-pre--nowrap {\n white-space: pre;\n word-wrap: normal;\n line-height: 1;\n overflow-x: auto;\n padding-right: 20px;\n}\n\n/* HTML content */\n.stuff-viewer-html {\n font-family: var(--sv-font-sans);\n font-size: 11px;\n color: var(--sv-text-muted);\n line-height: 1.5;\n}\n\n.stuff-viewer-html table {\n border-collapse: collapse;\n width: 100%;\n}\n\n.stuff-viewer-html th,\n.stuff-viewer-html td {\n border: 1px solid var(--sv-border);\n padding: 8px 12px;\n text-align: left;\n}\n\n.stuff-viewer-html th {\n background: var(--sv-surface-hover);\n color: var(--sv-text);\n font-weight: 600;\n}\n\n.stuff-viewer-html tr:hover {\n background: var(--sv-surface-hover);\n}\n\n.stuff-viewer-html a {\n color: var(--sv-accent);\n text-decoration: none;\n}\n\n.stuff-viewer-html a:hover {\n text-decoration: underline;\n}\n\n.stuff-viewer-html ul {\n list-style: none;\n padding-left: 0;\n margin: 0;\n}\n\n/* PDF embed */\n.stuff-viewer-pdf {\n min-height: 400px;\n height: 100%;\n}\n\n.stuff-viewer-pdf embed {\n width: 100%;\n height: 100%;\n min-height: 500px;\n border: none;\n}\n\n/* Image content */\n.stuff-viewer-image {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 200px;\n}\n\n.stuff-viewer-image img {\n max-width: 100%;\n max-height: 70vh;\n object-fit: contain;\n}\n\n/* Local file fallback (file:// URLs that can't render inline) */\n.stuff-viewer-local-file {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n border-radius: 6px;\n background: var(--sv-surface);\n border: 1px solid var(--sv-border);\n}\n\n.stuff-viewer-local-file-icon {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n color: var(--sv-text-muted);\n}\n\n.stuff-viewer-local-file-icon svg {\n width: 100%;\n height: 100%;\n fill: currentColor;\n}\n\n.stuff-viewer-local-file-info {\n flex: 1;\n min-width: 0;\n}\n\n.stuff-viewer-local-file-name {\n font-family: var(--sv-font-mono);\n font-size: 12px;\n color: var(--sv-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.stuff-viewer-local-file-hint {\n font-size: 11px;\n color: var(--sv-text-muted);\n margin-top: 2px;\n}\n\n/* Placeholder for missing data */\n.stuff-viewer-placeholder {\n color: var(--sv-text-muted);\n font-style: italic;\n font-size: 13px;\n}\n","/* ─── Detail Panel — sliding side panel for node inspection ─────────────── */\n\n.detail-panel {\n position: absolute;\n top: 0;\n right: 0;\n width: 380px;\n height: 100%;\n background: #111118;\n border-left: 1px solid rgba(255, 255, 255, 0.1);\n z-index: 10;\n display: flex;\n flex-direction: column;\n font-family: \"Inter\", -apple-system, sans-serif;\n color: #e2e8f0;\n overflow: hidden;\n transition: transform 0.2s ease;\n}\n\n.detail-panel--closed {\n transform: translateX(100%);\n pointer-events: none;\n}\n\n/* ─── Resize handle — left edge drag target ────────────────────────────── */\n\n.detail-panel-resize-handle {\n position: absolute;\n top: 0;\n left: -6px;\n width: 12px;\n height: 100%;\n cursor: col-resize;\n z-index: 2;\n background: transparent;\n}\n\n/* Visible bar — narrower than the hit area */\n.detail-panel-resize-handle::before {\n content: \"\";\n position: absolute;\n top: 0;\n left: 5px;\n width: 2px;\n height: 100%;\n background: transparent;\n transition: background 0.15s;\n}\n\n.detail-panel-resize-handle:hover::before,\n.detail-panel--dragging .detail-panel-resize-handle::before {\n background: rgba(59, 130, 246, 0.5);\n}\n\n/* Grip indicator — visible on hover */\n.detail-panel-resize-handle::after {\n content: \"\";\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2px;\n height: 24px;\n border-radius: 1px;\n background: transparent;\n transition: background 0.15s;\n}\n\n.detail-panel-resize-handle:hover::after,\n.detail-panel--dragging .detail-panel-resize-handle::after {\n background: rgba(59, 130, 246, 0.8);\n}\n\n/* Disable transition during drag for smooth resizing */\n.detail-panel--dragging {\n transition: none;\n}\n\n.detail-panel--dragging .detail-panel-content {\n pointer-events: none;\n}\n\n.detail-panel-close {\n all: unset;\n cursor: pointer;\n position: absolute;\n top: 12px;\n right: 12px;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n color: #64748b;\n font-size: 18px;\n line-height: 1;\n z-index: 3;\n}\n\n.detail-panel-close:hover {\n color: #94a3b8;\n background: rgba(255, 255, 255, 0.06);\n}\n\n.detail-panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 20px 16px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n/* ─── Sticky header (pipe info + IO stays pinned at top) ───────────────── */\n\n.detail-sticky-header {\n position: sticky;\n top: -20px;\n z-index: 1;\n background: #111118;\n padding-top: 20px;\n margin-top: -20px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n/* ─── Shared detail components ──────────────────────────────────────────── */\n\n.detail-section-label {\n font-size: 9px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: #64748b;\n margin-bottom: 6px;\n}\n\n.detail-header {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.detail-badge {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 2px 7px;\n border-radius: 4px;\n white-space: nowrap;\n}\n\n.detail-badge--operator {\n background: #ff6b6b;\n color: #0e0e0e;\n}\n\n.detail-badge--controller {\n background: #bd93f9;\n color: #0e0e0e;\n}\n\n.detail-pipe-code {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 14px;\n font-weight: 600;\n color: #ff6b6b;\n}\n\n.detail-pipe-code--controller {\n color: #bd93f9;\n}\n\n.detail-status {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.detail-status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n display: inline-block;\n}\n\n.detail-status-label {\n font-size: 12px;\n font-weight: 600;\n text-transform: capitalize;\n}\n\n.detail-duration {\n font-size: 11px;\n color: #64748b;\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n}\n\n.detail-description {\n font-size: 12px;\n color: #94a3b8;\n line-height: 1.5;\n}\n\n/* ─── IO Pills ──────────────────────────────────────────────────────────── */\n\n.detail-io-pill {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n padding: 3px 8px;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.04);\n border: 1px solid rgba(255, 255, 255, 0.06);\n}\n\n.detail-io-name {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #e2e8f0;\n}\n\n.detail-io-concept {\n color: #64748b;\n font-size: 10px;\n}\n\n.detail-io-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n/* ─── Blueprint-specific sections ───────────────────────────────────────── */\n\n.detail-prompt-block {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 11px;\n color: #94a3b8;\n background: rgba(255, 255, 255, 0.03);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 6px;\n padding: 10px 12px;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-y: auto;\n line-height: 1.5;\n}\n\n.detail-prompt-block--collapsed {\n max-height: 300px;\n}\n\n.detail-prompt-block--expanded {\n max-height: none;\n overflow-y: visible;\n}\n\n.detail-prompt-expand-btn {\n all: unset;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 9px;\n color: #64748b;\n padding: 2px 6px;\n border-radius: 3px;\n background: rgba(255, 255, 255, 0.04);\n border: 1px solid rgba(255, 255, 255, 0.06);\n transition: color 0.15s;\n}\n\n.detail-prompt-expand-btn:hover {\n color: #94a3b8;\n}\n\n.detail-kv-row {\n display: flex;\n justify-content: space-between;\n align-items: flex-start; /* top-align so the label stays next to the first line of a wrapped value */\n gap: 12px;\n font-size: 11px;\n padding: 3px 0;\n}\n\n.detail-kv-key {\n color: #64748b;\n flex-shrink: 0; /* label stays at its natural width */\n}\n\n.detail-kv-value {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #e2e8f0;\n flex: 1 1 0;\n min-width: 0;\n text-align: right;\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* ─── Field block: labeled multi-line text (for long resolved values) ─── */\n\n.detail-field-block {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-field-block-label {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 10px;\n color: #64748b;\n}\n\n.detail-field-block-value {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 11px;\n color: #e2e8f0;\n background: rgba(255, 255, 255, 0.03);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 6px;\n padding: 8px 10px;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n line-height: 1.5;\n max-height: 240px;\n overflow-y: auto;\n}\n\n/* ─── Nested construct sub-section header ───────────────────────────────── */\n/* Rendered before each nested sub-construct's recursive contents. The left\n * border + indent provides a visual \"branch\" cue so the tree structure is\n * obvious without needing collapse state. */\n\n.detail-nested-header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n margin-top: 6px;\n margin-bottom: 4px;\n padding: 4px 0 4px 8px;\n border-left: 2px solid rgba(80, 250, 123, 0.35);\n}\n\n.detail-nested-header-name {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 11px;\n font-weight: 600;\n color: #e2e8f0;\n}\n\n.detail-nested-header-meta {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 9px;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n/* ─── Concept schema table ──────────────────────────────────────────────── */\n\n.detail-schema-table {\n width: 100%;\n font-size: 11px;\n border-collapse: collapse;\n}\n\n.detail-schema-table th {\n text-align: left;\n font-weight: 700;\n color: #64748b;\n font-size: 9px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n padding: 4px 6px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n}\n\n.detail-schema-table td {\n padding: 4px 6px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.04);\n color: #94a3b8;\n}\n\n.detail-schema-field {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #e2e8f0;\n}\n\n.detail-schema-type {\n color: #8be9fd;\n}\n\n.detail-schema-required {\n color: #ff6b6b;\n font-size: 9px;\n}\n\n/* ─── Error section ─────────────────────────────────────────────────────── */\n\n.detail-error {\n background: rgba(255, 85, 85, 0.08);\n border: 1px solid rgba(255, 85, 85, 0.2);\n border-radius: 6px;\n padding: 10px 12px;\n}\n\n.detail-error-type {\n font-size: 12px;\n font-weight: 600;\n color: #ff5555;\n margin-bottom: 4px;\n}\n\n.detail-error-message {\n font-size: 11px;\n color: #94a3b8;\n line-height: 1.5;\n}\n\n.detail-error-stack {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 10px;\n color: #64748b;\n margin-top: 8px;\n max-height: 150px;\n overflow-y: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n/* ─── Steps list (PipeSequence, PipeCondition outcomes) ─────────────────── */\n\n.detail-steps-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-step-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 11px;\n padding: 4px 8px;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.03);\n border: 1px solid rgba(255, 255, 255, 0.06);\n}\n\n.detail-step-index {\n color: #64748b;\n font-size: 10px;\n font-weight: 700;\n min-width: 16px;\n}\n\n.detail-step-code {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #e2e8f0;\n}\n\n/* ─── Tags/Metrics ──────────────────────────────────────────────────────── */\n\n.detail-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n.detail-tag {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 3px;\n background: rgba(255, 255, 255, 0.04);\n border: 1px solid rgba(255, 255, 255, 0.06);\n}\n\n.detail-tag-key {\n color: #64748b;\n}\n\n.detail-tag-value {\n color: #e2e8f0;\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n}\n\n/* ─── Concept panel header ──────────────────────────────────────────────── */\n\n.detail-concept-code {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 14px;\n font-weight: 600;\n color: #50fa7b;\n}\n\n.detail-concept-domain {\n font-size: 11px;\n color: #64748b;\n}\n\n.detail-refines {\n font-size: 11px;\n color: #94a3b8;\n}\n\n.detail-refines-code {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #8be9fd;\n}\n\n/* ─── Not available fallback ────────────────────────────────────────────── */\n\n.detail-not-available {\n font-size: 12px;\n color: #64748b;\n font-style: italic;\n padding: 8px 0;\n}\n","/* ─── Graph Toolbar — floating controls over the graph background ─────── */\n\n.graph-toolbar {\n position: absolute;\n top: 8px;\n display: flex;\n align-items: center;\n gap: 4px;\n z-index: 11;\n pointer-events: auto;\n}\n\n.graph-toolbar-btn {\n all: unset;\n box-sizing: border-box;\n cursor: pointer;\n width: 28px;\n height: 28px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n background: rgba(17, 17, 24, 0.8);\n border: 1px solid rgba(255, 255, 255, 0.1);\n color: #cbd5e1;\n backdrop-filter: blur(6px);\n transition:\n background 0.15s,\n color 0.15s,\n border-color 0.15s;\n}\n\n.graph-toolbar-btn:hover {\n background: rgba(30, 30, 40, 0.9);\n color: #f1f5f9;\n border-color: rgba(255, 255, 255, 0.18);\n}\n\n.graph-toolbar-btn:focus-visible {\n outline: 2px solid rgba(59, 130, 246, 0.6);\n outline-offset: 1px;\n}\n\n.graph-toolbar-btn--active {\n background: #3b82f6;\n border-color: #3b82f6;\n color: #ffffff;\n}\n\n.graph-toolbar-btn--active:hover {\n background: #2563eb;\n border-color: #2563eb;\n color: #ffffff;\n}\n\n.graph-toolbar-separator {\n width: 1px;\n height: 18px;\n background: rgba(255, 255, 255, 0.12);\n margin: 0 2px;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/graph/react/stuff/StuffViewer.css","../../../src/graph/react/detail/DetailPanel.css","../../../src/graph/react/viewer/GraphToolbar.css"],"sourcesContent":["/* ─── StuffViewer component styles ────────────────────────────────────────── */\n/* Uses CSS custom properties for consumer theming. Defaults match graph-core.css. */\n\n.stuff-viewer {\n --sv-bg: var(--color-bg, #0a0a0a);\n --sv-surface: var(--color-surface, #16213e);\n --sv-surface-hover: var(--color-surface-hover, #1f2b47);\n --sv-border: var(--color-border, #2a3a5a);\n --sv-text: var(--color-text, #e2e8f0);\n --sv-text-muted: var(--color-text-muted, #94a3b8);\n --sv-accent: var(--color-accent, #3b82f6);\n --sv-success: #10b981;\n --sv-success-bg: rgba(16, 185, 129, 0.2);\n --sv-radius: 4px;\n --sv-font-sans: var(\n --font-sans,\n \"Inter\",\n -apple-system,\n BlinkMacSystemFont,\n \"Segoe UI\",\n sans-serif\n );\n --sv-font-mono: var(--font-mono, \"JetBrains Mono\", \"Monaco\", \"Menlo\", monospace);\n\n font-family: var(--sv-font-sans);\n color: var(--sv-text);\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n/* ─── Header ─────────────────────────────────────────────────────────────── */\n\n.stuff-viewer-header {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 12px 16px 8px;\n border-bottom: 1px solid var(--sv-border);\n flex-shrink: 0;\n}\n\n.stuff-viewer-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--sv-text);\n margin: 0;\n}\n\n.stuff-viewer-subtitle {\n font-size: 12px;\n color: var(--sv-text-muted);\n margin: 0;\n}\n\n/* ─── Toolbar: tabs + action buttons ─────────────────────────────────────── */\n\n.stuff-viewer-toolbar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 16px;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.stuff-viewer-tabs {\n display: flex;\n gap: 4px;\n}\n\n.stuff-viewer-tab {\n padding: 5px 10px;\n border-radius: var(--sv-radius);\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n background: var(--sv-surface-hover);\n color: var(--sv-text-muted);\n border: none;\n transition:\n background 0.15s,\n color 0.15s;\n}\n\n.stuff-viewer-tab:hover {\n background: var(--sv-border);\n color: var(--sv-text);\n}\n\n.stuff-viewer-tab--active {\n background: var(--sv-accent);\n color: #fff;\n}\n\n/* ─── Action buttons ─────────────────────────────────────────────────────── */\n\n.stuff-viewer-actions {\n display: flex;\n gap: 4px;\n}\n\n.stuff-viewer-action-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: var(--sv-radius);\n cursor: pointer;\n background: var(--sv-surface-hover);\n color: var(--sv-text-muted);\n border: none;\n transition:\n background 0.15s,\n color 0.15s;\n}\n\n.stuff-viewer-action-btn:hover {\n background: var(--sv-border);\n color: var(--sv-text);\n}\n\n.stuff-viewer-action-btn--copied {\n background: var(--sv-success-bg);\n color: var(--sv-success);\n}\n\n.stuff-viewer-action-btn svg {\n width: 14px;\n height: 14px;\n fill: currentColor;\n}\n\n/* ─── Content area ───────────────────────────────────────────────────────── */\n\n.stuff-viewer-content {\n flex: 1;\n overflow: auto;\n padding: 12px 16px 16px;\n min-height: 0;\n}\n\n/* Pre-formatted text (JSON and Pretty tabs) */\n.stuff-viewer-pre {\n font-family: var(--sv-font-mono);\n font-size: 11px;\n line-height: 1.5;\n white-space: pre-wrap;\n word-wrap: break-word;\n margin: 0;\n color: var(--sv-text-muted);\n}\n\n.stuff-viewer-pre--nowrap {\n white-space: pre;\n word-wrap: normal;\n line-height: 1;\n overflow-x: auto;\n padding-right: 20px;\n}\n\n/* HTML content */\n.stuff-viewer-html {\n font-family: var(--sv-font-sans);\n font-size: 11px;\n color: var(--sv-text-muted);\n line-height: 1.5;\n}\n\n.stuff-viewer-html table {\n border-collapse: collapse;\n width: 100%;\n}\n\n.stuff-viewer-html th,\n.stuff-viewer-html td {\n border: 1px solid var(--sv-border);\n padding: 8px 12px;\n text-align: left;\n}\n\n.stuff-viewer-html th {\n background: var(--sv-surface-hover);\n color: var(--sv-text);\n font-weight: 600;\n}\n\n.stuff-viewer-html tr:hover {\n background: var(--sv-surface-hover);\n}\n\n.stuff-viewer-html a {\n color: var(--sv-accent);\n text-decoration: none;\n}\n\n.stuff-viewer-html a:hover {\n text-decoration: underline;\n}\n\n.stuff-viewer-html ul {\n list-style: none;\n padding-left: 0;\n margin: 0;\n}\n\n/* PDF embed */\n.stuff-viewer-pdf {\n min-height: 400px;\n height: 100%;\n}\n\n.stuff-viewer-pdf embed {\n width: 100%;\n height: 100%;\n min-height: 500px;\n border: none;\n}\n\n/* Image content */\n.stuff-viewer-image {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 200px;\n}\n\n.stuff-viewer-image img {\n max-width: 100%;\n max-height: 70vh;\n object-fit: contain;\n}\n\n/* Local file fallback (file:// URLs that can't render inline) */\n.stuff-viewer-local-file {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px;\n border-radius: 6px;\n background: var(--sv-surface);\n border: 1px solid var(--sv-border);\n}\n\n/* Clickable variant — used when an open-externally action is bound (e.g. PDF\n fallback in hosts that can't render <embed type=\"application/pdf\">). */\nbutton.stuff-viewer-local-file--button {\n width: 100%;\n text-align: left;\n font: inherit;\n color: inherit;\n cursor: pointer;\n transition:\n background 0.15s ease,\n border-color 0.15s ease;\n}\n\nbutton.stuff-viewer-local-file--button:hover {\n background: var(--sv-surface-hover, var(--sv-surface));\n border-color: var(--sv-accent, var(--sv-border));\n}\n\nbutton.stuff-viewer-local-file--button:focus-visible {\n outline: 2px solid var(--sv-accent, var(--sv-border));\n outline-offset: 2px;\n}\n\n.stuff-viewer-local-file-icon {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n color: var(--sv-text-muted);\n}\n\n.stuff-viewer-local-file-icon svg {\n width: 100%;\n height: 100%;\n fill: currentColor;\n}\n\n.stuff-viewer-local-file-info {\n flex: 1;\n min-width: 0;\n}\n\n.stuff-viewer-local-file-name {\n font-family: var(--sv-font-mono);\n font-size: 12px;\n color: var(--sv-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.stuff-viewer-local-file-hint {\n font-size: 11px;\n color: var(--sv-text-muted);\n margin-top: 2px;\n}\n\n/* Placeholder for missing data */\n.stuff-viewer-placeholder {\n color: var(--sv-text-muted);\n font-style: italic;\n font-size: 13px;\n}\n","/* ─── Detail Panel — sliding side panel for node inspection ─────────────── */\n\n.detail-panel {\n position: absolute;\n top: 0;\n right: 0;\n width: 380px;\n height: 100%;\n background: #111118;\n border-left: 1px solid rgba(255, 255, 255, 0.1);\n z-index: 10;\n display: flex;\n flex-direction: column;\n font-family: \"Inter\", -apple-system, sans-serif;\n color: #e2e8f0;\n overflow: hidden;\n transition: transform 0.2s ease;\n}\n\n.detail-panel--closed {\n transform: translateX(100%);\n pointer-events: none;\n}\n\n/* ─── Resize handle — left edge drag target ────────────────────────────── */\n\n.detail-panel-resize-handle {\n position: absolute;\n top: 0;\n left: -6px;\n width: 12px;\n height: 100%;\n cursor: col-resize;\n z-index: 2;\n background: transparent;\n}\n\n/* Visible bar — narrower than the hit area */\n.detail-panel-resize-handle::before {\n content: \"\";\n position: absolute;\n top: 0;\n left: 5px;\n width: 2px;\n height: 100%;\n background: transparent;\n transition: background 0.15s;\n}\n\n.detail-panel-resize-handle:hover::before,\n.detail-panel--dragging .detail-panel-resize-handle::before {\n background: rgba(59, 130, 246, 0.5);\n}\n\n/* Grip indicator — visible on hover */\n.detail-panel-resize-handle::after {\n content: \"\";\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 2px;\n height: 24px;\n border-radius: 1px;\n background: transparent;\n transition: background 0.15s;\n}\n\n.detail-panel-resize-handle:hover::after,\n.detail-panel--dragging .detail-panel-resize-handle::after {\n background: rgba(59, 130, 246, 0.8);\n}\n\n/* Disable transition during drag for smooth resizing */\n.detail-panel--dragging {\n transition: none;\n}\n\n.detail-panel--dragging .detail-panel-content {\n pointer-events: none;\n}\n\n.detail-panel-close {\n all: unset;\n cursor: pointer;\n position: absolute;\n top: 12px;\n right: 12px;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n color: #64748b;\n font-size: 18px;\n line-height: 1;\n z-index: 3;\n}\n\n.detail-panel-close:hover {\n color: #94a3b8;\n background: rgba(255, 255, 255, 0.06);\n}\n\n.detail-panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 20px 16px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n/* ─── Sticky header (pipe info + IO stays pinned at top) ───────────────── */\n\n.detail-sticky-header {\n position: sticky;\n top: -20px;\n z-index: 1;\n background: #111118;\n padding-top: 20px;\n margin-top: -20px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n/* ─── Shared detail components ──────────────────────────────────────────── */\n\n.detail-section-label {\n font-size: 9px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: #64748b;\n margin-bottom: 6px;\n}\n\n.detail-header {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.detail-badge {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n padding: 2px 7px;\n border-radius: 4px;\n white-space: nowrap;\n}\n\n.detail-badge--operator {\n background: #ff6b6b;\n color: #0e0e0e;\n}\n\n.detail-badge--controller {\n background: #bd93f9;\n color: #0e0e0e;\n}\n\n.detail-pipe-code {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 14px;\n font-weight: 600;\n color: #ff6b6b;\n}\n\n.detail-pipe-code--controller {\n color: #bd93f9;\n}\n\n.detail-status {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.detail-status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n display: inline-block;\n}\n\n.detail-status-label {\n font-size: 12px;\n font-weight: 600;\n text-transform: capitalize;\n}\n\n.detail-duration {\n font-size: 11px;\n color: #64748b;\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n}\n\n.detail-description {\n font-size: 12px;\n color: #94a3b8;\n line-height: 1.5;\n}\n\n/* ─── IO Pills ──────────────────────────────────────────────────────────── */\n\n.detail-io-pill {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n padding: 3px 8px;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.04);\n border: 1px solid rgba(255, 255, 255, 0.06);\n}\n\n.detail-io-name {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #e2e8f0;\n}\n\n.detail-io-concept {\n color: #64748b;\n font-size: 10px;\n}\n\n.detail-io-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n/* ─── Blueprint-specific sections ───────────────────────────────────────── */\n\n.detail-prompt-block {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 11px;\n color: #94a3b8;\n background: rgba(255, 255, 255, 0.03);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 6px;\n padding: 10px 12px;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-y: auto;\n line-height: 1.5;\n}\n\n.detail-prompt-block--collapsed {\n max-height: 300px;\n}\n\n.detail-prompt-block--expanded {\n max-height: none;\n overflow-y: visible;\n}\n\n.detail-prompt-expand-btn {\n all: unset;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 9px;\n color: #64748b;\n padding: 2px 6px;\n border-radius: 3px;\n background: rgba(255, 255, 255, 0.04);\n border: 1px solid rgba(255, 255, 255, 0.06);\n transition: color 0.15s;\n}\n\n.detail-prompt-expand-btn:hover {\n color: #94a3b8;\n}\n\n.detail-kv-row {\n display: flex;\n justify-content: space-between;\n align-items: flex-start; /* top-align so the label stays next to the first line of a wrapped value */\n gap: 12px;\n font-size: 11px;\n padding: 3px 0;\n}\n\n.detail-kv-key {\n color: #64748b;\n flex-shrink: 0; /* label stays at its natural width */\n}\n\n.detail-kv-value {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #e2e8f0;\n flex: 1 1 0;\n min-width: 0;\n text-align: right;\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n/* ─── Field block: labeled multi-line text (for long resolved values) ─── */\n\n.detail-field-block {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-field-block-label {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 10px;\n color: #64748b;\n}\n\n.detail-field-block-value {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 11px;\n color: #e2e8f0;\n background: rgba(255, 255, 255, 0.03);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 6px;\n padding: 8px 10px;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n line-height: 1.5;\n max-height: 240px;\n overflow-y: auto;\n}\n\n/* ─── Nested construct sub-section header ───────────────────────────────── */\n/* Rendered before each nested sub-construct's recursive contents. The left\n * border + indent provides a visual \"branch\" cue so the tree structure is\n * obvious without needing collapse state. */\n\n.detail-nested-header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n margin-top: 6px;\n margin-bottom: 4px;\n padding: 4px 0 4px 8px;\n border-left: 2px solid rgba(80, 250, 123, 0.35);\n}\n\n.detail-nested-header-name {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 11px;\n font-weight: 600;\n color: #e2e8f0;\n}\n\n.detail-nested-header-meta {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 9px;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n/* ─── Concept schema table ──────────────────────────────────────────────── */\n\n.detail-schema-table {\n width: 100%;\n font-size: 11px;\n border-collapse: collapse;\n}\n\n.detail-schema-table th {\n text-align: left;\n font-weight: 700;\n color: #64748b;\n font-size: 9px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n padding: 4px 6px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n}\n\n.detail-schema-table td {\n padding: 4px 6px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.04);\n color: #94a3b8;\n}\n\n.detail-schema-field {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #e2e8f0;\n}\n\n.detail-schema-type {\n color: #8be9fd;\n}\n\n.detail-schema-required {\n color: #ff6b6b;\n font-size: 9px;\n}\n\n/* ─── Error section ─────────────────────────────────────────────────────── */\n\n.detail-error {\n background: rgba(255, 85, 85, 0.08);\n border: 1px solid rgba(255, 85, 85, 0.2);\n border-radius: 6px;\n padding: 10px 12px;\n}\n\n.detail-error-type {\n font-size: 12px;\n font-weight: 600;\n color: #ff5555;\n margin-bottom: 4px;\n}\n\n.detail-error-message {\n font-size: 11px;\n color: #94a3b8;\n line-height: 1.5;\n}\n\n.detail-error-stack {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 10px;\n color: #64748b;\n margin-top: 8px;\n max-height: 150px;\n overflow-y: auto;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n/* ─── Steps list (PipeSequence, PipeCondition outcomes) ─────────────────── */\n\n.detail-steps-list {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.detail-step-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 11px;\n padding: 4px 8px;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.03);\n border: 1px solid rgba(255, 255, 255, 0.06);\n}\n\n.detail-step-index {\n color: #64748b;\n font-size: 10px;\n font-weight: 700;\n min-width: 16px;\n}\n\n.detail-step-code {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #e2e8f0;\n}\n\n/* ─── Tags/Metrics ──────────────────────────────────────────────────────── */\n\n.detail-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n.detail-tag {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 3px;\n background: rgba(255, 255, 255, 0.04);\n border: 1px solid rgba(255, 255, 255, 0.06);\n}\n\n.detail-tag-key {\n color: #64748b;\n}\n\n.detail-tag-value {\n color: #e2e8f0;\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n}\n\n/* ─── Concept panel header ──────────────────────────────────────────────── */\n\n.detail-concept-code {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n font-size: 14px;\n font-weight: 600;\n color: #50fa7b;\n}\n\n.detail-concept-domain {\n font-size: 11px;\n color: #64748b;\n}\n\n.detail-refines {\n font-size: 11px;\n color: #94a3b8;\n}\n\n.detail-refines-code {\n font-family: \"JetBrains Mono\", \"Monaco\", monospace;\n color: #8be9fd;\n}\n\n/* ─── Not available fallback ────────────────────────────────────────────── */\n\n.detail-not-available {\n font-size: 12px;\n color: #64748b;\n font-style: italic;\n padding: 8px 0;\n}\n","/* ─── Graph Toolbar — floating controls over the graph background ─────── */\n\n.graph-toolbar {\n position: absolute;\n top: 8px;\n display: flex;\n align-items: center;\n gap: 4px;\n z-index: 11;\n pointer-events: auto;\n}\n\n.graph-toolbar-btn {\n all: unset;\n box-sizing: border-box;\n cursor: pointer;\n width: 28px;\n height: 28px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n background: rgba(17, 17, 24, 0.8);\n border: 1px solid rgba(255, 255, 255, 0.1);\n color: #cbd5e1;\n backdrop-filter: blur(6px);\n transition:\n background 0.15s,\n color 0.15s,\n border-color 0.15s;\n}\n\n.graph-toolbar-btn:hover {\n background: rgba(30, 30, 40, 0.9);\n color: #f1f5f9;\n border-color: rgba(255, 255, 255, 0.18);\n}\n\n.graph-toolbar-btn:focus-visible {\n outline: 2px solid rgba(59, 130, 246, 0.6);\n outline-offset: 1px;\n}\n\n.graph-toolbar-btn--active {\n background: #3b82f6;\n border-color: #3b82f6;\n color: #ffffff;\n}\n\n.graph-toolbar-btn--active:hover {\n background: #2563eb;\n border-color: #2563eb;\n color: #ffffff;\n}\n\n.graph-toolbar-separator {\n width: 1px;\n height: 18px;\n background: rgba(255, 255, 255, 0.12);\n margin: 0 2px;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { G as GraphNodeData, a as GraphEdge, b as GraphNode, c as GraphSpec, d as GraphConfig, e as GraphDirection, P as PipeStatus, L as LabelDescriptor, f as PipeControllerType, g as PipeOperatorType, h as GraphSpecNode, C as ConceptInfo, i as GraphSpecNodeIoItem } from '../../types-
|
|
3
|
+
import { G as GraphNodeData, a as GraphEdge, b as GraphNode, c as GraphSpec, d as GraphConfig, e as GraphDirection, P as PipeStatus, L as LabelDescriptor, f as PipeControllerType, g as PipeOperatorType, h as GraphSpecNode, C as ConceptInfo, i as GraphSpecNodeIoItem } from '../../types--1tl-afL.js';
|
|
4
4
|
import { Edge, Node, ReactFlowInstance } from '@xyflow/react';
|
|
5
5
|
|
|
6
6
|
/** Data for rendering a stuff (data item) in the StuffViewer component. */
|
|
@@ -80,6 +80,20 @@ interface GraphViewerProps {
|
|
|
80
80
|
* exchange internal URIs for browser-fetchable presigned URLs when rendering media.
|
|
81
81
|
*/
|
|
82
82
|
resolveStorageUrl?: ResolveStorageUrl;
|
|
83
|
+
/**
|
|
84
|
+
* Set to `false` when the host cannot render `<embed type="application/pdf">`
|
|
85
|
+
* — e.g. VS Code webviews, which run inside Electron without the Chromium
|
|
86
|
+
* PDFium plugin. Forwarded to StuffViewer.
|
|
87
|
+
*
|
|
88
|
+
* Default: `true`.
|
|
89
|
+
*/
|
|
90
|
+
canEmbedPdf?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Replaces the default `window.open(url, "_blank")` behavior used by the
|
|
93
|
+
* StuffViewer toolbar and the PDF fallback tile. Wire this to your host's
|
|
94
|
+
* external-open mechanism (e.g. `vscode.env.openExternal` via postMessage).
|
|
95
|
+
*/
|
|
96
|
+
onOpenExternally?: (url: string, filename?: string) => void;
|
|
83
97
|
}
|
|
84
98
|
/** Apply Layer 2 execution state overrides to rendered nodes. */
|
|
85
99
|
declare function applyStatusOverrides(nodes: AppNode[], statusMap: Record<string, PipeStatus> | undefined): AppNode[];
|
|
@@ -146,8 +160,25 @@ interface StuffViewerProps {
|
|
|
146
160
|
* internal URIs falls back to the "no preview" placeholder.
|
|
147
161
|
*/
|
|
148
162
|
resolveStorageUrl?: ResolveStorageUrl;
|
|
163
|
+
/**
|
|
164
|
+
* Set to `false` when the host cannot render `<embed type="application/pdf">`
|
|
165
|
+
* — e.g. VS Code webviews, which run inside Electron without the Chromium
|
|
166
|
+
* PDFium plugin. The PDF view then falls back to a clickable tile that
|
|
167
|
+
* triggers `onOpenExternally` (or `window.open` if not provided).
|
|
168
|
+
*
|
|
169
|
+
* Default: `true`.
|
|
170
|
+
*/
|
|
171
|
+
canEmbedPdf?: boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Replaces the default `window.open(url, "_blank")` behavior for both the
|
|
174
|
+
* toolbar "open externally" button and the PDF fallback tile. Use this in
|
|
175
|
+
* environments where `window.open` is blocked or undesirable — for example,
|
|
176
|
+
* VS Code webviews should wire this to `vscode.env.openExternal` via
|
|
177
|
+
* postMessage.
|
|
178
|
+
*/
|
|
179
|
+
onOpenExternally?: (url: string, filename?: string) => void;
|
|
149
180
|
}
|
|
150
|
-
declare function StuffViewer({ stuff, className, resolveStorageUrl }: StuffViewerProps): react_jsx_runtime.JSX.Element;
|
|
181
|
+
declare function StuffViewer({ stuff, className, resolveStorageUrl, canEmbedPdf, onOpenExternally, }: StuffViewerProps): react_jsx_runtime.JSX.Element;
|
|
151
182
|
|
|
152
183
|
/** Check whether a URL is safe for links/downloads (no javascript: or data: injection). */
|
|
153
184
|
declare function isSafeDisplayUrl(url: unknown): url is string;
|
|
@@ -226,8 +257,12 @@ interface ConceptDetailPanelProps {
|
|
|
226
257
|
isDryRun?: boolean;
|
|
227
258
|
/** Resolver for `pipelex-storage://` URIs when rendering media in StuffViewer. */
|
|
228
259
|
resolveStorageUrl?: ResolveStorageUrl;
|
|
260
|
+
/** Forwarded to {@link StuffViewer}. Set `false` when the host can't embed PDFs. */
|
|
261
|
+
canEmbedPdf?: boolean;
|
|
262
|
+
/** Forwarded to {@link StuffViewer}. Overrides default `window.open` behavior. */
|
|
263
|
+
onOpenExternally?: (url: string, filename?: string) => void;
|
|
229
264
|
}
|
|
230
|
-
declare function ConceptDetailPanel({ concept, ioData, isDryRun, resolveStorageUrl }: ConceptDetailPanelProps): react_jsx_runtime.JSX.Element;
|
|
265
|
+
declare function ConceptDetailPanel({ concept, ioData, isDryRun, resolveStorageUrl, canEmbedPdf, onOpenExternally, }: ConceptDetailPanelProps): react_jsx_runtime.JSX.Element;
|
|
231
266
|
|
|
232
267
|
interface UseResizableOptions {
|
|
233
268
|
/** Initial panel width in pixels. */
|