@sampleapp.ai/sdk 1.0.29 → 1.0.30

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 (143) hide show
  1. package/dist/components/guardian/app-layout-no-sidebar.js +8 -0
  2. package/dist/components/guardian/ask-ai-view.js +249 -0
  3. package/dist/components/guardian/code-focus-section.d.ts +41 -0
  4. package/dist/components/guardian/code-focus-section.js +174 -0
  5. package/dist/components/guardian/context/guardian-context.js +94 -0
  6. package/dist/components/guardian/context/vm-context.js +28 -0
  7. package/dist/components/guardian/default-guide-view.js +34 -0
  8. package/dist/components/guardian/demo/guardian-demo.js +35 -0
  9. package/dist/components/guardian/demo/left-view/toggle.js +28 -0
  10. package/dist/components/guardian/demo/left-view.js +49 -0
  11. package/dist/components/guardian/guardian-component.js +79 -0
  12. package/dist/components/guardian/guardian-demo.js +35 -0
  13. package/dist/components/guardian/guardian-home.d.ts +4 -0
  14. package/dist/components/guardian/guardian-home.js +61 -0
  15. package/dist/components/guardian/guardian-playground.js +45 -0
  16. package/dist/components/guardian/guardian-style-wrapper.js +29 -0
  17. package/dist/components/guardian/guardian-upload-spec.d.ts +14 -0
  18. package/dist/components/guardian/guardian-upload-spec.js +160 -0
  19. package/dist/components/guardian/header/glassmorphic-combobox.d.ts +15 -0
  20. package/dist/components/guardian/header/glassmorphic-combobox.js +30 -0
  21. package/dist/components/guardian/header.js +61 -0
  22. package/dist/components/guardian/hooks/use-frame-messages.js +65 -0
  23. package/dist/components/guardian/hooks/use-frame-params.js +44 -0
  24. package/dist/components/guardian/hooks/use-sandbox-url-loader.js +101 -0
  25. package/dist/components/guardian/ide/browser.js +538 -0
  26. package/dist/components/guardian/index.js +8 -0
  27. package/dist/components/guardian/layout/app-layout-no-sidebar.js +8 -0
  28. package/dist/components/guardian/layout/header/glassmorphic-combobox.js +48 -0
  29. package/dist/components/guardian/layout/header.js +63 -0
  30. package/dist/components/guardian/right-view/code-view.js +56 -0
  31. package/dist/components/guardian/right-view/pill-file-selector.js +233 -0
  32. package/dist/components/guardian/right-view/preview-control-bar.js +25 -0
  33. package/dist/components/guardian/right-view/right-panel-view.js +38 -0
  34. package/dist/components/guardian/right-view/right-top-down-view.js +289 -0
  35. package/dist/components/guardian/right-view/right-view.js +28 -0
  36. package/dist/components/guardian/right-view/simplified-editor.js +234 -0
  37. package/dist/components/guardian/types/ide-types.js +162 -0
  38. package/dist/components/guardian/types.js +3 -0
  39. package/dist/components/guardian/ui/ai-loader.js +48 -0
  40. package/dist/components/guardian/ui/badge.js +24 -0
  41. package/dist/components/guardian/ui/button.js +45 -0
  42. package/dist/components/guardian/ui/command.js +63 -0
  43. package/dist/components/guardian/ui/console-with-app.js +17 -0
  44. package/dist/components/guardian/ui/dialog.js +57 -0
  45. package/dist/components/guardian/ui/dropdown-menu.js +82 -0
  46. package/dist/components/guardian/ui/markdown.js +57 -0
  47. package/dist/components/guardian/ui/popover.js +25 -0
  48. package/dist/components/guardian/ui/tooltip.js +25 -0
  49. package/dist/components/guardian/utils.js +88 -0
  50. package/dist/components/guardian/zip-to-codebase.js +246 -0
  51. package/dist/components/guardian/zip-to-filetree.js +284 -0
  52. package/dist/components/icons.js +22 -0
  53. package/dist/components/sandbox/Sandbox.js +87 -0
  54. package/dist/components/sandbox/SandboxHome.js +141 -0
  55. package/dist/components/sandbox/api.js +108 -0
  56. package/dist/components/sandbox/guardian/app-layout-no-sidebar.js +8 -0
  57. package/dist/components/sandbox/guardian/ask-ai-view.js +249 -0
  58. package/dist/components/sandbox/guardian/code-focus-section.js +174 -0
  59. package/dist/components/sandbox/guardian/context/guardian-context.js +94 -0
  60. package/dist/components/sandbox/guardian/context/vm-context.js +28 -0
  61. package/dist/components/sandbox/guardian/default-guide-view.js +34 -0
  62. package/dist/components/sandbox/guardian/demo/guardian-demo.js +35 -0
  63. package/dist/components/sandbox/guardian/demo/left-view/toggle.js +28 -0
  64. package/dist/components/sandbox/guardian/demo/left-view.js +58 -0
  65. package/dist/components/sandbox/guardian/guardian-component.js +97 -0
  66. package/dist/components/sandbox/guardian/guardian-demo.js +35 -0
  67. package/dist/components/sandbox/guardian/guardian-home.d.ts +4 -0
  68. package/dist/components/sandbox/guardian/guardian-home.js +61 -0
  69. package/dist/components/sandbox/guardian/guardian-playground.js +45 -0
  70. package/dist/components/sandbox/guardian/guardian-style-wrapper.js +33 -0
  71. package/dist/components/sandbox/guardian/guardian-upload-spec.d.ts +14 -0
  72. package/dist/components/sandbox/guardian/guardian-upload-spec.js +160 -0
  73. package/dist/components/sandbox/guardian/header/glassmorphic-combobox.js +30 -0
  74. package/dist/components/sandbox/guardian/header.js +61 -0
  75. package/dist/components/sandbox/guardian/hooks/use-frame-messages.js +65 -0
  76. package/dist/components/sandbox/guardian/hooks/use-frame-params.js +44 -0
  77. package/dist/components/sandbox/guardian/hooks/use-sandbox-url-loader.js +145 -0
  78. package/dist/components/sandbox/guardian/ide/browser.js +538 -0
  79. package/dist/components/sandbox/guardian/index.js +8 -0
  80. package/dist/components/sandbox/guardian/right-view/code-view.js +60 -0
  81. package/dist/components/sandbox/guardian/right-view/pill-file-selector.js +233 -0
  82. package/dist/components/sandbox/guardian/right-view/preview-control-bar.js +25 -0
  83. package/dist/components/sandbox/guardian/right-view/right-panel-view.js +38 -0
  84. package/dist/components/sandbox/guardian/right-view/right-top-down-view.js +289 -0
  85. package/dist/components/sandbox/guardian/right-view/right-view.js +28 -0
  86. package/dist/components/sandbox/guardian/right-view/simplified-editor.js +234 -0
  87. package/dist/components/sandbox/guardian/types/ide-types.js +162 -0
  88. package/dist/components/sandbox/guardian/types.js +3 -0
  89. package/dist/components/sandbox/guardian/ui/ai-loader.js +48 -0
  90. package/dist/components/sandbox/guardian/ui/badge.js +24 -0
  91. package/dist/components/sandbox/guardian/ui/button.js +45 -0
  92. package/dist/components/sandbox/guardian/ui/command.js +63 -0
  93. package/dist/components/sandbox/guardian/ui/console-with-app.js +17 -0
  94. package/dist/components/sandbox/guardian/ui/dialog.js +57 -0
  95. package/dist/components/sandbox/guardian/ui/dropdown-menu.js +82 -0
  96. package/dist/components/sandbox/guardian/ui/markdown/accordion-group/accordion.js +62 -0
  97. package/dist/components/sandbox/guardian/ui/markdown/accordion-group.js +23 -0
  98. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-check.js +4 -0
  99. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-error.js +4 -0
  100. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-info.js +4 -0
  101. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-note.js +4 -0
  102. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-tip.js +4 -0
  103. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-warning.js +4 -0
  104. package/dist/components/sandbox/guardian/ui/markdown/callout/shared/callout.js +9 -0
  105. package/dist/components/sandbox/guardian/ui/markdown/callout/shared/types.js +1 -0
  106. package/dist/components/sandbox/guardian/ui/markdown/card-group/card.js +18 -0
  107. package/dist/components/sandbox/guardian/ui/markdown/card-group.js +25 -0
  108. package/dist/components/sandbox/guardian/ui/markdown/code-group/code-block.js +87 -0
  109. package/dist/components/sandbox/guardian/ui/markdown/code-group.js +101 -0
  110. package/dist/components/sandbox/guardian/ui/markdown/icon.js +31 -0
  111. package/dist/components/sandbox/guardian/ui/markdown.js +786 -0
  112. package/dist/components/sandbox/guardian/ui/popover.js +25 -0
  113. package/dist/components/sandbox/guardian/ui/tooltip.js +25 -0
  114. package/dist/components/sandbox/guardian/utils.js +88 -0
  115. package/dist/components/sandbox/guardian/zip-to-codebase.js +259 -0
  116. package/dist/components/sandbox/guardian/zip-to-filetree.js +284 -0
  117. package/dist/components/sandbox/index.js +4 -0
  118. package/dist/components/sandbox/sandbox-control-bar.js +91 -0
  119. package/dist/components/sandbox/sandbox-header.js +52 -0
  120. package/dist/components/sandbox/sandbox-home/SandboxCard.js +59 -0
  121. package/dist/components/sandbox/sandbox-home/SandboxHome.js +174 -0
  122. package/dist/components/sandbox/sandbox-home/SearchBar.js +12 -0
  123. package/dist/components/sandbox/sandbox-home/index.js +3 -0
  124. package/dist/components/sandbox/sandbox-left-panel.js +248 -0
  125. package/dist/components/sandbox/sandbox-loading.js +48 -0
  126. package/dist/components/sandbox/sandbox-right-panel.js +247 -0
  127. package/dist/components/sandbox/types.js +1 -0
  128. package/dist/components/sandbox.js +32 -0
  129. package/dist/components/tailwind-example.js +46 -0
  130. package/dist/index.d.ts +336 -1
  131. package/dist/index.es.js +90131 -421
  132. package/dist/index.js +13 -2
  133. package/dist/index.standalone.js +61 -53
  134. package/dist/index.standalone.umd.js +17 -24
  135. package/dist/lib/api-client.example.js +60 -0
  136. package/dist/lib/api-client.js +98 -0
  137. package/dist/lib/generated-css.js +4 -0
  138. package/dist/lib/inject-styles.js +42 -0
  139. package/dist/lib/shadow-dom-wrapper.js +42 -0
  140. package/dist/lib/utils.js +5 -0
  141. package/dist/sdk.css +1 -1
  142. package/dist/tailwind.css +1 -0
  143. package/package.json +32 -5
