- {/* ResizablePanelGroup sets an inline height:100%, so the panels' fixed
- height comes from this wrapper's definite height (a height class on
- the group itself would lose to that inline style). */}
-
- {/* Split-pane docked panels: drag a handle to grow one panel and shrink
- its neighbor in tandem, exercising the width-sensitive tree layout. */}
-
-
- {/* Keyed so switching the data variant remounts with fresh edit state. */}
-
-
-
-
-
-
-
-
-
-
-
-
-
- ),
-};
diff --git a/packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx b/packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx
index b31028287..239820a0e 100644
--- a/packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx
+++ b/packages/apollo-react/src/canvas/components/NodePropertyPanel/NodePropertyPanel.stories.tsx
@@ -11,6 +11,9 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
MetadataForm,
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
ScrollableTabsList,
Switch,
Tabs,
@@ -31,17 +34,40 @@ import {
CircleAlert,
CircleCheck,
Code2,
+ Eye,
+ File,
GitFork,
Globe,
GripVertical,
+ HardDrive,
Play,
Plus,
+ ScanText,
Sparkles,
+ Trash2,
Type,
+ Upload,
X,
+ Zap,
} from 'lucide-react';
import type { CSSProperties, ReactNode } from 'react';
-import { lazy, Suspense, useEffect, useRef, useState } from 'react';
+import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';
+import { NodeOutputModeSelect } from '../../controls';
+import type {
+ DeriveTypeIcon,
+ JsonCodeEditorRenderProps,
+ JsonContainer,
+ JsonSchema,
+ JsonTreeFilterOption,
+ JsonTreeNode,
+ JsonValue,
+ NodeAction,
+ NodeActionsResolver,
+ NodeDecoration,
+ RenderValueCell,
+} from '../JsonTree';
+import { isJsonObject } from '../JsonTree';
+import { NodeIOView, type NodeIOViewTab } from '../NodeIOView';
import { NodePropertyPanel } from './NodePropertyPanel';
// @monaco-editor/react uses a CJS build without an `exports` field, which
@@ -1833,3 +1859,822 @@ export const Responsive: Story = {
),
};
+
+// ============================================================================
+// Input / Output panels (NodeIOView)
+// ============================================================================
+
+const JSON_VIEWER_OPTIONS = {
+ readOnly: true,
+ fontSize: 12,
+ lineHeight: 18,
+ minimap: { enabled: false },
+ scrollBeyondLastLine: false,
+ wordWrap: 'off',
+ fontFamily:
+ 'ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace',
+ padding: { top: 8, bottom: 8 },
+ lineNumbers: 'off' as const,
+ lineDecorationsWidth: 0,
+ glyphMargin: false,
+ folding: true,
+ renderLineHighlight: 'none' as const,
+ hideCursorInOverviewRuler: true,
+ overviewRulerBorder: false,
+ overviewRulerLanes: 0,
+ scrollbar: {
+ vertical: 'auto' as const,
+ horizontal: 'auto' as const,
+ alwaysConsumeMouseWheel: false,
+ },
+ automaticLayout: true,
+} as const;
+
+function MonacoJsonView({ value }: { value: JsonValue | undefined }) {
+ const monacoTheme = useMonacoTheme();
+ return (
+ {
+ if (e.key === 'Escape') {
+ e.stopPropagation();
+ onCancel();
+ }
+ if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
+ e.preventDefault();
+ onApply();
+ }
+ }}
+ >
+ onChange(next ?? '')}
+ onMount={(editor) => {
+ if (autoFocus) editor.focus();
+ }}
+ options={CODE_EDITOR_OPTIONS}
+ />
+
+ );
+}
+
+const renderJsonCodeEditor = (props: JsonCodeEditorRenderProps) =>