@simten/ui 0.1.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/LICENSE +176 -0
- package/README.md +41 -0
- package/dist/canvas/CircuitCanvas.d.ts +45 -0
- package/dist/canvas/CircuitCanvas.d.ts.map +1 -0
- package/dist/canvas/CircuitCanvas.js +293 -0
- package/dist/canvas/CircuitCanvas.js.map +1 -0
- package/dist/canvas/ClockControls.d.ts +31 -0
- package/dist/canvas/ClockControls.d.ts.map +1 -0
- package/dist/canvas/ClockControls.js +33 -0
- package/dist/canvas/ClockControls.js.map +1 -0
- package/dist/canvas/CompositeInspectorDialog.d.ts +24 -0
- package/dist/canvas/CompositeInspectorDialog.d.ts.map +1 -0
- package/dist/canvas/CompositeInspectorDialog.js +290 -0
- package/dist/canvas/CompositeInspectorDialog.js.map +1 -0
- package/dist/canvas/dagre-layout.d.ts +40 -0
- package/dist/canvas/dagre-layout.d.ts.map +1 -0
- package/dist/canvas/dagre-layout.js +86 -0
- package/dist/canvas/dagre-layout.js.map +1 -0
- package/dist/canvas/drill-down-view.d.ts +35 -0
- package/dist/canvas/drill-down-view.d.ts.map +1 -0
- package/dist/canvas/drill-down-view.js +134 -0
- package/dist/canvas/drill-down-view.js.map +1 -0
- package/dist/canvas/hooks/useDetectTheme.d.ts +6 -0
- package/dist/canvas/hooks/useDetectTheme.d.ts.map +1 -0
- package/dist/canvas/hooks/useDetectTheme.js +20 -0
- package/dist/canvas/hooks/useDetectTheme.js.map +1 -0
- package/dist/canvas/hooks/useIsMobile.d.ts +2 -0
- package/dist/canvas/hooks/useIsMobile.d.ts.map +1 -0
- package/dist/canvas/hooks/useIsMobile.js +20 -0
- package/dist/canvas/hooks/useIsMobile.js.map +1 -0
- package/dist/canvas/hooks/useSimulationSession.d.ts +23 -0
- package/dist/canvas/hooks/useSimulationSession.d.ts.map +1 -0
- package/dist/canvas/hooks/useSimulationSession.js +41 -0
- package/dist/canvas/hooks/useSimulationSession.js.map +1 -0
- package/dist/canvas/index.d.ts +22 -0
- package/dist/canvas/index.d.ts.map +1 -0
- package/dist/canvas/index.js +17 -0
- package/dist/canvas/index.js.map +1 -0
- package/dist/canvas/label-utils.d.ts +10 -0
- package/dist/canvas/label-utils.d.ts.map +1 -0
- package/dist/canvas/label-utils.js +32 -0
- package/dist/canvas/label-utils.js.map +1 -0
- package/dist/canvas/node-types.d.ts +10 -0
- package/dist/canvas/node-types.d.ts.map +1 -0
- package/dist/canvas/node-types.js +29 -0
- package/dist/canvas/node-types.js.map +1 -0
- package/dist/canvas/projection.d.ts +19 -0
- package/dist/canvas/projection.d.ts.map +1 -0
- package/dist/canvas/projection.js +317 -0
- package/dist/canvas/projection.js.map +1 -0
- package/dist/canvas/types.d.ts +56 -0
- package/dist/canvas/types.d.ts.map +1 -0
- package/dist/canvas/types.js +6 -0
- package/dist/canvas/types.js.map +1 -0
- package/dist/canvas/useLayout.d.ts +21 -0
- package/dist/canvas/useLayout.d.ts.map +1 -0
- package/dist/canvas/useLayout.js +26 -0
- package/dist/canvas/useLayout.js.map +1 -0
- package/dist/editor/components/CircuitSelector.d.ts +9 -0
- package/dist/editor/components/CircuitSelector.d.ts.map +1 -0
- package/dist/editor/components/CircuitSelector.js +20 -0
- package/dist/editor/components/CircuitSelector.js.map +1 -0
- package/dist/editor/components/CircuitTabBar.d.ts +8 -0
- package/dist/editor/components/CircuitTabBar.d.ts.map +1 -0
- package/dist/editor/components/CircuitTabBar.js +23 -0
- package/dist/editor/components/CircuitTabBar.js.map +1 -0
- package/dist/editor/components/ClockControls.d.ts +6 -0
- package/dist/editor/components/ClockControls.d.ts.map +1 -0
- package/dist/editor/components/ClockControls.js +7 -0
- package/dist/editor/components/ClockControls.js.map +1 -0
- package/dist/editor/components/ComponentTooltip.d.ts +25 -0
- package/dist/editor/components/ComponentTooltip.d.ts.map +1 -0
- package/dist/editor/components/ComponentTooltip.js +82 -0
- package/dist/editor/components/ComponentTooltip.js.map +1 -0
- package/dist/editor/components/ConflictResolutionModal.d.ts +19 -0
- package/dist/editor/components/ConflictResolutionModal.d.ts.map +1 -0
- package/dist/editor/components/ConflictResolutionModal.js +20 -0
- package/dist/editor/components/ConflictResolutionModal.js.map +1 -0
- package/dist/editor/components/HierarchyBreadcrumb.d.ts +9 -0
- package/dist/editor/components/HierarchyBreadcrumb.d.ts.map +1 -0
- package/dist/editor/components/HierarchyBreadcrumb.js +32 -0
- package/dist/editor/components/HierarchyBreadcrumb.js.map +1 -0
- package/dist/editor/components/LabelEditor.d.ts +17 -0
- package/dist/editor/components/LabelEditor.d.ts.map +1 -0
- package/dist/editor/components/LabelEditor.js +40 -0
- package/dist/editor/components/LabelEditor.js.map +1 -0
- package/dist/editor/components/SignalOutputPanel.d.ts +11 -0
- package/dist/editor/components/SignalOutputPanel.d.ts.map +1 -0
- package/dist/editor/components/SignalOutputPanel.js +34 -0
- package/dist/editor/components/SignalOutputPanel.js.map +1 -0
- package/dist/editor/components/index.d.ts +9 -0
- package/dist/editor/components/index.d.ts.map +1 -0
- package/dist/editor/components/index.js +9 -0
- package/dist/editor/components/index.js.map +1 -0
- package/dist/editor/hooks/index.d.ts +1 -0
- package/dist/editor/hooks/index.d.ts.map +1 -0
- package/dist/editor/hooks/index.js +2 -0
- package/dist/editor/hooks/index.js.map +1 -0
- package/dist/editor/index.d.ts +5 -0
- package/dist/editor/index.d.ts.map +1 -0
- package/dist/editor/index.js +5 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/editor/lib/simulation/index.d.ts +7 -0
- package/dist/editor/lib/simulation/index.d.ts.map +1 -0
- package/dist/editor/lib/simulation/index.js +8 -0
- package/dist/editor/lib/simulation/index.js.map +1 -0
- package/dist/editor/lib/utils/circuit-flattener.d.ts +29 -0
- package/dist/editor/lib/utils/circuit-flattener.d.ts.map +1 -0
- package/dist/editor/lib/utils/circuit-flattener.js +230 -0
- package/dist/editor/lib/utils/circuit-flattener.js.map +1 -0
- package/dist/editor/lib/utils/component-utils.d.ts +28 -0
- package/dist/editor/lib/utils/component-utils.d.ts.map +1 -0
- package/dist/editor/lib/utils/component-utils.js +72 -0
- package/dist/editor/lib/utils/component-utils.js.map +1 -0
- package/dist/editor/lib/utils/index.d.ts +3 -0
- package/dist/editor/lib/utils/index.d.ts.map +1 -0
- package/dist/editor/lib/utils/index.js +3 -0
- package/dist/editor/lib/utils/index.js.map +1 -0
- package/dist/editor/lib/visualization/index.d.ts +2 -0
- package/dist/editor/lib/visualization/index.d.ts.map +1 -0
- package/dist/editor/lib/visualization/index.js +2 -0
- package/dist/editor/lib/visualization/index.js.map +1 -0
- package/dist/editor/lib/visualization/vcd-generator.d.ts +63 -0
- package/dist/editor/lib/visualization/vcd-generator.d.ts.map +1 -0
- package/dist/editor/lib/visualization/vcd-generator.js +269 -0
- package/dist/editor/lib/visualization/vcd-generator.js.map +1 -0
- package/dist/editor/stores/circuit-library-store.d.ts +25 -0
- package/dist/editor/stores/circuit-library-store.d.ts.map +1 -0
- package/dist/editor/stores/circuit-library-store.js +51 -0
- package/dist/editor/stores/circuit-library-store.js.map +1 -0
- package/dist/editor/stores/circuit-preview-store.d.ts +687 -0
- package/dist/editor/stores/circuit-preview-store.d.ts.map +1 -0
- package/dist/editor/stores/circuit-preview-store.js +226 -0
- package/dist/editor/stores/circuit-preview-store.js.map +1 -0
- package/dist/editor/stores/circuit-store.d.ts +354 -0
- package/dist/editor/stores/circuit-store.d.ts.map +1 -0
- package/dist/editor/stores/circuit-store.js +227 -0
- package/dist/editor/stores/circuit-store.js.map +1 -0
- package/dist/editor/stores/index.d.ts +11 -0
- package/dist/editor/stores/index.d.ts.map +1 -0
- package/dist/editor/stores/index.js +8 -0
- package/dist/editor/stores/index.js.map +1 -0
- package/dist/editor/stores/ui-store.d.ts +96 -0
- package/dist/editor/stores/ui-store.d.ts.map +1 -0
- package/dist/editor/stores/ui-store.js +101 -0
- package/dist/editor/stores/ui-store.js.map +1 -0
- package/dist/editor/types/circuit.d.ts +207 -0
- package/dist/editor/types/circuit.d.ts.map +1 -0
- package/dist/editor/types/circuit.js +62 -0
- package/dist/editor/types/circuit.js.map +1 -0
- package/dist/editor/types/index.d.ts +12 -0
- package/dist/editor/types/index.d.ts.map +1 -0
- package/dist/editor/types/index.js +11 -0
- package/dist/editor/types/index.js.map +1 -0
- package/dist/editor/types/testbench.d.ts +150 -0
- package/dist/editor/types/testbench.d.ts.map +1 -0
- package/dist/editor/types/testbench.js +85 -0
- package/dist/editor/types/testbench.js.map +1 -0
- package/dist/editor/types/testing.d.ts +88 -0
- package/dist/editor/types/testing.d.ts.map +1 -0
- package/dist/editor/types/testing.js +6 -0
- package/dist/editor/types/testing.js.map +1 -0
- package/dist/editor/types/ui-model.d.ts +68 -0
- package/dist/editor/types/ui-model.d.ts.map +1 -0
- package/dist/editor/types/ui-model.js +66 -0
- package/dist/editor/types/ui-model.js.map +1 -0
- package/dist/editor/types/ui.d.ts +33 -0
- package/dist/editor/types/ui.d.ts.map +1 -0
- package/dist/editor/types/ui.js +8 -0
- package/dist/editor/types/ui.js.map +1 -0
- package/dist/editor/types/visual.d.ts +45 -0
- package/dist/editor/types/visual.d.ts.map +1 -0
- package/dist/editor/types/visual.js +23 -0
- package/dist/editor/types/visual.js.map +1 -0
- package/dist/editor/utils/index.d.ts +5 -0
- package/dist/editor/utils/index.d.ts.map +1 -0
- package/dist/editor/utils/index.js +6 -0
- package/dist/editor/utils/index.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/nodes/BaseNode.d.ts +20 -0
- package/dist/nodes/BaseNode.d.ts.map +1 -0
- package/dist/nodes/BaseNode.js +26 -0
- package/dist/nodes/BaseNode.js.map +1 -0
- package/dist/nodes/CompositeBadge.d.ts +6 -0
- package/dist/nodes/CompositeBadge.d.ts.map +1 -0
- package/dist/nodes/CompositeBadge.js +10 -0
- package/dist/nodes/CompositeBadge.js.map +1 -0
- package/dist/nodes/ConsoleNode.d.ts +8 -0
- package/dist/nodes/ConsoleNode.d.ts.map +1 -0
- package/dist/nodes/ConsoleNode.js +16 -0
- package/dist/nodes/ConsoleNode.js.map +1 -0
- package/dist/nodes/EmbedConsoleNode.d.ts +8 -0
- package/dist/nodes/EmbedConsoleNode.d.ts.map +1 -0
- package/dist/nodes/EmbedConsoleNode.js +24 -0
- package/dist/nodes/EmbedConsoleNode.js.map +1 -0
- package/dist/nodes/EmbedScreenNode.d.ts +8 -0
- package/dist/nodes/EmbedScreenNode.d.ts.map +1 -0
- package/dist/nodes/EmbedScreenNode.js +24 -0
- package/dist/nodes/EmbedScreenNode.js.map +1 -0
- package/dist/nodes/EthFrameInputNode.d.ts +8 -0
- package/dist/nodes/EthFrameInputNode.d.ts.map +1 -0
- package/dist/nodes/EthFrameInputNode.js +14 -0
- package/dist/nodes/EthFrameInputNode.js.map +1 -0
- package/dist/nodes/InputNode.d.ts +8 -0
- package/dist/nodes/InputNode.d.ts.map +1 -0
- package/dist/nodes/InputNode.js +57 -0
- package/dist/nodes/InputNode.js.map +1 -0
- package/dist/nodes/LogicGateNode.d.ts +8 -0
- package/dist/nodes/LogicGateNode.d.ts.map +1 -0
- package/dist/nodes/LogicGateNode.js +51 -0
- package/dist/nodes/LogicGateNode.js.map +1 -0
- package/dist/nodes/NicFifoNode.d.ts +8 -0
- package/dist/nodes/NicFifoNode.d.ts.map +1 -0
- package/dist/nodes/NicFifoNode.js +10 -0
- package/dist/nodes/NicFifoNode.js.map +1 -0
- package/dist/nodes/NodeData.d.ts +34 -0
- package/dist/nodes/NodeData.d.ts.map +1 -0
- package/dist/nodes/NodeData.js +2 -0
- package/dist/nodes/NodeData.js.map +1 -0
- package/dist/nodes/NumericInputNode.d.ts +8 -0
- package/dist/nodes/NumericInputNode.d.ts.map +1 -0
- package/dist/nodes/NumericInputNode.js +47 -0
- package/dist/nodes/NumericInputNode.js.map +1 -0
- package/dist/nodes/OutputNode.d.ts +8 -0
- package/dist/nodes/OutputNode.d.ts.map +1 -0
- package/dist/nodes/OutputNode.js +32 -0
- package/dist/nodes/OutputNode.js.map +1 -0
- package/dist/nodes/RAMNode.d.ts +8 -0
- package/dist/nodes/RAMNode.d.ts.map +1 -0
- package/dist/nodes/RAMNode.js +23 -0
- package/dist/nodes/RAMNode.js.map +1 -0
- package/dist/nodes/ROMNode.d.ts +8 -0
- package/dist/nodes/ROMNode.d.ts.map +1 -0
- package/dist/nodes/ROMNode.js +23 -0
- package/dist/nodes/ROMNode.js.map +1 -0
- package/dist/nodes/RV32IInstrMemNode.d.ts +16 -0
- package/dist/nodes/RV32IInstrMemNode.d.ts.map +1 -0
- package/dist/nodes/RV32IInstrMemNode.js +183 -0
- package/dist/nodes/RV32IInstrMemNode.js.map +1 -0
- package/dist/nodes/RasterDisplayNode.d.ts +8 -0
- package/dist/nodes/RasterDisplayNode.d.ts.map +1 -0
- package/dist/nodes/RasterDisplayNode.js +14 -0
- package/dist/nodes/RasterDisplayNode.js.map +1 -0
- package/dist/nodes/RegisterNode.d.ts +8 -0
- package/dist/nodes/RegisterNode.d.ts.map +1 -0
- package/dist/nodes/RegisterNode.js +14 -0
- package/dist/nodes/RegisterNode.js.map +1 -0
- package/dist/nodes/ScreenNode.d.ts +8 -0
- package/dist/nodes/ScreenNode.d.ts.map +1 -0
- package/dist/nodes/ScreenNode.js +16 -0
- package/dist/nodes/ScreenNode.js.map +1 -0
- package/dist/nodes/UartTxNode.d.ts +8 -0
- package/dist/nodes/UartTxNode.d.ts.map +1 -0
- package/dist/nodes/UartTxNode.js +16 -0
- package/dist/nodes/UartTxNode.js.map +1 -0
- package/dist/nodes/index.d.ts +27 -0
- package/dist/nodes/index.d.ts.map +1 -0
- package/dist/nodes/index.js +30 -0
- package/dist/nodes/index.js.map +1 -0
- package/dist/primitives/button.d.ts +12 -0
- package/dist/primitives/button.d.ts.map +1 -0
- package/dist/primitives/button.js +32 -0
- package/dist/primitives/button.js.map +1 -0
- package/dist/primitives/index.d.ts +4 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +4 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/primitives/sheet.d.ts +15 -0
- package/dist/primitives/sheet.d.ts.map +1 -0
- package/dist/primitives/sheet.js +40 -0
- package/dist/primitives/sheet.js.map +1 -0
- package/dist/primitives/tooltip.d.ts +8 -0
- package/dist/primitives/tooltip.d.ts.map +1 -0
- package/dist/primitives/tooltip.js +17 -0
- package/dist/primitives/tooltip.js.map +1 -0
- package/dist/sandbox/SandboxProvider.d.ts +13 -0
- package/dist/sandbox/SandboxProvider.d.ts.map +1 -0
- package/dist/sandbox/SandboxProvider.js +34 -0
- package/dist/sandbox/SandboxProvider.js.map +1 -0
- package/dist/sandbox/index.d.ts +4 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +3 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/useSandbox.d.ts +197 -0
- package/dist/sandbox/useSandbox.d.ts.map +1 -0
- package/dist/sandbox/useSandbox.js +250 -0
- package/dist/sandbox/useSandbox.js.map +1 -0
- package/dist/share/encode-source.d.ts +13 -0
- package/dist/share/encode-source.d.ts.map +1 -0
- package/dist/share/encode-source.js +31 -0
- package/dist/share/encode-source.js.map +1 -0
- package/dist/share/index.d.ts +2 -0
- package/dist/share/index.d.ts.map +1 -0
- package/dist/share/index.js +2 -0
- package/dist/share/index.js.map +1 -0
- package/dist/waveform/WaveformViewer.d.ts +30 -0
- package/dist/waveform/WaveformViewer.d.ts.map +1 -0
- package/dist/waveform/WaveformViewer.js +356 -0
- package/dist/waveform/WaveformViewer.js.map +1 -0
- package/package.json +110 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified ClockControls — one design, used everywhere.
|
|
3
|
+
*
|
|
4
|
+
* Icon buttons (Step, Play/Pause, Reset) + cycle counter + time-travel.
|
|
5
|
+
* Optional: speed slider, scrubber.
|
|
6
|
+
* Floating style — position via parent container.
|
|
7
|
+
*/
|
|
8
|
+
"use client";
|
|
9
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { SkipForward, Play, Pause, RotateCcw, ChevronLeft, ChevronRight, Gauge, History, } from "lucide-react";
|
|
11
|
+
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../primitives/tooltip";
|
|
12
|
+
import { Button } from "../primitives/button";
|
|
13
|
+
/**
|
|
14
|
+
* Dense icon button used throughout this toolbar. Wraps shadcn `Button`
|
|
15
|
+
* with `ghost` + `icon` variants but tightens the size for the embed bar,
|
|
16
|
+
* and bakes in the Tooltip so each call site is a one-liner. The `label`
|
|
17
|
+
* doubles as `aria-label` and visible tooltip content.
|
|
18
|
+
*/
|
|
19
|
+
function IconBtn({ label, icon: Icon, onClick, disabled, }) {
|
|
20
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", onClick: onClick, disabled: disabled, "aria-label": label, className: "h-7 w-7 text-muted-foreground disabled:opacity-40 [&_svg]:size-3.5", children: _jsx(Icon, {}) }) }), _jsx(TooltipContent, { side: "bottom", children: label })] }));
|
|
21
|
+
}
|
|
22
|
+
export function ClockControls({ cycle, historyLength, historyIndex, isRunning, isViewingPast, onStep, onRun, onPause, onReset, onStepBack, onStepForward, onSeek, onSpeedChange, speed = 1, maxSpeed = 100, showScrubber, floating, chromeless, }) {
|
|
23
|
+
const wrapper = floating
|
|
24
|
+
? "absolute top-3 left-1/2 -translate-x-1/2 z-10"
|
|
25
|
+
: "";
|
|
26
|
+
const inner = chromeless
|
|
27
|
+
? "flex items-center gap-1.5"
|
|
28
|
+
: "flex items-center gap-1.5 border-t border-border bg-card/95 px-3 py-1.5";
|
|
29
|
+
return (_jsx(TooltipProvider, { children: _jsx("div", { className: wrapper, children: _jsxs("div", { className: inner, children: [_jsx(IconBtn, { label: "Tick", icon: SkipForward, onClick: onStep, disabled: isRunning || isViewingPast }), isRunning
|
|
30
|
+
? _jsx(IconBtn, { label: "Pause", icon: Pause, onClick: onPause })
|
|
31
|
+
: _jsx(IconBtn, { label: "Run", icon: Play, onClick: onRun, disabled: isViewingPast }), _jsx(IconBtn, { label: "Reset", icon: RotateCcw, onClick: onReset }), onSpeedChange && (_jsxs("div", { className: "flex items-center gap-2 border-l border-border pl-2 ml-0.5", children: [_jsx(Gauge, { className: "h-3.5 w-3.5 text-muted-foreground/70", "aria-hidden": true }), _jsx("input", { type: "range", min: "1", max: maxSpeed, value: speed, onChange: (e) => onSpeedChange(Number(e.target.value)), className: "w-20 h-1 rounded-lg appearance-none cursor-pointer accent-blue-600", disabled: isViewingPast, "aria-label": "Simulation speed" }), _jsxs("span", { className: "min-w-[55px] text-[10px] text-muted-foreground font-mono tabular-nums", children: [speed, " tick/s"] })] })), _jsx("div", { className: "border-l border-border pl-1.5 ml-0.5", children: _jsxs("span", { className: "text-[11px] text-muted-foreground", children: ["Cycle ", _jsx("span", { className: "font-mono font-semibold text-foreground", children: cycle })] }) }), historyLength > 1 && (_jsxs("div", { className: "flex items-center gap-0.5 border-l border-border pl-1.5 ml-0.5", children: [_jsx(IconBtn, { label: "Step back", icon: ChevronLeft, onClick: onStepBack, disabled: historyIndex <= 0 || isRunning }), _jsx("span", { className: "min-w-[40px] text-center text-[11px] text-muted-foreground", children: isViewingPast ? (_jsxs("span", { className: "font-mono text-amber-600 dark:text-amber-400", children: [historyIndex + 1, "/", historyLength] })) : (_jsxs("span", { className: "font-mono", children: [historyLength, "/", historyLength] })) }), _jsx(IconBtn, { label: "Step forward", icon: ChevronRight, onClick: onStepForward, disabled: !isViewingPast || isRunning })] })), showScrubber && onSeek && historyLength > 1 && (_jsxs("div", { className: "flex items-center gap-2 border-l border-border pl-2 ml-0.5", children: [_jsx(History, { className: "h-3.5 w-3.5 text-muted-foreground/70", "aria-hidden": true }), _jsx("input", { type: "range", min: "0", max: historyLength - 1, value: historyIndex, onChange: (e) => onSeek(Number(e.target.value)), className: "w-24 h-1 rounded-lg appearance-none cursor-pointer accent-blue-600", disabled: isRunning, "aria-label": "Cycle scrubber" })] }))] }) }) }));
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=ClockControls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClockControls.js","sourceRoot":"","sources":["../../src/canvas/ClockControls.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CompositeInspectorDialog (Store-Free)
|
|
3
|
+
*
|
|
4
|
+
* Modal dialog that shows the internals of a composite component with its own
|
|
5
|
+
* canvas and independent simulation engine. Supports nested drill-down — double-
|
|
6
|
+
* clicking a composite inside the dialog pushes another level onto the stack.
|
|
7
|
+
*
|
|
8
|
+
* This version is fully props-driven with no Zustand store dependencies,
|
|
9
|
+
* so it can be used anywhere a CircuitCanvas renders (editor, embeds, blog, etc.).
|
|
10
|
+
*/
|
|
11
|
+
import type { InspectorFrame } from "./types";
|
|
12
|
+
import type { CircuitLibrary } from "@simten/core/simulator";
|
|
13
|
+
import type { Circuit } from "@simten/core";
|
|
14
|
+
export interface CompositeInspectorDialogProps {
|
|
15
|
+
stack: InspectorFrame[];
|
|
16
|
+
componentLibrary: CircuitLibrary;
|
|
17
|
+
theme?: "light" | "dark";
|
|
18
|
+
onClose: () => void;
|
|
19
|
+
onPopLevel: () => void;
|
|
20
|
+
onPushLevel: (name: string, def: Circuit, label: string) => void;
|
|
21
|
+
onNavigate: (index: number) => void;
|
|
22
|
+
}
|
|
23
|
+
export declare function CompositeInspectorDialog({ stack, componentLibrary, theme, onClose, onPopLevel, onPushLevel, onNavigate, }: CompositeInspectorDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
//# sourceMappingURL=CompositeInspectorDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompositeInspectorDialog.d.ts","sourceRoot":"","sources":["../../src/canvas/CompositeInspectorDialog.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAaH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,wBAAwB,CAAC;AAE9E,OAAO,KAAK,EAAE,OAAO,EAAsB,MAAM,cAAc,CAAC;AA2WhE,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,gBAAgB,EAAE,cAAc,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,gBAAgB,EAChB,KAAc,EACd,OAAO,EACP,UAAU,EACV,WAAW,EACX,UAAU,GACX,EAAE,6BAA6B,2CAiJ/B"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CompositeInspectorDialog (Store-Free)
|
|
3
|
+
*
|
|
4
|
+
* Modal dialog that shows the internals of a composite component with its own
|
|
5
|
+
* canvas and independent simulation engine. Supports nested drill-down — double-
|
|
6
|
+
* clicking a composite inside the dialog pushes another level onto the stack.
|
|
7
|
+
*
|
|
8
|
+
* This version is fully props-driven with no Zustand store dependencies,
|
|
9
|
+
* so it can be used anywhere a CircuitCanvas renders (editor, embeds, blog, etc.).
|
|
10
|
+
*/
|
|
11
|
+
"use client";
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
|
+
import React, { useMemo, useState, useCallback, useEffect, useRef, } from "react";
|
|
14
|
+
import { motion, AnimatePresence } from "framer-motion";
|
|
15
|
+
import { createDrillDownViewCircuit } from "./drill-down-view";
|
|
16
|
+
import { createSimulatorFromCircuit } from "@simten/core/simulator";
|
|
17
|
+
import { isSequentialCircuit } from "@simten/core/circuit";
|
|
18
|
+
import { CircuitCanvas } from "./CircuitCanvas";
|
|
19
|
+
import { ClockControls } from "./ClockControls";
|
|
20
|
+
import { NODE_TYPES, EDGE_TYPES } from "./node-types";
|
|
21
|
+
import { useSandboxContext } from "../sandbox/SandboxProvider";
|
|
22
|
+
function InspectorCanvas({ frame, componentLibrary, onPushLevel, theme = "dark", }) {
|
|
23
|
+
const viewCircuit = useMemo(() => createDrillDownViewCircuit(frame.componentDef), [frame.componentDef]);
|
|
24
|
+
const isSequential = useMemo(() => isSequentialCircuit(viewCircuit, componentLibrary.resolveCircuit), [viewCircuit, componentLibrary]);
|
|
25
|
+
const handleNodeDoubleClick = useCallback((nodeData) => {
|
|
26
|
+
if (!nodeData.isComposite)
|
|
27
|
+
return;
|
|
28
|
+
const componentDef = componentLibrary.resolveCircuit(nodeData.componentRef);
|
|
29
|
+
if (!componentDef)
|
|
30
|
+
return;
|
|
31
|
+
if (componentDef.implementation.kind === "composite" &&
|
|
32
|
+
componentDef.nodes.length > 0) {
|
|
33
|
+
onPushLevel(nodeData.componentRef, componentDef, nodeData.label ?? nodeData.componentRef);
|
|
34
|
+
}
|
|
35
|
+
}, [componentLibrary, onPushLevel]);
|
|
36
|
+
// ── Simulation: prefer sandbox, fall back to local simulator ──
|
|
37
|
+
const sandbox = useSandboxContext();
|
|
38
|
+
const [portValues, setPortValues] = useState(new Map());
|
|
39
|
+
const [useSandbox, setUseSandbox] = useState(false);
|
|
40
|
+
const localEngineRef = useRef(null);
|
|
41
|
+
// Clock-control state — minimal time-travel via sandbox snapshots, scoped
|
|
42
|
+
// to this drill-down's slot.
|
|
43
|
+
const [cycle, setCycle] = useState(0);
|
|
44
|
+
const [isRunning, setIsRunning] = useState(false);
|
|
45
|
+
const historyRef = useRef([]);
|
|
46
|
+
const [historyLen, setHistoryLen] = useState(0);
|
|
47
|
+
const [historyIndex, setHistoryIndex] = useState(-1);
|
|
48
|
+
// Unique slot ID per drill-down instance (supports nested drill-downs)
|
|
49
|
+
const slotIdRef = useRef('');
|
|
50
|
+
if (!slotIdRef.current) {
|
|
51
|
+
slotIdRef.current = `drill-${typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2)}`;
|
|
52
|
+
}
|
|
53
|
+
const slotId = slotIdRef.current;
|
|
54
|
+
// Cleanup slot on unmount
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
return () => {
|
|
57
|
+
if (useSandbox)
|
|
58
|
+
sandbox.dispose(slotId).catch(() => { });
|
|
59
|
+
};
|
|
60
|
+
}, [sandbox, slotId, useSandbox]);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
// Send the drill-down view circuit to the sandbox for simulation.
|
|
63
|
+
// The sandbox already has eval functions from the source compile.
|
|
64
|
+
// Include every circuit the view references (primitives AND composites,
|
|
65
|
+
// recursively) — without composite defs, the sandbox can't simulate
|
|
66
|
+
// composite children and their outputs stay stuck.
|
|
67
|
+
const allLib = [];
|
|
68
|
+
const seen = new Set();
|
|
69
|
+
for (const name of componentLibrary.getAllPrimitiveNames()) {
|
|
70
|
+
const c = componentLibrary.resolveCircuit(name);
|
|
71
|
+
if (c && !seen.has(name)) {
|
|
72
|
+
seen.add(name);
|
|
73
|
+
allLib.push(c);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const walk = (c) => {
|
|
77
|
+
for (const node of c.nodes) {
|
|
78
|
+
if (seen.has(node.componentRef))
|
|
79
|
+
continue;
|
|
80
|
+
const resolved = componentLibrary.resolveCircuit(node.componentRef);
|
|
81
|
+
if (!resolved)
|
|
82
|
+
continue;
|
|
83
|
+
seen.add(node.componentRef);
|
|
84
|
+
allLib.push(resolved);
|
|
85
|
+
if (resolved.implementation.kind === 'composite')
|
|
86
|
+
walk(resolved);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
walk(viewCircuit);
|
|
90
|
+
sandbox.compileIR(viewCircuit, allLib, slotId, { snapshot: isSequential }).then(result => {
|
|
91
|
+
if ('error' in result) {
|
|
92
|
+
// Fall back to local simulator (for embed contexts where no source was compiled)
|
|
93
|
+
try {
|
|
94
|
+
const engine = createSimulatorFromCircuit(viewCircuit, componentLibrary);
|
|
95
|
+
engine.runCombinational();
|
|
96
|
+
localEngineRef.current = engine;
|
|
97
|
+
setUseSandbox(false);
|
|
98
|
+
const pvMap = new Map();
|
|
99
|
+
for (const [k, v] of engine.getPortValues()) {
|
|
100
|
+
pvMap.set(k, v);
|
|
101
|
+
}
|
|
102
|
+
setPortValues(pvMap);
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
console.warn("[InspectorCanvas] Both sandbox and local failed:", e);
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
setUseSandbox(true);
|
|
110
|
+
const pvMap = new Map();
|
|
111
|
+
for (const [k, v] of Object.entries(result.portValues)) {
|
|
112
|
+
pvMap.set(k, v);
|
|
113
|
+
}
|
|
114
|
+
setPortValues(pvMap);
|
|
115
|
+
// Seed history with the initial snapshot (sequential circuits only).
|
|
116
|
+
historyRef.current = result.snapshotId !== undefined
|
|
117
|
+
? [{ snapshotId: result.snapshotId, cycle: 0 }]
|
|
118
|
+
: [];
|
|
119
|
+
setHistoryLen(historyRef.current.length);
|
|
120
|
+
setHistoryIndex(historyRef.current.length === 0 ? -1 : 0);
|
|
121
|
+
setCycle(0);
|
|
122
|
+
});
|
|
123
|
+
}, [viewCircuit, componentLibrary, sandbox, slotId, isSequential]);
|
|
124
|
+
const handleToggle = useCallback((nodeId) => {
|
|
125
|
+
const outKey = `${nodeId}.out`;
|
|
126
|
+
const currentValue = portValues.get(outKey);
|
|
127
|
+
sandbox.setNode(nodeId, !currentValue, slotId).then(result => {
|
|
128
|
+
if ('error' in result)
|
|
129
|
+
return;
|
|
130
|
+
const pvMap = new Map();
|
|
131
|
+
for (const [k, v] of Object.entries(result.portValues))
|
|
132
|
+
pvMap.set(k, v);
|
|
133
|
+
setPortValues(pvMap);
|
|
134
|
+
});
|
|
135
|
+
}, [sandbox, portValues]);
|
|
136
|
+
const handleNumericChange = useCallback((nodeId, newValue) => {
|
|
137
|
+
sandbox.setNode(nodeId, newValue, slotId).then(result => {
|
|
138
|
+
if ('error' in result)
|
|
139
|
+
return;
|
|
140
|
+
const pvMap = new Map();
|
|
141
|
+
for (const [k, v] of Object.entries(result.portValues))
|
|
142
|
+
pvMap.set(k, v);
|
|
143
|
+
setPortValues(pvMap);
|
|
144
|
+
});
|
|
145
|
+
}, [sandbox]);
|
|
146
|
+
// ── Clock controls ─────────────────────────────────────────────────────
|
|
147
|
+
// Tick the sandbox slot, capture a snapshot, and record it in history.
|
|
148
|
+
// If we're currently viewing the past, ticking truncates future entries
|
|
149
|
+
// (mirrors the embed's history semantics).
|
|
150
|
+
const handleTick = useCallback(() => {
|
|
151
|
+
sandbox.tick(undefined, slotId, { snapshot: isSequential }).then(result => {
|
|
152
|
+
if ('error' in result)
|
|
153
|
+
return;
|
|
154
|
+
const pvMap = new Map();
|
|
155
|
+
for (const [k, v] of Object.entries(result.portValues))
|
|
156
|
+
pvMap.set(k, v);
|
|
157
|
+
setPortValues(pvMap);
|
|
158
|
+
setCycle(result.cycle);
|
|
159
|
+
if (result.snapshotId !== undefined) {
|
|
160
|
+
const truncated = historyRef.current.slice(0, historyIndex + 1);
|
|
161
|
+
truncated.push({ snapshotId: result.snapshotId, cycle: result.cycle });
|
|
162
|
+
historyRef.current = truncated;
|
|
163
|
+
setHistoryLen(truncated.length);
|
|
164
|
+
setHistoryIndex(truncated.length - 1);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}, [sandbox, slotId, isSequential, historyIndex]);
|
|
168
|
+
const handleReset = useCallback(() => {
|
|
169
|
+
setIsRunning(false);
|
|
170
|
+
sandbox.reset(slotId).then(result => {
|
|
171
|
+
if ('error' in result)
|
|
172
|
+
return;
|
|
173
|
+
const pvMap = new Map();
|
|
174
|
+
for (const [k, v] of Object.entries(result.portValues))
|
|
175
|
+
pvMap.set(k, v);
|
|
176
|
+
setPortValues(pvMap);
|
|
177
|
+
setCycle(0);
|
|
178
|
+
// Reset clears all history; if the slot is sequential, take a fresh
|
|
179
|
+
// snapshot of the post-reset state to seed history again.
|
|
180
|
+
historyRef.current = [];
|
|
181
|
+
setHistoryLen(0);
|
|
182
|
+
setHistoryIndex(-1);
|
|
183
|
+
if (isSequential) {
|
|
184
|
+
sandbox.snapshot(slotId).then(snap => {
|
|
185
|
+
if ('error' in snap || snap.snapshotId === undefined)
|
|
186
|
+
return;
|
|
187
|
+
historyRef.current = [{ snapshotId: snap.snapshotId, cycle: 0 }];
|
|
188
|
+
setHistoryLen(1);
|
|
189
|
+
setHistoryIndex(0);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}, [sandbox, slotId, isSequential]);
|
|
194
|
+
const restoreTo = useCallback((index) => {
|
|
195
|
+
const entry = historyRef.current[index];
|
|
196
|
+
if (!entry)
|
|
197
|
+
return;
|
|
198
|
+
sandbox.restore(entry.snapshotId, slotId).then(result => {
|
|
199
|
+
if ('error' in result)
|
|
200
|
+
return;
|
|
201
|
+
const pvMap = new Map();
|
|
202
|
+
for (const [k, v] of Object.entries(result.portValues))
|
|
203
|
+
pvMap.set(k, v);
|
|
204
|
+
setPortValues(pvMap);
|
|
205
|
+
setCycle(entry.cycle);
|
|
206
|
+
setHistoryIndex(index);
|
|
207
|
+
});
|
|
208
|
+
}, [sandbox, slotId]);
|
|
209
|
+
const handleStepBack = useCallback(() => {
|
|
210
|
+
setIsRunning(false);
|
|
211
|
+
if (historyIndex > 0)
|
|
212
|
+
restoreTo(historyIndex - 1);
|
|
213
|
+
}, [historyIndex, restoreTo]);
|
|
214
|
+
const handleStepForward = useCallback(() => {
|
|
215
|
+
if (historyIndex < historyLen - 1)
|
|
216
|
+
restoreTo(historyIndex + 1);
|
|
217
|
+
else
|
|
218
|
+
handleTick();
|
|
219
|
+
}, [historyIndex, historyLen, restoreTo, handleTick]);
|
|
220
|
+
// Auto-run loop while isRunning.
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
if (!isRunning)
|
|
223
|
+
return;
|
|
224
|
+
const id = window.setInterval(() => { handleTick(); }, 200);
|
|
225
|
+
return () => window.clearInterval(id);
|
|
226
|
+
}, [isRunning, handleTick]);
|
|
227
|
+
return (_jsxs("div", { className: "relative h-full w-full", children: [isSequential && (_jsx(ClockControls, { floating: true, cycle: cycle, historyLength: historyLen, historyIndex: historyIndex, isRunning: isRunning, isViewingPast: historyIndex >= 0 && historyIndex < historyLen - 1, onStep: handleTick, onRun: () => setIsRunning(true), onPause: () => setIsRunning(false), onReset: handleReset, onStepBack: handleStepBack, onStepForward: handleStepForward })), _jsx(CircuitCanvas, { circuit: viewCircuit, componentLibrary: componentLibrary, portValues: portValues, sequentialState: null, onToggleNode: handleToggle, onSetNodeValue: handleNumericChange, onNodeDoubleClick: handleNodeDoubleClick, nodeTypes: NODE_TYPES, edgeTypes: EDGE_TYPES, theme: theme, showControls: true, height: "100%", panOnMobile: true })] }));
|
|
228
|
+
}
|
|
229
|
+
function InspectorBreadcrumb({ stack, onNavigate, theme = "dark", }) {
|
|
230
|
+
const topFrame = stack[stack.length - 1];
|
|
231
|
+
const description = topFrame?.componentDef.metadata?.description;
|
|
232
|
+
const dark = theme === "dark";
|
|
233
|
+
return (_jsxs("div", { className: "flex items-center gap-1 text-sm min-w-0", children: [stack.map((frame, index) => (_jsxs(React.Fragment, { children: [index > 0 && (_jsx("span", { className: `${dark ? "text-gray-500" : "text-gray-400"} shrink-0`, children: ">" })), index < stack.length - 1 ? (_jsxs("button", { onClick: () => onNavigate(index), className: `${dark
|
|
234
|
+
? "text-blue-400 hover:text-blue-300"
|
|
235
|
+
: "text-blue-600 hover:text-blue-800"} hover:underline font-medium shrink-0`, children: [frame.nodeLabel, " (", frame.componentName, ")"] })) : (_jsxs("span", { className: `font-semibold shrink-0 ${dark ? "text-gray-100" : "text-gray-900"}`, children: [frame.nodeLabel, " (", frame.componentName, ")"] }))] }, index))), description && (_jsxs(_Fragment, { children: [_jsx("span", { className: `${dark ? "text-gray-600" : "text-gray-300"} shrink-0`, children: "\u2014" }), _jsx("span", { className: `${dark ? "text-gray-400" : "text-gray-500"} text-xs italic truncate`, children: description })] }))] }));
|
|
236
|
+
}
|
|
237
|
+
const levelVariants = {
|
|
238
|
+
enterIn: { opacity: 0 },
|
|
239
|
+
enterOut: { opacity: 0 },
|
|
240
|
+
center: { opacity: 1 },
|
|
241
|
+
exitIn: { opacity: 0 },
|
|
242
|
+
exitOut: { opacity: 0 },
|
|
243
|
+
};
|
|
244
|
+
export function CompositeInspectorDialog({ stack, componentLibrary, theme = "dark", onClose, onPopLevel, onPushLevel, onNavigate, }) {
|
|
245
|
+
const isOpen = stack.length > 0;
|
|
246
|
+
const prevDepthRef = useRef(0);
|
|
247
|
+
const [direction, setDirection] = useState("in");
|
|
248
|
+
useEffect(() => {
|
|
249
|
+
if (stack.length > prevDepthRef.current) {
|
|
250
|
+
setDirection("in");
|
|
251
|
+
}
|
|
252
|
+
else if (stack.length < prevDepthRef.current) {
|
|
253
|
+
setDirection("out");
|
|
254
|
+
}
|
|
255
|
+
prevDepthRef.current = stack.length;
|
|
256
|
+
}, [stack.length]);
|
|
257
|
+
// Lock body scroll while the inspector is open. This is a hand-rolled modal
|
|
258
|
+
// (motion.div + fixed positioning), so the browser doesn't lock scroll for
|
|
259
|
+
// us the way native <dialog> would. Without this, swiping the modal scrolls
|
|
260
|
+
// the page underneath. Tracked for proper Radix Dialog refactor in #84.
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
if (!isOpen)
|
|
263
|
+
return;
|
|
264
|
+
const previousOverflow = document.body.style.overflow;
|
|
265
|
+
document.body.style.overflow = "hidden";
|
|
266
|
+
return () => {
|
|
267
|
+
document.body.style.overflow = previousOverflow;
|
|
268
|
+
};
|
|
269
|
+
}, [isOpen]);
|
|
270
|
+
const handleBackdropClick = useCallback((e) => {
|
|
271
|
+
if (e.target === e.currentTarget)
|
|
272
|
+
onClose();
|
|
273
|
+
}, [onClose]);
|
|
274
|
+
const handleKeyDown = useCallback((e) => {
|
|
275
|
+
if (e.key === "Escape") {
|
|
276
|
+
e.stopPropagation();
|
|
277
|
+
if (stack.length > 1) {
|
|
278
|
+
onPopLevel();
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
onClose();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}, [stack.length, onPopLevel, onClose]);
|
|
285
|
+
const topFrame = isOpen ? stack[stack.length - 1] : null;
|
|
286
|
+
return (_jsx(AnimatePresence, { children: isOpen && topFrame && (_jsxs(_Fragment, { children: [_jsx(motion.div, { className: "fixed inset-0 z-50 bg-black/50", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.25 }, onClick: handleBackdropClick, onKeyDown: handleKeyDown, tabIndex: -1 }, "inspector-backdrop"), _jsx(motion.div, { className: "fixed inset-0 z-50 flex items-center justify-center p-8 pointer-events-none", children: _jsxs(motion.div, { className: `flex h-[80vh] w-full max-w-5xl flex-col rounded-lg shadow-xl pointer-events-auto overflow-hidden ${theme === "dark" ? "bg-gray-900" : "bg-white"}`, initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, children: [_jsxs("div", { className: `flex items-center justify-between border-b px-4 py-3 ${theme === "dark" ? "border-gray-700" : "border-gray-200"}`, children: [_jsx(InspectorBreadcrumb, { stack: stack, onNavigate: onNavigate, theme: theme }), _jsx("button", { onClick: onClose, className: `rounded p-1 ${theme === "dark"
|
|
287
|
+
? "text-gray-400 hover:bg-gray-800 hover:text-gray-300"
|
|
288
|
+
: "text-gray-400 hover:bg-gray-100 hover:text-gray-600"}`, "aria-label": "Close inspector", children: _jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), _jsx("div", { className: "relative flex-1 overflow-hidden", children: _jsx(AnimatePresence, { mode: "wait", initial: false, children: _jsx(motion.div, { className: "absolute inset-0", initial: direction === "in" ? "enterIn" : "enterOut", animate: "center", exit: direction === "in" ? "exitIn" : "exitOut", variants: levelVariants, transition: { duration: 0.2, ease: "easeInOut" }, children: _jsx(InspectorCanvas, { frame: topFrame, componentLibrary: componentLibrary, onPushLevel: onPushLevel, theme: theme }) }, `${stack.length}-${topFrame.componentName}`) }) })] }) }, "inspector-dialog")] })) }));
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=CompositeInspectorDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompositeInspectorDialog.js","sourceRoot":"","sources":["../../src/canvas/CompositeInspectorDialog.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dagre layout computation — synchronous, no I/O.
|
|
3
|
+
*
|
|
4
|
+
* Uses @dagrejs/dagre (~30 KB gzip) for Sugiyama-style layered layouts
|
|
5
|
+
* — the right shape for digital circuits with their natural left-to-right
|
|
6
|
+
* data flow. Dagre returns node positions as CENTER coordinates; we
|
|
7
|
+
* convert to top-left to match React Flow's expected convention.
|
|
8
|
+
*/
|
|
9
|
+
import type { Circuit } from "@simten/core";
|
|
10
|
+
import type { MetadataState } from "./types";
|
|
11
|
+
/** Node size constants by component type. Used to feed dagre. */
|
|
12
|
+
export declare const NODE_DIMENSIONS: Record<string, {
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
}>;
|
|
16
|
+
export declare const DEFAULT_DIMENSIONS: {
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
};
|
|
20
|
+
export declare function getDimensions(componentRef: string): {
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
};
|
|
24
|
+
export interface DagreLayoutOptions {
|
|
25
|
+
/** Layout direction. "LR" = left-to-right (default), "TB" = top-to-bottom. */
|
|
26
|
+
direction?: "LR" | "TB" | "RL" | "BT";
|
|
27
|
+
/** Inter-node spacing in the same rank. */
|
|
28
|
+
nodeSpacing?: number;
|
|
29
|
+
/** Spacing between ranks. */
|
|
30
|
+
rankSpacing?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Compute dagre layout for a circuit. Returns a MetadataState with node
|
|
34
|
+
* positions in top-left coordinates.
|
|
35
|
+
*
|
|
36
|
+
* Synchronous — dagre.layout() does no I/O. Callers can use the result
|
|
37
|
+
* immediately on first render.
|
|
38
|
+
*/
|
|
39
|
+
export declare function computeDagreLayout(circuit: Circuit, options?: DagreLayoutOptions): MetadataState;
|
|
40
|
+
//# sourceMappingURL=dagre-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dagre-layout.d.ts","sourceRoot":"","sources":["../../src/canvas/dagre-layout.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,iEAAiE;AACjE,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAe7E,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;CAA6B,CAAC;AAE7D,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM;WAnBI,MAAM;YAAU,MAAM;EAqB3E;AAED,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACtC,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,aAAa,CAmDf"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dagre layout computation — synchronous, no I/O.
|
|
3
|
+
*
|
|
4
|
+
* Uses @dagrejs/dagre (~30 KB gzip) for Sugiyama-style layered layouts
|
|
5
|
+
* — the right shape for digital circuits with their natural left-to-right
|
|
6
|
+
* data flow. Dagre returns node positions as CENTER coordinates; we
|
|
7
|
+
* convert to top-left to match React Flow's expected convention.
|
|
8
|
+
*/
|
|
9
|
+
import dagre from "@dagrejs/dagre";
|
|
10
|
+
/** Node size constants by component type. Used to feed dagre. */
|
|
11
|
+
export const NODE_DIMENSIONS = {
|
|
12
|
+
Switch: { width: 140, height: 110 },
|
|
13
|
+
Button: { width: 120, height: 80 },
|
|
14
|
+
Input: { width: 140, height: 80 },
|
|
15
|
+
Led: { width: 100, height: 110 },
|
|
16
|
+
Output: { width: 100, height: 80 },
|
|
17
|
+
HexDisplay: { width: 100, height: 80 },
|
|
18
|
+
SevenSegment: { width: 100, height: 80 },
|
|
19
|
+
Screen: { width: 200, height: 200 },
|
|
20
|
+
RasterDisplay: { width: 200, height: 200 },
|
|
21
|
+
Console: { width: 380, height: 220 },
|
|
22
|
+
Register: { width: 120, height: 80 },
|
|
23
|
+
RAM: { width: 120, height: 80 },
|
|
24
|
+
ROM: { width: 120, height: 80 },
|
|
25
|
+
DualPortRAM: { width: 140, height: 100 },
|
|
26
|
+
};
|
|
27
|
+
export const DEFAULT_DIMENSIONS = { width: 160, height: 80 };
|
|
28
|
+
export function getDimensions(componentRef) {
|
|
29
|
+
return NODE_DIMENSIONS[componentRef] ?? DEFAULT_DIMENSIONS;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Compute dagre layout for a circuit. Returns a MetadataState with node
|
|
33
|
+
* positions in top-left coordinates.
|
|
34
|
+
*
|
|
35
|
+
* Synchronous — dagre.layout() does no I/O. Callers can use the result
|
|
36
|
+
* immediately on first render.
|
|
37
|
+
*/
|
|
38
|
+
export function computeDagreLayout(circuit, options) {
|
|
39
|
+
const direction = options?.direction ?? "LR";
|
|
40
|
+
const nodeSpacing = options?.nodeSpacing ?? 60;
|
|
41
|
+
const rankSpacing = options?.rankSpacing ?? 90;
|
|
42
|
+
const g = new dagre.graphlib.Graph();
|
|
43
|
+
g.setGraph({
|
|
44
|
+
rankdir: direction,
|
|
45
|
+
nodesep: nodeSpacing,
|
|
46
|
+
ranksep: rankSpacing,
|
|
47
|
+
marginx: 20,
|
|
48
|
+
marginy: 20,
|
|
49
|
+
});
|
|
50
|
+
g.setDefaultEdgeLabel(() => ({}));
|
|
51
|
+
// Add nodes with their dimensions.
|
|
52
|
+
const nodeIds = new Set();
|
|
53
|
+
for (const node of circuit.nodes) {
|
|
54
|
+
const dims = getDimensions(node.componentRef);
|
|
55
|
+
g.setNode(node.id, { width: dims.width, height: dims.height });
|
|
56
|
+
nodeIds.add(node.id);
|
|
57
|
+
}
|
|
58
|
+
// Add edges. Dagre doesn't track per-port connections, so we just
|
|
59
|
+
// record source→target. Skip connections whose endpoints aren't real
|
|
60
|
+
// nodes (e.g. circuit-level input/output ports) — calling setEdge with
|
|
61
|
+
// unknown ids would auto-create dimensionless phantom nodes and crash
|
|
62
|
+
// dagre's layout passes.
|
|
63
|
+
for (const conn of circuit.connections) {
|
|
64
|
+
if (!nodeIds.has(conn.source.nodeId) || !nodeIds.has(conn.target.nodeId))
|
|
65
|
+
continue;
|
|
66
|
+
g.setEdge(conn.source.nodeId, conn.target.nodeId);
|
|
67
|
+
}
|
|
68
|
+
// Synchronous; no I/O.
|
|
69
|
+
dagre.layout(g);
|
|
70
|
+
const metadata = { components: {}, connections: {} };
|
|
71
|
+
for (const node of circuit.nodes) {
|
|
72
|
+
const laid = g.node(node.id);
|
|
73
|
+
if (!laid)
|
|
74
|
+
continue;
|
|
75
|
+
// Dagre returns center; convert to top-left.
|
|
76
|
+
metadata.components[node.id] = {
|
|
77
|
+
id: node.id,
|
|
78
|
+
position: {
|
|
79
|
+
x: laid.x - laid.width / 2,
|
|
80
|
+
y: laid.y - laid.height / 2,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return metadata;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=dagre-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dagre-layout.js","sourceRoot":"","sources":["../../src/canvas/dagre-layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drill-Down View Utilities
|
|
3
|
+
*
|
|
4
|
+
* Creates viewable circuits for composite component internals.
|
|
5
|
+
* When a user drills into a composite (e.g., HalfAdder), we need to:
|
|
6
|
+
* 1. Show its internal nodes on the canvas
|
|
7
|
+
* 2. Add synthetic boundary nodes for the composite's ports
|
|
8
|
+
* 3. Scope port values so internal node IDs match simulation keys
|
|
9
|
+
*/
|
|
10
|
+
import type { Circuit } from '@simten/core';
|
|
11
|
+
import type { FlatPortValueMap } from '@simten/core/simulator';
|
|
12
|
+
/** Prefix for synthetic boundary input nodes */
|
|
13
|
+
export declare const BOUNDARY_IN_PREFIX = "__boundary_in_";
|
|
14
|
+
/** Prefix for synthetic boundary output nodes */
|
|
15
|
+
export declare const BOUNDARY_OUT_PREFIX = "__boundary_out_";
|
|
16
|
+
/**
|
|
17
|
+
* Creates a viewable circuit from a composite's definition.
|
|
18
|
+
*
|
|
19
|
+
* The composite Circuit has internal nodes and connections where circuit-level
|
|
20
|
+
* ports use `nodeId: ""`. We replace those with synthetic Switch/Input (for inputs)
|
|
21
|
+
* and Led (for outputs) boundary nodes, so the canvas renders them naturally.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createDrillDownViewCircuit(composite: Circuit): Circuit;
|
|
24
|
+
/**
|
|
25
|
+
* Scopes port values for a drilled-in view.
|
|
26
|
+
*
|
|
27
|
+
* The flat simulator produces port value keys with hierarchical prefixes like
|
|
28
|
+
* "ha1_abc.xor1_def.out". When we drill into "ha1_abc", we need to strip
|
|
29
|
+
* that prefix so keys become "xor1_def.out" — matching the composite's internal node IDs.
|
|
30
|
+
*
|
|
31
|
+
* Also maps boundary port values: the composite instance's own port values
|
|
32
|
+
* get mapped to synthetic boundary node IDs.
|
|
33
|
+
*/
|
|
34
|
+
export declare function scopePortValues(portValues: FlatPortValueMap, prefix: string, composite?: Circuit): FlatPortValueMap;
|
|
35
|
+
//# sourceMappingURL=drill-down-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drill-down-view.d.ts","sourceRoot":"","sources":["../../src/canvas/drill-down-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAwC,MAAM,cAAc,CAAC;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,gDAAgD;AAChD,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,iDAAiD;AACjD,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CA8EtE;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,gBAAgB,EAC5B,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,OAAO,GAClB,gBAAgB,CAqClB"}
|