@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.
Files changed (92) hide show
  1. package/README.md +107 -0
  2. package/dist/console.d.ts +3 -0
  3. package/dist/console.d.ts.map +1 -0
  4. package/dist/console.js +161 -0
  5. package/dist/console.js.map +1 -0
  6. package/dist/editor/internal/language.d.ts +3 -0
  7. package/dist/editor/internal/language.d.ts.map +1 -0
  8. package/dist/editor/internal/tree.d.ts +13 -0
  9. package/dist/editor/internal/tree.d.ts.map +1 -0
  10. package/dist/editor/primitives/code-editor.d.ts +26 -0
  11. package/dist/editor/primitives/code-editor.d.ts.map +1 -0
  12. package/dist/editor/primitives/file-tree.d.ts +27 -0
  13. package/dist/editor/primitives/file-tree.d.ts.map +1 -0
  14. package/dist/editor/sandbox-code-editor.d.ts +32 -0
  15. package/dist/editor/sandbox-code-editor.d.ts.map +1 -0
  16. package/dist/editor/sandbox-file-tree.d.ts +29 -0
  17. package/dist/editor/sandbox-file-tree.d.ts.map +1 -0
  18. package/dist/editor/sandbox-ide.d.ts +23 -0
  19. package/dist/editor/sandbox-ide.d.ts.map +1 -0
  20. package/dist/editor.d.ts +6 -0
  21. package/dist/editor.d.ts.map +1 -0
  22. package/dist/editor.js +990 -0
  23. package/dist/editor.js.map +1 -0
  24. package/dist/files/geist-cyrillic-wght-normal.woff2 +0 -0
  25. package/dist/files/geist-latin-ext-wght-normal.woff2 +0 -0
  26. package/dist/files/geist-latin-wght-normal.woff2 +0 -0
  27. package/dist/index.d.ts +9 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +2556 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/preview/primitives/web-preview.d.ts +36 -0
  32. package/dist/preview/primitives/web-preview.d.ts.map +1 -0
  33. package/dist/preview/sandbox-preview.d.ts +58 -0
  34. package/dist/preview/sandbox-preview.d.ts.map +1 -0
  35. package/dist/primitives/lib/utils.d.ts +3 -0
  36. package/dist/primitives/lib/utils.d.ts.map +1 -0
  37. package/dist/primitives/stack-trace.d.ts +38 -0
  38. package/dist/primitives/stack-trace.d.ts.map +1 -0
  39. package/dist/primitives/ui/avatar.d.ts +12 -0
  40. package/dist/primitives/ui/avatar.d.ts.map +1 -0
  41. package/dist/primitives/ui/badge.d.ts +8 -0
  42. package/dist/primitives/ui/badge.d.ts.map +1 -0
  43. package/dist/primitives/ui/button-group.d.ts +11 -0
  44. package/dist/primitives/ui/button-group.d.ts.map +1 -0
  45. package/dist/primitives/ui/button.d.ts +9 -0
  46. package/dist/primitives/ui/button.d.ts.map +1 -0
  47. package/dist/primitives/ui/collapsible.d.ts +6 -0
  48. package/dist/primitives/ui/collapsible.d.ts.map +1 -0
  49. package/dist/primitives/ui/dialog.d.ts +18 -0
  50. package/dist/primitives/ui/dialog.d.ts.map +1 -0
  51. package/dist/primitives/ui/dropdown-menu.d.ts +30 -0
  52. package/dist/primitives/ui/dropdown-menu.d.ts.map +1 -0
  53. package/dist/primitives/ui/empty.d.ts +12 -0
  54. package/dist/primitives/ui/empty.d.ts.map +1 -0
  55. package/dist/primitives/ui/hover-card.d.ts +6 -0
  56. package/dist/primitives/ui/hover-card.d.ts.map +1 -0
  57. package/dist/primitives/ui/input-group.d.ts +19 -0
  58. package/dist/primitives/ui/input-group.d.ts.map +1 -0
  59. package/dist/primitives/ui/input.d.ts +4 -0
  60. package/dist/primitives/ui/input.d.ts.map +1 -0
  61. package/dist/primitives/ui/loading-dots.d.ts +7 -0
  62. package/dist/primitives/ui/loading-dots.d.ts.map +1 -0
  63. package/dist/primitives/ui/loading.d.ts +6 -0
  64. package/dist/primitives/ui/loading.d.ts.map +1 -0
  65. package/dist/primitives/ui/popover.d.ts +10 -0
  66. package/dist/primitives/ui/popover.d.ts.map +1 -0
  67. package/dist/primitives/ui/scroll-area.d.ts +5 -0
  68. package/dist/primitives/ui/scroll-area.d.ts.map +1 -0
  69. package/dist/primitives/ui/select.d.ts +16 -0
  70. package/dist/primitives/ui/select.d.ts.map +1 -0
  71. package/dist/primitives/ui/separator.d.ts +4 -0
  72. package/dist/primitives/ui/separator.d.ts.map +1 -0
  73. package/dist/primitives/ui/spinner.d.ts +3 -0
  74. package/dist/primitives/ui/spinner.d.ts.map +1 -0
  75. package/dist/primitives/ui/tabs.d.ts +11 -0
  76. package/dist/primitives/ui/tabs.d.ts.map +1 -0
  77. package/dist/primitives/ui/textarea.d.ts +4 -0
  78. package/dist/primitives/ui/textarea.d.ts.map +1 -0
  79. package/dist/primitives/ui/tooltip.d.ts +7 -0
  80. package/dist/primitives/ui/tooltip.d.ts.map +1 -0
  81. package/dist/provider/sandbox-provider.d.ts +44 -0
  82. package/dist/provider/sandbox-provider.d.ts.map +1 -0
  83. package/dist/sandbox-attribution.d.ts +9 -0
  84. package/dist/sandbox-attribution.d.ts.map +1 -0
  85. package/dist/sandbox-chrome.d.ts +38 -0
  86. package/dist/sandbox-chrome.d.ts.map +1 -0
  87. package/dist/sandbox.d.ts +10 -0
  88. package/dist/sandbox.d.ts.map +1 -0
  89. package/dist/snapshots/sandbox-snapshots.d.ts +14 -0
  90. package/dist/snapshots/sandbox-snapshots.d.ts.map +1 -0
  91. package/dist/styles.css +2 -0
  92. 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,3 @@
1
+ export { WebPreviewConsole as SandboxConsole } from './preview/primitives/web-preview';
2
+ export type { WebPreviewConsoleProps as SandboxConsoleProps } from './preview/primitives/web-preview';
3
+ //# sourceMappingURL=console.d.ts.map
@@ -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"}
@@ -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,3 @@
1
+ import type { CodeEditorLanguage } from '../primitives/code-editor';
2
+ export declare function guessLanguage(path: string): CodeEditorLanguage;
3
+ //# sourceMappingURL=language.d.ts.map
@@ -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"}
@@ -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"}