@sampleapp.ai/sdk 1.0.29 → 1.0.31

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 (145) 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 +88 -0
  54. package/dist/components/sandbox/SandboxHome.js +141 -0
  55. package/dist/components/sandbox/api.js +84 -0
  56. package/dist/components/sandbox/guardian/app-layout-no-sidebar.js +11 -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 +70 -0
  65. package/dist/components/sandbox/guardian/guardian-component.js +99 -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 +47 -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 +125 -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 +246 -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 +51 -0
  84. package/dist/components/sandbox/guardian/right-view/right-top-down-view.js +281 -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 +91 -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/download-and-open-buttons.js +117 -0
  96. package/dist/components/sandbox/guardian/ui/dropdown-menu.js +82 -0
  97. package/dist/components/sandbox/guardian/ui/markdown/accordion-group/accordion.js +62 -0
  98. package/dist/components/sandbox/guardian/ui/markdown/accordion-group.js +23 -0
  99. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-check.js +4 -0
  100. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-error.js +4 -0
  101. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-info.js +4 -0
  102. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-note.js +4 -0
  103. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-tip.js +4 -0
  104. package/dist/components/sandbox/guardian/ui/markdown/callout/callout-warning.js +4 -0
  105. package/dist/components/sandbox/guardian/ui/markdown/callout/shared/callout.js +9 -0
  106. package/dist/components/sandbox/guardian/ui/markdown/callout/shared/types.js +1 -0
  107. package/dist/components/sandbox/guardian/ui/markdown/card-group/card.js +18 -0
  108. package/dist/components/sandbox/guardian/ui/markdown/card-group.js +25 -0
  109. package/dist/components/sandbox/guardian/ui/markdown/code-group/code-block.js +54 -0
  110. package/dist/components/sandbox/guardian/ui/markdown/code-group.js +101 -0
  111. package/dist/components/sandbox/guardian/ui/markdown/icon.js +31 -0
  112. package/dist/components/sandbox/guardian/ui/markdown.js +791 -0
  113. package/dist/components/sandbox/guardian/ui/popover.js +25 -0
  114. package/dist/components/sandbox/guardian/ui/tooltip.js +25 -0
  115. package/dist/components/sandbox/guardian/utils.js +89 -0
  116. package/dist/components/sandbox/guardian/zip-to-codebase.js +259 -0
  117. package/dist/components/sandbox/guardian/zip-to-filetree.js +284 -0
  118. package/dist/components/sandbox/index.js +4 -0
  119. package/dist/components/sandbox/sandbox-control-bar.js +91 -0
  120. package/dist/components/sandbox/sandbox-header.js +52 -0
  121. package/dist/components/sandbox/sandbox-home/SandboxCard.js +65 -0
  122. package/dist/components/sandbox/sandbox-home/SandboxHome.js +115 -0
  123. package/dist/components/sandbox/sandbox-home/SearchBar.js +12 -0
  124. package/dist/components/sandbox/sandbox-home/index.js +3 -0
  125. package/dist/components/sandbox/sandbox-left-panel.js +248 -0
  126. package/dist/components/sandbox/sandbox-loading.js +48 -0
  127. package/dist/components/sandbox/sandbox-right-panel.js +247 -0
  128. package/dist/components/sandbox/types.js +1 -0
  129. package/dist/components/sandbox.js +32 -0
  130. package/dist/components/tailwind-example.js +46 -0
  131. package/dist/components/ui/skeleton.js +18 -0
  132. package/dist/index.d.ts +32 -103
  133. package/dist/index.es.js +90529 -423
  134. package/dist/index.js +13 -2
  135. package/dist/index.standalone.js +61 -53
  136. package/dist/index.standalone.umd.js +17 -24
  137. package/dist/lib/api-client.example.js +60 -0
  138. package/dist/lib/api-client.js +140 -0
  139. package/dist/lib/generated-css.js +4 -0
  140. package/dist/lib/inject-styles.js +42 -0
  141. package/dist/lib/shadow-dom-wrapper.js +42 -0
  142. package/dist/lib/utils.js +5 -0
  143. package/dist/sdk.css +1 -1
  144. package/dist/tailwind.css +1 -0
  145. package/package.json +41 -9
