@illuma-ai/code-sandbox 1.0.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.
- package/LICENSE +15 -0
- package/dist/__sw__.js +712 -0
- package/dist/code-sandbox.css +1 -0
- package/dist/components/BootOverlay.d.ts +17 -0
- package/dist/components/CodeEditor.d.ts +11 -0
- package/dist/components/FileTree.d.ts +19 -0
- package/dist/components/Preview.d.ts +15 -0
- package/dist/components/Terminal.d.ts +15 -0
- package/dist/components/ViewSlider.d.ts +25 -0
- package/dist/components/Workbench.d.ts +28 -0
- package/dist/hooks/useRuntime.d.ts +25 -0
- package/dist/index.cjs +50074 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +77335 -0
- package/dist/index.js.map +1 -0
- package/dist/services/git.d.ts +57 -0
- package/dist/services/runtime.d.ts +119 -0
- package/dist/templates/fullstack-starter.d.ts +38 -0
- package/dist/templates/index.d.ts +38 -0
- package/dist/types.d.ts +137 -0
- package/package.json +69 -0
- package/src/components/BootOverlay.tsx +145 -0
- package/src/components/CodeEditor.tsx +168 -0
- package/src/components/FileTree.tsx +286 -0
- package/src/components/Preview.tsx +50 -0
- package/src/components/Terminal.tsx +68 -0
- package/src/components/ViewSlider.tsx +87 -0
- package/src/components/Workbench.tsx +301 -0
- package/src/hooks/useRuntime.ts +236 -0
- package/src/index.ts +48 -0
- package/src/services/git.ts +415 -0
- package/src/services/runtime.ts +536 -0
- package/src/styles.css +24 -0
- package/src/templates/fullstack-starter.ts +3297 -0
- package/src/templates/index.ts +607 -0
- package/src/types.ts +179 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--separator-border: rgba(128, 128, 128, .35);--sash-hover-transition-duration: .1s}.allotment-module_splitView__L-yRc{height:100%;overflow:hidden;position:relative;width:100%}.allotment-module_splitView__L-yRc>.allotment-module_sashContainer__fzwJF{height:100%;pointer-events:none;position:absolute;width:100%}.allotment-module_splitView__L-yRc>.allotment-module_sashContainer__fzwJF>.allotment-module_sash__QA-2t{pointer-events:auto}.allotment-module_splitView__L-yRc>.allotment-module_splitViewContainer__rQnVa{height:100%;position:relative;white-space:nowrap;width:100%}.allotment-module_splitView__L-yRc>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O{overflow:hidden;position:absolute;white-space:initial}.allotment-module_splitView__L-yRc.allotment-module_vertical__WSwwa>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O{width:100%}.allotment-module_splitView__L-yRc.allotment-module_horizontal__7doS8>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O{height:100%}.allotment-module_splitView__L-yRc.allotment-module_separatorBorder__x-rDS>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O:not(:first-child):before{background-color:var(--separator-border);content:" ";left:0;pointer-events:none;position:absolute;top:0;z-index:5}.allotment-module_splitView__L-yRc.allotment-module_separatorBorder__x-rDS.allotment-module_vertical__WSwwa>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O:not(:first-child):before{height:1px;width:100%}.allotment-module_splitView__L-yRc.allotment-module_separatorBorder__x-rDS.allotment-module_horizontal__7doS8>.allotment-module_splitViewContainer__rQnVa>.allotment-module_splitViewView__MGZ6O:not(:first-child):before{height:100%;width:1px}:root{--focus-border: #007fd4;--sash-size: 8px;--sash-hover-size: 4px}.sash-module_sash__K-9lB{position:absolute;z-index:35;touch-action:none;pointer-events:auto;text-align:initial}.sash-module_sash__K-9lB.sash-module_disabled__Hm-wx{pointer-events:none}.sash-module_sash__K-9lB.sash-module_mac__Jf6OJ.sash-module_vertical__pB-rs{cursor:col-resize}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs.sash-module_minimum__-UKxp{cursor:e-resize}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs.sash-module_maximum__TCWxD{cursor:w-resize}.sash-module_sash__K-9lB.sash-module_mac__Jf6OJ.sash-module_horizontal__kFbiw{cursor:row-resize}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_minimum__-UKxp{cursor:s-resize}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_maximum__TCWxD{cursor:n-resize}.sash-module_sash__K-9lB.sash-module_disabled__Hm-wx{cursor:default!important;pointer-events:none!important}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs{cursor:ew-resize;top:0;width:var(--sash-size);height:100%}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw{cursor:ns-resize;left:0;width:100%;height:var(--sash-size)}.sash-module_sash__K-9lB:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-{content:" ";height:calc(var(--sash-size) * 2);width:calc(var(--sash-size) * 2);z-index:100;display:block;cursor:all-scroll;position:absolute}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-north__f7Noe:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk,.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-south__6ZrFC:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R{cursor:nwse-resize}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-north__f7Noe:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R,.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw.sash-module_orthogonal-edge-south__6ZrFC:not(.sash-module_disabled__Hm-wx)>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk{cursor:nesw-resize}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk{left:calc(var(--sash-size) * -.5);top:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R{left:calc(var(--sash-size) * -.5);bottom:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_start__uZEDk{top:calc(var(--sash-size) * -.5);left:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw>.sash-module_orthogonal-drag-handle__Yii2-.sash-module_end__0TP-R{top:calc(var(--sash-size) * -.5);right:calc(var(--sash-size) * -1)}.sash-module_sash__K-9lB:before{content:"";pointer-events:none;position:absolute;width:100%;height:100%;transition:background-color var(--sash-hover-transition-duration) ease-out;background:transparent}.sash-module_sash__K-9lB.sash-module_vertical__pB-rs:before{width:var(--sash-hover-size);left:calc(50% - (var(--sash-hover-size) / 2))}.sash-module_sash__K-9lB.sash-module_horizontal__kFbiw:before{height:var(--sash-hover-size);top:calc(50% - (var(--sash-hover-size) / 2))}.sash-module_sash__K-9lB.sash-module_hover__80W6I:before,.sash-module_sash__K-9lB.sash-module_active__bJspD:before{background:var(--focus-border)}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BootOverlay — Loading animation displayed while Nodepod boots.
|
|
3
|
+
*
|
|
4
|
+
* Shows staged progress: initializing → writing files → installing → starting → ready.
|
|
5
|
+
* Includes a progress bar and stage-specific messaging with a pulsing animation.
|
|
6
|
+
*/
|
|
7
|
+
import type { BootOverlayProps } from "../types";
|
|
8
|
+
/**
|
|
9
|
+
* Full-screen loading overlay with staged boot progress.
|
|
10
|
+
*
|
|
11
|
+
* Renders over the workbench while Nodepod boots. Shows:
|
|
12
|
+
* - Current stage icon + label
|
|
13
|
+
* - Progress bar with percentage
|
|
14
|
+
* - Descriptive message of what's happening
|
|
15
|
+
* - Pulsing dots animation
|
|
16
|
+
*/
|
|
17
|
+
export declare function BootOverlay({ progress, className }: BootOverlayProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeEditor — Monaco editor with file tabs.
|
|
3
|
+
*
|
|
4
|
+
* Uses @monaco-editor/react for the editor and renders a tab bar
|
|
5
|
+
* of open files. Supports dark theme that matches the sandbox.
|
|
6
|
+
*/
|
|
7
|
+
import type { CodeEditorProps } from "../types";
|
|
8
|
+
/**
|
|
9
|
+
* CodeEditor component — Monaco editor with file tabs.
|
|
10
|
+
*/
|
|
11
|
+
export declare function CodeEditor({ files, activeFile, openFiles, onSelectFile, onCloseFile, onFileChange, readOnly, }: CodeEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FileTree — Collapsible file/folder tree with icons.
|
|
3
|
+
*
|
|
4
|
+
* Renders a recursive tree of FileNodes. Folders expand/collapse on click.
|
|
5
|
+
* Files are selectable and show the appropriate icon based on extension.
|
|
6
|
+
* Uses inline SVG icons for reliable cross-platform rendering.
|
|
7
|
+
*/
|
|
8
|
+
import type { FileMap, FileNode, FileTreeProps } from "../types";
|
|
9
|
+
/**
|
|
10
|
+
* Build a tree structure from a flat FileMap.
|
|
11
|
+
*
|
|
12
|
+
* Converts { "routes/api.js": "...", "server.js": "..." }
|
|
13
|
+
* into a nested FileNode[] tree.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildFileTree(files: FileMap): FileNode[];
|
|
16
|
+
/**
|
|
17
|
+
* FileTree component — renders a collapsible tree of files and folders.
|
|
18
|
+
*/
|
|
19
|
+
export declare function FileTree({ files, selectedFile, onSelectFile }: FileTreeProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preview — Full-width iframe that renders the Nodepod virtual server.
|
|
3
|
+
*
|
|
4
|
+
* Loads the URL from Nodepod's Service Worker proxy (/__virtual__/PORT/).
|
|
5
|
+
* The toolbar handles the URL bar and refresh — this is just the iframe.
|
|
6
|
+
*/
|
|
7
|
+
import type { PreviewProps } from "../types";
|
|
8
|
+
/**
|
|
9
|
+
* Preview component — renders the dev server output in a full-width iframe.
|
|
10
|
+
*
|
|
11
|
+
* The URL points to /__virtual__/PORT/ which is intercepted by the
|
|
12
|
+
* Nodepod Service Worker and proxied to the Express server running
|
|
13
|
+
* in the Web Worker.
|
|
14
|
+
*/
|
|
15
|
+
export declare function Preview({ url, className }: PreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal — Display terminal output from Nodepod processes.
|
|
3
|
+
*
|
|
4
|
+
* Simple scrolling output panel styled like a terminal.
|
|
5
|
+
* Auto-scrolls to the bottom as new output arrives.
|
|
6
|
+
*/
|
|
7
|
+
import type { TerminalProps } from "../types";
|
|
8
|
+
/**
|
|
9
|
+
* Terminal component — renders process stdout/stderr in a terminal-style panel.
|
|
10
|
+
*
|
|
11
|
+
* Uses a simple div-based approach (not xterm.js) for the initial version.
|
|
12
|
+
* This keeps the bundle small and avoids the xterm peer dependency
|
|
13
|
+
* for consumers who don't need full terminal emulation.
|
|
14
|
+
*/
|
|
15
|
+
export declare function Terminal({ output, className }: TerminalProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ViewSlider — Pill-shaped toggle to switch between Code and Preview views.
|
|
3
|
+
*
|
|
4
|
+
* Inspired by bolt.diy's Slider component. Uses Framer Motion's layoutId
|
|
5
|
+
* for a smooth animated pill that slides between options.
|
|
6
|
+
*
|
|
7
|
+
* @see bolt.diy: app/components/ui/Slider.tsx
|
|
8
|
+
*/
|
|
9
|
+
import React from "react";
|
|
10
|
+
/** The two views available in the workbench */
|
|
11
|
+
export type WorkbenchView = "code" | "preview";
|
|
12
|
+
interface ViewSliderProps {
|
|
13
|
+
selected: WorkbenchView;
|
|
14
|
+
onSelect: (view: WorkbenchView) => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* ViewSlider — renders a pill-shaped toggle with animated selection indicator.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <ViewSlider selected={view} onSelect={setView} />
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare const ViewSlider: React.NamedExoticComponent<ViewSliderProps>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workbench — Main layout component for the code sandbox.
|
|
3
|
+
*
|
|
4
|
+
* Two full-width views toggled via a pill slider in the toolbar:
|
|
5
|
+
* - Code: FileTree (left) + Editor (top-right) + Terminal (bottom-right)
|
|
6
|
+
* - Preview: Full-width browser iframe with URL bar
|
|
7
|
+
*
|
|
8
|
+
* The toggle lives inside a compact toolbar row shared with the URL bar.
|
|
9
|
+
* Both views are full-width — Preview has no file tree, Code has no iframe.
|
|
10
|
+
*
|
|
11
|
+
* Responsive: works from ~320px up. On narrow screens the file tree
|
|
12
|
+
* collapses to a smaller width, and the allotment handles overflow.
|
|
13
|
+
*
|
|
14
|
+
* @see bolt.diy: app/components/workbench/Workbench.client.tsx (reference)
|
|
15
|
+
*/
|
|
16
|
+
import "allotment/dist/style.css";
|
|
17
|
+
import type { CodeSandboxProps } from "../types";
|
|
18
|
+
/**
|
|
19
|
+
* CodeSandbox — The main entrypoint component.
|
|
20
|
+
*
|
|
21
|
+
* Renders a complete IDE-like workbench with two full-width views:
|
|
22
|
+
* - Code: file tree + editor + terminal (split panes)
|
|
23
|
+
* - Preview: full-width browser iframe
|
|
24
|
+
*
|
|
25
|
+
* A compact toolbar row contains the view toggle and (in preview mode)
|
|
26
|
+
* a URL bar with refresh button.
|
|
27
|
+
*/
|
|
28
|
+
export declare function CodeSandbox(props: CodeSandboxProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useRuntime — React hook wrapping NodepodRuntime lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* Manages the Nodepod runtime instance and exposes reactive state
|
|
5
|
+
* for all UI components (progress, files, terminal output, preview URL).
|
|
6
|
+
*/
|
|
7
|
+
import { NodepodRuntime } from "../services/runtime";
|
|
8
|
+
import type { CodeSandboxProps, FileMap, RuntimeState } from "../types";
|
|
9
|
+
/**
|
|
10
|
+
* Hook that manages the full Nodepod runtime lifecycle.
|
|
11
|
+
*
|
|
12
|
+
* @param props - CodeSandbox component props
|
|
13
|
+
* @returns Reactive runtime state + control functions
|
|
14
|
+
*/
|
|
15
|
+
export declare function useRuntime(props: CodeSandboxProps): {
|
|
16
|
+
state: RuntimeState;
|
|
17
|
+
selectedFile: string | null;
|
|
18
|
+
openFiles: string[];
|
|
19
|
+
handleFileChange: (path: string, content: string) => Promise<void>;
|
|
20
|
+
handleSelectFile: (path: string) => void;
|
|
21
|
+
handleCloseFile: (path: string) => void;
|
|
22
|
+
restart: () => Promise<void>;
|
|
23
|
+
getChangedFiles: () => FileMap;
|
|
24
|
+
runtime: import("react").MutableRefObject<NodepodRuntime | null>;
|
|
25
|
+
};
|