@pipelex/mthds-ui 0.19.0 → 0.21.0

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.
@@ -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/* StuffViewer is also exported standalone (used outside GraphViewer — e.g.\n * docs pages, embedded previews). The theme tokens are normally applied to\n * the GraphViewer container, but when this component is rendered on its own\n * those tokens may not be set. The fallbacks below match the dark palette\n * from `graphConfig.ts` (DARK_PALETTE_COLORS) so the component always\n * renders with valid colors and fonts. */\n\n.stuff-viewer {\n --sv-bg: var(--surface-page, #0a0a0a);\n --sv-surface: var(--surface-panel, #111118);\n --sv-surface-hover: var(--surface-elevated, rgba(255, 255, 255, 0.06));\n --sv-border: var(--border-default, rgba(255, 255, 255, 0.1));\n --sv-text: var(--text-default, #e2e8f0);\n --sv-text-muted: var(--text-muted, #94a3b8);\n --sv-accent: var(--color-accent, #8be9fd);\n --sv-success: var(--color-success, #50fa7b);\n --sv-success-bg: var(--color-success-bg, rgba(80, 250, 123, 0.15));\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: var(--text-on-accent, #0e0e0e);\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/* Native `Html` concept — rendered in a sandboxed iframe so the document's own\n <style>/layout is faithful and isolated from the host. White backdrop because\n these documents (invoices, quotes, reports) are authored for print/light. */\n.stuff-viewer-html-frame {\n width: 100%;\n height: 100%;\n min-height: 480px;\n border: none;\n border-radius: var(--sv-radius);\n background: #fff;\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\n.stuff-viewer-error {\n border: 1px solid var(--color-status-failed, #ff5555);\n border-radius: 6px;\n padding: 12px;\n background: rgba(255, 85, 85, 0.08);\n}\n\n.stuff-viewer-error-title {\n color: var(--color-status-failed, #ff5555);\n font-weight: 600;\n font-size: 13px;\n margin-bottom: 4px;\n}\n\n.stuff-viewer-error-detail {\n color: var(--sv-text-muted);\n font-family: var(--font-mono, monospace);\n font-size: 12px;\n white-space: pre-wrap;\n word-break: break-word;\n}\n","/* ─── Detail Panel — sliding side panel for node inspection ─────────────── */\n/* Token-only — all colors come from the active theme palette on the */\n/* container. See `graphConfig.ts` for token definitions. */\n\n.detail-panel {\n position: absolute;\n top: 0;\n right: 0;\n width: 380px;\n height: 100%;\n background: var(--surface-panel);\n border-left: 1px solid var(--border-default);\n z-index: 10;\n display: flex;\n flex-direction: column;\n font-family: var(--font-sans);\n color: var(--text-default);\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: var(--color-accent);\n opacity: 0.6;\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: var(--color-accent);\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/* ─── Close row — scrolls away with the content (intentionally NOT pinned) ─ */\n/* The close button is part of the content's top, not panel chrome: it\n * scrolls out of view with the content, and closing the panel means\n * scrolling back up. The negative margin tucks the following section up\n * beside it so the row doesn't cost a full line of vertical space. */\n\n.detail-panel-close-row {\n display: flex;\n justify-content: flex-end;\n /* Pull the next section up by exactly this row's height + the column\n * gap, so the close button sits ON the first content line (concept /\n * pipe header), right-aligned — not on its own line above it. */\n margin-bottom: -40px;\n}\n\n.detail-panel-close {\n all: unset;\n cursor: pointer;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n color: var(--text-dim);\n font-size: 18px;\n line-height: 1;\n /* Above the sticky pipe header (z 1) so the X is visible at rest while\n * sharing its line; on scroll it briefly slides over the stuck header's\n * empty right side before leaving the viewport. */\n z-index: 2;\n}\n\n.detail-panel-close:hover {\n color: var(--text-muted);\n background: var(--surface-elevated);\n}\n\n.detail-panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 12px 16px 20px;\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: -12px; /* must mirror .detail-panel-content's top padding */\n z-index: 1;\n background: var(--surface-panel);\n padding-top: 12px;\n margin-top: -12px;\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: var(--text-dim);\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: var(--color-pipe);\n color: var(--text-on-accent);\n}\n\n.detail-badge--controller {\n background: var(--color-batch-item);\n color: var(--text-on-accent);\n}\n\n.detail-pipe-code {\n font-family: var(--font-mono);\n font-size: 14px;\n font-weight: 600;\n color: var(--color-pipe);\n}\n\n.detail-pipe-code--controller {\n color: var(--color-batch-item);\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: var(--text-dim);\n font-family: var(--font-mono);\n}\n\n.detail-description {\n font-size: 12px;\n color: var(--text-muted);\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: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\n}\n\n.detail-io-name {\n font-family: var(--font-mono);\n color: var(--text-default);\n}\n\n.detail-io-concept {\n color: var(--text-dim);\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: var(--font-mono);\n font-size: 11px;\n color: var(--text-muted);\n background: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\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: var(--text-dim);\n padding: 2px 6px;\n border-radius: 3px;\n background: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\n transition: color 0.15s;\n}\n\n.detail-prompt-expand-btn:hover {\n color: var(--text-muted);\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: var(--text-dim);\n flex-shrink: 0; /* label stays at its natural width */\n}\n\n.detail-kv-value {\n font-family: var(--font-mono);\n color: var(--text-default);\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: var(--font-mono);\n font-size: 10px;\n color: var(--text-dim);\n}\n\n.detail-field-block-value {\n font-family: var(--font-mono);\n font-size: 11px;\n color: var(--text-default);\n background: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\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 var(--color-success);\n}\n\n.detail-nested-header-name {\n font-family: var(--font-mono);\n font-size: 11px;\n font-weight: 600;\n color: var(--text-default);\n}\n\n.detail-nested-header-meta {\n font-family: var(--font-mono);\n font-size: 9px;\n color: var(--text-dim);\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: var(--text-dim);\n font-size: 9px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n padding: 4px 6px;\n border-bottom: 1px solid var(--border-default);\n}\n\n.detail-schema-table td {\n padding: 4px 6px;\n border-bottom: 1px solid var(--border-subtle);\n color: var(--text-muted);\n}\n\n.detail-schema-field {\n font-family: var(--font-mono);\n color: var(--text-default);\n}\n\n.detail-schema-type {\n color: var(--color-accent);\n}\n\n.detail-schema-required {\n color: var(--color-pipe);\n font-size: 9px;\n}\n\n/* ─── Error section ─────────────────────────────────────────────────────── */\n\n.detail-error {\n background: var(--color-error-bg);\n border: 1px solid var(--color-error-border);\n border-radius: 6px;\n padding: 10px 12px;\n}\n\n.detail-error-type {\n font-size: 12px;\n font-weight: 600;\n color: var(--color-error);\n margin-bottom: 4px;\n}\n\n.detail-error-message {\n font-size: 11px;\n color: var(--text-muted);\n line-height: 1.5;\n}\n\n.detail-error-stack {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--text-dim);\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: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\n}\n\n.detail-step-index {\n color: var(--text-dim);\n font-size: 10px;\n font-weight: 700;\n min-width: 16px;\n}\n\n.detail-step-code {\n font-family: var(--font-mono);\n color: var(--text-default);\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: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\n}\n\n.detail-tag-key {\n color: var(--text-dim);\n}\n\n.detail-tag-value {\n color: var(--text-default);\n font-family: var(--font-mono);\n}\n\n/* ─── Detail tabs (Data / Structure) ────────────────────────────────────── */\n\n.detail-tabs {\n display: flex;\n gap: 2px;\n border-bottom: 1px solid var(--border-default);\n}\n\n.detail-tab {\n all: unset;\n cursor: pointer;\n font-size: 11px;\n font-weight: 600;\n color: var(--text-dim);\n padding: 5px 10px;\n border-radius: 4px 4px 0 0;\n border-bottom: 2px solid transparent;\n margin-bottom: -1px;\n transition:\n color 0.15s,\n border-color 0.15s;\n}\n\n.detail-tab:hover {\n color: var(--text-muted);\n}\n\n.detail-tab--active {\n color: var(--text-default);\n border-bottom-color: var(--color-accent);\n}\n\n/* `all: unset` strips the UA focus ring — restore a visible indicator for\n * keyboard users (WCAG 2.4.7) on every unset button in the panel. */\n.detail-tab:focus-visible,\n.detail-panel-close:focus-visible,\n.detail-prompt-expand-btn:focus-visible {\n outline: 2px solid var(--color-accent);\n outline-offset: 2px;\n}\n\n/* ─── Concept panel header ──────────────────────────────────────────────── */\n\n.detail-concept-code {\n font-family: var(--font-mono);\n font-size: 14px;\n font-weight: 600;\n color: var(--color-success);\n}\n\n.detail-concept-domain {\n font-size: 11px;\n color: var(--text-dim);\n}\n\n.detail-refines {\n font-size: 11px;\n color: var(--text-muted);\n}\n\n.detail-refines-code {\n font-family: var(--font-mono);\n color: var(--color-accent);\n}\n\n/* ─── Not available fallback ────────────────────────────────────────────── */\n\n.detail-not-available {\n font-size: 12px;\n color: var(--text-dim);\n font-style: italic;\n padding: 8px 0;\n}\n\n/* ─── Usage (inline cost + disclosure) ──────────────────────────────────── */\n\n/* Cost sits on the status line, formatted exactly like the duration beside it:\n they are two facts of the same kind about the same run. The button carries no\n chrome of its own — only the chevron marks it as expandable. */\n.detail-usage-inline {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0;\n background: none;\n border: none;\n cursor: pointer;\n font: inherit;\n color: inherit;\n}\n\n.detail-usage-value {\n font-size: 11px;\n color: var(--text-dim);\n font-family: var(--font-mono);\n font-variant-numeric: tabular-nums;\n}\n\n.detail-usage-inline:hover .detail-usage-value {\n color: var(--text-muted);\n}\n\n/* Quieter than the number it follows: it is an affordance, not information. */\n.detail-usage-chevron {\n color: var(--text-dim);\n opacity: 0.55;\n transition:\n transform 120ms ease,\n opacity 120ms ease;\n}\n\n.detail-usage-inline:hover .detail-usage-chevron {\n opacity: 0.9;\n}\n\n.detail-usage-chevron--open {\n transform: rotate(180deg);\n}\n\n.detail-usage-details {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* Model row: request on top, what it resolved to underneath. The secondary line\n is dimmer so the pair reads as one fact with its consequence, not two facts. */\n.detail-model-value {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 1px;\n}\n\n.detail-model-resolved {\n color: var(--text-dim);\n font-size: 10px;\n}\n","/* ─── Graph Toolbar — floating controls over the graph background ─────── */\n/* Token-only styling: theme switching happens by swapping `--surface-*`, */\n/* `--text-*`, `--border-*`, and `--color-accent` values on the container. */\n\n/* The ReactFlow <Panel> owns positioning now (anchor + margin). It sits above\n the graph but the old code used z-index 11, so keep parity. */\n.graph-toolbar-panel {\n z-index: 11;\n}\n\n.graph-toolbar {\n display: flex;\n align-items: center;\n gap: 4px;\n pointer-events: auto;\n}\n\n/* Vertical bar — `center-left` / `center-right` anchors. Stack the buttons in a\n column and rotate the separators so they divide rows instead of columns. */\n.graph-toolbar--vertical {\n flex-direction: column;\n}\n\n.graph-toolbar--vertical .graph-toolbar-separator {\n width: 18px;\n height: 1px;\n margin: 2px 0;\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: var(--surface-overlay);\n border: 1px solid var(--border-default);\n color: var(--text-secondary);\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: var(--surface-overlay-hover);\n color: var(--text-primary);\n border-color: var(--border-strong);\n}\n\n.graph-toolbar-btn:focus-visible {\n outline: 2px solid var(--focus-ring);\n outline-offset: 1px;\n}\n\n.graph-toolbar-btn--active {\n background: var(--color-accent);\n border-color: var(--color-accent);\n color: var(--text-on-accent);\n}\n\n.graph-toolbar-btn--active:hover {\n background: var(--color-accent);\n border-color: var(--color-accent);\n color: var(--text-on-accent);\n filter: brightness(1.1);\n}\n\n.graph-toolbar-btn:disabled,\n.graph-toolbar-btn:disabled:hover {\n opacity: 0.4;\n cursor: not-allowed;\n background: var(--surface-overlay-disabled);\n color: var(--text-dim);\n border-color: var(--border-subtle);\n}\n\n.graph-toolbar-separator {\n width: 1px;\n height: 18px;\n background: var(--border-default);\n margin: 0 2px;\n}\n\n/* ─── Validation widget ─────────────────────────────────────────────────── */\n/* Lives in GraphToolbar.css on purpose: the VS Code extension copies exactly\n this stylesheet into its webview, so a separate file would need host build\n changes for no benefit. */\n\n.graph-toolbar-validation {\n position: relative;\n display: inline-flex;\n}\n\n.graph-toolbar-validation-btn {\n position: relative;\n}\n\n.graph-toolbar-validation-btn--valid,\n.graph-toolbar-validation-btn--valid:hover {\n color: var(--color-success);\n}\n\n.graph-toolbar-validation-btn--invalid,\n.graph-toolbar-validation-btn--invalid:hover {\n color: var(--color-error);\n}\n\n.graph-toolbar-validation-btn--error,\n.graph-toolbar-validation-btn--error:hover {\n color: var(--color-warning);\n}\n\n.graph-toolbar-validation-spin {\n animation: graph-toolbar-validation-rotate 1s linear infinite;\n}\n\n@keyframes graph-toolbar-validation-rotate {\n to {\n transform: rotate(360deg);\n }\n}\n\n.graph-toolbar-validation-badge {\n position: absolute;\n top: -5px;\n right: -5px;\n min-width: 14px;\n height: 14px;\n padding: 0 3px;\n box-sizing: border-box;\n border-radius: 7px;\n background: var(--color-error);\n color: var(--text-on-accent);\n font-family: var(--font-sans);\n font-size: 9px;\n line-height: 14px;\n font-weight: 600;\n text-align: center;\n pointer-events: none;\n}\n\n.graph-toolbar-validation-btn--valid .graph-toolbar-validation-badge,\n.graph-toolbar-validation-btn--error .graph-toolbar-validation-badge {\n background: var(--color-warning);\n}\n\n/* ─── Validation dropdown panel ─────────────────────────────────────────── */\n\n.graph-validation-panel {\n position: absolute;\n z-index: 12;\n /* Viewport clamp: narrow webviews (VS Code panels) can be under 260px wide. */\n min-width: min(260px, calc(100vw - 24px));\n max-width: min(360px, calc(100vw - 24px));\n max-height: 320px;\n overflow-y: auto;\n padding: 6px;\n border-radius: 8px;\n background: var(--surface-overlay);\n border: 1px solid var(--border-default);\n box-shadow: var(--shadow-md);\n backdrop-filter: blur(6px);\n pointer-events: auto;\n font-family: var(--font-sans);\n cursor: default;\n}\n\n/* Placement relative to the widget button — always unfolds toward the graph. */\n.graph-validation-panel--down-start {\n top: calc(100% + 6px);\n left: 0;\n}\n.graph-validation-panel--down-end {\n top: calc(100% + 6px);\n right: 0;\n}\n.graph-validation-panel--up-start {\n bottom: calc(100% + 6px);\n left: 0;\n}\n.graph-validation-panel--up-end {\n bottom: calc(100% + 6px);\n right: 0;\n}\n.graph-validation-panel--side-end {\n left: calc(100% + 6px);\n top: 0;\n}\n.graph-validation-panel--side-start {\n right: calc(100% + 6px);\n top: 0;\n}\n\n.graph-validation-panel-header {\n padding: 4px 6px 6px;\n font-size: 11px;\n font-weight: 600;\n color: var(--text-secondary);\n}\n\n.graph-validation-empty {\n padding: 2px 6px 6px;\n font-size: 12px;\n color: var(--text-secondary);\n}\n\n.graph-validation-issues {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.graph-validation-issue {\n padding: 6px 8px;\n border-radius: 6px;\n border-left: 3px solid var(--color-error);\n background: var(--color-error-bg);\n font-size: 12px;\n color: var(--text-primary);\n}\n\n/* The focusable/clickable element inside each <li> (keeps listitem semantics). */\n.graph-validation-issue-body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.graph-validation-issue--warning {\n border-left-color: var(--color-warning);\n background: var(--surface-sunken);\n}\n\n.graph-validation-issue--clickable {\n cursor: pointer;\n}\n\n.graph-validation-issue--clickable:hover {\n filter: brightness(1.1);\n}\n\n.graph-validation-issue-body:focus-visible {\n outline: 2px solid var(--focus-ring);\n outline-offset: 1px;\n border-radius: 4px;\n}\n\n.graph-validation-issue-meta {\n display: flex;\n align-items: baseline;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.graph-validation-issue-context {\n font-family: var(--font-mono);\n font-size: 11px;\n font-weight: 600;\n color: var(--text-secondary);\n}\n\n.graph-validation-issue-file {\n font-size: 10px;\n color: var(--text-dim);\n}\n\n.graph-validation-issue-message {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.graph-validation-issue-fix {\n font-size: 11px;\n color: var(--text-secondary);\n}\n\n.graph-validation-issue-fix::before {\n content: \"Fix: \";\n font-weight: 600;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/graph/react/detail/DetailPanel.css","../../../src/graph/react/viewer/GraphToolbar.css"],"sourcesContent":["/* ─── Detail Panel — sliding side panel for node inspection ─────────────── */\n/* Token-only — all colors come from the active theme palette on the */\n/* container. See `graphConfig.ts` for token definitions. */\n\n.detail-panel {\n position: absolute;\n top: 0;\n right: 0;\n width: 380px;\n height: 100%;\n background: var(--surface-panel);\n border-left: 1px solid var(--border-default);\n z-index: 10;\n display: flex;\n flex-direction: column;\n font-family: var(--font-sans);\n color: var(--text-default);\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: var(--color-accent);\n opacity: 0.6;\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: var(--color-accent);\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/* ─── Close row — scrolls away with the content (intentionally NOT pinned) ─ */\n/* The close button is part of the content's top, not panel chrome: it\n * scrolls out of view with the content, and closing the panel means\n * scrolling back up. The negative margin tucks the following section up\n * beside it so the row doesn't cost a full line of vertical space. */\n\n.detail-panel-close-row {\n display: flex;\n justify-content: flex-end;\n /* Pull the next section up by exactly this row's height + the column\n * gap, so the close button sits ON the first content line (concept /\n * pipe header), right-aligned — not on its own line above it. */\n margin-bottom: -40px;\n}\n\n.detail-panel-close {\n all: unset;\n cursor: pointer;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n color: var(--text-dim);\n font-size: 18px;\n line-height: 1;\n /* Above the sticky pipe header (z 1) so the X is visible at rest while\n * sharing its line; on scroll it briefly slides over the stuck header's\n * empty right side before leaving the viewport. */\n z-index: 2;\n}\n\n.detail-panel-close:hover {\n color: var(--text-muted);\n background: var(--surface-elevated);\n}\n\n.detail-panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 12px 16px 20px;\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: -12px; /* must mirror .detail-panel-content's top padding */\n z-index: 1;\n background: var(--surface-panel);\n padding-top: 12px;\n margin-top: -12px;\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: var(--text-dim);\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: var(--color-pipe);\n color: var(--text-on-accent);\n}\n\n.detail-badge--controller {\n background: var(--color-batch-item);\n color: var(--text-on-accent);\n}\n\n.detail-pipe-code {\n font-family: var(--font-mono);\n font-size: 14px;\n font-weight: 600;\n color: var(--color-pipe);\n}\n\n.detail-pipe-code--controller {\n color: var(--color-batch-item);\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: var(--text-dim);\n font-family: var(--font-mono);\n}\n\n.detail-description {\n font-size: 12px;\n color: var(--text-muted);\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: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\n}\n\n.detail-io-name {\n font-family: var(--font-mono);\n color: var(--text-default);\n}\n\n.detail-io-concept {\n color: var(--text-dim);\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: var(--font-mono);\n font-size: 11px;\n color: var(--text-muted);\n background: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\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: var(--text-dim);\n padding: 2px 6px;\n border-radius: 3px;\n background: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\n transition: color 0.15s;\n}\n\n.detail-prompt-expand-btn:hover {\n color: var(--text-muted);\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: var(--text-dim);\n flex-shrink: 0; /* label stays at its natural width */\n}\n\n.detail-kv-value {\n font-family: var(--font-mono);\n color: var(--text-default);\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: var(--font-mono);\n font-size: 10px;\n color: var(--text-dim);\n}\n\n.detail-field-block-value {\n font-family: var(--font-mono);\n font-size: 11px;\n color: var(--text-default);\n background: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\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 var(--color-success);\n}\n\n.detail-nested-header-name {\n font-family: var(--font-mono);\n font-size: 11px;\n font-weight: 600;\n color: var(--text-default);\n}\n\n.detail-nested-header-meta {\n font-family: var(--font-mono);\n font-size: 9px;\n color: var(--text-dim);\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: var(--text-dim);\n font-size: 9px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n padding: 4px 6px;\n border-bottom: 1px solid var(--border-default);\n}\n\n.detail-schema-table td {\n padding: 4px 6px;\n border-bottom: 1px solid var(--border-subtle);\n color: var(--text-muted);\n}\n\n.detail-schema-field {\n font-family: var(--font-mono);\n color: var(--text-default);\n}\n\n.detail-schema-type {\n color: var(--color-accent);\n}\n\n.detail-schema-required {\n color: var(--color-pipe);\n font-size: 9px;\n}\n\n/* ─── Error section ─────────────────────────────────────────────────────── */\n\n.detail-error {\n background: var(--color-error-bg);\n border: 1px solid var(--color-error-border);\n border-radius: 6px;\n padding: 10px 12px;\n}\n\n.detail-error-type {\n font-size: 12px;\n font-weight: 600;\n color: var(--color-error);\n margin-bottom: 4px;\n}\n\n.detail-error-message {\n font-size: 11px;\n color: var(--text-muted);\n line-height: 1.5;\n}\n\n.detail-error-stack {\n font-family: var(--font-mono);\n font-size: 10px;\n color: var(--text-dim);\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: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\n}\n\n.detail-step-index {\n color: var(--text-dim);\n font-size: 10px;\n font-weight: 700;\n min-width: 16px;\n}\n\n.detail-step-code {\n font-family: var(--font-mono);\n color: var(--text-default);\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: var(--surface-sunken);\n border: 1px solid var(--border-subtle);\n}\n\n.detail-tag-key {\n color: var(--text-dim);\n}\n\n.detail-tag-value {\n color: var(--text-default);\n font-family: var(--font-mono);\n}\n\n/* ─── Detail tabs (Data / Structure) ────────────────────────────────────── */\n\n.detail-tabs {\n display: flex;\n gap: 2px;\n border-bottom: 1px solid var(--border-default);\n}\n\n.detail-tab {\n all: unset;\n cursor: pointer;\n font-size: 11px;\n font-weight: 600;\n color: var(--text-dim);\n padding: 5px 10px;\n border-radius: 4px 4px 0 0;\n border-bottom: 2px solid transparent;\n margin-bottom: -1px;\n transition:\n color 0.15s,\n border-color 0.15s;\n}\n\n.detail-tab:hover {\n color: var(--text-muted);\n}\n\n.detail-tab--active {\n color: var(--text-default);\n border-bottom-color: var(--color-accent);\n}\n\n/* `all: unset` strips the UA focus ring — restore a visible indicator for\n * keyboard users (WCAG 2.4.7) on every unset button in the panel. */\n.detail-tab:focus-visible,\n.detail-panel-close:focus-visible,\n.detail-prompt-expand-btn:focus-visible {\n outline: 2px solid var(--color-accent);\n outline-offset: 2px;\n}\n\n/* ─── Concept panel header ──────────────────────────────────────────────── */\n\n.detail-concept-code {\n font-family: var(--font-mono);\n font-size: 14px;\n font-weight: 600;\n color: var(--color-success);\n}\n\n.detail-concept-domain {\n font-size: 11px;\n color: var(--text-dim);\n}\n\n.detail-refines {\n font-size: 11px;\n color: var(--text-muted);\n}\n\n.detail-refines-code {\n font-family: var(--font-mono);\n color: var(--color-accent);\n}\n\n/* ─── Not available fallback ────────────────────────────────────────────── */\n\n.detail-not-available {\n font-size: 12px;\n color: var(--text-dim);\n font-style: italic;\n padding: 8px 0;\n}\n\n/* ─── Usage (inline cost + disclosure) ──────────────────────────────────── */\n\n/* Cost sits on the status line, formatted exactly like the duration beside it:\n they are two facts of the same kind about the same run. The button carries no\n chrome of its own — only the chevron marks it as expandable. */\n.detail-usage-inline {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 0;\n background: none;\n border: none;\n cursor: pointer;\n font: inherit;\n color: inherit;\n}\n\n.detail-usage-value {\n font-size: 11px;\n color: var(--text-dim);\n font-family: var(--font-mono);\n font-variant-numeric: tabular-nums;\n}\n\n.detail-usage-inline:hover .detail-usage-value {\n color: var(--text-muted);\n}\n\n/* Quieter than the number it follows: it is an affordance, not information. */\n.detail-usage-chevron {\n color: var(--text-dim);\n opacity: 0.55;\n transition:\n transform 120ms ease,\n opacity 120ms ease;\n}\n\n.detail-usage-inline:hover .detail-usage-chevron {\n opacity: 0.9;\n}\n\n.detail-usage-chevron--open {\n transform: rotate(180deg);\n}\n\n.detail-usage-details {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* Model row: request on top, what it resolved to underneath. The secondary line\n is dimmer so the pair reads as one fact with its consequence, not two facts. */\n.detail-model-value {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 1px;\n}\n\n.detail-model-resolved {\n color: var(--text-dim);\n font-size: 10px;\n}\n","/* ─── Graph Toolbar — floating controls over the graph background ─────── */\n/* Token-only styling: theme switching happens by swapping `--surface-*`, */\n/* `--text-*`, `--border-*`, and `--color-accent` values on the container. */\n\n/* The ReactFlow <Panel> owns positioning now (anchor + margin). It sits above\n the graph but the old code used z-index 11, so keep parity. */\n.graph-toolbar-panel {\n z-index: 11;\n}\n\n.graph-toolbar {\n display: flex;\n align-items: center;\n gap: 4px;\n pointer-events: auto;\n}\n\n/* Vertical bar — `center-left` / `center-right` anchors. Stack the buttons in a\n column and rotate the separators so they divide rows instead of columns. */\n.graph-toolbar--vertical {\n flex-direction: column;\n}\n\n.graph-toolbar--vertical .graph-toolbar-separator {\n width: 18px;\n height: 1px;\n margin: 2px 0;\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: var(--surface-overlay);\n border: 1px solid var(--border-default);\n color: var(--text-secondary);\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: var(--surface-overlay-hover);\n color: var(--text-primary);\n border-color: var(--border-strong);\n}\n\n.graph-toolbar-btn:focus-visible {\n outline: 2px solid var(--focus-ring);\n outline-offset: 1px;\n}\n\n.graph-toolbar-btn--active {\n background: var(--color-accent);\n border-color: var(--color-accent);\n color: var(--text-on-accent);\n}\n\n.graph-toolbar-btn--active:hover {\n background: var(--color-accent);\n border-color: var(--color-accent);\n color: var(--text-on-accent);\n filter: brightness(1.1);\n}\n\n.graph-toolbar-btn:disabled,\n.graph-toolbar-btn:disabled:hover {\n opacity: 0.4;\n cursor: not-allowed;\n background: var(--surface-overlay-disabled);\n color: var(--text-dim);\n border-color: var(--border-subtle);\n}\n\n.graph-toolbar-separator {\n width: 1px;\n height: 18px;\n background: var(--border-default);\n margin: 0 2px;\n}\n\n/* ─── Validation widget ─────────────────────────────────────────────────── */\n/* Lives in GraphToolbar.css on purpose: the VS Code extension copies exactly\n this stylesheet into its webview, so a separate file would need host build\n changes for no benefit. */\n\n.graph-toolbar-validation {\n position: relative;\n display: inline-flex;\n}\n\n.graph-toolbar-validation-btn {\n position: relative;\n}\n\n.graph-toolbar-validation-btn--valid,\n.graph-toolbar-validation-btn--valid:hover {\n color: var(--color-success);\n}\n\n.graph-toolbar-validation-btn--invalid,\n.graph-toolbar-validation-btn--invalid:hover {\n color: var(--color-error);\n}\n\n.graph-toolbar-validation-btn--error,\n.graph-toolbar-validation-btn--error:hover {\n color: var(--color-warning);\n}\n\n.graph-toolbar-validation-spin {\n animation: graph-toolbar-validation-rotate 1s linear infinite;\n}\n\n@keyframes graph-toolbar-validation-rotate {\n to {\n transform: rotate(360deg);\n }\n}\n\n.graph-toolbar-validation-badge {\n position: absolute;\n top: -5px;\n right: -5px;\n min-width: 14px;\n height: 14px;\n padding: 0 3px;\n box-sizing: border-box;\n border-radius: 7px;\n background: var(--color-error);\n color: var(--text-on-accent);\n font-family: var(--font-sans);\n font-size: 9px;\n line-height: 14px;\n font-weight: 600;\n text-align: center;\n pointer-events: none;\n}\n\n.graph-toolbar-validation-btn--valid .graph-toolbar-validation-badge,\n.graph-toolbar-validation-btn--error .graph-toolbar-validation-badge {\n background: var(--color-warning);\n}\n\n/* ─── Validation dropdown panel ─────────────────────────────────────────── */\n\n.graph-validation-panel {\n position: absolute;\n z-index: 12;\n /* Viewport clamp: narrow webviews (VS Code panels) can be under 260px wide. */\n min-width: min(260px, calc(100vw - 24px));\n max-width: min(360px, calc(100vw - 24px));\n max-height: 320px;\n overflow-y: auto;\n padding: 6px;\n border-radius: 8px;\n background: var(--surface-overlay);\n border: 1px solid var(--border-default);\n box-shadow: var(--shadow-md);\n backdrop-filter: blur(6px);\n pointer-events: auto;\n font-family: var(--font-sans);\n cursor: default;\n}\n\n/* Placement relative to the widget button — always unfolds toward the graph. */\n.graph-validation-panel--down-start {\n top: calc(100% + 6px);\n left: 0;\n}\n.graph-validation-panel--down-end {\n top: calc(100% + 6px);\n right: 0;\n}\n.graph-validation-panel--up-start {\n bottom: calc(100% + 6px);\n left: 0;\n}\n.graph-validation-panel--up-end {\n bottom: calc(100% + 6px);\n right: 0;\n}\n.graph-validation-panel--side-end {\n left: calc(100% + 6px);\n top: 0;\n}\n.graph-validation-panel--side-start {\n right: calc(100% + 6px);\n top: 0;\n}\n\n.graph-validation-panel-header {\n padding: 4px 6px 6px;\n font-size: 11px;\n font-weight: 600;\n color: var(--text-secondary);\n}\n\n.graph-validation-empty {\n padding: 2px 6px 6px;\n font-size: 12px;\n color: var(--text-secondary);\n}\n\n.graph-validation-issues {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.graph-validation-issue {\n padding: 6px 8px;\n border-radius: 6px;\n border-left: 3px solid var(--color-error);\n background: var(--color-error-bg);\n font-size: 12px;\n color: var(--text-primary);\n}\n\n/* The focusable/clickable element inside each <li> (keeps listitem semantics). */\n.graph-validation-issue-body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.graph-validation-issue--warning {\n border-left-color: var(--color-warning);\n background: var(--surface-sunken);\n}\n\n.graph-validation-issue--clickable {\n cursor: pointer;\n}\n\n.graph-validation-issue--clickable:hover {\n filter: brightness(1.1);\n}\n\n.graph-validation-issue-body:focus-visible {\n outline: 2px solid var(--focus-ring);\n outline-offset: 1px;\n border-radius: 4px;\n}\n\n.graph-validation-issue-meta {\n display: flex;\n align-items: baseline;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.graph-validation-issue-context {\n font-family: var(--font-mono);\n font-size: 11px;\n font-weight: 600;\n color: var(--text-secondary);\n}\n\n.graph-validation-issue-file {\n font-size: 10px;\n color: var(--text-dim);\n}\n\n.graph-validation-issue-message {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.graph-validation-issue-fix {\n font-size: 11px;\n color: var(--text-secondary);\n}\n\n.graph-validation-issue-fix::before {\n content: \"Fix: \";\n font-weight: 600;\n}\n"],"mappings":"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","names":[]}
@@ -1,38 +1,11 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
- import { c as GraphNodeData, d as GraphEdge, e as GraphNode, b as GraphSpec, f as GraphConfig, g as GraphDirection, F as FoldMode, h as GraphThemeMode, T as ToolbarPosition, G as GraphTheme, i as PipeStatus, j as ValidationState, V as ValidationIssue, L as LabelDescriptor, k as PipeControllerType, l as FoldToggleOptions, N as NodeValidationSummary, m as PipeType, n as GraphSpecMode, o as GraphSpecNode, C as ConceptInfo, p as GraphSpecNodeIoItem } from '../../types-Cv5Elty8.js';
4
- export { q as PipeOperatorType } from '../../types-Cv5Elty8.js';
3
+ import { c as GraphNodeData, d as GraphEdge, e as GraphNode, b as GraphSpec, f as GraphConfig, g as GraphDirection, F as FoldMode, h as GraphThemeMode, T as ToolbarPosition, G as GraphTheme, i as PipeStatus, j as GraphSpecNodeIoItem, k as ValidationState, V as ValidationIssue, L as LabelDescriptor, l as PipeControllerType, m as FoldToggleOptions, N as NodeValidationSummary, n as PipeType, o as GraphSpecMode, C as ConceptInfo, p as GraphSpecNode } from '../../types-Cn2FttBC.js';
4
+ export { q as PipeOperatorType } from '../../types-Cn2FttBC.js';
5
+ import { PipeIOContracts, OutputForm, InputForm } from '@pipelex/mthds-form';
6
+ import { ResolveUrl, ResolveShareUrl } from '@pipelex/mthds-form/react';
5
7
  import { Edge, Node, ReactFlowInstance } from '@xyflow/react';
6
8
 
7
- /** Data for rendering a stuff (data item) in the StuffViewer component. */
8
- interface StuffViewerData {
9
- digest: string;
10
- name?: string;
11
- concept?: string;
12
- contentType?: string;
13
- data?: unknown;
14
- dataText?: string;
15
- dataHtml?: string;
16
- }
17
- /**
18
- * Resolver for `pipelex-storage://` URIs.
19
- *
20
- * Internal pipelex-storage URIs are not directly fetchable by a browser. Callers
21
- * pass this function to components that may render such URIs (StuffViewer etc.)
22
- * to exchange them for short-lived, browser-fetchable URLs (e.g. presigned S3).
23
- *
24
- * The resolved URL has a limited lifetime. Components displaying media for
25
- * extended periods should re-invoke the resolver before expiry.
26
- *
27
- * **Stability requirement:** keep the reference stable across renders (wrap in
28
- * `useCallback` or define outside the component). StuffViewer uses this as a
29
- * `useEffect` dependency — a fresh arrow on every render re-triggers the
30
- * presigned-URL fetch on every parent re-render.
31
- *
32
- * Returns null if the URI cannot be resolved (auth failure, ownership mismatch, etc.).
33
- */
34
- type ResolveStorageUrl = (uri: string) => Promise<string | null>;
35
-
36
9
  /** ReactFlow node parameterized with our domain data. */
37
10
  type AppNode = Node<GraphNodeData>;
38
11
  /** ReactFlow edge with standard fields (domain-only fields are dropped at the boundary). */
@@ -119,7 +92,7 @@ interface GraphViewerProps {
119
92
  */
120
93
  onThemeChange?: (mode: GraphThemeMode, resolvedTheme: GraphTheme) => void;
121
94
  onNavigateToPipe?: (pipeCode: string, status?: PipeStatus) => void;
122
- onStuffNodeClick?: (stuffData: StuffViewerData) => void;
95
+ onStuffNodeClick?: (stuff: GraphSpecNodeIoItem) => void;
123
96
  onReactFlowInit?: (instance: AppRFInstance) => void;
124
97
  /** Layer 2 execution state: pipe_code → current status. Updates node status dots in real-time. */
125
98
  statusMap?: Record<string, PipeStatus>;
@@ -130,24 +103,56 @@ interface GraphViewerProps {
130
103
  /** Render extra content below the built-in detail panel content for the selected node. */
131
104
  renderDetailExtra?: (nodeId: string, nodeData: GraphNodeData) => React.ReactNode;
132
105
  /**
133
- * Resolver for `pipelex-storage://` URIs. Passed down to StuffViewer so it can
134
- * exchange internal URIs for browser-fetchable presigned URLs when rendering media.
106
+ * `pipe_io_contracts` for the method this spec is a run of — one half of what
107
+ * the detail panel needs to render a data node's VALUE.
108
+ *
109
+ * The graph renders results itself now. It used to take a render prop instead,
110
+ * because the form kernel was an optional peer and `./graph/react` had to keep
111
+ * resolving without it — an arrangement that made sense while the kernel only
112
+ * powered an optional run form, and stopped making sense the moment the
113
+ * standard's `output_form` became how this viewer shows a result at all. A
114
+ * viewer whose detail panel cannot show data is not a viewer, so the kernel is
115
+ * a required peer and the seam is gone.
116
+ *
117
+ * Omit these and the panel still works: it shows the concept's structure table
118
+ * and no data tab, which is the honest floor for a spec whose artifacts the
119
+ * host does not hold (a static graph, a spec restored without its validate
120
+ * report).
121
+ */
122
+ contracts?: PipeIOContracts;
123
+ /**
124
+ * `output_form` from the SAME `/validate` call — the other half. The contract
125
+ * names the payload's shape; the descriptor says what the result IS.
135
126
  */
136
- resolveStorageUrl?: ResolveStorageUrl;
127
+ outputForm?: OutputForm;
137
128
  /**
138
- * Set to `false` when the host cannot render `<embed type="application/pdf">`
139
- * — e.g. VS Code webviews, which run inside Electron without the Chromium
140
- * PDFium plugin. Forwarded to StuffViewer.
129
+ * `input_form`, optional even here. It is what lets a method's own INPUTS show
130
+ * their value: no pipe produced them, so no output descriptor describes them,
131
+ * and the CONSUMING pipe's descriptor for their slot is what names them.
132
+ */
133
+ inputForm?: InputForm;
134
+ /**
135
+ * Turns the runtime's own `pipelex-storage://…` reference into a URL a
136
+ * browser can fetch, so files in a result actually paint.
141
137
  *
142
- * Default: `true`.
138
+ * Without it the panel falls back to whatever `public_url` the payload
139
+ * carries — which on the hosted platform is a PRESIGNED URL with an hour's
140
+ * life, baked into the stored result. Yesterday's run then shows broken
141
+ * images, and the URL answers `403` in a way that reads as a permissions
142
+ * problem rather than an expiry. A resolver is what makes a stored result
143
+ * durable, so supply one if your storage has an authenticated read path.
143
144
  */
144
- canEmbedPdf?: boolean;
145
+ resolveUrl?: ResolveUrl;
145
146
  /**
146
- * Replaces the default `window.open(url, "_blank")` behavior used by the
147
- * StuffViewer toolbar and the PDF fallback tile. Wire this to your host's
148
- * external-open mechanism (e.g. `vscode.env.openExternal` via postMessage).
147
+ * Mints a URL that works OUTSIDE this page, for the copy control.
148
+ *
149
+ * Distinct from `resolveUrl` because the two answers genuinely differ: a
150
+ * display URL may be a path behind the host's own session — which is what
151
+ * lets a strict `img-src 'self'` stand — and that URL is useless to whoever
152
+ * pastes it. A shared one carries its own credential and is minted per click,
153
+ * since it starts expiring the moment it exists.
149
154
  */
150
- onOpenExternally?: (url: string, filename?: string) => void;
155
+ resolveShareUrl?: ResolveShareUrl;
151
156
  /**
152
157
  * State of the toolbar's validation widget. The widget renders only when this
153
158
  * is set — `undefined` (the default) disables the feature entirely. Reactive:
@@ -287,82 +292,118 @@ interface PipeCardBaseProps {
287
292
  }
288
293
  declare function PipeCardBase({ data, children }: PipeCardBaseProps): react_jsx_runtime.JSX.Element;
289
294
 
290
- interface StuffViewerProps {
291
- stuff: StuffViewerData;
292
- className?: string;
295
+ /**
296
+ * The graph's stuff panel — the replacement for `StuffViewer`.
297
+ *
298
+ * ## What changed, and why it is not a reskin
299
+ *
300
+ * `StuffViewer` had three tabs — HTML, JSON, Pretty — and that was an admission:
301
+ * a `GraphSpec` states a concept and a payload, and nothing about what the
302
+ * payload IS, so the only honest thing it could do was hand the reader three
303
+ * renderings and let them pick. It sniffed for URLs, guessed MIME types from
304
+ * file extensions, and ran any `data_html` through DOMPurify because the markup
305
+ * was model output going into the host's own document.
306
+ *
307
+ * None of that guessing is necessary, because the standard answers the question
308
+ * in an artifact built for it. `output_form` gives a pipe's result ONE
309
+ * descriptor node — kind, concept identity, refinement chain, nested fields in
310
+ * authored order — and the output half of `pipe_io_contracts` gives the
311
+ * payload's JSON Schema beside it, naming the property the content model wraps
312
+ * the value under. `buildResultField` pairs them into a `RunField`, and
313
+ * `StuffViewer` lays that out without ever inspecting the value: a table for a
314
+ * list of records, a gallery for images, a sandboxed frame for markup, a
315
+ * two-column grid for a structure. The JSON view survives as one of the panel's
316
+ * two, because a receipt is worth having; "Pretty" and "HTML" do not, because
317
+ * they were two guesses at a question now answered.
318
+ *
319
+ * ## What it needs from the host, and why
320
+ *
321
+ * The artifacts every `/validate` call returns beside the graph spec, keyed by
322
+ * `pipe_ref`. The join is the producing pipe: the graph hands over
323
+ * `producerPipeRef` (see `stuffLookup.ts`), and `output_form` plus the output
324
+ * half of the contract are looked up by it.
325
+ *
326
+ * ## The method's own inputs, which no pipe produced
327
+ *
328
+ * They have no `producerPipeRef`, so no output descriptor describes them — and
329
+ * showing nothing for the top of every graph is not acceptable, because a
330
+ * method's arguments are as much a part of what happened as its results. What
331
+ * DOES describe them is the CONSUMING pipe's `input_form` entry for the slot
332
+ * they arrive in: the same field, seen from the other side. So `inputForm` is
333
+ * an optional third artifact, and when it is supplied the panel falls back to
334
+ * it.
335
+ *
336
+ * **Only on the `single` arm, and that is a correctness boundary rather than a
337
+ * conservative default.** An input's `json_schema` describes what a CALLER
338
+ * SENDS, so a plural slot's is a bare array; a stuff's payload is what the
339
+ * runtime HOLDS, which for a plural value is a `ListContent {items}` envelope.
340
+ * The two disagree exactly where the standard says they do, and rendering a
341
+ * plural input against its caller-side schema would unwrap by a property that
342
+ * is not there. On the single arm the two are byte-identical by construction —
343
+ * both are `render_stuff_spec`'s output — so the fallback is exact there and
344
+ * declines everywhere else.
345
+ *
346
+ * ## What it deliberately does not do
347
+ *
348
+ * It does not resolve `pipelex-storage://` URIs. `StuffViewer` took a
349
+ * `resolveStorageUrl` and exchanged them for presigned URLs before painting
350
+ * media; the kernel has no such seam yet, so a result carrying a storage
351
+ * reference shows the file named rather than rendered. That is a real gap, not
352
+ * an oversight — porting it belongs in the kernel's file arms, where every
353
+ * consumer gets it, rather than being re-implemented here for one host.
354
+ */
355
+ interface StuffResultRendererOptions {
356
+ /** `pipe_io_contracts` for the method being displayed. */
357
+ contracts: PipeIOContracts;
358
+ /** `output_form` for the same method — the SAME `/validate` call. */
359
+ outputForm: OutputForm;
360
+ /**
361
+ * `input_form`, optional. Supplying it is what lets a method's own INPUTS
362
+ * render as described fields rather than as nothing: they have no producing
363
+ * pipe, so the consuming pipe's descriptor for their slot is what names them.
364
+ */
365
+ inputForm?: InputForm;
366
+ }
367
+ interface StuffResultPanelProps extends StuffResultRendererOptions {
368
+ /** The data item as the spec holds it. */
369
+ stuff: GraphSpecNodeIoItem;
370
+ /** Its concept, resolved against the spec's concept table, when it has one. */
371
+ concept?: ConceptInfo;
372
+ /**
373
+ * `domain.code` of the pipe that PRODUCED it — the key both output artifacts
374
+ * are keyed by. Absent for a method's own inputs, which no pipe produced.
375
+ */
376
+ producerPipeRef?: string;
293
377
  /**
294
- * Resolver for `pipelex-storage://` URIs. If provided and the stuff data
295
- * references an internal URI, the viewer will call this to obtain a
296
- * presigned URL for inline rendering. Without a resolver, media with only
297
- * internal URIs falls back to the "no preview" placeholder.
378
+ * The first pipe that CONSUMES it, and the slot it arrives in — the fallback
379
+ * identity for those method inputs.
298
380
  */
299
- resolveStorageUrl?: ResolveStorageUrl;
381
+ consumer?: {
382
+ pipeRef: string;
383
+ slotName: string;
384
+ };
385
+ /** The viewer's resolved theme, so the panel matches the chrome it sits in. */
386
+ theme?: GraphTheme;
300
387
  /**
301
- * Set to `false` when the host cannot render `<embed type="application/pdf">`
302
- * — e.g. VS Code webviews, which run inside Electron without the Chromium
303
- * PDFium plugin. The PDF view then falls back to a clickable tile that
304
- * triggers `onOpenExternally` (or `window.open` if not provided).
388
+ * Turns the runtime's own `pipelex-storage://…` reference into something a
389
+ * browser can fetch.
305
390
  *
306
- * Default: `true`.
391
+ * Supply it and the panel paints files through it; omit it and the panel
392
+ * falls back to whatever `public_url` the payload carries. On the hosted
393
+ * platform that fallback is a PRESIGNED S3 URL with an hour's life, baked
394
+ * into the stored result — so a run opened the next morning shows broken
395
+ * images, and the URL answers `403` in a way that reads as a permissions
396
+ * problem rather than an expiry. A resolver is what makes a result durable.
307
397
  */
308
- canEmbedPdf?: boolean;
398
+ resolveUrl?: ResolveUrl;
309
399
  /**
310
- * Replaces the default `window.open(url, "_blank")` behavior for both the
311
- * toolbar "open externally" button and the PDF fallback tile. Use this in
312
- * environments where `window.open` is blocked or undesirable — for example,
313
- * VS Code webviews should wire this to `vscode.env.openExternal` via
314
- * postMessage.
400
+ * Mints a URL that works OUTSIDE this page — what the copy control hands over.
401
+ * A display URL may sit behind the host's session; a shared one carries its
402
+ * own credential.
315
403
  */
316
- onOpenExternally?: (url: string, filename?: string) => void;
404
+ resolveShareUrl?: ResolveShareUrl;
317
405
  }
318
- declare function StuffViewer({ stuff, className, resolveStorageUrl, canEmbedPdf, onOpenExternally, }: StuffViewerProps): react_jsx_runtime.JSX.Element;
319
-
320
- /** Check whether a URL is safe for links/downloads (no javascript: or data: injection). */
321
- declare function isSafeDisplayUrl(url: unknown): url is string;
322
- /** Check whether a URL can be rendered inline in an <img> or <embed> tag.
323
- * Allows http://, https://, file:// (local dev / Electron), and relative paths. */
324
- declare function isInlineRenderableUrl(url: unknown): url is string;
325
- /**
326
- * Extract a displayable URL from stuff data (for links, downloads, open-external).
327
- * Prefers public_url (pre-signed S3 / file:// URI) over internal pipelex-storage:// URLs.
328
- * Returns null for unsafe or missing URLs.
329
- */
330
- declare function extractUrl(data: unknown): string | null;
331
- /**
332
- * Extract a URL that can be rendered inline in <img>/<embed> tags.
333
- * Returns http/https, file://, and relative URLs.
334
- * Internal schemes like pipelex-storage:// are excluded.
335
- */
336
- declare function extractInlineUrl(data: unknown): string | null;
337
- /**
338
- * Extract a `pipelex-storage://` URI from stuff data, if present.
339
- *
340
- * Pipelex-storage URIs are internal logical pointers that need to be resolved
341
- * to a browser-fetchable URL (e.g. presigned S3) before rendering inline.
342
- */
343
- declare function extractStorageUri(data: unknown): string | null;
344
- /** Extract the filename from stuff data, if available. */
345
- declare function extractFilename(data: unknown): string | null;
346
- /**
347
- * Determine the effective MIME type of a stuff item for preview rendering.
348
- *
349
- * Checks (in order):
350
- * 1. Stuff-level `contentType` (when it's already a MIME type like "application/pdf")
351
- * 2. The `mime_type` field on the data object (Document content carries this)
352
- * 3. The file extension from `filename` or from the URL/URI
353
- *
354
- * The concept-level `contentType` (e.g. "document") is not a MIME type; we
355
- * ignore it and look at the data instead. Returns null when nothing recognizable
356
- * is found.
357
- */
358
- declare function resolveMimeType(data: unknown, contentType: string | undefined, url: string | null): string | null;
359
- /** Get the appropriate first-tab label based on content MIME type. */
360
- declare function getHtmlTabLabel(contentType?: string | null): string;
361
- /**
362
- * Find stuff data by digest in a GraphSpec.
363
- * Scans all nodes' IO items — outputs first (producer data), then inputs as fallback.
364
- */
365
- declare function findStuffDataByDigest(graphspec: GraphSpec, digest: string): StuffViewerData | null;
406
+ declare function StuffResultPanel({ contracts, outputForm, inputForm, stuff, producerPipeRef, consumer, resolveUrl, resolveShareUrl, }: StuffResultPanelProps): react_jsx_runtime.JSX.Element | null;
366
407
 
367
408
  interface DetailPanelProps {
368
409
  isOpen: boolean;
@@ -388,16 +429,21 @@ declare function PipeDetailPanel({ node, spec, onConceptClick }: PipeDetailPanel
388
429
 
389
430
  interface ConceptDetailPanelProps {
390
431
  concept: ConceptInfo;
391
- /** IO data for this concept instance. Accepts GraphSpecNodeIoItem or StuffViewerData. */
392
- ioData?: GraphSpecNodeIoItem | StuffViewerData;
432
+ /** The data item for this concept instance, as the `GraphSpec` holds it. */
433
+ ioData?: GraphSpecNodeIoItem;
393
434
  /** Whether this is a dry run (schema only, no real data). */
394
435
  isDryRun?: boolean;
395
- /** Resolver for `pipelex-storage://` URIs when rendering media in StuffViewer. */
396
- resolveStorageUrl?: ResolveStorageUrl;
397
- /** Forwarded to {@link StuffViewer}. Set `false` when the host can't embed PDFs. */
398
- canEmbedPdf?: boolean;
399
- /** Forwarded to {@link StuffViewer}. Overrides default `window.open` behavior. */
400
- onOpenExternally?: (url: string, filename?: string) => void;
436
+ /**
437
+ * Renders the data half. Supplied by the host (or by this package's own
438
+ * `./form/react` entry, which renders it through the form kernel's
439
+ * descriptor-driven `StuffViewer`); see `stuffRender.ts` for why the graph
440
+ * does not render data itself any more.
441
+ *
442
+ * Without it — or when it returns nothing for this item — the panel shows the
443
+ * structure table alone and no tabs, which is what a viewer that has not been
444
+ * given a renderer honestly has to offer.
445
+ */
446
+ renderData?: () => React.ReactNode;
401
447
  /**
402
448
  * Identity of the selected node/instance (e.g. the graph node id). Drives
403
449
  * the Data/Structure tab reset: a new `instanceKey` remounts the body so
@@ -407,7 +453,7 @@ interface ConceptDetailPanelProps {
407
453
  */
408
454
  instanceKey?: string;
409
455
  }
410
- declare function ConceptDetailPanel({ concept, ioData, isDryRun, resolveStorageUrl, canEmbedPdf, onOpenExternally, instanceKey, }: ConceptDetailPanelProps): react_jsx_runtime.JSX.Element;
456
+ declare function ConceptDetailPanel({ concept, ioData, isDryRun, renderData, instanceKey, }: ConceptDetailPanelProps): react_jsx_runtime.JSX.Element;
411
457
 
412
458
  interface UseResizableOptions {
413
459
  /** Initial panel width in pixels. */
@@ -429,4 +475,4 @@ interface UseResizableResult {
429
475
  }
430
476
  declare function useResizable({ defaultWidth, minWidth, maxWidth, containerRef, }: UseResizableOptions): UseResizableResult;
431
477
 
432
- export { type AppEdge, type AppNode, type AppRFInstance, ConceptDetailPanel, type ConceptDetailPanelProps, ControllerGroupNode, DetailPanel, type DetailPanelProps, GraphViewer, type GraphViewerProps, PipeCardBase, type PipeCardBaseProps, type PipeCardData, PipeCardNode, PipeDetailPanel, type PipeDetailPanelProps, PipeStatus, type ResolveStorageUrl, StuffViewer, type StuffViewerData, type StuffViewerProps, type UseResizableOptions, type UseResizableResult, ValidationPanel, type ValidationPanelPlacement, type ValidationPanelProps, applyStatusOverrides, controllerNodeTypes, detectSystemTheme, extractFilename, extractInlineUrl, extractStorageUri, extractUrl, findStuffDataByDigest, getHtmlTabLabel, hydrateLabels, isInlineRenderableUrl, isSafeDisplayUrl, renderLabel, resolveMimeType, toAppEdges, toAppNodes, useResizable, useSystemTheme, validationLabel, validationPanelPlacement };
478
+ export { type AppEdge, type AppNode, type AppRFInstance, ConceptDetailPanel, type ConceptDetailPanelProps, ControllerGroupNode, DetailPanel, type DetailPanelProps, GraphViewer, type GraphViewerProps, PipeCardBase, type PipeCardBaseProps, type PipeCardData, PipeCardNode, PipeDetailPanel, type PipeDetailPanelProps, PipeStatus, StuffResultPanel, type StuffResultPanelProps, type StuffResultRendererOptions, type UseResizableOptions, type UseResizableResult, ValidationPanel, type ValidationPanelPlacement, type ValidationPanelProps, applyStatusOverrides, controllerNodeTypes, detectSystemTheme, hydrateLabels, renderLabel, toAppEdges, toAppNodes, useResizable, useSystemTheme, validationLabel, validationPanelPlacement };