@@ -0,0 +1,248 @@
1
+ "use client";
2
+ import React, { useState, useCallback, useRef, useEffect } from "react";
3
+ import { LoaderIcon, ArrowUpIcon } from "../icons";
4
+ /**
5
+ * Left panel with Guide and Ask AI tabs
6
+ */
7
+ export function SandboxLeftPanel({ mdx, GuideComponent, playgroundUid, themeColor, apiKey, apiBaseUrl = "https://api.sampleapp.ai", files, }) {
8
+ const [activeTab, setActiveTab] = useState("guide");
9
+ return (React.createElement("div", { style: {
10
+ display: "flex",
11
+ flexDirection: "column",
12
+ height: "100%",
13
+ backgroundColor: "#18181b",
14
+ borderRight: "1px solid rgba(255, 255, 255, 0.1)",
15
+ } },
16
+ React.createElement("div", { style: {
17
+ display: "flex",
18
+ justifyContent: "center",
19
+ padding: "12px 16px",
20
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
21
+ } },
22
+ React.createElement("div", { style: {
23
+ display: "flex",
24
+ gap: "4px",
25
+ padding: "4px",
26
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
27
+ borderRadius: "8px",
28
+ } },
29
+ React.createElement(TabButton, { active: activeTab === "guide", onClick: () => setActiveTab("guide"), themeColor: themeColor }, "Guide"),
30
+ React.createElement(TabButton, { active: activeTab === "chat", onClick: () => setActiveTab("chat"), themeColor: themeColor }, "Ask AI"))),
31
+ React.createElement("div", { style: { flex: 1, overflow: "hidden", minHeight: 0 } },
32
+ activeTab === "guide" && (React.createElement(GuideTab, { mdx: mdx, GuideComponent: GuideComponent, themeColor: themeColor })),
33
+ activeTab === "chat" && (React.createElement(ChatTab, { playgroundUid: playgroundUid, themeColor: themeColor, apiKey: apiKey, apiBaseUrl: apiBaseUrl, files: files })))));
34
+ }
35
+ function TabButton({ children, active, onClick, themeColor, }) {
36
+ return (React.createElement("button", { onClick: onClick, style: {
37
+ padding: "8px 16px",
38
+ fontSize: "13px",
39
+ fontWeight: 500,
40
+ borderRadius: "6px",
41
+ border: "none",
42
+ cursor: "pointer",
43
+ transition: "all 0.15s ease",
44
+ backgroundColor: active ? themeColor : "transparent",
45
+ color: active ? "white" : "rgba(255, 255, 255, 0.6)",
46
+ } }, children));
47
+ }
48
+ function GuideTab({ mdx, GuideComponent, themeColor, }) {
49
+ if (GuideComponent) {
50
+ return (React.createElement("div", { style: { height: "100%", overflow: "auto", padding: "24px" } },
51
+ React.createElement(GuideComponent, null)));
52
+ }
53
+ if (mdx) {
54
+ return (React.createElement("div", { style: {
55
+ height: "100%",
56
+ overflow: "auto",
57
+ padding: "24px",
58
+ } },
59
+ React.createElement("div", { style: {
60
+ fontSize: "14px",
61
+ lineHeight: 1.7,
62
+ color: "rgba(255, 255, 255, 0.8)",
63
+ }, dangerouslySetInnerHTML: { __html: mdx } })));
64
+ }
65
+ return (React.createElement("div", { style: {
66
+ height: "100%",
67
+ display: "flex",
68
+ alignItems: "center",
69
+ justifyContent: "center",
70
+ padding: "24px",
71
+ } },
72
+ React.createElement("div", { style: { textAlign: "center" } },
73
+ React.createElement("p", { style: {
74
+ fontSize: "14px",
75
+ color: "rgba(255, 255, 255, 0.5)",
76
+ } }, "No guide content provided."),
77
+ React.createElement("p", { style: {
78
+ fontSize: "12px",
79
+ color: "rgba(255, 255, 255, 0.3)",
80
+ marginTop: "8px",
81
+ } },
82
+ "Pass ",
83
+ React.createElement("code", { style: { color: themeColor } }, "mdx"),
84
+ " or",
85
+ " ",
86
+ React.createElement("code", { style: { color: themeColor } }, "GuideComponent"),
87
+ " prop to display content."))));
88
+ }
89
+ function ChatTab({ playgroundUid, themeColor, apiKey, apiBaseUrl, files, }) {
90
+ const [messages, setMessages] = useState([]);
91
+ const [input, setInput] = useState("");
92
+ const [isLoading, setIsLoading] = useState(false);
93
+ const messagesEndRef = useRef(null);
94
+ const textareaRef = useRef(null);
95
+ // Scroll to bottom when messages change
96
+ useEffect(() => {
97
+ var _a;
98
+ (_a = messagesEndRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
99
+ }, [messages]);
100
+ const handleSubmit = useCallback(async (e) => {
101
+ e.preventDefault();
102
+ if (!input.trim() || isLoading)
103
+ return;
104
+ const userMessage = input.trim();
105
+ setInput("");
106
+ setMessages((prev) => [...prev, { role: "user", content: userMessage }]);
107
+ setIsLoading(true);
108
+ try {
109
+ // Build context from files if available
110
+ const codeContext = files
111
+ ? files.map((f) => `--- ${f.path} ---\n${f.content}`).join("\n\n")
112
+ : "";
113
+ const response = await fetch(`${apiBaseUrl}/v1/chat`, {
114
+ method: "POST",
115
+ headers: Object.assign({ "Content-Type": "application/json" }, (apiKey && { Authorization: `Bearer ${apiKey}` })),
116
+ body: JSON.stringify({
117
+ playgroundUid,
118
+ messages: [
119
+ ...messages,
120
+ { role: "user", content: userMessage },
121
+ ],
122
+ context: codeContext,
123
+ }),
124
+ });
125
+ if (!response.ok) {
126
+ throw new Error(`API error: ${response.status}`);
127
+ }
128
+ const data = await response.json();
129
+ setMessages((prev) => [
130
+ ...prev,
131
+ { role: "assistant", content: data.message || data.content },
132
+ ]);
133
+ }
134
+ catch (error) {
135
+ console.error("Chat error:", error);
136
+ setMessages((prev) => [
137
+ ...prev,
138
+ {
139
+ role: "assistant",
140
+ content: "Sorry, I encountered an error. Please check your API key and try again.",
141
+ },
142
+ ]);
143
+ }
144
+ finally {
145
+ setIsLoading(false);
146
+ }
147
+ }, [input, isLoading, messages, playgroundUid, apiKey, apiBaseUrl, files]);
148
+ return (React.createElement("div", { style: {
149
+ height: "100%",
150
+ display: "flex",
151
+ flexDirection: "column",
152
+ } },
153
+ React.createElement("div", { style: {
154
+ flex: 1,
155
+ overflow: "auto",
156
+ padding: "16px",
157
+ } }, messages.length === 0 ? (React.createElement("div", { style: {
158
+ height: "100%",
159
+ display: "flex",
160
+ alignItems: "center",
161
+ justifyContent: "center",
162
+ } },
163
+ React.createElement("div", { style: { textAlign: "center", maxWidth: "280px" } },
164
+ React.createElement("div", { style: {
165
+ width: "48px",
166
+ height: "48px",
167
+ borderRadius: "12px",
168
+ backgroundColor: `${themeColor}20`,
169
+ display: "flex",
170
+ alignItems: "center",
171
+ justifyContent: "center",
172
+ margin: "0 auto 16px",
173
+ } },
174
+ React.createElement("span", { style: { fontSize: "24px" } }, "\uD83D\uDCAC")),
175
+ React.createElement("p", { style: {
176
+ fontSize: "14px",
177
+ fontWeight: 500,
178
+ color: "rgba(255, 255, 255, 0.8)",
179
+ marginBottom: "8px",
180
+ } }, "Ask AI about this code"),
181
+ React.createElement("p", { style: {
182
+ fontSize: "12px",
183
+ color: "rgba(255, 255, 255, 0.4)",
184
+ } }, "Get help understanding the code, debugging issues, or extending functionality.")))) : (React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "16px" } },
185
+ messages.map((msg, i) => (React.createElement("div", { key: i, style: {
186
+ display: "flex",
187
+ flexDirection: "column",
188
+ alignItems: msg.role === "user" ? "flex-end" : "flex-start",
189
+ } },
190
+ React.createElement("div", { style: {
191
+ maxWidth: "85%",
192
+ padding: "12px 16px",
193
+ borderRadius: "12px",
194
+ backgroundColor: msg.role === "user" ? themeColor : "rgba(255, 255, 255, 0.1)",
195
+ color: "rgba(255, 255, 255, 0.9)",
196
+ fontSize: "13px",
197
+ lineHeight: 1.5,
198
+ } }, msg.content)))),
199
+ isLoading && (React.createElement("div", { style: { display: "flex", alignItems: "flex-start" } },
200
+ React.createElement("div", { style: {
201
+ padding: "12px 16px",
202
+ borderRadius: "12px",
203
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
204
+ } },
205
+ React.createElement(LoaderIcon, { size: 16, style: { color: themeColor } })))),
206
+ React.createElement("div", { ref: messagesEndRef })))),
207
+ React.createElement("div", { style: {
208
+ padding: "16px",
209
+ borderTop: "1px solid rgba(255, 255, 255, 0.1)",
210
+ } },
211
+ React.createElement("form", { onSubmit: handleSubmit },
212
+ React.createElement("div", { style: {
213
+ display: "flex",
214
+ gap: "8px",
215
+ alignItems: "flex-end",
216
+ } },
217
+ React.createElement("textarea", { ref: textareaRef, value: input, onChange: (e) => setInput(e.target.value), onKeyDown: (e) => {
218
+ if (e.key === "Enter" && !e.shiftKey) {
219
+ e.preventDefault();
220
+ handleSubmit(e);
221
+ }
222
+ }, placeholder: "Ask a question...", rows: 1, style: {
223
+ flex: 1,
224
+ padding: "12px",
225
+ borderRadius: "8px",
226
+ border: "1px solid rgba(255, 255, 255, 0.1)",
227
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
228
+ color: "rgba(255, 255, 255, 0.9)",
229
+ fontSize: "13px",
230
+ resize: "none",
231
+ outline: "none",
232
+ fontFamily: "inherit",
233
+ } }),
234
+ React.createElement("button", { type: "submit", disabled: !input.trim() || isLoading, style: {
235
+ width: "40px",
236
+ height: "40px",
237
+ borderRadius: "8px",
238
+ border: "none",
239
+ backgroundColor: input.trim() ? themeColor : "rgba(255, 255, 255, 0.1)",
240
+ color: "white",
241
+ cursor: input.trim() && !isLoading ? "pointer" : "not-allowed",
242
+ display: "flex",
243
+ alignItems: "center",
244
+ justifyContent: "center",
245
+ transition: "all 0.15s ease",
246
+ opacity: isLoading ? 0.5 : 1,
247
+ } }, isLoading ? (React.createElement(LoaderIcon, { size: 18 })) : (React.createElement(ArrowUpIcon, { size: 18 }))))))));
248
+ }
@@ -0,0 +1,48 @@
1
+ import React from "react";
2
+ import { LoaderIcon } from "../icons";
3
+ /**
4
+ * Loading overlay for the sandbox iframe.
5
+ */
6
+ export function SandboxLoading({ themeColor }) {
7
+ return (React.createElement("div", { style: {
8
+ position: "absolute",
9
+ inset: 0,
10
+ display: "flex",
11
+ flexDirection: "column",
12
+ alignItems: "center",
13
+ justifyContent: "center",
14
+ backgroundColor: "rgba(0, 0, 0, 0.8)",
15
+ backdropFilter: "blur(4px)",
16
+ zIndex: 10,
17
+ } },
18
+ React.createElement("div", { style: {
19
+ display: "flex",
20
+ flexDirection: "column",
21
+ alignItems: "center",
22
+ gap: "16px",
23
+ } },
24
+ React.createElement("div", { style: {
25
+ width: "48px",
26
+ height: "48px",
27
+ borderRadius: "12px",
28
+ backgroundColor: `${themeColor}20`,
29
+ display: "flex",
30
+ alignItems: "center",
31
+ justifyContent: "center",
32
+ } },
33
+ React.createElement(LoaderIcon, { size: 24, style: {
34
+ color: themeColor,
35
+ animation: "spin 1s linear infinite",
36
+ } })),
37
+ React.createElement("span", { style: {
38
+ fontSize: "14px",
39
+ color: "rgba(255, 255, 255, 0.7)",
40
+ fontWeight: 500,
41
+ } }, "Loading sandbox...")),
42
+ React.createElement("style", null, `
43
+ @keyframes spin {
44
+ from { transform: rotate(0deg); }
45
+ to { transform: rotate(360deg); }
46
+ }
47
+ `)));
48
+ }
@@ -0,0 +1,247 @@
1
+ "use client";
2
+ import React, { useState, useCallback, useEffect } from "react";
3
+ import { SandboxLoading } from "./sandbox-loading";
4
+ import { RefreshCwIcon, ExternalLinkIcon, LoaderIcon } from "../icons";
5
+ /**
6
+ * Right panel with Preview and Code Editor
7
+ */
8
+ export function SandboxRightPanel({ previewUrl, files = [], defaultActiveFile, themeColor, showPreview, showCode, onLoad, onError, }) {
9
+ var _a;
10
+ const [isLoading, setIsLoading] = useState(true);
11
+ const [reloadKey, setReloadKey] = useState(0);
12
+ const [activeFile, setActiveFile] = useState(defaultActiveFile || ((_a = files[0]) === null || _a === void 0 ? void 0 : _a.path) || "");
13
+ const [previewHeight, setPreviewHeight] = useState(60); // percentage
14
+ const [isDragging, setIsDragging] = useState(false);
15
+ const handleRefresh = useCallback(() => {
16
+ setIsLoading(true);
17
+ setReloadKey((k) => k + 1);
18
+ }, []);
19
+ const handleOpenExternal = useCallback(() => {
20
+ if (previewUrl) {
21
+ window.open(previewUrl, "_blank", "noopener,noreferrer");
22
+ }
23
+ }, [previewUrl]);
24
+ const handleIframeLoad = useCallback(() => {
25
+ setIsLoading(false);
26
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad();
27
+ }, [onLoad]);
28
+ const handleIframeError = useCallback(() => {
29
+ setIsLoading(false);
30
+ onError === null || onError === void 0 ? void 0 : onError(new Error(`Failed to load: ${previewUrl}`));
31
+ }, [onError, previewUrl]);
32
+ // Reset loading when URL changes
33
+ useEffect(() => {
34
+ if (previewUrl) {
35
+ setIsLoading(true);
36
+ }
37
+ }, [previewUrl, reloadKey]);
38
+ // Handle resize drag
39
+ const handleMouseDown = useCallback(() => {
40
+ setIsDragging(true);
41
+ }, []);
42
+ useEffect(() => {
43
+ if (!isDragging)
44
+ return;
45
+ const handleMouseMove = (e) => {
46
+ const container = document.getElementById("sandbox-right-panel");
47
+ if (!container)
48
+ return;
49
+ const rect = container.getBoundingClientRect();
50
+ const percentage = ((e.clientY - rect.top) / rect.height) * 100;
51
+ setPreviewHeight(Math.min(80, Math.max(20, percentage)));
52
+ };
53
+ const handleMouseUp = () => {
54
+ setIsDragging(false);
55
+ };
56
+ document.addEventListener("mousemove", handleMouseMove);
57
+ document.addEventListener("mouseup", handleMouseUp);
58
+ return () => {
59
+ document.removeEventListener("mousemove", handleMouseMove);
60
+ document.removeEventListener("mouseup", handleMouseUp);
61
+ };
62
+ }, [isDragging]);
63
+ const activeFileContent = files.find((f) => f.path === activeFile);
64
+ // If only showing preview
65
+ if (showPreview && !showCode) {
66
+ return (React.createElement("div", { style: { height: "100%", display: "flex", flexDirection: "column" } },
67
+ React.createElement(PreviewControlBar, { previewUrl: previewUrl, themeColor: themeColor, isLoading: isLoading, onRefresh: handleRefresh, onOpenExternal: handleOpenExternal }),
68
+ React.createElement("div", { style: { flex: 1, position: "relative" } },
69
+ isLoading && React.createElement(SandboxLoading, { themeColor: themeColor }),
70
+ previewUrl ? (React.createElement("iframe", { key: reloadKey, src: previewUrl, onLoad: handleIframeLoad, onError: handleIframeError, sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-modals", allow: "clipboard-read; clipboard-write", style: {
71
+ width: "100%",
72
+ height: "100%",
73
+ border: "none",
74
+ backgroundColor: "#000",
75
+ }, title: "Preview" })) : (React.createElement("div", { style: {
76
+ height: "100%",
77
+ display: "flex",
78
+ alignItems: "center",
79
+ justifyContent: "center",
80
+ backgroundColor: "#000",
81
+ } },
82
+ React.createElement("p", { style: { color: "rgba(255, 255, 255, 0.5)", fontSize: "14px" } }, "No preview URL provided"))))));
83
+ }
84
+ // If only showing code
85
+ if (showCode && !showPreview) {
86
+ return (React.createElement("div", { style: { height: "100%", display: "flex", flexDirection: "column" } },
87
+ React.createElement(CodePanel, { files: files, activeFile: activeFile, setActiveFile: setActiveFile, themeColor: themeColor, content: (activeFileContent === null || activeFileContent === void 0 ? void 0 : activeFileContent.content) || "", language: activeFileContent === null || activeFileContent === void 0 ? void 0 : activeFileContent.language })));
88
+ }
89
+ // Show both preview and code (default)
90
+ return (React.createElement("div", { id: "sandbox-right-panel", style: {
91
+ height: "100%",
92
+ display: "flex",
93
+ flexDirection: "column",
94
+ position: "relative",
95
+ } },
96
+ React.createElement("div", { style: { height: `${previewHeight}%`, display: "flex", flexDirection: "column" } },
97
+ React.createElement(PreviewControlBar, { previewUrl: previewUrl, themeColor: themeColor, isLoading: isLoading, onRefresh: handleRefresh, onOpenExternal: handleOpenExternal }),
98
+ React.createElement("div", { style: { flex: 1, position: "relative", minHeight: 0 } },
99
+ isLoading && React.createElement(SandboxLoading, { themeColor: themeColor }),
100
+ previewUrl ? (React.createElement("iframe", { key: reloadKey, src: previewUrl, onLoad: handleIframeLoad, onError: handleIframeError, sandbox: "allow-scripts allow-same-origin allow-forms allow-popups allow-modals", allow: "clipboard-read; clipboard-write", style: {
101
+ width: "100%",
102
+ height: "100%",
103
+ border: "none",
104
+ backgroundColor: "#000",
105
+ }, title: "Preview" })) : (React.createElement("div", { style: {
106
+ height: "100%",
107
+ display: "flex",
108
+ alignItems: "center",
109
+ justifyContent: "center",
110
+ backgroundColor: "#000",
111
+ } },
112
+ React.createElement(LoaderIcon, { size: 24, style: { color: themeColor } }))))),
113
+ React.createElement("div", { onMouseDown: handleMouseDown, style: {
114
+ height: "8px",
115
+ cursor: "row-resize",
116
+ display: "flex",
117
+ alignItems: "center",
118
+ justifyContent: "center",
119
+ backgroundColor: isDragging ? `${themeColor}30` : "transparent",
120
+ transition: "background-color 0.15s",
121
+ flexShrink: 0,
122
+ } },
123
+ React.createElement("div", { style: {
124
+ width: "40px",
125
+ height: "4px",
126
+ borderRadius: "2px",
127
+ backgroundColor: isDragging
128
+ ? themeColor
129
+ : "rgba(255, 255, 255, 0.2)",
130
+ transition: "background-color 0.15s",
131
+ } })),
132
+ React.createElement("div", { style: { flex: 1, minHeight: 0 } },
133
+ React.createElement(CodePanel, { files: files, activeFile: activeFile, setActiveFile: setActiveFile, themeColor: themeColor, content: (activeFileContent === null || activeFileContent === void 0 ? void 0 : activeFileContent.content) || "", language: activeFileContent === null || activeFileContent === void 0 ? void 0 : activeFileContent.language }))));
134
+ }
135
+ function PreviewControlBar({ previewUrl, themeColor, isLoading, onRefresh, onOpenExternal, }) {
136
+ return (React.createElement("div", { style: {
137
+ display: "flex",
138
+ alignItems: "center",
139
+ justifyContent: "space-between",
140
+ padding: "8px 12px",
141
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
142
+ backgroundColor: "rgba(0, 0, 0, 0.3)",
143
+ flexShrink: 0,
144
+ } },
145
+ React.createElement("div", { style: {
146
+ display: "flex",
147
+ alignItems: "center",
148
+ gap: "8px",
149
+ flex: 1,
150
+ minWidth: 0,
151
+ } },
152
+ React.createElement("div", { style: {
153
+ width: "8px",
154
+ height: "8px",
155
+ borderRadius: "50%",
156
+ backgroundColor: isLoading ? "#f59e0b" : "#22c55e",
157
+ flexShrink: 0,
158
+ } }),
159
+ React.createElement("span", { style: {
160
+ fontSize: "12px",
161
+ color: "rgba(255, 255, 255, 0.6)",
162
+ overflow: "hidden",
163
+ textOverflow: "ellipsis",
164
+ whiteSpace: "nowrap",
165
+ fontFamily: "monospace",
166
+ } }, previewUrl || "Loading...")),
167
+ React.createElement("div", { style: { display: "flex", alignItems: "center", gap: "4px" } },
168
+ React.createElement(IconButton, { onClick: onRefresh, disabled: isLoading, themeColor: themeColor, title: "Refresh" }, isLoading ? (React.createElement(LoaderIcon, { size: 14 })) : (React.createElement(RefreshCwIcon, { size: 14 }))),
169
+ React.createElement(IconButton, { onClick: onOpenExternal, themeColor: themeColor, title: "Open in new tab" },
170
+ React.createElement(ExternalLinkIcon, { size: 14 })))));
171
+ }
172
+ function IconButton({ children, onClick, disabled, themeColor, title, }) {
173
+ const [isHovered, setIsHovered] = useState(false);
174
+ return (React.createElement("button", { onClick: onClick, disabled: disabled, title: title, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), style: {
175
+ display: "flex",
176
+ alignItems: "center",
177
+ justifyContent: "center",
178
+ width: "28px",
179
+ height: "28px",
180
+ borderRadius: "6px",
181
+ border: "none",
182
+ backgroundColor: isHovered ? "rgba(255, 255, 255, 0.1)" : "transparent",
183
+ color: isHovered ? themeColor : "rgba(255, 255, 255, 0.7)",
184
+ cursor: disabled ? "not-allowed" : "pointer",
185
+ opacity: disabled ? 0.5 : 1,
186
+ transition: "all 0.15s ease",
187
+ } }, children));
188
+ }
189
+ function CodePanel({ files, activeFile, setActiveFile, themeColor, content, language, }) {
190
+ return (React.createElement("div", { style: {
191
+ height: "100%",
192
+ display: "flex",
193
+ flexDirection: "column",
194
+ backgroundColor: "#0d0d0d",
195
+ } },
196
+ files.length > 0 && (React.createElement("div", { style: {
197
+ display: "flex",
198
+ alignItems: "center",
199
+ gap: "4px",
200
+ padding: "8px 12px",
201
+ borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
202
+ backgroundColor: "#18181b",
203
+ overflowX: "auto",
204
+ flexShrink: 0,
205
+ } }, files.map((file) => (React.createElement("button", { key: file.path, onClick: () => setActiveFile(file.path), style: {
206
+ padding: "6px 12px",
207
+ fontSize: "12px",
208
+ fontFamily: "monospace",
209
+ borderRadius: "4px",
210
+ border: "none",
211
+ cursor: "pointer",
212
+ whiteSpace: "nowrap",
213
+ transition: "all 0.15s ease",
214
+ backgroundColor: activeFile === file.path
215
+ ? `${themeColor}20`
216
+ : "transparent",
217
+ color: activeFile === file.path
218
+ ? themeColor
219
+ : "rgba(255, 255, 255, 0.6)",
220
+ } }, file.path.split("/").pop()))))),
221
+ React.createElement("div", { style: {
222
+ flex: 1,
223
+ overflow: "auto",
224
+ minHeight: 0,
225
+ } }, content ? (React.createElement("pre", { style: {
226
+ margin: 0,
227
+ padding: "16px",
228
+ fontSize: "13px",
229
+ fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
230
+ lineHeight: 1.6,
231
+ color: "rgba(255, 255, 255, 0.85)",
232
+ whiteSpace: "pre-wrap",
233
+ wordBreak: "break-word",
234
+ } },
235
+ React.createElement("code", null, content))) : (React.createElement("div", { style: {
236
+ height: "100%",
237
+ display: "flex",
238
+ alignItems: "center",
239
+ justifyContent: "center",
240
+ } },
241
+ React.createElement("p", { style: {
242
+ fontSize: "13px",
243
+ color: "rgba(255, 255, 255, 0.4)",
244
+ } }, files.length === 0
245
+ ? "No files provided"
246
+ : "Select a file to view"))))));
247
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ import React from "react";
3
+ /**
4
+ * Sandbox component for displaying code files
5
+ */
6
+ export const Sandbox = ({ files, defaultFile, height = "400px", theme = "dark", }) => {
7
+ var _a;
8
+ const [activeFile, setActiveFile] = React.useState(defaultFile || ((_a = files[0]) === null || _a === void 0 ? void 0 : _a.name));
9
+ const currentFile = files.find((f) => f.name === activeFile) || files[0];
10
+ return (React.createElement("div", { className: "rounded-lg border overflow-hidden", style: {
11
+ height: typeof height === "number" ? `${height}px` : height,
12
+ backgroundColor: theme === "dark" ? "#1e1e1e" : "#ffffff",
13
+ } },
14
+ React.createElement("div", { className: "flex border-b", style: {
15
+ backgroundColor: theme === "dark" ? "#252526" : "#f3f3f3",
16
+ } }, files.map((file) => (React.createElement("button", { key: file.name, onClick: () => setActiveFile(file.name), className: "px-4 py-2 text-sm", style: {
17
+ backgroundColor: activeFile === file.name
18
+ ? theme === "dark"
19
+ ? "#1e1e1e"
20
+ : "#ffffff"
21
+ : "transparent",
22
+ color: theme === "dark" ? "#cccccc" : "#333333",
23
+ borderRight: `1px solid ${theme === "dark" ? "#3c3c3c" : "#e0e0e0"}`,
24
+ } }, file.name)))),
25
+ React.createElement("pre", { className: "p-4 overflow-auto h-full", style: {
26
+ color: theme === "dark" ? "#d4d4d4" : "#333333",
27
+ fontSize: "14px",
28
+ fontFamily: "monospace",
29
+ margin: 0,
30
+ } },
31
+ React.createElement("code", null, currentFile === null || currentFile === void 0 ? void 0 : currentFile.content))));
32
+ };
@@ -0,0 +1,46 @@
1
+ import React, { useState } from "react";
2
+ /**
3
+ * Example component demonstrating Tailwind CSS with Shadow DOM isolation.
4
+ * All styling uses pure Tailwind CSS classes.
5
+ */
6
+ export const TailwindExample = ({ title = "SDK Tailwind Component", description = "Fully isolated with Shadow DOM - host styles can't affect this!", }) => {
7
+ const [count, setCount] = useState(0);
8
+ const [isHovered, setIsHovered] = useState(false);
9
+ return (React.createElement("div", { className: "flex flex-col items-center p-4" },
10
+ React.createElement("div", { className: "relative rounded-[2.5rem] p-2 bg-gradient-to-br from-zinc-700 to-zinc-900 shadow-2xl shadow-black/50" },
11
+ React.createElement("div", { className: "rounded-[2rem] p-1 bg-black" },
12
+ React.createElement("div", { className: "rounded-[1.75rem] w-[280px] h-[560px] bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 overflow-hidden flex flex-col relative" },
13
+ React.createElement("div", { className: "absolute top-0 left-1/2 -translate-x-1/2 w-32 h-6 bg-black rounded-b-xl z-10" }),
14
+ React.createElement("div", { className: "pt-8 px-6 pb-2 flex justify-between items-center text-white text-xs font-semibold" },
15
+ React.createElement("span", null, "9:41"),
16
+ React.createElement("div", { className: "flex items-center gap-1" },
17
+ React.createElement("div", { className: "w-4 h-2 border border-white rounded-sm relative" },
18
+ React.createElement("div", { className: "absolute inset-0.5 bg-white rounded-sm" })),
19
+ React.createElement("div", { className: "flex gap-0.5" }, [1, 2, 3, 4].map((i) => (React.createElement("div", { key: i, className: "w-0.5 h-2 bg-white rounded-full" })))))),
20
+ React.createElement("div", { className: "flex-1 px-6 py-4 overflow-y-auto" },
21
+ React.createElement("div", { className: "mb-6" },
22
+ React.createElement("h2", { className: "text-2xl font-bold text-white mb-2" }, title),
23
+ React.createElement("p", { className: "text-sm text-slate-400" }, description)),
24
+ React.createElement("div", { className: "bg-white/10 backdrop-blur-sm rounded-2xl p-6 mb-6 border border-white/20" },
25
+ React.createElement("div", { className: "flex flex-col items-center" },
26
+ React.createElement("span", { className: "text-slate-400 text-sm font-medium mb-2" }, "Counter"),
27
+ React.createElement("span", { className: "text-6xl font-bold text-white" }, count))),
28
+ React.createElement("div", { className: "flex flex-col gap-3 mb-6" },
29
+ React.createElement("button", { onClick: () => setCount((c) => c + 1), onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), className: "w-full px-6 py-4 bg-blue-500 hover:bg-blue-600 active:bg-blue-700 text-white rounded-xl font-semibold text-lg transition-colors shadow-lg shadow-blue-500/30" }, "Increment"),
30
+ React.createElement("button", { onClick: () => setCount(0), className: "w-full px-6 py-4 bg-white/10 hover:bg-white/20 active:bg-white/30 backdrop-blur-sm text-white rounded-xl font-semibold text-lg transition-colors border border-white/20" }, "Reset")),
31
+ React.createElement("div", { className: "flex items-center justify-center gap-2 mb-6" },
32
+ React.createElement("div", { className: `w-3 h-3 rounded-full transition-colors ${isHovered ? "bg-green-400" : "bg-slate-500"}` }),
33
+ React.createElement("span", { className: "text-xs text-slate-400" }, isHovered ? "Button hovered" : "Idle")),
34
+ React.createElement("div", { className: "bg-white/5 backdrop-blur-sm rounded-xl p-4 border border-white/10" },
35
+ React.createElement("p", { className: "text-xs font-semibold text-slate-300 mb-3 uppercase tracking-wide" }, "Features"),
36
+ React.createElement("ul", { className: "space-y-2" }, [
37
+ "Tailwind utility classes",
38
+ "CSS variable theming",
39
+ "Hover/active states",
40
+ "Shadow DOM isolation",
41
+ ].map((feature, index) => (React.createElement("li", { key: index, className: "flex items-center gap-3 text-sm text-slate-300" },
42
+ React.createElement("div", { className: "w-1.5 h-1.5 bg-blue-400 rounded-full" }),
43
+ feature)))))),
44
+ React.createElement("div", { className: "pb-2 flex justify-center" },
45
+ React.createElement("div", { className: "w-32 h-1 bg-white/30 rounded-full" })))))));
46
+ };
@@ -0,0 +1,18 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React from "react";
13
+ import { cn } from "@/lib/utils";
14
+ function Skeleton(_a) {
15
+ var { className } = _a, props = __rest(_a, ["className"]);
16
+ return (React.createElement("div", Object.assign({ className: cn("animate-pulse rounded-md bg-zinc-100 dark:bg-zinc-900", className) }, props)));
17
+ }
18
+ export { Skeleton };