@@ -0,0 +1,8 @@
1
+ export { default as GuardianPlayground } from "./guardian-playground";
2
+ export { default as GuardianComponent } from "./guardian-component";
3
+ export { VmProvider, useVmContext } from "./context/vm-context";
4
+ export { GuardianProvider, useGuardianContext } from "./context/guardian-context";
5
+ export * from "./types";
6
+ export { default as CodeFocusSection } from "./code-focus-section";
7
+ export { buildGuardianConfig, createSandboxUrlConfigs } from "./utils";
8
+ export { Framework, FrameworkLabel } from "./types";
@@ -0,0 +1,60 @@
1
+ "use client";
2
+ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
3
+ // FileExplorer and Editor components are not yet implemented in SDK
4
+ // These imports are commented out until those components are added
5
+ // import FileExplorer, {
6
+ // FileTreeNode,
7
+ // } from "../ide/file-explorer";
8
+ // import Editor from "../ide/Editor";
9
+ import React, { useEffect } from "react";
10
+ import { useGuardianContext } from "../context/guardian-context";
11
+ import { zipPathToFileTree } from "../zip-to-filetree";
12
+ import { codeZipFileToCodebase } from "../zip-to-codebase";
13
+ // Stub components until FileExplorer and Editor are implemented
14
+ const FileExplorer = ({ isGenerating }) => (React.createElement("div", { className: "h-full flex items-center justify-center text-muted-foreground text-sm" }, "File Explorer - Coming Soon"));
15
+ const Editor = () => (React.createElement("div", { className: "h-full flex items-center justify-center text-muted-foreground text-sm" }, "Code Editor - Coming Soon"));
16
+ // ORIGINAL URL: https://launchdarkly.sampleapp.ai/chat/mgl0vkr1IPwCIR
17
+ export default function CodeView({ codeZipFile, }) {
18
+ const { setFileTree, setGeneratedCode } = useGuardianContext();
19
+ useEffect(() => {
20
+ let isMounted = true;
21
+ // Only load file tree if codeZipFile is a string path
22
+ if (typeof codeZipFile === "string") {
23
+ zipPathToFileTree(codeZipFile)
24
+ .then((fileTree) => {
25
+ if (isMounted) {
26
+ setFileTree(fileTree);
27
+ }
28
+ })
29
+ .catch((error) => {
30
+ console.error("Failed to load zip file:", error);
31
+ });
32
+ }
33
+ // Handle both string path and object
34
+ codeZipFileToCodebase(codeZipFile)
35
+ .then((codebase) => {
36
+ if (isMounted) {
37
+ setGeneratedCode(codebase);
38
+ }
39
+ })
40
+ .catch((error) => {
41
+ console.error("Failed to load codebase:", error);
42
+ });
43
+ return () => {
44
+ isMounted = false;
45
+ };
46
+ }, [codeZipFile, setFileTree, setGeneratedCode]);
47
+ return (React.createElement("div", { className: "h-[calc(100vh-12.9rem)] w-full" },
48
+ React.createElement(PanelGroup, { direction: "horizontal", className: "relative h-full" },
49
+ React.createElement(Panel, { defaultSize: 25, minSize: 15, maxSize: 50, order: 1 },
50
+ React.createElement("div", { className: "h-full" },
51
+ React.createElement(FileExplorer, { isGenerating: false }))),
52
+ React.createElement(PanelResizeHandle, { className: "w-0 relative group flex-shrink-0" },
53
+ React.createElement("div", { className: "absolute inset-y-0 left-1/2 -translate-x-1/2 w-2 -ml-1 transition-colors flex justify-center items-center bg-transparent" },
54
+ React.createElement("div", { className: "absolute inset-y-0 left-0 w-1/2 group-hover:bg-blue-400/20 transition-colors" }),
55
+ React.createElement("div", { className: "absolute inset-y-0 right-0 w-1/2 group-hover:bg-blue-400/20 transition-colors" }),
56
+ React.createElement("div", { className: "h-full w-px bg-border group-hover:bg-blue-400 transition-colors relative z-10" }))),
57
+ React.createElement(Panel, { defaultSize: 75, order: 2 },
58
+ React.createElement("div", { className: "h-full" },
59
+ React.createElement(Editor, null))))));
60
+ }
@@ -0,0 +1,233 @@
1
+ "use client";
2
+ import React from "react";
3
+ import { useGuardianContext } from "../context/guardian-context";
4
+ import { cn } from "../../../../lib/utils";
5
+ import { useFrameParams } from "../hooks/use-frame-params";
6
+ import { FileCode, FileJson, FileText, Settings, Layout, Database, Image, Terminal, } from "lucide-react";
7
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../ui/tooltip";
8
+ const FILE_ICONS = {
9
+ // JavaScript/React
10
+ js: { icon: FileCode, color: "text-yellow-600" },
11
+ jsx: { icon: FileCode, color: "text-blue-500" },
12
+ ts: { icon: FileCode, color: "text-blue-600" },
13
+ tsx: { icon: FileCode, color: "text-blue-500" },
14
+ json: { icon: FileJson, color: "text-yellow-500" },
15
+ html: { icon: Layout, color: "text-orange-500" },
16
+ css: { icon: FileText, color: "text-blue-400" },
17
+ scss: { icon: FileText, color: "text-pink-500" },
18
+ less: { icon: FileText, color: "text-indigo-500" },
19
+ // Python
20
+ py: { icon: FileCode, color: "text-green-500" },
21
+ pyc: { icon: FileCode, color: "text-green-400" },
22
+ pyw: { icon: FileCode, color: "text-green-500" },
23
+ ipynb: { icon: Terminal, color: "text-red-500" },
24
+ // Config files
25
+ env: { icon: Settings, color: "text-zinc-500" },
26
+ gitignore: { icon: Settings, color: "text-zinc-500" },
27
+ yml: { icon: Settings, color: "text-purple-500" },
28
+ yaml: { icon: Settings, color: "text-purple-500" },
29
+ toml: { icon: Settings, color: "text-purple-500" },
30
+ ini: { icon: Settings, color: "text-zinc-500" },
31
+ cfg: { icon: Settings, color: "text-zinc-500" },
32
+ config: { icon: Settings, color: "text-zinc-500" },
33
+ // Database
34
+ sql: { icon: Database, color: "text-blue-500" },
35
+ sqlite: { icon: Database, color: "text-blue-500" },
36
+ sqlite3: { icon: Database, color: "text-blue-500" },
37
+ // Images
38
+ png: { icon: Image, color: "text-green-500" },
39
+ jpg: { icon: Image, color: "text-green-500" },
40
+ jpeg: { icon: Image, color: "text-green-500" },
41
+ gif: { icon: Image, color: "text-green-500" },
42
+ svg: { icon: Image, color: "text-green-500" },
43
+ ico: { icon: Image, color: "text-green-500" },
44
+ // Default
45
+ default: { icon: FileText, color: "text-zinc-500" },
46
+ };
47
+ export default function PillFileSelector({ themeColor }) {
48
+ const containerRef = React.useRef(null);
49
+ const fileRefs = React.useRef({});
50
+ const lastInitializedFilePath = React.useRef(null);
51
+ const { generatedCode, updateCode, setLanguage, activeFilePath: contextActiveFilePath, setActiveFileName, setActiveFilePath, setActiveDependenciesToInstall, setActiveLineRange, filesEdited, } = useGuardianContext();
52
+ // Read frame params - these override context when isFrame=true
53
+ const frameParams = useFrameParams();
54
+ // Use frame param overrides when in frame mode
55
+ const activeFilePath = frameParams.isFrame && frameParams.activeFilePath
56
+ ? frameParams.activeFilePath
57
+ : contextActiveFilePath;
58
+ const effectiveThemeColor = frameParams.isFrame && frameParams.theme ? frameParams.theme : themeColor;
59
+ // Get file entries and sort them
60
+ const fileEntries = Object.entries(generatedCode).sort(([a], [b]) => {
61
+ const aName = a.split("/").pop() || a;
62
+ const bName = b.split("/").pop() || b;
63
+ return aName.localeCompare(bName);
64
+ });
65
+ const handleFileClick = (filePath, fileData) => {
66
+ // In frame mode, replace all frame params with activeFilePath and isFrame only
67
+ if (frameParams.isFrame) {
68
+ const url = new URL(window.location.href);
69
+ url.search = "";
70
+ url.searchParams.set("activeFilePath", filePath);
71
+ url.searchParams.set("isFrame", "true");
72
+ url.searchParams.set("theme", effectiveThemeColor);
73
+ window.history.replaceState({}, "", url.toString());
74
+ }
75
+ const fileName = filePath.split("/").pop() || filePath;
76
+ setActiveFileName(fileName);
77
+ setActiveFilePath(filePath);
78
+ setLanguage(fileData.code_language);
79
+ updateCode(filePath in filesEdited
80
+ ? filesEdited[filePath].full_code
81
+ : fileData.full_code);
82
+ setActiveDependenciesToInstall(fileData.dependencies_to_install);
83
+ };
84
+ const getFileIcon = (fileName) => {
85
+ var _a;
86
+ const ext = ((_a = fileName.split(".").pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || "";
87
+ return FILE_ICONS[ext] || FILE_ICONS.default;
88
+ };
89
+ // Exclude certain files from display
90
+ const excludedFiles = [
91
+ ".env",
92
+ "vite-plugin-react-instrumentation.ts",
93
+ "instrumentation-client.ts",
94
+ ];
95
+ const filteredFiles = fileEntries.filter(([filePath]) => {
96
+ const fileName = filePath.split("/").pop() || filePath;
97
+ return !excludedFiles.includes(fileName);
98
+ });
99
+ // Scroll a pill into view whenever the active file changes
100
+ const scrollActivePillIntoView = React.useCallback((filePath) => {
101
+ const targetPath = filePath !== null && filePath !== void 0 ? filePath : activeFilePath;
102
+ if (!targetPath)
103
+ return;
104
+ const container = containerRef.current;
105
+ const activeButton = fileRefs.current[targetPath];
106
+ if (!container || !activeButton)
107
+ return;
108
+ // Small delay to ensure DOM has updated
109
+ setTimeout(() => {
110
+ const containerRect = container.getBoundingClientRect();
111
+ const activeRect = activeButton.getBoundingClientRect();
112
+ const isOutOfView = activeRect.left < containerRect.left ||
113
+ activeRect.right > containerRect.right;
114
+ if (isOutOfView) {
115
+ activeButton.scrollIntoView({
116
+ behavior: "instant",
117
+ block: "nearest",
118
+ inline: "center",
119
+ });
120
+ }
121
+ }, 50);
122
+ }, [activeFilePath]);
123
+ // Ensure the active file pill is always visible in the scroll area
124
+ React.useEffect(() => {
125
+ scrollActivePillIntoView();
126
+ }, [scrollActivePillIntoView, filteredFiles.length]);
127
+ // Listen for frame param updates from postMessage
128
+ React.useEffect(() => {
129
+ if (!frameParams.isFrame)
130
+ return;
131
+ const handleFrameParamsUpdate = (event) => {
132
+ var _a;
133
+ try {
134
+ const customEvent = event;
135
+ const nextPath = (_a = customEvent.detail) === null || _a === void 0 ? void 0 : _a.activeFilePath;
136
+ scrollActivePillIntoView(nextPath);
137
+ }
138
+ catch (_b) {
139
+ // Fallback to current activeFilePath if parsing fails
140
+ scrollActivePillIntoView();
141
+ }
142
+ };
143
+ window.addEventListener("frameParamsUpdated", handleFrameParamsUpdate);
144
+ return () => window.removeEventListener("frameParamsUpdated", handleFrameParamsUpdate);
145
+ }, [frameParams.isFrame, scrollActivePillIntoView]);
146
+ // Load file from frame params when they change
147
+ React.useEffect(() => {
148
+ // Skip if not in frame mode or no file path specified
149
+ if (!frameParams.isFrame || !frameParams.activeFilePath) {
150
+ return;
151
+ }
152
+ // Skip if we've already initialized this exact file path
153
+ if (lastInitializedFilePath.current === frameParams.activeFilePath) {
154
+ return;
155
+ }
156
+ // Skip if generatedCode isn't loaded yet
157
+ if (!generatedCode || Object.keys(generatedCode).length === 0) {
158
+ return;
159
+ }
160
+ // Search by file_path property first (source of truth), then fallback to key lookup
161
+ let fileData;
162
+ let resolvedFilePath;
163
+ // First, search through all code outputs to find one matching file_path
164
+ const matchingCodeOutput = Object.values(generatedCode).find((output) => output.file_path === frameParams.activeFilePath);
165
+ if (matchingCodeOutput) {
166
+ fileData = matchingCodeOutput;
167
+ resolvedFilePath = matchingCodeOutput.file_path;
168
+ }
169
+ else {
170
+ // Fallback: try to get from generatedCode by key
171
+ if (generatedCode[frameParams.activeFilePath]) {
172
+ fileData = generatedCode[frameParams.activeFilePath];
173
+ resolvedFilePath = fileData.file_path || frameParams.activeFilePath;
174
+ }
175
+ }
176
+ if (fileData && resolvedFilePath) {
177
+ lastInitializedFilePath.current = frameParams.activeFilePath; // Track initialized path
178
+ const fileName = fileData.code_file_name ||
179
+ resolvedFilePath.split("/").pop() ||
180
+ resolvedFilePath;
181
+ setActiveFileName(fileName);
182
+ setActiveFilePath(resolvedFilePath);
183
+ setLanguage(fileData.code_language);
184
+ updateCode(resolvedFilePath in filesEdited
185
+ ? filesEdited[resolvedFilePath].full_code
186
+ : fileData.full_code);
187
+ setActiveDependenciesToInstall(fileData.dependencies_to_install);
188
+ // Set line range if provided in frame params
189
+ if (frameParams.linesStart !== undefined) {
190
+ setActiveLineRange({
191
+ start: frameParams.linesStart,
192
+ end: frameParams.linesEnd,
193
+ });
194
+ }
195
+ else {
196
+ setActiveLineRange(undefined);
197
+ }
198
+ }
199
+ // eslint-disable-next-line react-hooks/exhaustive-deps
200
+ }, [frameParams.isFrame, frameParams.activeFilePath, generatedCode]);
201
+ if (filteredFiles.length === 0) {
202
+ return null;
203
+ }
204
+ return (React.createElement(TooltipProvider, null,
205
+ React.createElement("div", { ref: containerRef, className: "flex items-center gap-1 px-2 py-1.5 overflow-x-auto no-scrollbar [-ms-overflow-style:none] [scrollbar-width:none] flex-1" }, filteredFiles.map(([filePath, fileData]) => {
206
+ const fileName = filePath.split("/").pop() || filePath;
207
+ const isActive = filePath === activeFilePath;
208
+ const isEdited = filePath in filesEdited;
209
+ const fileIcon = getFileIcon(fileName);
210
+ const IconComponent = fileIcon.icon;
211
+ return (React.createElement(Tooltip, { key: filePath },
212
+ React.createElement(TooltipTrigger, { asChild: true },
213
+ React.createElement("button", { ref: (el) => {
214
+ if (el) {
215
+ fileRefs.current[filePath] = el;
216
+ }
217
+ else {
218
+ delete fileRefs.current[filePath];
219
+ }
220
+ }, onClick: () => handleFileClick(filePath, fileData), className: cn("flex items-center gap-1.5 px-2.5 py-1 rounded text-xs font-normal transition-colors whitespace-nowrap", isActive
221
+ ? "rounded-2xl text-zinc-100"
222
+ : "text-zinc-400 hover:text-zinc-200", isEdited && "ring-1 ring-yellow-500/50"), style: isActive
223
+ ? {
224
+ backgroundColor: `${effectiveThemeColor}33`, // ~20% opacity
225
+ color: effectiveThemeColor,
226
+ }
227
+ : undefined },
228
+ React.createElement(IconComponent, { size: 12, className: cn("flex-shrink-0", !isActive && "text-zinc-500"), style: isActive ? { color: effectiveThemeColor } : undefined }),
229
+ React.createElement("span", { className: "truncate max-w-[180px]" }, fileName),
230
+ isEdited && (React.createElement("span", { className: "h-1 w-1 rounded-full bg-yellow-400 flex-shrink-0" })))),
231
+ React.createElement(TooltipContent, { side: "top", className: "bg-zinc-900 text-zinc-200 text-[11px] px-2 py-1 rounded shadow border border-zinc-700 whitespace-pre font-mono" }, filePath)));
232
+ }))));
233
+ }
@@ -0,0 +1,25 @@
1
+ import React from "react";
2
+ import { useFrameParams } from "../hooks/use-frame-params";
3
+ import { useGuardianContext } from "../context/guardian-context";
4
+ import { ChevronDown, RefreshCw, Maximize2, Minimize2, ExternalLink, } from "lucide-react";
5
+ export default function PreviewControlBar({ isMinimized, onToggle, onRefresh, themeColor, externalUrl, // <-- NEW PROP
6
+ }) {
7
+ const { isBrowserMaximized, setIsBrowserMaximized } = useGuardianContext();
8
+ const frameParams = useFrameParams();
9
+ const effectiveThemeColor = frameParams.isFrame && frameParams.theme ? frameParams.theme : themeColor;
10
+ return (React.createElement("div", { className: "w-full flex items-center justify-between px-4 py-[0.32rem] border-b" },
11
+ React.createElement("button", { onClick: onToggle, className: "flex items-center gap-2 transition-colors", title: isMinimized ? "Show preview" : "Hide preview" },
12
+ React.createElement("div", { className: "transition-transform duration-300 ease-in-out", style: {
13
+ transform: isMinimized ? "rotate(0deg)" : "rotate(180deg)",
14
+ color: effectiveThemeColor,
15
+ } },
16
+ React.createElement(ChevronDown, { className: "w-4 h-4" })),
17
+ React.createElement("span", { className: "text-sm font-medium", style: { color: effectiveThemeColor } }, "Preview")),
18
+ React.createElement("div", { className: "flex items-center gap-2" },
19
+ externalUrl && (React.createElement("a", { href: externalUrl, target: "_blank", rel: "noopener noreferrer", title: "Open in new tab", style: { color: effectiveThemeColor }, className: "p-1.5 rounded transition-colors hover:bg-zinc-800 dark:hover:bg-zinc-800" },
20
+ React.createElement(ExternalLink, { className: "w-4 h-4" }),
21
+ React.createElement("span", { className: "sr-only" }, "Open external link"))),
22
+ React.createElement("button", { onClick: onRefresh, className: "p-1.5 rounded transition-colors hover:bg-zinc-800 dark:hover:bg-zinc-800", title: "Refresh preview", style: { color: effectiveThemeColor } },
23
+ React.createElement(RefreshCw, { className: "w-4 h-4" })),
24
+ React.createElement("button", { onClick: () => setIsBrowserMaximized(!isBrowserMaximized), className: "p-1.5 rounded transition-colors hover:bg-zinc-800 dark:hover:bg-zinc-800", title: isBrowserMaximized ? "Exit fullscreen" : "Fullscreen preview", style: { color: effectiveThemeColor } }, isBrowserMaximized ? (React.createElement(Minimize2, { className: "w-4 h-4" })) : (React.createElement(Maximize2, { className: "w-4 h-4" }))))));
25
+ }
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import React from "react";
3
+ import SlidingEditPreviewToggle from "../demo/left-view/toggle";
4
+ import Browser from "../ide/browser";
5
+ import CodeView from "./code-view";
6
+ import { useGuardianContext } from "../context/guardian-context";
7
+ import { Component as AiLoader } from "../ui/ai-loader";
8
+ export default function RightPanelView({ reloadCounter, overlayStage, browserUrl, useVm, codeZipFile, }) {
9
+ const { setCurrentView, currentView } = useGuardianContext();
10
+ return (React.createElement("div", null,
11
+ React.createElement("div", { className: "flex justify-center border-b" },
12
+ React.createElement(SlidingEditPreviewToggle, { playgroundUid: "guardian", currentView: currentView, setCurrentView: (view) => setCurrentView(view), variant: "pill", buttonClassName: "text-sm px-4 py-1 h-auto", tabs: [
13
+ { id: "editor", label: "Code" },
14
+ { id: "preview", label: "Preview" },
15
+ ] })),
16
+ React.createElement("div", { style: {
17
+ display: currentView === "preview" ? "block" : "none",
18
+ } }, !browserUrl ? (React.createElement("div", { className: "h-[calc(100vh-12.2rem)] w-full relative overflow-hidden rounded-b-none" },
19
+ React.createElement(AiLoader, { text: "Booting up...", fullScreen: false }))) : (React.createElement(Browser, { previewUrl: browserUrl, setPreviewUrl: () => { }, containerEndpoint: browserUrl, outerContainerClassName: useVm
20
+ ? "h-[calc(100vh-9.6rem)] w-full border-none rounded-b-none"
21
+ : "h-[calc(100vh-12.2rem)] w-full border-none rounded-b-none", reloadSignal: reloadCounter, useVm: useVm }, overlayStage !== "hidden" && (React.createElement("div", { className: "absolute inset-0 z-20 flex items-center justify-center" },
22
+ overlayStage === "error" && (React.createElement("div", { className: "w-full h-full bg-red-950 text-red-200 flex items-center justify-center" },
23
+ React.createElement("div", { className: "text-center" },
24
+ React.createElement("div", { className: "text-2xl font-semibold" }, "Service Unavailable"),
25
+ React.createElement("div", { className: "text-sm mt-2 opacity-80" }, "Elevated error rates detected. Initiating rollback...")))),
26
+ overlayStage === "rebuilding" && (React.createElement("div", { className: "w-full h-full bg-amber-900 text-amber-100 flex items-center justify-center" },
27
+ React.createElement("div", { className: "text-center" },
28
+ React.createElement("div", { className: "text-2xl font-semibold" }, "Rebuilding preview\u2026"),
29
+ React.createElement("div", { className: "text-sm mt-2 opacity-80" }, "Applying safe configuration"),
30
+ React.createElement("div", { className: "mt-4 inline-flex items-center gap-2" },
31
+ React.createElement("span", { className: "h-2 w-2 rounded-full bg-amber-300 animate-pulse" }),
32
+ React.createElement("span", { className: "h-2 w-2 rounded-full bg-amber-300 animate-pulse [animation-delay:150ms]" }),
33
+ React.createElement("span", { className: "h-2 w-2 rounded-full bg-amber-300 animate-pulse [animation-delay:300ms]" })))))))))),
34
+ React.createElement("div", { style: {
35
+ display: currentView === "editor" ? "block" : "none",
36
+ } },
37
+ React.createElement(CodeView, { codeZipFile: codeZipFile }))));
38
+ }