@sampleapp.ai/sdk 1.0.35 → 1.0.37
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/dist/components/sandbox/Sandbox.js +20 -8
- package/dist/components/sandbox/api.js +3 -2
- package/dist/components/sandbox/guardian/ask-ai-view.js +4 -4
- package/dist/components/sandbox/guardian/default-guide-view.js +1 -1
- package/dist/components/sandbox/guardian/demo/left-view.js +2 -2
- package/dist/components/sandbox/guardian/guardian-component.js +7 -38
- package/dist/components/sandbox/guardian/guardian-playground.js +3 -3
- package/dist/components/sandbox/guardian/guardian-style-wrapper.js +21 -2
- package/dist/components/sandbox/guardian/hooks/use-sandbox-url-loader.js +12 -10
- package/dist/components/sandbox/guardian/ide/browser.js +30 -30
- package/dist/components/sandbox/guardian/index.js +1 -1
- package/dist/components/sandbox/guardian/right-view/preview-control-bar.js +3 -3
- package/dist/components/sandbox/guardian/right-view/right-top-down-view.js +2 -2
- package/dist/components/sandbox/guardian/ui/download-and-open-buttons.js +1 -1
- package/dist/components/sandbox/guardian/ui/markdown/code-group/code-block.js +48 -11
- package/dist/components/sandbox/guardian/ui/markdown.js +3 -3
- package/dist/components/sandbox/guardian/utils.js +0 -18
- package/dist/components/sandbox/index.js +1 -1
- package/dist/components/sandbox/sandbox-home/SandboxCard.js +4 -4
- package/dist/components/sandbox/sandbox-home/SandboxHome.js +14 -9
- package/dist/components/sandbox/sandbox-home/SearchBar.js +2 -2
- package/dist/index.d.ts +29 -42
- package/dist/index.es.js +8208 -7715
- package/dist/index.js +1 -1
- package/dist/index.standalone.umd.js +1 -1
- package/dist/lib/api-client.js +9 -26
- package/dist/lib/generated-css.js +1 -1
- package/dist/sdk.css +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +1 -1
- package/dist/components/guardian/app-layout-no-sidebar.js +0 -8
- package/dist/components/guardian/ask-ai-view.js +0 -249
- package/dist/components/guardian/code-focus-section.d.ts +0 -41
- package/dist/components/guardian/code-focus-section.js +0 -174
- package/dist/components/guardian/context/guardian-context.js +0 -94
- package/dist/components/guardian/context/vm-context.js +0 -28
- package/dist/components/guardian/default-guide-view.js +0 -34
- package/dist/components/guardian/demo/guardian-demo.js +0 -35
- package/dist/components/guardian/demo/left-view/toggle.js +0 -28
- package/dist/components/guardian/demo/left-view.js +0 -49
- package/dist/components/guardian/guardian-component.js +0 -79
- package/dist/components/guardian/guardian-demo.js +0 -35
- package/dist/components/guardian/guardian-home.d.ts +0 -4
- package/dist/components/guardian/guardian-home.js +0 -61
- package/dist/components/guardian/guardian-playground.js +0 -45
- package/dist/components/guardian/guardian-style-wrapper.js +0 -29
- package/dist/components/guardian/guardian-upload-spec.d.ts +0 -14
- package/dist/components/guardian/guardian-upload-spec.js +0 -160
- package/dist/components/guardian/header/glassmorphic-combobox.d.ts +0 -15
- package/dist/components/guardian/header/glassmorphic-combobox.js +0 -30
- package/dist/components/guardian/header.js +0 -61
- package/dist/components/guardian/hooks/use-frame-messages.js +0 -65
- package/dist/components/guardian/hooks/use-frame-params.js +0 -44
- package/dist/components/guardian/hooks/use-sandbox-url-loader.js +0 -101
- package/dist/components/guardian/ide/browser.js +0 -538
- package/dist/components/guardian/index.js +0 -8
- package/dist/components/guardian/layout/app-layout-no-sidebar.js +0 -8
- package/dist/components/guardian/layout/header/glassmorphic-combobox.js +0 -48
- package/dist/components/guardian/layout/header.js +0 -63
- package/dist/components/guardian/right-view/code-view.js +0 -56
- package/dist/components/guardian/right-view/pill-file-selector.js +0 -233
- package/dist/components/guardian/right-view/preview-control-bar.js +0 -25
- package/dist/components/guardian/right-view/right-panel-view.js +0 -38
- package/dist/components/guardian/right-view/right-top-down-view.js +0 -289
- package/dist/components/guardian/right-view/right-view.js +0 -28
- package/dist/components/guardian/right-view/simplified-editor.js +0 -234
- package/dist/components/guardian/types/ide-types.js +0 -162
- package/dist/components/guardian/types.js +0 -3
- package/dist/components/guardian/ui/ai-loader.js +0 -48
- package/dist/components/guardian/ui/badge.js +0 -24
- package/dist/components/guardian/ui/button.js +0 -45
- package/dist/components/guardian/ui/command.js +0 -63
- package/dist/components/guardian/ui/console-with-app.js +0 -17
- package/dist/components/guardian/ui/dialog.js +0 -57
- package/dist/components/guardian/ui/dropdown-menu.js +0 -82
- package/dist/components/guardian/ui/markdown.js +0 -57
- package/dist/components/guardian/ui/popover.js +0 -25
- package/dist/components/guardian/ui/tooltip.js +0 -25
- package/dist/components/guardian/utils.js +0 -88
- package/dist/components/guardian/zip-to-codebase.js +0 -246
- package/dist/components/guardian/zip-to-filetree.js +0 -284
- package/dist/components/sandbox/SandboxHome.js +0 -141
- package/dist/components/sandbox/guardian/guardian-demo.js +0 -35
- package/dist/components/sandbox/guardian/guardian-home.d.ts +0 -4
- package/dist/components/sandbox/guardian/guardian-home.js +0 -61
- package/dist/components/sandbox/guardian/guardian-upload-spec.d.ts +0 -14
- package/dist/components/sandbox/guardian/guardian-upload-spec.js +0 -160
- package/dist/components/sandbox/guardian/ui/theme-color-context.d.ts +0 -6
- package/dist/components/sandbox/sandbox-control-bar.js +0 -91
- package/dist/components/sandbox/sandbox-header.js +0 -52
- package/dist/components/sandbox/sandbox-left-panel.js +0 -248
- package/dist/components/sandbox/sandbox-loading.js +0 -48
- package/dist/components/sandbox/sandbox-right-panel.js +0 -247
- package/dist/components/sandbox.js +0 -32
- package/dist/lib/api-client.example.js +0 -60
- package/dist/lib/ssr-safe-decode-entity.js +0 -16
|
@@ -24,10 +24,22 @@ import { Skeleton } from "../ui/skeleton";
|
|
|
24
24
|
* apiKey={process.env.NEXT_PUBLIC_SAMPLEAPP_API_KEY!}
|
|
25
25
|
* sandboxId="launchdarkly-feature-flags"
|
|
26
26
|
* />
|
|
27
|
+
*
|
|
28
|
+
* // Light mode
|
|
29
|
+
* <Sandbox
|
|
30
|
+
* apiKey={process.env.NEXT_PUBLIC_SAMPLEAPP_API_KEY!}
|
|
31
|
+
* sandboxId="launchdarkly-feature-flags"
|
|
32
|
+
* theme="light"
|
|
33
|
+
* />
|
|
27
34
|
* ```
|
|
28
35
|
*/
|
|
29
|
-
export default function Sandbox({ apiKey, sandboxId, env, themeColor, }) {
|
|
36
|
+
export default function Sandbox({ apiKey, sandboxId, env, themeColor, theme = "dark", }) {
|
|
30
37
|
var _a;
|
|
38
|
+
// Validate apiKey immediately
|
|
39
|
+
if (!apiKey || apiKey.trim() === "") {
|
|
40
|
+
return (React.createElement("div", { className: "flex items-center justify-center h-screen bg-white dark:bg-black" },
|
|
41
|
+
React.createElement("div", { className: "text-red-500" }, "Error: apiKey is required. Please provide a valid API key.")));
|
|
42
|
+
}
|
|
31
43
|
const [config, setConfig] = useState(null);
|
|
32
44
|
const [loading, setLoading] = useState(true);
|
|
33
45
|
const [error, setError] = useState(null);
|
|
@@ -61,11 +73,11 @@ export default function Sandbox({ apiKey, sandboxId, env, themeColor, }) {
|
|
|
61
73
|
};
|
|
62
74
|
}, [apiKey, sandboxId, themeColor]);
|
|
63
75
|
if (loading) {
|
|
64
|
-
return (React.createElement("div", { className: "h-screen w-screen bg-black" },
|
|
65
|
-
React.createElement(Skeleton, { className: "w-full h-full bg-zinc-900" })));
|
|
76
|
+
return (React.createElement("div", { className: "h-screen w-screen bg-white dark:bg-black" },
|
|
77
|
+
React.createElement(Skeleton, { className: "w-full h-full bg-zinc-100 dark:bg-zinc-900" })));
|
|
66
78
|
}
|
|
67
79
|
if (error) {
|
|
68
|
-
return (React.createElement("div", { className: "flex items-center justify-center h-screen bg-black" },
|
|
80
|
+
return (React.createElement("div", { className: "flex items-center justify-center h-screen bg-white dark:bg-black" },
|
|
69
81
|
React.createElement("div", { className: "text-red-500" },
|
|
70
82
|
"Error: ",
|
|
71
83
|
error)));
|
|
@@ -76,19 +88,19 @@ export default function Sandbox({ apiKey, sandboxId, env, themeColor, }) {
|
|
|
76
88
|
// Build the nested config from use cases
|
|
77
89
|
const nestedConfig = buildGuardianConfig(config.useCases, {
|
|
78
90
|
playgroundUid: sandboxId,
|
|
79
|
-
playgroundLogo: config.playgroundLogo || (React.createElement("div", { className: "text-white font-bold text-xl" }, config.name)),
|
|
91
|
+
playgroundLogo: config.playgroundLogo || (React.createElement("div", { className: "text-zinc-900 dark:text-white font-bold text-xl" }, config.name)),
|
|
80
92
|
});
|
|
81
93
|
// Get the first use case and framework as defaults
|
|
82
94
|
const firstUseCase = config.useCases[0];
|
|
83
95
|
const firstFramework = (_a = firstUseCase === null || firstUseCase === void 0 ? void 0 : firstUseCase.frameworks[0]) === null || _a === void 0 ? void 0 : _a.key;
|
|
84
96
|
if (!firstUseCase || !firstFramework) {
|
|
85
|
-
return (React.createElement("div", { className: "flex items-center justify-center h-screen bg-black" },
|
|
97
|
+
return (React.createElement("div", { className: "flex items-center justify-center h-screen bg-white dark:bg-black" },
|
|
86
98
|
React.createElement("div", { className: "text-red-500" }, "No use cases or frameworks found")));
|
|
87
99
|
}
|
|
88
100
|
// TODO: Pass env variables to the container runtime
|
|
89
101
|
// This will be implemented when integrating with the container technology
|
|
90
102
|
return (React.createElement(GuardianProvider, null,
|
|
91
103
|
React.createElement(VmProvider, null,
|
|
92
|
-
React.createElement("div", { className: "h-screen w-screen bg-black" },
|
|
93
|
-
React.createElement(GuardianPlayground, { nestedConfig: nestedConfig, useCase: firstUseCase.id, framework: firstFramework, isFrame: false, apiKey: apiKey, env: env, chatUid: config.chatUid })))));
|
|
104
|
+
React.createElement("div", { className: "h-screen w-screen bg-white dark:bg-black" },
|
|
105
|
+
React.createElement(GuardianPlayground, { nestedConfig: nestedConfig, useCase: firstUseCase.id, framework: firstFramework, isFrame: false, apiKey: apiKey, env: env, chatUid: config.chatUid, theme: theme })))));
|
|
94
106
|
}
|
|
@@ -21,6 +21,7 @@ function createDownloadLink(downloadEndpoint) {
|
|
|
21
21
|
* @returns Sandbox configuration
|
|
22
22
|
*/
|
|
23
23
|
export async function fetchSandboxConfig(apiKey, sandboxId) {
|
|
24
|
+
var _a, _b;
|
|
24
25
|
const client = createApiClient({
|
|
25
26
|
apiKey,
|
|
26
27
|
});
|
|
@@ -54,7 +55,7 @@ export async function fetchSandboxConfig(apiKey, sandboxId) {
|
|
|
54
55
|
name: sandboxContent.uid, // Use UID as name if no name field exists
|
|
55
56
|
description: sandboxContent.markdown || "", // Use markdown as description
|
|
56
57
|
themeColor: "#3b82f6", // Default theme color
|
|
57
|
-
hasPreview:
|
|
58
|
+
hasPreview: (_a = sandboxContent.has_preview) !== null && _a !== void 0 ? _a : false,
|
|
58
59
|
chatUid: sandboxContent.chat_uid || "", // Fallback: only used if published_url is not available
|
|
59
60
|
useCases: [
|
|
60
61
|
{
|
|
@@ -62,7 +63,7 @@ export async function fetchSandboxConfig(apiKey, sandboxId) {
|
|
|
62
63
|
name: sandboxContent.uid,
|
|
63
64
|
description: sandboxContent.markdown || "",
|
|
64
65
|
themeColor: "#3b82f6",
|
|
65
|
-
hasPreview:
|
|
66
|
+
hasPreview: (_b = sandboxContent.has_preview) !== null && _b !== void 0 ? _b : false,
|
|
66
67
|
frameworks: [
|
|
67
68
|
{
|
|
68
69
|
key: frameworkKey,
|
|
@@ -181,12 +181,12 @@ export default function AskAiView({ codeZipFile, playgroundUid, themeColor, }) {
|
|
|
181
181
|
React.createElement("span", { className: "text-muted-foreground text-sm" }, "Thinking...")))))) : (React.createElement("div", { className: "flex h-full items-center justify-center" },
|
|
182
182
|
React.createElement("div", { className: "flex flex-col items-start space-y-4 px-4 max-w-4xl" },
|
|
183
183
|
React.createElement("div", { className: "text-start" },
|
|
184
|
-
React.createElement("h2", { className: "mb-2 text-2xl font-semibold tracking-tight text-gray-200" }, "Hi! Ask me anything"),
|
|
184
|
+
React.createElement("h2", { className: "mb-2 text-2xl font-semibold tracking-tight text-zinc-800 dark:text-gray-200" }, "Hi! Ask me anything"),
|
|
185
185
|
React.createElement("p", { className: "text-muted-foreground text-base" }, "Try: \u201CHow does this sample app work?\u201D"))))),
|
|
186
186
|
React.createElement("div", { ref: messagesEndRef })),
|
|
187
|
-
React.createElement("div", { className: "shrink-0 border-t border-gray-800/50 bg-[#0a0b0f]/95 backdrop-blur-sm" },
|
|
187
|
+
React.createElement("div", { className: "shrink-0 border-t border-zinc-200 dark:border-gray-800/50 bg-zinc-50/95 dark:bg-[#0a0b0f]/95 backdrop-blur-sm" },
|
|
188
188
|
React.createElement("div", { className: "max-w-4xl mx-auto px-4 py-4" },
|
|
189
|
-
React.createElement("div", { className: "flex items-end gap-3 bg-[#1a1b23] rounded-2xl border border-gray-800/50 px-4 py-3 transition-all", style: {
|
|
189
|
+
React.createElement("div", { className: "flex items-end gap-3 bg-white dark:bg-[#1a1b23] rounded-2xl border border-zinc-200 dark:border-gray-800/50 px-4 py-3 transition-all", style: {
|
|
190
190
|
boxShadow: `0 0 0 1px transparent`,
|
|
191
191
|
} },
|
|
192
192
|
React.createElement("div", { className: "flex-1 min-w-0" },
|
|
@@ -195,7 +195,7 @@ export default function AskAiView({ codeZipFile, playgroundUid, themeColor, }) {
|
|
|
195
195
|
e.preventDefault();
|
|
196
196
|
handleSend();
|
|
197
197
|
}
|
|
198
|
-
}, placeholder: "Type your message...", disabled: isLoading, rows: 1, className: "w-full bg-transparent border-0 resize-none text-base text-gray-200 placeholder:text-gray-500 focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed max-h-40 overflow-y-auto leading-relaxed", style: {
|
|
198
|
+
}, placeholder: "Type your message...", disabled: isLoading, rows: 1, className: "w-full bg-transparent border-0 resize-none text-base text-zinc-800 dark:text-gray-200 placeholder:text-zinc-400 dark:placeholder:text-gray-500 focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed max-h-40 overflow-y-auto leading-relaxed", style: {
|
|
199
199
|
height: "auto",
|
|
200
200
|
minHeight: "32px",
|
|
201
201
|
}, onInput: (e) => {
|
|
@@ -4,7 +4,7 @@ import { Markdown } from "./ui/markdown";
|
|
|
4
4
|
export default function DefaultGuideView({ themeColor, }) {
|
|
5
5
|
return (React.createElement("div", { className: "h-full flex flex-col" },
|
|
6
6
|
React.createElement("div", { className: "flex-1 px-8 py-6" },
|
|
7
|
-
React.createElement(Markdown, { className: "text-gray-100", themeColor: themeColor }, `# Guardian Guide
|
|
7
|
+
React.createElement(Markdown, { className: "text-zinc-900 dark:text-gray-100", themeColor: themeColor }, `# Guardian Guide
|
|
8
8
|
|
|
9
9
|
Learn how to use Guardian to build and deploy your application with confidence.
|
|
10
10
|
|
|
@@ -20,7 +20,7 @@ export default function ConsoleWithGuide({ CustomConsole, GuideView, playgroundU
|
|
|
20
20
|
if (typeof CustomConsole === "string") {
|
|
21
21
|
return (React.createElement("div", { className: "h-full flex flex-col" },
|
|
22
22
|
React.createElement("div", { className: "flex-1 px-8 py-6" },
|
|
23
|
-
React.createElement(Markdown, { className: "text-gray-100", themeColor: themeColor, browserUrl: browserUrl, gitUrl: gitUrl, sandboxId: sandboxId, apiKey: apiKey }, CustomConsole))));
|
|
23
|
+
React.createElement(Markdown, { className: "text-zinc-900 dark:text-gray-100", themeColor: themeColor, browserUrl: browserUrl, gitUrl: gitUrl, sandboxId: sandboxId, apiKey: apiKey }, CustomConsole))));
|
|
24
24
|
}
|
|
25
25
|
const CustomConsoleComponent = CustomConsole;
|
|
26
26
|
return (React.createElement(CustomConsoleComponent, { onReloadPreview: onReloadPreview !== null && onReloadPreview !== void 0 ? onReloadPreview : (() => { }), onStageChange: onStageChange !== null && onStageChange !== void 0 ? onStageChange : (() => { }), themeColor: themeColor }));
|
|
@@ -64,7 +64,7 @@ export default function ConsoleWithGuide({ CustomConsole, GuideView, playgroundU
|
|
|
64
64
|
React.createElement("div", { className: "flex-1 min-h-0 overflow-y-auto" }, isConsoleView && renderCustomConsole()),
|
|
65
65
|
React.createElement("div", { className: "relative" },
|
|
66
66
|
React.createElement("div", { className: "flex flex-row w-full items-center text-xs justify-center opacity-30 mt-1 pb-2 bg-background" },
|
|
67
|
-
React.createElement("span", { className: "text-gray-300" }, "Powered by"),
|
|
67
|
+
React.createElement("span", { className: "text-zinc-600 dark:text-gray-300" }, "Powered by"),
|
|
68
68
|
React.createElement("span", { className: "hover:bg-accent rounded-sm p-1 mx-1" },
|
|
69
69
|
React.createElement(Logo, { width: 100, href: "https://sampleapp.ai" })))))));
|
|
70
70
|
}
|
|
@@ -4,54 +4,28 @@ import AppLayoutNoSidebar from "./app-layout-no-sidebar";
|
|
|
4
4
|
import GuardianDemo from "./demo/guardian-demo";
|
|
5
5
|
import React, { useEffect, useRef } from "react";
|
|
6
6
|
import { useGuardianContext } from "./context/guardian-context";
|
|
7
|
-
import { useSandboxUrlLoader
|
|
7
|
+
import { useSandboxUrlLoader } from "./hooks/use-sandbox-url-loader";
|
|
8
8
|
import { useFrameMessages } from "./hooks/use-frame-messages";
|
|
9
9
|
import { useVmContext } from "./context/vm-context";
|
|
10
10
|
import { cn } from "../../../lib/utils";
|
|
11
|
-
export default function GuardianComponent({ demoOptions, frameworkOptions, firstFrameworkByUseCase, currentFramework, currentUseCase, CustomConsole, GuideView, playgroundLogo, playgroundUid, browserUrl, useVm, sandboxUid, codeZipFile,
|
|
11
|
+
export default function GuardianComponent({ demoOptions, frameworkOptions, firstFrameworkByUseCase, currentFramework, currentUseCase, CustomConsole, GuideView, playgroundLogo, playgroundUid, browserUrl, useVm, sandboxUid, codeZipFile, completeCodeZipFile, variant, themeColor, hasPreview = true, isFrame = false, apiKey, env, chatUid, hideHeader = true, // Hardcoded to true by default, not exposed in Sandbox.tsx
|
|
12
12
|
gitUrl, }) {
|
|
13
13
|
const { previewUrl, setPreviewUrl } = useGuardianContext();
|
|
14
14
|
const { vmResolution } = useVmContext();
|
|
15
15
|
const [sandboxError, setSandboxError] = React.useState(null);
|
|
16
|
-
// Build startSandboxConfig
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
// PRECEDENCE: published_url takes precedence over chat_uid
|
|
21
|
-
// - If browserUrl (published_url) exists, it will be used directly (no startSandbox API call needed)
|
|
22
|
-
// - If browserUrl is not available, we need startSandboxConfig with chatUid to call startSandbox API
|
|
23
|
-
// This ensures backward compatibility while prioritizing published_url when available
|
|
24
|
-
const startSandboxConfig = apiKey
|
|
25
|
-
? Object.assign({ apiKey }, (!browserUrl && chatUid ? { env, chatUid } : {})) : undefined;
|
|
16
|
+
// Build startSandboxConfig for use-sandbox-url-loader
|
|
17
|
+
// apiKey is always included (guaranteed by parent validation)
|
|
18
|
+
// Include chatUid and env when browserUrl is missing (needed for startSandbox API call)
|
|
19
|
+
const startSandboxConfig = Object.assign({ apiKey }, (!browserUrl && chatUid ? { env, chatUid } : {}));
|
|
26
20
|
// Determine if browserUrl is ready to use immediately (from published_url)
|
|
27
21
|
// If browserUrl exists, it's ready (startSandboxConfig may still exist with just apiKey for VM calls)
|
|
28
22
|
const isBrowserUrlReady = !!browserUrl;
|
|
29
|
-
const { getSandboxUrl, loadSandboxUrl
|
|
23
|
+
const { getSandboxUrl, loadSandboxUrl } = useSandboxUrlLoader(startSandboxConfig);
|
|
30
24
|
// Initialize postMessage listener for iframe communication
|
|
31
25
|
// This sends IFRAME_READY and listens for UPDATE_VIEW messages
|
|
32
26
|
useFrameMessages();
|
|
33
|
-
// Track which console configs we've preloaded to prevent duplicates
|
|
34
|
-
const preloadedConfigsRef = useRef("");
|
|
35
27
|
// Track which main sandbox we've loaded to prevent duplicates
|
|
36
28
|
const loadedSandboxRef = useRef("");
|
|
37
|
-
// Preload console URLs when component mounts
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (consoleUrlConfigs && consoleUrlConfigs.length > 0 && apiKey) {
|
|
40
|
-
// Create a key from the configs to detect changes
|
|
41
|
-
const configKey = JSON.stringify(consoleUrlConfigs.map((c) => c.sandboxUid));
|
|
42
|
-
// Only preload if we haven't already preloaded these configs
|
|
43
|
-
if (preloadedConfigsRef.current !== configKey) {
|
|
44
|
-
preloadedConfigsRef.current = configKey;
|
|
45
|
-
// Ensure apiKey is passed to all configs
|
|
46
|
-
const configsWithApiKey = consoleUrlConfigs.map((config) => (Object.assign(Object.assign({}, config), { apiKey: config.apiKey || apiKey })));
|
|
47
|
-
preloadSandboxUrls(configsWithApiKey).catch((error) => {
|
|
48
|
-
console.error("Failed to preload console URLs:", error);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// Only re-run if consoleUrlConfigs or apiKey changes
|
|
53
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
54
|
-
}, [consoleUrlConfigs, apiKey]);
|
|
55
29
|
useEffect(() => {
|
|
56
30
|
// Create a key for this sandbox load
|
|
57
31
|
const sandboxKey = `${sandboxUid}-${browserUrl}-${useVm}`;
|
|
@@ -74,11 +48,6 @@ gitUrl, }) {
|
|
|
74
48
|
// The resolution will be set by Browser component via context
|
|
75
49
|
return;
|
|
76
50
|
}
|
|
77
|
-
// If useVm is true, apiKey is required
|
|
78
|
-
if (useVm && !apiKey) {
|
|
79
|
-
console.error("apiKey is required when useVm is true");
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
51
|
// Mark as loading to prevent duplicate requests
|
|
83
52
|
loadedSandboxRef.current = sandboxKey;
|
|
84
53
|
// Load the sandbox URL (will be cached by sandboxUid + browserUrl)
|
|
@@ -9,7 +9,7 @@ import { GuardianStyleWrapper } from "./guardian-style-wrapper";
|
|
|
9
9
|
*
|
|
10
10
|
* When isFrame=true, reads framework from URL params client-side.
|
|
11
11
|
*/
|
|
12
|
-
export default function GuardianPlayground({ nestedConfig, useCase, framework: serverFramework, isFrame = false, apiKey, env, chatUid, }) {
|
|
12
|
+
export default function GuardianPlayground({ nestedConfig, useCase, framework: serverFramework, isFrame = false, apiKey, env, chatUid, theme = "dark", }) {
|
|
13
13
|
var _a, _b;
|
|
14
14
|
// When in frame mode, allow URL params to override framework
|
|
15
15
|
const frameParams = useFrameParams();
|
|
@@ -40,6 +40,6 @@ export default function GuardianPlayground({ nestedConfig, useCase, framework: s
|
|
|
40
40
|
firstFrameworkByUseCase[useCaseId] = firstFrameworkKey;
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
|
-
return (React.createElement(GuardianStyleWrapper, { themeColor: frameworkConfig.themeColor },
|
|
44
|
-
React.createElement(GuardianComponent, { demoOptions: frameworkConfig.demoOptions, frameworkOptions: frameworkConfig.frameworkOptions, firstFrameworkByUseCase: firstFrameworkByUseCase, currentFramework: frameworkConfig.currentFramework, CustomConsole: frameworkConfig.CustomConsole, GuideView: frameworkConfig.GuideView, playgroundUid: frameworkConfig.playgroundUid, browserUrl: (_a = frameParams.iframeUrl) !== null && _a !== void 0 ? _a : frameworkConfig.browserUrl, useVm: frameworkConfig.useVm, playgroundLogo: frameworkConfig.playgroundLogo, sandboxUid: frameworkConfig.sandboxUid, name: frameworkConfig.name, description: frameworkConfig.description, codeZipFile: frameworkConfig.codeZipFile, completeCodeZipFile: frameworkConfig.completeCodeZipFile,
|
|
43
|
+
return (React.createElement(GuardianStyleWrapper, { themeColor: frameworkConfig.themeColor, theme: theme },
|
|
44
|
+
React.createElement(GuardianComponent, { demoOptions: frameworkConfig.demoOptions, frameworkOptions: frameworkConfig.frameworkOptions, firstFrameworkByUseCase: firstFrameworkByUseCase, currentFramework: frameworkConfig.currentFramework, CustomConsole: frameworkConfig.CustomConsole, GuideView: frameworkConfig.GuideView, playgroundUid: frameworkConfig.playgroundUid, browserUrl: (_a = frameParams.iframeUrl) !== null && _a !== void 0 ? _a : frameworkConfig.browserUrl, useVm: frameworkConfig.useVm, playgroundLogo: frameworkConfig.playgroundLogo, sandboxUid: frameworkConfig.sandboxUid, name: frameworkConfig.name, description: frameworkConfig.description, codeZipFile: frameworkConfig.codeZipFile, completeCodeZipFile: frameworkConfig.completeCodeZipFile, variant: frameworkConfig.variant, themeColor: frameworkConfig.themeColor, hasPreview: (_b = frameworkConfig.hasPreview) !== null && _b !== void 0 ? _b : true, currentUseCase: useCase, isFrame: isFrame, apiKey: apiKey, env: env, chatUid: chatUid, gitUrl: frameworkConfig.gitUrl })));
|
|
45
45
|
}
|
|
@@ -5,9 +5,28 @@ import { TAILWIND_CSS } from "../../../lib/generated-css";
|
|
|
5
5
|
* Style wrapper for Guardian components that injects Tailwind CSS
|
|
6
6
|
* into the document without using Shadow DOM (preserves React context)
|
|
7
7
|
*/
|
|
8
|
-
export const GuardianStyleWrapper = ({ children, themeColor = "#3b82f6", }) => {
|
|
8
|
+
export const GuardianStyleWrapper = ({ children, themeColor = "#3b82f6", theme = "dark", }) => {
|
|
9
9
|
const [stylesInjected, setStylesInjected] = useState(false);
|
|
10
|
+
const [resolvedTheme, setResolvedTheme] = useState(theme === "system" ? "dark" : theme);
|
|
10
11
|
const rootRef = useRef(null);
|
|
12
|
+
// Handle system theme preference
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (theme === "system") {
|
|
15
|
+
// Check if we're in browser environment
|
|
16
|
+
if (typeof window === "undefined")
|
|
17
|
+
return;
|
|
18
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
19
|
+
setResolvedTheme(mediaQuery.matches ? "dark" : "light");
|
|
20
|
+
const handler = (e) => {
|
|
21
|
+
setResolvedTheme(e.matches ? "dark" : "light");
|
|
22
|
+
};
|
|
23
|
+
mediaQuery.addEventListener("change", handler);
|
|
24
|
+
return () => mediaQuery.removeEventListener("change", handler);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
setResolvedTheme(theme);
|
|
28
|
+
}
|
|
29
|
+
}, [theme]);
|
|
11
30
|
useEffect(() => {
|
|
12
31
|
// Only run on client side
|
|
13
32
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
@@ -39,7 +58,7 @@ export const GuardianStyleWrapper = ({ children, themeColor = "#3b82f6", }) => {
|
|
|
39
58
|
rootRef.current.style.setProperty("--colors-secondary", secondaryColor);
|
|
40
59
|
}
|
|
41
60
|
}, [themeColor]);
|
|
42
|
-
return (React.createElement("div", { ref: rootRef, className:
|
|
61
|
+
return (React.createElement("div", { ref: rootRef, className: `guardian-sdk-root bg-background text-foreground ${resolvedTheme === "dark" ? "dark" : ""}`, style: {
|
|
43
62
|
width: "100%",
|
|
44
63
|
height: "100%",
|
|
45
64
|
fontFamily: 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',
|
|
@@ -36,12 +36,12 @@ export function useSandboxUrlLoader(startSandboxConfig) {
|
|
|
36
36
|
}
|
|
37
37
|
if (useVm) {
|
|
38
38
|
try {
|
|
39
|
-
// API key is required - use from config
|
|
40
|
-
const apiKey = config.apiKey
|
|
39
|
+
// API key is required - use directly from config
|
|
40
|
+
const apiKey = config.apiKey;
|
|
41
41
|
if (!apiKey) {
|
|
42
42
|
throw new Error("API key is required for VM sandbox creation");
|
|
43
43
|
}
|
|
44
|
-
// Fetch VM URL from API using the SDK API client
|
|
44
|
+
// Fetch VM URL from API using the SDK API client
|
|
45
45
|
const client = createApiClient({ apiKey });
|
|
46
46
|
if (config === null || config === void 0 ? void 0 : config.resolution) {
|
|
47
47
|
config.resolution[0] += 20;
|
|
@@ -107,10 +107,13 @@ export function useSandboxUrlLoader(startSandboxConfig) {
|
|
|
107
107
|
if (!startSandboxConfig.env) {
|
|
108
108
|
throw new Error("env is required when published_url is not available (needed to start sandbox)");
|
|
109
109
|
}
|
|
110
|
-
//
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
// API key is required - use directly from config
|
|
111
|
+
const apiKey = config.apiKey;
|
|
112
|
+
if (!apiKey) {
|
|
113
|
+
throw new Error("API key is required for starting sandbox");
|
|
114
|
+
}
|
|
115
|
+
// Create client with apiKey (will be sent as Bearer token)
|
|
116
|
+
const client = createApiClient({ apiKey });
|
|
114
117
|
const response = await client.sdk.startSandbox({
|
|
115
118
|
env: startSandboxConfig.env,
|
|
116
119
|
chatUid: startSandboxConfig.chatUid,
|
|
@@ -153,9 +156,8 @@ export function useSandboxUrlLoader(startSandboxConfig) {
|
|
|
153
156
|
return getVmUrl(cacheKey) === undefined && !hasError(cacheKey);
|
|
154
157
|
});
|
|
155
158
|
// Load all URLs in parallel, but catch errors individually
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}, [getVmUrl, loadSandboxUrl, hasError, startSandboxConfig]);
|
|
159
|
+
await Promise.allSettled(configsToLoad.map((config) => loadSandboxUrl(config)));
|
|
160
|
+
}, [getVmUrl, loadSandboxUrl, hasError]);
|
|
159
161
|
return {
|
|
160
162
|
loadSandboxUrl,
|
|
161
163
|
getSandboxUrl,
|
|
@@ -494,57 +494,57 @@ export default function Browser({ previewUrl, setPreviewUrl, containerEndpoint,
|
|
|
494
494
|
} }));
|
|
495
495
|
};
|
|
496
496
|
return (React.createElement("div", { className: "flex h-full w-full flex-col" },
|
|
497
|
-
!useVm && !isGuardian && (React.createElement("div", { className: "bg-
|
|
497
|
+
!useVm && !isGuardian && (React.createElement("div", { className: "bg-black border-b border-zinc-800 flex-shrink-0" },
|
|
498
498
|
React.createElement("div", { className: "flex items-center gap-1.5 px-2 py-1.5 h-[2.38rem]" },
|
|
499
499
|
React.createElement("div", { className: "flex gap-0.5" },
|
|
500
|
-
React.createElement("button", { onClick: handleBack, disabled: historyIndex === 0, className: "p-1 hover:bg-zinc-
|
|
501
|
-
React.createElement(ChevronLeft, { size: 14, className: "text-zinc-
|
|
502
|
-
React.createElement("button", { onClick: handleForward, disabled: historyIndex === historyLength - 1, className: "p-1 hover:bg-zinc-
|
|
503
|
-
React.createElement(ChevronRight, { size: 14, className: "text-zinc-
|
|
504
|
-
React.createElement("button", { onClick: handleRefresh, className: "p-1 hover:bg-zinc-
|
|
505
|
-
React.createElement(RefreshCw, { size: 14, className: `text-zinc-
|
|
506
|
-
React.createElement("div", { className: "flex-1 flex items-center gap-1.5 px-2 py-1 bg-zinc-
|
|
507
|
-
error ? (React.createElement(AlertTriangle, { size: 12, className: "text-red-500 flex-shrink-0" })) : (React.createElement(Lock, { size: 12, className: "text-zinc-
|
|
500
|
+
React.createElement("button", { onClick: handleBack, disabled: historyIndex === 0, className: "p-1 hover:bg-zinc-900 rounded disabled:opacity-30 disabled:hover:bg-transparent transition-colors", title: "Back" },
|
|
501
|
+
React.createElement(ChevronLeft, { size: 14, className: "text-zinc-400" })),
|
|
502
|
+
React.createElement("button", { onClick: handleForward, disabled: historyIndex === historyLength - 1, className: "p-1 hover:bg-zinc-900 rounded disabled:opacity-30 disabled:hover:bg-transparent transition-colors", title: "Forward" },
|
|
503
|
+
React.createElement(ChevronRight, { size: 14, className: "text-zinc-400" })),
|
|
504
|
+
React.createElement("button", { onClick: handleRefresh, className: "p-1 hover:bg-zinc-900 rounded transition-colors", title: "Refresh" },
|
|
505
|
+
React.createElement(RefreshCw, { size: 14, className: `text-zinc-400 ${isLoading ? "animate-spin" : ""}` }))),
|
|
506
|
+
React.createElement("div", { className: "flex-1 flex items-center gap-1.5 px-2 py-1 bg-zinc-950 rounded text-zinc-400 focus-within:bg-zinc-900 transition-colors" },
|
|
507
|
+
error ? (React.createElement(AlertTriangle, { size: 12, className: "text-red-500 flex-shrink-0" })) : (React.createElement(Lock, { size: 12, className: "text-zinc-600 flex-shrink-0" })),
|
|
508
508
|
React.createElement("input", { type: "text",
|
|
509
509
|
// value={urlInput}
|
|
510
|
-
value: "/", onChange: (e) => setUrlInput(e.target.value), onKeyDown: handleUrlChange, className: "flex-1 text-xs border-none outline-none bg-transparent text-zinc-
|
|
511
|
-
isGuardian && (React.createElement("button", { onClick: () => setIsBrowserMaximized(!isBrowserMaximized), className: "p-1 hover:bg-zinc-
|
|
510
|
+
value: "/", onChange: (e) => setUrlInput(e.target.value), onKeyDown: handleUrlChange, className: "flex-1 text-xs border-none outline-none bg-transparent text-zinc-300 placeholder:text-zinc-600", placeholder: "Enter URL" }),
|
|
511
|
+
isGuardian && (React.createElement("button", { onClick: () => setIsBrowserMaximized(!isBrowserMaximized), className: "p-1 hover:bg-zinc-900 rounded transition-colors", title: isBrowserMaximized
|
|
512
512
|
? "Exit fullscreen"
|
|
513
|
-
: "Fullscreen preview" }, isBrowserMaximized ? (React.createElement(Minimize2, { size: 14, className: "text-zinc-
|
|
513
|
+
: "Fullscreen preview" }, isBrowserMaximized ? (React.createElement(Minimize2, { size: 14, className: "text-zinc-400" })) : (React.createElement(Maximize2, { size: 14, className: "text-zinc-400" })))),
|
|
514
514
|
React.createElement("button", { onClick: () => {
|
|
515
515
|
window.open(previewUrl, "_blank", "noopener,noreferrer");
|
|
516
|
-
}, className: "ml-1 p-1 hover:bg-zinc-
|
|
517
|
-
React.createElement(ExternalLink, { size: 14, className: "text-zinc-
|
|
516
|
+
}, className: "ml-1 p-1 hover:bg-zinc-900 rounded transition-colors", title: "Open in new tab", disabled: !urlInput || !!error, tabIndex: -1, type: "button" },
|
|
517
|
+
React.createElement(ExternalLink, { size: 14, className: "text-zinc-400" })),
|
|
518
518
|
React.createElement(DropdownMenu, null,
|
|
519
519
|
React.createElement(DropdownMenuTrigger, { asChild: true },
|
|
520
|
-
React.createElement("button", { className: "ml-1 p-1 hover:bg-zinc-
|
|
521
|
-
React.createElement(MoreVertical, { size: 14, className: "text-zinc-
|
|
522
|
-
React.createElement(DropdownMenuContent, { align: "end", className: "bg-
|
|
520
|
+
React.createElement("button", { className: "ml-1 p-1 hover:bg-zinc-900 rounded transition-colors", title: "More options", type: "button" },
|
|
521
|
+
React.createElement(MoreVertical, { size: 14, className: "text-zinc-400" }))),
|
|
522
|
+
React.createElement(DropdownMenuContent, { align: "end", className: "bg-zinc-900 border border-zinc-800" },
|
|
523
523
|
React.createElement(DropdownMenuItem, { onClick: () => {
|
|
524
524
|
// Restart functionality - can be implemented if needed
|
|
525
|
-
}, className: "cursor-pointer text-zinc-
|
|
526
|
-
error && (React.createElement("div", { className: "p-4 bg-red-
|
|
525
|
+
}, className: "cursor-pointer text-zinc-300 hover:bg-zinc-800" }, "Restart App"))))))),
|
|
526
|
+
error && (React.createElement("div", { className: "p-4 bg-red-950 border-b border-red-800 text-red-200 text-sm" },
|
|
527
527
|
React.createElement("div", { className: "flex items-center gap-2" },
|
|
528
528
|
React.createElement(AlertTriangle, { size: 16 }),
|
|
529
529
|
React.createElement("span", null, error)))),
|
|
530
|
-
React.createElement("div", { ref: containerRef, className: "flex-1 min-h-0 relative" }, sandboxError && sandboxError.includes("env is required") ? (React.createElement("div", { className: "h-full w-full flex items-center justify-center bg-zinc-
|
|
530
|
+
React.createElement("div", { ref: containerRef, className: "flex-1 min-h-0 relative" }, sandboxError && sandboxError.includes("env is required") ? (React.createElement("div", { className: "h-full w-full flex items-center justify-center bg-zinc-900" },
|
|
531
531
|
React.createElement("div", { className: "max-w-md mx-auto p-8 text-center" },
|
|
532
532
|
React.createElement("div", { className: "mb-4 flex justify-center" },
|
|
533
|
-
React.createElement(AlertTriangle, { size: 48, className: "text-amber-
|
|
534
|
-
React.createElement("h2", { className: "text-xl font-semibold text-zinc-
|
|
535
|
-
React.createElement("p", { className: "text-sm text-zinc-
|
|
533
|
+
React.createElement(AlertTriangle, { size: 48, className: "text-amber-400" })),
|
|
534
|
+
React.createElement("h2", { className: "text-xl font-semibold text-zinc-100 mb-2" }, "Environment Variables Required"),
|
|
535
|
+
React.createElement("p", { className: "text-sm text-zinc-400 mb-4" },
|
|
536
536
|
"This sandbox doesn't have a published URL and needs to be started dynamically. Please provide the",
|
|
537
537
|
" ",
|
|
538
|
-
React.createElement("code", { className: "px-1.5 py-0.5 bg-zinc-
|
|
538
|
+
React.createElement("code", { className: "px-1.5 py-0.5 bg-zinc-800 rounded text-xs font-mono" }, "env"),
|
|
539
539
|
" ",
|
|
540
540
|
"prop to the",
|
|
541
541
|
" ",
|
|
542
|
-
React.createElement("code", { className: "px-1.5 py-0.5 bg-zinc-
|
|
542
|
+
React.createElement("code", { className: "px-1.5 py-0.5 bg-zinc-800 rounded text-xs font-mono" }, "<Sandbox>"),
|
|
543
543
|
" ",
|
|
544
544
|
"component."),
|
|
545
|
-
React.createElement("div", { className: "mt-6 p-4 bg-zinc-
|
|
546
|
-
React.createElement("p", { className: "text-xs font-mono text-zinc-
|
|
547
|
-
React.createElement("pre", { className: "text-xs text-zinc-
|
|
545
|
+
React.createElement("div", { className: "mt-6 p-4 bg-zinc-800 rounded-lg text-left" },
|
|
546
|
+
React.createElement("p", { className: "text-xs font-mono text-zinc-300 mb-2" }, "Example:"),
|
|
547
|
+
React.createElement("pre", { className: "text-xs text-zinc-400 overflow-x-auto" }, `<Sandbox
|
|
548
548
|
apiKey="your-api-key"
|
|
549
549
|
sandboxId="sandbox-id"
|
|
550
550
|
env={{
|
|
@@ -553,8 +553,8 @@ export default function Browser({ previewUrl, setPreviewUrl, containerEndpoint,
|
|
|
553
553
|
}}
|
|
554
554
|
/>`))))) : (React.createElement(React.Fragment, null,
|
|
555
555
|
renderIframe(),
|
|
556
|
-
isLoading && (React.createElement("div", { className: "absolute inset-0 bg-zinc-
|
|
557
|
-
React.createElement("div", { className: "text-sm text-zinc-
|
|
556
|
+
isLoading && (React.createElement("div", { className: "absolute inset-0 bg-zinc-800 bg-opacity-50 flex items-center justify-center z-10" },
|
|
557
|
+
React.createElement("div", { className: "text-sm text-zinc-400 bg-black p-3 rounded-lg shadow-md" },
|
|
558
558
|
"Loading ",
|
|
559
559
|
urlInput,
|
|
560
560
|
"..."))),
|
|
@@ -4,5 +4,5 @@ export { VmProvider, useVmContext } from "./context/vm-context";
|
|
|
4
4
|
export { GuardianProvider, useGuardianContext } from "./context/guardian-context";
|
|
5
5
|
export * from "./types";
|
|
6
6
|
export { default as CodeFocusSection } from "./code-focus-section";
|
|
7
|
-
export { buildGuardianConfig
|
|
7
|
+
export { buildGuardianConfig } from "./utils";
|
|
8
8
|
export { Framework, FrameworkLabel } from "./types";
|
|
@@ -16,10 +16,10 @@ export default function PreviewControlBar({ isMinimized, onToggle, onRefresh, th
|
|
|
16
16
|
React.createElement(ChevronDown, { className: "w-4 h-4" })),
|
|
17
17
|
React.createElement("span", { className: "text-sm font-medium", style: { color: effectiveThemeColor } }, "Preview")),
|
|
18
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
|
|
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" },
|
|
20
20
|
React.createElement(ExternalLink, { className: "w-4 h-4" }),
|
|
21
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
|
|
22
|
+
React.createElement("button", { onClick: onRefresh, className: "p-1.5 rounded transition-colors hover:bg-zinc-800", title: "Refresh preview", style: { color: effectiveThemeColor } },
|
|
23
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
|
|
24
|
+
React.createElement("button", { onClick: () => setIsBrowserMaximized(!isBrowserMaximized), className: "p-1.5 rounded transition-colors 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
25
|
}
|
|
@@ -213,11 +213,11 @@ export default function RightView({ reloadCounter, overlayStage, browserUrl, use
|
|
|
213
213
|
React.createElement("div", { className: "absolute inset-x-0 top-0 h-1/2 group-hover:bg-blue-400/20 transition-colors" }),
|
|
214
214
|
React.createElement("div", { className: "absolute inset-x-0 bottom-0 h-1/2 group-hover:bg-blue-400/20 transition-colors" }),
|
|
215
215
|
React.createElement("div", { className: "h-full w-px bg-border group-hover:bg-blue-400 transition-colors relative z-10" }))))),
|
|
216
|
-
React.createElement(Panel, { defaultSize: 32, minSize: 20, maxSize: 80, order: 2 },
|
|
216
|
+
React.createElement(Panel, { defaultSize: hasPreview ? 32 : 100, minSize: 20, maxSize: hasPreview ? 80 : 100, order: 2 },
|
|
217
217
|
React.createElement("div", { className: "h-full w-full flex flex-col" },
|
|
218
218
|
React.createElement("div", { className: "flex-1 min-h-0 flex flex-col" },
|
|
219
219
|
React.createElement(React.Fragment, null,
|
|
220
|
-
React.createElement("div", { className: "flex items-center justify-between border-b border-zinc-800
|
|
220
|
+
React.createElement("div", { className: "flex items-center justify-between border-b border-zinc-800 bg-zinc-900" },
|
|
221
221
|
React.createElement(PillFileSelector, { themeColor: effectiveThemeColor }),
|
|
222
222
|
React.createElement("div", { className: "px-2 flex-shrink-0" },
|
|
223
223
|
React.createElement("button", { type: "button", className: "inline-flex items-center gap-1 text-[10px] font-medium transition-colors hover:opacity-80", style: { color: effectiveThemeColor }, onClick: handleDownloadAsZip },
|
|
@@ -59,7 +59,7 @@ export const DownloadAndOpenButtons = ({ downloadUrl, themeColor, gitUrl, browse
|
|
|
59
59
|
React.createElement("button", { type: "button", className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md !text-white transition-all hover:opacity-90 active:scale-[0.98]", style: { backgroundColor: themeColor }, onClick: handleDownload },
|
|
60
60
|
React.createElement(DownloadIcon, { className: "w-3.5 h-3.5 !text-white" }),
|
|
61
61
|
"Download example"),
|
|
62
|
-
React.createElement("button", { type: "button", className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md border transition-all hover:opacity-90 active:scale-[0.98] bg-zinc-
|
|
62
|
+
React.createElement("button", { type: "button", className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md border transition-all hover:opacity-90 active:scale-[0.98] bg-zinc-100 dark:bg-zinc-800 border-zinc-300 dark:border-zinc-700 text-zinc-900 dark:text-white", onClick: handleOpenInVSCode },
|
|
63
63
|
React.createElement(VSCodeLogo, { className: "w-3.5 h-3.5" }),
|
|
64
64
|
"Integrate in VS Code")),
|
|
65
65
|
React.createElement(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen },
|
|
@@ -1,10 +1,39 @@
|
|
|
1
|
-
import React, { memo, useState } from "react";
|
|
1
|
+
import React, { memo, useState, useEffect } from "react";
|
|
2
2
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
|
3
3
|
import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism";
|
|
4
|
+
import { oneLight } from "react-syntax-highlighter/dist/esm/styles/prism";
|
|
4
5
|
import { cn } from "../../../../../../lib/utils";
|
|
5
6
|
import { Copy, CheckCircle2 } from "lucide-react";
|
|
6
7
|
export const CodeBlock = memo(({ language, value, title, className, children, isInsideCodeGroup = false, maxH, }) => {
|
|
7
8
|
const [copied, setCopied] = useState(false);
|
|
9
|
+
const [isDark, setIsDark] = useState(true);
|
|
10
|
+
// Detect if we're in dark mode by checking for .dark class on ancestor
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const checkTheme = () => {
|
|
13
|
+
var _a;
|
|
14
|
+
if (typeof document === "undefined")
|
|
15
|
+
return;
|
|
16
|
+
// Check if guardian-sdk-root has dark class
|
|
17
|
+
const root = document.querySelector(".guardian-sdk-root");
|
|
18
|
+
setIsDark((_a = root === null || root === void 0 ? void 0 : root.classList.contains("dark")) !== null && _a !== void 0 ? _a : true);
|
|
19
|
+
};
|
|
20
|
+
checkTheme();
|
|
21
|
+
// Also check on mount with a slight delay to ensure DOM is ready
|
|
22
|
+
const timer = setTimeout(checkTheme, 100);
|
|
23
|
+
// Watch for changes using MutationObserver
|
|
24
|
+
const observer = new MutationObserver(checkTheme);
|
|
25
|
+
const root = document.querySelector(".guardian-sdk-root");
|
|
26
|
+
if (root) {
|
|
27
|
+
observer.observe(root, {
|
|
28
|
+
attributes: true,
|
|
29
|
+
attributeFilter: ["class"],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return () => {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
observer.disconnect();
|
|
35
|
+
};
|
|
36
|
+
}, []);
|
|
8
37
|
let code = value;
|
|
9
38
|
if (typeof children === "string") {
|
|
10
39
|
code = children;
|
|
@@ -22,33 +51,41 @@ export const CodeBlock = memo(({ language, value, title, className, children, is
|
|
|
22
51
|
// If inside CodeGroup, render just the code content
|
|
23
52
|
if (isInsideCodeGroup) {
|
|
24
53
|
return (React.createElement("div", { className: "group relative overflow-x-auto" },
|
|
25
|
-
React.createElement("div", { className: `${maxH || "max-h-[40vh]"} rounded-b-md bg-zinc-900 px-5 py-3 overflow-y-auto [&>pre]:overflow-x-auto` },
|
|
26
|
-
React.createElement("div", { className: "min-w-0 text-[13px]" },
|
|
27
|
-
React.createElement(SyntaxHighlighter, { language: language || "javascript", style: vscDarkPlus, PreTag: "div", customStyle: {
|
|
54
|
+
React.createElement("div", { className: `${maxH || "max-h-[40vh]"} rounded-b-md bg-zinc-100 dark:bg-zinc-900 px-5 py-3 overflow-y-auto [&>pre]:overflow-x-auto` },
|
|
55
|
+
React.createElement("div", { className: "min-w-0 text-[13px] [&_*]:!bg-transparent" },
|
|
56
|
+
React.createElement(SyntaxHighlighter, { language: language || "javascript", style: isDark ? vscDarkPlus : oneLight, PreTag: "div", customStyle: {
|
|
28
57
|
margin: 0,
|
|
29
58
|
padding: 0,
|
|
30
|
-
background: "transparent",
|
|
59
|
+
background: "transparent !important",
|
|
31
60
|
fontSize: "13px",
|
|
32
61
|
width: "100%",
|
|
33
62
|
minWidth: 0,
|
|
34
63
|
maxWidth: "100%",
|
|
64
|
+
}, codeTagProps: {
|
|
65
|
+
style: {
|
|
66
|
+
background: "transparent !important",
|
|
67
|
+
},
|
|
35
68
|
}, wrapLongLines: false }, code || "")))));
|
|
36
69
|
}
|
|
37
70
|
// Standalone code block with title
|
|
38
71
|
return (React.createElement("div", { className: cn("relative w-full border rounded-lg mb-4", className) },
|
|
39
|
-
React.createElement("div", { className: "flex items-center justify-between px-4 py-2 bg-zinc-900 text-primary border-b rounded-t-md" },
|
|
72
|
+
React.createElement("div", { className: "flex items-center justify-between px-4 py-2 bg-zinc-100 dark:bg-zinc-900 text-primary border-b rounded-t-md" },
|
|
40
73
|
React.createElement("span", { className: "text-xs text-primary font-mono" }, language || title || ""),
|
|
41
|
-
React.createElement("button", { type: "button", className: "h-5 w-5 flex items-center justify-center hover:bg-transparent text-zinc-200 hover:text-zinc-300 border-none", onClick: handleCopy }, copied ? (React.createElement(CheckCircle2, { className: "h-3 w-3 text-green-500" })) : (React.createElement(Copy, { className: "h-3 w-3" })))),
|
|
42
|
-
React.createElement("div", { className: `${maxH || "max-h-[40vh]"} rounded-b-md bg-zinc-900 px-5 py-3 overflow-y-auto [&>pre]:overflow-x-auto` },
|
|
43
|
-
React.createElement("div", { className: "min-w-0 text-[13px]" },
|
|
44
|
-
React.createElement(SyntaxHighlighter, { language: language || "javascript", style: vscDarkPlus, PreTag: "div", customStyle: {
|
|
74
|
+
React.createElement("button", { type: "button", className: "h-5 w-5 flex items-center justify-center hover:bg-transparent text-zinc-700 dark:text-zinc-200 hover:text-zinc-900 dark:hover:text-zinc-300 border-none", onClick: handleCopy }, copied ? (React.createElement(CheckCircle2, { className: "h-3 w-3 text-green-500" })) : (React.createElement(Copy, { className: "h-3 w-3" })))),
|
|
75
|
+
React.createElement("div", { className: `${maxH || "max-h-[40vh]"} rounded-b-md bg-zinc-100 dark:bg-zinc-900 px-5 py-3 overflow-y-auto [&>pre]:overflow-x-auto` },
|
|
76
|
+
React.createElement("div", { className: "min-w-0 text-[13px] [&_*]:!bg-transparent" },
|
|
77
|
+
React.createElement(SyntaxHighlighter, { language: language || "javascript", style: isDark ? vscDarkPlus : oneLight, PreTag: "div", customStyle: {
|
|
45
78
|
margin: 0,
|
|
46
79
|
padding: 0,
|
|
47
|
-
background: "transparent",
|
|
80
|
+
background: "transparent !important",
|
|
48
81
|
fontSize: "13px",
|
|
49
82
|
width: "100%",
|
|
50
83
|
minWidth: 0,
|
|
51
84
|
maxWidth: "100%",
|
|
85
|
+
}, codeTagProps: {
|
|
86
|
+
style: {
|
|
87
|
+
background: "transparent !important",
|
|
88
|
+
},
|
|
52
89
|
}, wrapLongLines: false }, code || "")))));
|
|
53
90
|
});
|
|
54
91
|
CodeBlock.displayName = "CodeBlock";
|