@browsernode/elements 0.0.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/README.md +107 -0
- package/dist/console.d.ts +3 -0
- package/dist/console.d.ts.map +1 -0
- package/dist/console.js +161 -0
- package/dist/console.js.map +1 -0
- package/dist/editor/internal/language.d.ts +3 -0
- package/dist/editor/internal/language.d.ts.map +1 -0
- package/dist/editor/internal/tree.d.ts +13 -0
- package/dist/editor/internal/tree.d.ts.map +1 -0
- package/dist/editor/primitives/code-editor.d.ts +26 -0
- package/dist/editor/primitives/code-editor.d.ts.map +1 -0
- package/dist/editor/primitives/file-tree.d.ts +27 -0
- package/dist/editor/primitives/file-tree.d.ts.map +1 -0
- package/dist/editor/sandbox-code-editor.d.ts +32 -0
- package/dist/editor/sandbox-code-editor.d.ts.map +1 -0
- package/dist/editor/sandbox-file-tree.d.ts +29 -0
- package/dist/editor/sandbox-file-tree.d.ts.map +1 -0
- package/dist/editor/sandbox-ide.d.ts +23 -0
- package/dist/editor/sandbox-ide.d.ts.map +1 -0
- package/dist/editor.d.ts +6 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +990 -0
- package/dist/editor.js.map +1 -0
- package/dist/files/geist-cyrillic-wght-normal.woff2 +0 -0
- package/dist/files/geist-latin-ext-wght-normal.woff2 +0 -0
- package/dist/files/geist-latin-wght-normal.woff2 +0 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2556 -0
- package/dist/index.js.map +1 -0
- package/dist/preview/primitives/web-preview.d.ts +36 -0
- package/dist/preview/primitives/web-preview.d.ts.map +1 -0
- package/dist/preview/sandbox-preview.d.ts +58 -0
- package/dist/preview/sandbox-preview.d.ts.map +1 -0
- package/dist/primitives/lib/utils.d.ts +3 -0
- package/dist/primitives/lib/utils.d.ts.map +1 -0
- package/dist/primitives/stack-trace.d.ts +38 -0
- package/dist/primitives/stack-trace.d.ts.map +1 -0
- package/dist/primitives/ui/avatar.d.ts +12 -0
- package/dist/primitives/ui/avatar.d.ts.map +1 -0
- package/dist/primitives/ui/badge.d.ts +8 -0
- package/dist/primitives/ui/badge.d.ts.map +1 -0
- package/dist/primitives/ui/button-group.d.ts +11 -0
- package/dist/primitives/ui/button-group.d.ts.map +1 -0
- package/dist/primitives/ui/button.d.ts +9 -0
- package/dist/primitives/ui/button.d.ts.map +1 -0
- package/dist/primitives/ui/collapsible.d.ts +6 -0
- package/dist/primitives/ui/collapsible.d.ts.map +1 -0
- package/dist/primitives/ui/dialog.d.ts +18 -0
- package/dist/primitives/ui/dialog.d.ts.map +1 -0
- package/dist/primitives/ui/dropdown-menu.d.ts +30 -0
- package/dist/primitives/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/primitives/ui/empty.d.ts +12 -0
- package/dist/primitives/ui/empty.d.ts.map +1 -0
- package/dist/primitives/ui/hover-card.d.ts +6 -0
- package/dist/primitives/ui/hover-card.d.ts.map +1 -0
- package/dist/primitives/ui/input-group.d.ts +19 -0
- package/dist/primitives/ui/input-group.d.ts.map +1 -0
- package/dist/primitives/ui/input.d.ts +4 -0
- package/dist/primitives/ui/input.d.ts.map +1 -0
- package/dist/primitives/ui/loading-dots.d.ts +7 -0
- package/dist/primitives/ui/loading-dots.d.ts.map +1 -0
- package/dist/primitives/ui/loading.d.ts +6 -0
- package/dist/primitives/ui/loading.d.ts.map +1 -0
- package/dist/primitives/ui/popover.d.ts +10 -0
- package/dist/primitives/ui/popover.d.ts.map +1 -0
- package/dist/primitives/ui/scroll-area.d.ts +5 -0
- package/dist/primitives/ui/scroll-area.d.ts.map +1 -0
- package/dist/primitives/ui/select.d.ts +16 -0
- package/dist/primitives/ui/select.d.ts.map +1 -0
- package/dist/primitives/ui/separator.d.ts +4 -0
- package/dist/primitives/ui/separator.d.ts.map +1 -0
- package/dist/primitives/ui/spinner.d.ts +3 -0
- package/dist/primitives/ui/spinner.d.ts.map +1 -0
- package/dist/primitives/ui/tabs.d.ts +11 -0
- package/dist/primitives/ui/tabs.d.ts.map +1 -0
- package/dist/primitives/ui/textarea.d.ts +4 -0
- package/dist/primitives/ui/textarea.d.ts.map +1 -0
- package/dist/primitives/ui/tooltip.d.ts +7 -0
- package/dist/primitives/ui/tooltip.d.ts.map +1 -0
- package/dist/provider/sandbox-provider.d.ts +44 -0
- package/dist/provider/sandbox-provider.d.ts.map +1 -0
- package/dist/sandbox-attribution.d.ts +9 -0
- package/dist/sandbox-attribution.d.ts.map +1 -0
- package/dist/sandbox-chrome.d.ts +38 -0
- package/dist/sandbox-chrome.d.ts.map +1 -0
- package/dist/sandbox.d.ts +10 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/snapshots/sandbox-snapshots.d.ts +14 -0
- package/dist/snapshots/sandbox-snapshots.d.ts.map +1 -0
- package/dist/styles.css +2 -0
- package/package.json +76 -0
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @browsernode/elements
|
|
2
|
+
|
|
3
|
+
Composable React UI elements for [`@browsernode/sandbox`](https://www.npmjs.com/package/@browsernode/sandbox) — a complete IDE shell (toolbar, code editor, file tree, console, live preview) plus the underlying primitives, designed to drop in or compose freely.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @browsernode/elements @browsernode/react @browsernode/sandbox
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
(`react`, `react-dom`, plus the framework/bundler adapters you intend to use — e.g. `@browsernode/nextjs` and `@browsernode/esbuild-wasm` — are peer dependencies.)
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Import the stylesheet once at your app entry, then drop in `<Sandbox>`:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import '@browsernode/elements/styles.css';
|
|
19
|
+
import { Sandbox } from '@browsernode/elements';
|
|
20
|
+
|
|
21
|
+
export default function App() {
|
|
22
|
+
return (
|
|
23
|
+
<Sandbox
|
|
24
|
+
framework="nextjs"
|
|
25
|
+
source={{
|
|
26
|
+
'/app/page.tsx': `export default () => <h1>Hello sandbox</h1>;`,
|
|
27
|
+
}}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
That's the zero-config drop-in: it bundles `<SandboxProvider>` (sandbox lifecycle + UI extras) with `<SandboxChrome>` (toolbar + web/code body + console drawer) into a single tag.
|
|
34
|
+
|
|
35
|
+
## Composition
|
|
36
|
+
|
|
37
|
+
For sibling layouts (e.g. a chat panel beside the IDE that shares the same sandbox), lift the provider yourself:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import {
|
|
41
|
+
SandboxProvider,
|
|
42
|
+
SandboxChrome,
|
|
43
|
+
useSandbox,
|
|
44
|
+
} from '@browsernode/elements';
|
|
45
|
+
|
|
46
|
+
function MyChat() {
|
|
47
|
+
const { sandbox, fs, build } = useSandbox();
|
|
48
|
+
// ...
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default function App() {
|
|
52
|
+
return (
|
|
53
|
+
<SandboxProvider framework="nextjs" source={...}>
|
|
54
|
+
<MyChat />
|
|
55
|
+
<SandboxChrome />
|
|
56
|
+
</SandboxProvider>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Public surface
|
|
62
|
+
|
|
63
|
+
### Top-level (`@browsernode/elements`)
|
|
64
|
+
|
|
65
|
+
| Component | Role |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `<Sandbox>` | Drop-in: provider + chrome in one tag |
|
|
68
|
+
| `<SandboxProvider>` | Lifecycle + UI extras (theme, openTabs, selectedPath, chatStorage, activePanel) |
|
|
69
|
+
| `<SandboxChrome>` | UI shell consuming the provider — toolbar, web/code body, console |
|
|
70
|
+
| `<SandboxIDE>` | File tree + code editor pair |
|
|
71
|
+
| `<SandboxFileTree>` | File tree only |
|
|
72
|
+
| `<SandboxCodeEditor>` | Code editor only |
|
|
73
|
+
| `<SandboxConsole>` | Console drawer |
|
|
74
|
+
|
|
75
|
+
Hooks: `useSandbox`, `useElementsContext`, `useElementsContextOrThrow`.
|
|
76
|
+
|
|
77
|
+
### Subpaths
|
|
78
|
+
|
|
79
|
+
- `@browsernode/elements/editor` — `<SandboxIDE>`, `<SandboxFileTree>`, `<SandboxCodeEditor>`, plus headless primitives (`<CodeEditor>`, `<FileTree>`, `<CodeBlock>` family)
|
|
80
|
+
- `@browsernode/elements/console` — `<SandboxConsole>` alone
|
|
81
|
+
- `@browsernode/elements/styles.css` — compiled stylesheet (Tailwind utilities + shadcn vars + Geist font)
|
|
82
|
+
|
|
83
|
+
## UI toggles
|
|
84
|
+
|
|
85
|
+
`<Sandbox>` and `<SandboxChrome>` accept a `ui` prop with per-control flags. All default to `true` except `showSettings`:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
<Sandbox
|
|
89
|
+
ui={{
|
|
90
|
+
showCodeEditor: true,
|
|
91
|
+
showNavigation: true,
|
|
92
|
+
showReload: true,
|
|
93
|
+
showDeviceToggle: true,
|
|
94
|
+
showFullScreenToggle: true,
|
|
95
|
+
showSnapshots: true,
|
|
96
|
+
showExportFiles: true,
|
|
97
|
+
showSettings: false,
|
|
98
|
+
showConsole: true,
|
|
99
|
+
}}
|
|
100
|
+
framework="nextjs"
|
|
101
|
+
source={...}
|
|
102
|
+
/>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
Apache-2.0 © Frontend AI, Inc.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,IAAI,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvF,YAAY,EAAE,sBAAsB,IAAI,mBAAmB,EAAE,MAAM,kCAAkC,CAAC"}
|
package/dist/console.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// src/primitives/ui/button.tsx
|
|
2
|
+
import { Button as ButtonPrimitive } from "@base-ui/react/button";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
|
|
5
|
+
// src/primitives/lib/utils.ts
|
|
6
|
+
import { clsx } from "clsx";
|
|
7
|
+
import { twMerge } from "tailwind-merge";
|
|
8
|
+
function cn(...inputs) {
|
|
9
|
+
return twMerge(clsx(inputs));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/primitives/ui/button.tsx
|
|
13
|
+
import { jsx } from "react/jsx-runtime";
|
|
14
|
+
var buttonVariants = cva(
|
|
15
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
16
|
+
{
|
|
17
|
+
variants: {
|
|
18
|
+
variant: {
|
|
19
|
+
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
20
|
+
outline: "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
21
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
22
|
+
ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
23
|
+
destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
|
24
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
25
|
+
},
|
|
26
|
+
size: {
|
|
27
|
+
default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
28
|
+
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
29
|
+
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
|
30
|
+
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
31
|
+
icon: "size-8",
|
|
32
|
+
"icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
|
33
|
+
"icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
|
|
34
|
+
"icon-lg": "size-9"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
variant: "default",
|
|
39
|
+
size: "default"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
function Button({
|
|
44
|
+
className,
|
|
45
|
+
variant = "default",
|
|
46
|
+
size = "default",
|
|
47
|
+
...props
|
|
48
|
+
}) {
|
|
49
|
+
return /* @__PURE__ */ jsx(
|
|
50
|
+
ButtonPrimitive,
|
|
51
|
+
{
|
|
52
|
+
"data-slot": "button",
|
|
53
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
54
|
+
...props
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/primitives/ui/collapsible.tsx
|
|
60
|
+
import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible";
|
|
61
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
62
|
+
function Collapsible({ ...props }) {
|
|
63
|
+
return /* @__PURE__ */ jsx2(CollapsiblePrimitive.Root, { "data-slot": "collapsible", ...props });
|
|
64
|
+
}
|
|
65
|
+
function CollapsibleTrigger({ ...props }) {
|
|
66
|
+
return /* @__PURE__ */ jsx2(CollapsiblePrimitive.Trigger, { "data-slot": "collapsible-trigger", ...props });
|
|
67
|
+
}
|
|
68
|
+
function CollapsibleContent({ ...props }) {
|
|
69
|
+
return /* @__PURE__ */ jsx2(CollapsiblePrimitive.Panel, { "data-slot": "collapsible-content", ...props });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/primitives/ui/input.tsx
|
|
73
|
+
import { Input as InputPrimitive } from "@base-ui/react/input";
|
|
74
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
75
|
+
|
|
76
|
+
// src/primitives/ui/tooltip.tsx
|
|
77
|
+
import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
|
|
78
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
79
|
+
|
|
80
|
+
// src/preview/primitives/web-preview.tsx
|
|
81
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
82
|
+
import {
|
|
83
|
+
createContext,
|
|
84
|
+
useCallback,
|
|
85
|
+
useContext,
|
|
86
|
+
useMemo,
|
|
87
|
+
useState
|
|
88
|
+
} from "react";
|
|
89
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
90
|
+
var WebPreviewContext = createContext(null);
|
|
91
|
+
var useWebPreview = () => {
|
|
92
|
+
const context = useContext(WebPreviewContext);
|
|
93
|
+
if (!context) {
|
|
94
|
+
throw new Error("WebPreview components must be used within a WebPreview");
|
|
95
|
+
}
|
|
96
|
+
return context;
|
|
97
|
+
};
|
|
98
|
+
var WebPreviewConsole = ({
|
|
99
|
+
className,
|
|
100
|
+
logs = [],
|
|
101
|
+
children,
|
|
102
|
+
...props
|
|
103
|
+
}) => {
|
|
104
|
+
const { consoleOpen, setConsoleOpen } = useWebPreview();
|
|
105
|
+
return /* @__PURE__ */ jsxs2(
|
|
106
|
+
Collapsible,
|
|
107
|
+
{
|
|
108
|
+
className: cn("border-t bg-muted/50 font-mono text-sm", className),
|
|
109
|
+
onOpenChange: setConsoleOpen,
|
|
110
|
+
open: consoleOpen,
|
|
111
|
+
...props,
|
|
112
|
+
children: [
|
|
113
|
+
/* @__PURE__ */ jsxs2(CollapsibleTrigger, { render: /* @__PURE__ */ jsx5(Button, { className: "flex w-full items-center justify-between p-4 text-left font-medium hover:bg-muted/50", variant: "ghost" }), children: [
|
|
114
|
+
"Console",
|
|
115
|
+
/* @__PURE__ */ jsx5(
|
|
116
|
+
ChevronDownIcon,
|
|
117
|
+
{
|
|
118
|
+
className: cn(
|
|
119
|
+
"h-4 w-4 transition-transform duration-200",
|
|
120
|
+
consoleOpen && "rotate-180"
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
] }),
|
|
125
|
+
/* @__PURE__ */ jsx5(
|
|
126
|
+
CollapsibleContent,
|
|
127
|
+
{
|
|
128
|
+
className: cn(
|
|
129
|
+
"px-4 pb-4",
|
|
130
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 outline-none data-[state=closed]:animate-out data-[state=open]:animate-in"
|
|
131
|
+
),
|
|
132
|
+
children: /* @__PURE__ */ jsxs2("div", { className: "max-h-48 space-y-1 overflow-y-auto", children: [
|
|
133
|
+
logs.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground", children: "No console output" }) : logs.map((log) => /* @__PURE__ */ jsxs2(
|
|
134
|
+
"div",
|
|
135
|
+
{
|
|
136
|
+
className: cn(
|
|
137
|
+
"text-xs",
|
|
138
|
+
log.level === "error" && "text-destructive",
|
|
139
|
+
log.level === "warn" && "text-yellow-600",
|
|
140
|
+
log.level === "log" && "text-foreground"
|
|
141
|
+
),
|
|
142
|
+
children: [
|
|
143
|
+
/* @__PURE__ */ jsx5("span", { className: "text-muted-foreground", children: log.timestamp.toLocaleTimeString() }),
|
|
144
|
+
" ",
|
|
145
|
+
log.message
|
|
146
|
+
]
|
|
147
|
+
},
|
|
148
|
+
`${log.timestamp.getTime()}-${log.level}-${log.message}`
|
|
149
|
+
)),
|
|
150
|
+
children
|
|
151
|
+
] })
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
};
|
|
158
|
+
export {
|
|
159
|
+
WebPreviewConsole as SandboxConsole
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=console.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/primitives/ui/button.tsx","../src/primitives/lib/utils.ts","../src/primitives/ui/collapsible.tsx","../src/primitives/ui/input.tsx","../src/primitives/ui/tooltip.tsx","../src/preview/primitives/web-preview.tsx"],"sourcesContent":["import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\"\n\nimport { Collapsible as CollapsiblePrimitive } from \"@base-ui/react/collapsible\"\n\nfunction Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />\n}\n\nfunction CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {\n return (\n <CollapsiblePrimitive.Trigger data-slot=\"collapsible-trigger\" {...props} />\n )\n}\n\nfunction CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {\n return (\n <CollapsiblePrimitive.Panel data-slot=\"collapsible-content\" {...props} />\n )\n}\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\n","import * as React from \"react\"\nimport { Input as InputPrimitive } from \"@base-ui/react/input\"\n\nimport { cn } from \"../lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <InputPrimitive\n type={type}\n data-slot=\"input\"\n className={cn(\n \"h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","import { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\"\n\nimport { cn } from \"../lib/utils\"\n\nfunction TooltipProvider({\n delay = 0,\n ...props\n}: TooltipPrimitive.Provider.Props) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delay={delay}\n {...props}\n />\n )\n}\n\nfunction Tooltip({ ...props }: TooltipPrimitive.Root.Props) {\n return <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n}\n\nfunction TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />\n}\n\nfunction TooltipContent({\n className,\n side = \"top\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 0,\n children,\n ...props\n}: TooltipPrimitive.Popup.Props &\n Pick<\n TooltipPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <TooltipPrimitive.Popup\n data-slot=\"tooltip-content\"\n className={cn(\n \"z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5\" />\n </TooltipPrimitive.Popup>\n </TooltipPrimitive.Positioner>\n </TooltipPrimitive.Portal>\n )\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n","\"use client\";\n\nimport { Button } from \"../../primitives/ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../../primitives/ui/collapsible\";\nimport { Input } from \"../../primitives/ui/input\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../../primitives/ui/tooltip\";\nimport { cn } from \"../../primitives/lib/utils\";\nimport { ChevronDownIcon } from \"lucide-react\";\nimport type { ComponentProps, ReactNode } from \"react\";\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useState,\n} from \"react\";\n\nexport interface WebPreviewContextValue {\n url: string;\n setUrl: (url: string) => void;\n consoleOpen: boolean;\n setConsoleOpen: (open: boolean) => void;\n}\n\nexport const WebPreviewContext = createContext<WebPreviewContextValue | null>(null);\n\nconst useWebPreview = () => {\n const context = useContext(WebPreviewContext);\n if (!context) {\n throw new Error(\"WebPreview components must be used within a WebPreview\");\n }\n return context;\n};\n\nexport type WebPreviewProps = ComponentProps<\"div\"> & {\n defaultUrl?: string;\n onUrlChange?: (url: string) => void;\n};\n\nexport const WebPreview = ({\n className,\n children,\n defaultUrl = \"\",\n onUrlChange,\n ...props\n}: WebPreviewProps) => {\n const [url, setUrl] = useState(defaultUrl);\n const [consoleOpen, setConsoleOpen] = useState(false);\n\n const handleUrlChange = useCallback(\n (newUrl: string) => {\n setUrl(newUrl);\n onUrlChange?.(newUrl);\n },\n [onUrlChange]\n );\n\n const contextValue = useMemo<WebPreviewContextValue>(\n () => ({\n consoleOpen,\n setConsoleOpen,\n setUrl: handleUrlChange,\n url,\n }),\n [consoleOpen, handleUrlChange, url]\n );\n\n return (\n <WebPreviewContext.Provider value={contextValue}>\n <div\n className={cn(\n \"flex size-full flex-col rounded-lg border bg-card\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n </WebPreviewContext.Provider>\n );\n};\n\nexport type WebPreviewNavigationProps = ComponentProps<\"div\">;\n\nexport const WebPreviewNavigation = ({\n className,\n children,\n ...props\n}: WebPreviewNavigationProps) => (\n <div\n className={cn(\"flex items-center gap-1 border-b p-2\", className)}\n {...props}\n >\n {children}\n </div>\n);\n\nexport type WebPreviewNavigationButtonProps = ComponentProps<typeof Button> & {\n tooltip?: string;\n};\n\nexport const WebPreviewNavigationButton = ({\n onClick,\n disabled,\n tooltip,\n children,\n className,\n ...props\n}: WebPreviewNavigationButtonProps) => (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger\n render={\n <Button\n className={cn(\"h-8 w-8 p-0 hover:text-foreground\", className)}\n disabled={disabled}\n onClick={onClick}\n size=\"sm\"\n variant=\"ghost\"\n {...props}\n />\n }\n >\n {children}\n </TooltipTrigger>\n <TooltipContent>\n <p>{tooltip}</p>\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n);\n\nexport type WebPreviewUrlProps = ComponentProps<typeof Input>;\n\nexport const WebPreviewUrl = ({\n value,\n onChange,\n onKeyDown,\n ...props\n}: WebPreviewUrlProps) => {\n const { url, setUrl } = useWebPreview();\n const [prevUrl, setPrevUrl] = useState(url);\n const [inputValue, setInputValue] = useState(url);\n\n // Sync input value with context URL when it changes externally (derived state pattern)\n if (url !== prevUrl) {\n setPrevUrl(url);\n setInputValue(url);\n }\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setInputValue(event.target.value);\n onChange?.(event);\n };\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Enter\") {\n const target = event.target as HTMLInputElement;\n setUrl(target.value);\n }\n onKeyDown?.(event);\n },\n [setUrl, onKeyDown]\n );\n\n return (\n <Input\n className=\"h-8 flex-1 text-sm\"\n onChange={onChange ?? handleChange}\n onKeyDown={handleKeyDown}\n placeholder=\"Enter URL...\"\n value={value ?? inputValue}\n {...props}\n />\n );\n};\n\nexport type WebPreviewBodyProps = ComponentProps<\"iframe\"> & {\n loading?: ReactNode;\n};\n\nexport const WebPreviewBody = ({\n className,\n loading,\n src,\n ...props\n}: WebPreviewBodyProps) => {\n const { url } = useWebPreview();\n\n return (\n <div className=\"flex-1\">\n <iframe\n className={cn(\"size-full\", className)}\n // oxlint-disable-next-line eslint-plugin-react(iframe-missing-sandbox)\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-presentation\"\n src={(src ?? url) || undefined}\n title=\"Preview\"\n {...props}\n />\n {loading}\n </div>\n );\n};\n\nexport type WebPreviewConsoleProps = ComponentProps<\"div\"> & {\n logs?: {\n level: \"log\" | \"warn\" | \"error\";\n message: string;\n timestamp: Date;\n }[];\n};\n\nexport const WebPreviewConsole = ({\n className,\n logs = [],\n children,\n ...props\n}: WebPreviewConsoleProps) => {\n const { consoleOpen, setConsoleOpen } = useWebPreview();\n\n return (\n <Collapsible\n className={cn(\"border-t bg-muted/50 font-mono text-sm\", className)}\n onOpenChange={setConsoleOpen}\n open={consoleOpen}\n {...props}\n >\n <CollapsibleTrigger render={<Button className=\"flex w-full items-center justify-between p-4 text-left font-medium hover:bg-muted/50\" variant=\"ghost\" />}>Console\n <ChevronDownIcon\n className={cn(\n \"h-4 w-4 transition-transform duration-200\",\n consoleOpen && \"rotate-180\"\n )}\n /></CollapsibleTrigger>\n <CollapsibleContent\n className={cn(\n \"px-4 pb-4\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\"\n )}\n >\n <div className=\"max-h-48 space-y-1 overflow-y-auto\">\n {logs.length === 0 ? (\n <p className=\"text-muted-foreground\">No console output</p>\n ) : (\n logs.map((log) => (\n <div\n className={cn(\n \"text-xs\",\n log.level === \"error\" && \"text-destructive\",\n log.level === \"warn\" && \"text-yellow-600\",\n log.level === \"log\" && \"text-foreground\"\n )}\n key={`${log.timestamp.getTime()}-${log.level}-${log.message}`}\n >\n <span className=\"text-muted-foreground\">\n {log.timestamp.toLocaleTimeString()}\n </span>{\" \"}\n {log.message}\n </div>\n ))\n )}\n {children}\n </div>\n </CollapsibleContent>\n </Collapsible>\n );\n};\n"],"mappings":"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","names":["jsx","jsx","jsx","jsx","jsxs","jsxs","jsx"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.d.ts","sourceRoot":"","sources":["../../../src/editor/internal/language.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAkBpE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAK9D"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
interface TreeNode {
|
|
3
|
+
name: string;
|
|
4
|
+
path: string;
|
|
5
|
+
/** null = file leaf. */
|
|
6
|
+
children: Map<string, TreeNode> | null;
|
|
7
|
+
}
|
|
8
|
+
export declare function buildTree(paths: string[]): TreeNode;
|
|
9
|
+
export declare function renderTree(node: TreeNode): ReactNode;
|
|
10
|
+
export declare function isFile(path: string, files: string[]): boolean;
|
|
11
|
+
export declare function defaultExpansion(files: string[]): Set<string>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/editor/internal/tree.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC;CACxC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,CAuBnD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAkBpD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAU7D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type Extension, type ReactCodeMirrorProps } from '@uiw/react-codemirror';
|
|
2
|
+
export type CodeEditorLanguage = 'typescript' | 'tsx' | 'javascript' | 'jsx' | 'css' | 'html' | 'json' | 'markdown' | 'plaintext';
|
|
3
|
+
export type CodeEditorTheme = 'light' | 'dark' | Extension;
|
|
4
|
+
export interface CodeEditorProps extends Omit<ReactCodeMirrorProps, 'value' | 'onChange' | 'extensions' | 'theme'> {
|
|
5
|
+
value: string;
|
|
6
|
+
onChange?: (next: string) => void;
|
|
7
|
+
language?: CodeEditorLanguage;
|
|
8
|
+
/**
|
|
9
|
+
* Editor color scheme. If omitted, falls back to `<SandboxProvider>`'s
|
|
10
|
+
* `theme` (or `'light'` when no provider is mounted). Pass an
|
|
11
|
+
* `Extension` to fully override CodeMirror's theme system.
|
|
12
|
+
*/
|
|
13
|
+
theme?: CodeEditorTheme;
|
|
14
|
+
/** Extra CodeMirror extensions appended to the language-derived ones. */
|
|
15
|
+
extensions?: Extension[];
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* `<CodeEditor>` — thin CodeMirror 6 wrapper. Pass `value` + `onChange`
|
|
20
|
+
* for controlled editing; `language` selects the syntax extension.
|
|
21
|
+
*
|
|
22
|
+
* The host is responsible for debouncing writes back to disk; this
|
|
23
|
+
* component fires `onChange` for every keystroke.
|
|
24
|
+
*/
|
|
25
|
+
export declare function CodeEditor({ value, onChange, language, theme, extensions: extraExtensions, className, basicSetup, ...rest }: CodeEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
//# sourceMappingURL=code-editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-editor.d.ts","sourceRoot":"","sources":["../../../src/editor/primitives/code-editor.tsx"],"names":[],"mappings":"AACA,OAAmB,EAEjB,KAAK,SAAS,EACd,KAAK,oBAAoB,EAC1B,MAAM,uBAAuB,CAAC;AAQ/B,MAAM,MAAM,kBAAkB,GAC1B,YAAY,GACZ,KAAK,GACL,YAAY,GACZ,KAAK,GACL,KAAK,GACL,MAAM,GACN,MAAM,GACN,UAAU,GACV,WAAW,CAAC;AAEhB,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAE3D,MAAM,WAAW,eACf,SAAQ,IAAI,CACV,oBAAoB,EACpB,OAAO,GAAG,UAAU,GAAG,YAAY,GAAG,OAAO,CAC9C;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B;;;;OAIG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,yEAAyE;IACzE,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,QAAsB,EACtB,KAAK,EACL,UAAU,EAAE,eAAe,EAC3B,SAAS,EACT,UAAU,EACV,GAAG,IAAI,EACR,EAAE,eAAe,2CAmCjB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
export type FileTreeProps = Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> & {
|
|
3
|
+
expanded?: Set<string>;
|
|
4
|
+
defaultExpanded?: Set<string>;
|
|
5
|
+
selectedPath?: string;
|
|
6
|
+
onSelect?: (path: string) => void;
|
|
7
|
+
onExpandedChange?: (expanded: Set<string>) => void;
|
|
8
|
+
};
|
|
9
|
+
export declare const FileTree: ({ expanded: controlledExpanded, defaultExpanded, selectedPath, onSelect, onExpandedChange, className, children, ...props }: FileTreeProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export type FileTreeIconProps = HTMLAttributes<HTMLSpanElement>;
|
|
11
|
+
export declare const FileTreeIcon: ({ className, children, ...props }: FileTreeIconProps) => import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export type FileTreeNameProps = HTMLAttributes<HTMLSpanElement>;
|
|
13
|
+
export declare const FileTreeName: ({ className, children, ...props }: FileTreeNameProps) => import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export type FileTreeFolderProps = HTMLAttributes<HTMLDivElement> & {
|
|
15
|
+
path: string;
|
|
16
|
+
name: string;
|
|
17
|
+
};
|
|
18
|
+
export declare const FileTreeFolder: ({ path, name, className, children, ...props }: FileTreeFolderProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export type FileTreeFileProps = HTMLAttributes<HTMLDivElement> & {
|
|
20
|
+
path: string;
|
|
21
|
+
name: string;
|
|
22
|
+
icon?: ReactNode;
|
|
23
|
+
};
|
|
24
|
+
export declare const FileTreeFile: ({ path, name, icon, className, children, ...props }: FileTreeFileProps) => import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export type FileTreeActionsProps = HTMLAttributes<HTMLDivElement>;
|
|
26
|
+
export declare const FileTreeActions: ({ className, children, ...props }: FileTreeActionsProps) => import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
//# sourceMappingURL=file-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-tree.d.ts","sourceRoot":"","sources":["../../../src/editor/primitives/file-tree.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA0BvD,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IAC7E,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;CACpD,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,4HAStB,aAAa,4CAqCf,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAEhE,eAAO,MAAM,YAAY,GAAI,mCAI1B,iBAAiB,4CAInB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAEhE,eAAO,MAAM,YAAY,GAAI,mCAI1B,iBAAiB,4CAInB,CAAC;AAcF,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,+CAM5B,mBAAmB,4CAiErB,CAAC;AAYF,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,qDAO1B,iBAAiB,4CA8CnB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;AAIlE,eAAO,MAAM,eAAe,GAAI,mCAI7B,oBAAoB,4CAUtB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { Extension } from '@codemirror/state';
|
|
3
|
+
import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
|
|
4
|
+
import type { Sandbox } from '@browsernode/sandbox';
|
|
5
|
+
import { type CodeEditorLanguage, type CodeEditorTheme } from './primitives/code-editor';
|
|
6
|
+
export interface SandboxCodeEditorProps {
|
|
7
|
+
/** Override the sandbox from the surrounding `<SandboxProvider>`. */
|
|
8
|
+
sandbox?: Sandbox | null;
|
|
9
|
+
/** Disable saves (Save button hidden, Cmd-S no-op). Default false. */
|
|
10
|
+
readOnly?: boolean;
|
|
11
|
+
/** CodeMirror theme override (forwarded to `<CodeEditor>`). */
|
|
12
|
+
theme?: CodeEditorTheme;
|
|
13
|
+
/** CodeMirror basic-setup overrides (line numbers, fold gutter, etc.). */
|
|
14
|
+
basicSetup?: ReactCodeMirrorProps['basicSetup'];
|
|
15
|
+
/** Extra CodeMirror extensions appended after the language ones. */
|
|
16
|
+
extensions?: Extension[];
|
|
17
|
+
/** Force a CodeMirror language regardless of file extension. */
|
|
18
|
+
language?: CodeEditorLanguage;
|
|
19
|
+
/** Hide the file header (filename + dirty dot + Save + More). */
|
|
20
|
+
hideHeader?: boolean;
|
|
21
|
+
/** Custom empty state when no file is selected. */
|
|
22
|
+
emptyState?: ReactNode;
|
|
23
|
+
/**
|
|
24
|
+
* Slot rendered inside the header, immediately after the filename and
|
|
25
|
+
* before the Save button. Used by `<SandboxIDELayout>` to inject the
|
|
26
|
+
* mobile dropdown trigger; consumers can use it for any leading chrome.
|
|
27
|
+
*/
|
|
28
|
+
headerStartSlot?: ReactNode;
|
|
29
|
+
className?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function SandboxCodeEditor({ sandbox: sandboxProp, readOnly, theme, basicSetup, extensions, language: languageProp, hideHeader, emptyState, headerStartSlot, className, }: SandboxCodeEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
//# sourceMappingURL=sandbox-code-editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-code-editor.d.ts","sourceRoot":"","sources":["../../src/editor/sandbox-code-editor.tsx"],"names":[],"mappings":"AASA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACrB,MAAM,0BAA0B,CAAC;AAYlC,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAChD,oEAAoE;IACpE,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,iEAAiE;IACjE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mDAAmD;IACnD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EAAE,WAAW,EACpB,QAAgB,EAChB,KAAK,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EAAE,YAAY,EACtB,UAAkB,EAClB,UAAU,EACV,eAAe,EACf,SAAS,GACV,EAAE,sBAAsB,2CAiPxB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { Sandbox } from '@browsernode/sandbox';
|
|
3
|
+
export interface SandboxFileTreeProps {
|
|
4
|
+
/** Override the sandbox from the surrounding `<SandboxProvider>`. */
|
|
5
|
+
sandbox?: Sandbox | null;
|
|
6
|
+
/** Initial folders to expand. Defaults to common roots when present. */
|
|
7
|
+
defaultExpanded?: Set<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Called when a file is selected. Fires *in addition* to updating the
|
|
10
|
+
* elements context's `selectedPath`.
|
|
11
|
+
*/
|
|
12
|
+
onSelect?: (path: string) => void;
|
|
13
|
+
/**
|
|
14
|
+
* Render mode:
|
|
15
|
+
* • `"tree"` (default) — full inline tree, expects a parent that
|
|
16
|
+
* gives it height to scroll within
|
|
17
|
+
* • `"dropdown"` — folder-icon button that opens a popover with the
|
|
18
|
+
* tree inside; selecting a file closes the popover
|
|
19
|
+
*/
|
|
20
|
+
display?: 'tree' | 'dropdown';
|
|
21
|
+
/**
|
|
22
|
+
* Trigger contents (dropdown variant). Defaults to a hamburger icon
|
|
23
|
+
* + "Select file" label.
|
|
24
|
+
*/
|
|
25
|
+
triggerLabel?: ReactNode;
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function SandboxFileTree({ sandbox: sandboxProp, defaultExpanded, onSelect, display, triggerLabel, className, }: SandboxFileTreeProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
//# sourceMappingURL=sandbox-file-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-file-tree.d.ts","sourceRoot":"","sources":["../../src/editor/sandbox-file-tree.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAErE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAgBpD,MAAM,WAAW,oBAAoB;IACnC,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,wEAAwE;IACxE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EAAE,WAAW,EACpB,eAAe,EACf,QAAQ,EACR,OAAgB,EAChB,YAAY,EACZ,SAAS,GACV,EAAE,oBAAoB,2CA+EtB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type CSSProperties } from 'react';
|
|
2
|
+
import type { Sandbox } from '@browsernode/sandbox';
|
|
3
|
+
import { type SandboxCodeEditorProps } from './sandbox-code-editor';
|
|
4
|
+
export interface SandboxIDEProps extends Omit<SandboxCodeEditorProps, 'headerStartSlot' | 'className'> {
|
|
5
|
+
/** Override the sandbox from the surrounding `<SandboxProvider>`. */
|
|
6
|
+
sandbox?: Sandbox | null;
|
|
7
|
+
/** Initial folders to expand (forwarded to `<SandboxFileTree>`). */
|
|
8
|
+
defaultExpanded?: Set<string>;
|
|
9
|
+
/** Hide the file tree entirely (editor-only layout). */
|
|
10
|
+
hideTree?: boolean;
|
|
11
|
+
/** Hide the code editor entirely (tree-only layout). */
|
|
12
|
+
hideViewer?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Drop the rounded-lg + border on the outer wrapper. Use when embedded
|
|
15
|
+
* inside a host frame that already provides chrome (e.g. inside
|
|
16
|
+
* `<Sandbox>`).
|
|
17
|
+
*/
|
|
18
|
+
hideBorder?: boolean;
|
|
19
|
+
className?: string;
|
|
20
|
+
style?: CSSProperties;
|
|
21
|
+
}
|
|
22
|
+
export declare function SandboxIDE({ sandbox, defaultExpanded, hideTree, hideViewer, hideBorder, className, style, ...codeProps }: SandboxIDEProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=sandbox-ide.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-ide.d.ts","sourceRoot":"","sources":["../../src/editor/sandbox-ide.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,eACf,SAAQ,IAAI,CAAC,sBAAsB,EAAE,iBAAiB,GAAG,WAAW,CAAC;IACrE,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,oEAAoE;IACpE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,wDAAwD;IACxD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,eAAe,EACf,QAAgB,EAChB,UAAkB,EAClB,UAAkB,EAClB,SAAS,EACT,KAAK,EACL,GAAG,SAAS,EACb,EAAE,eAAe,2CA0DjB"}
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { SandboxIDE, type SandboxIDEProps, } from './editor/sandbox-ide';
|
|
2
|
+
export { SandboxFileTree, type SandboxFileTreeProps, } from './editor/sandbox-file-tree';
|
|
3
|
+
export { SandboxCodeEditor, type SandboxCodeEditorProps, } from './editor/sandbox-code-editor';
|
|
4
|
+
export { CodeEditor, type CodeEditorProps, type CodeEditorLanguage, type CodeEditorTheme, } from './editor/primitives/code-editor';
|
|
5
|
+
export { FileTree, FileTreeFile, FileTreeFolder, type FileTreeProps, type FileTreeFileProps, type FileTreeFolderProps, } from './editor/primitives/file-tree';
|
|
6
|
+
//# sourceMappingURL=editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,GAC1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,eAAe,GACrB,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,+BAA+B,CAAC"}
|