@djangocfg/ui-tools 2.1.91

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 (174) hide show
  1. package/dist/LottiePlayer.client-LBEC2JKY.mjs +161 -0
  2. package/dist/LottiePlayer.client-LBEC2JKY.mjs.map +1 -0
  3. package/dist/LottiePlayer.client-WFMG2OOW.cjs +168 -0
  4. package/dist/LottiePlayer.client-WFMG2OOW.cjs.map +1 -0
  5. package/dist/Mermaid.client-4TU2TSH3.mjs +477 -0
  6. package/dist/Mermaid.client-4TU2TSH3.mjs.map +1 -0
  7. package/dist/Mermaid.client-SBYY364Q.cjs +483 -0
  8. package/dist/Mermaid.client-SBYY364Q.cjs.map +1 -0
  9. package/dist/PlaygroundLayout-3YVSAEAF.cjs +1003 -0
  10. package/dist/PlaygroundLayout-3YVSAEAF.cjs.map +1 -0
  11. package/dist/PlaygroundLayout-4DYBORAS.mjs +996 -0
  12. package/dist/PlaygroundLayout-4DYBORAS.mjs.map +1 -0
  13. package/dist/PrettyCode.client-LCBPPTIX.mjs +152 -0
  14. package/dist/PrettyCode.client-LCBPPTIX.mjs.map +1 -0
  15. package/dist/PrettyCode.client-PNPLXRH6.cjs +154 -0
  16. package/dist/PrettyCode.client-PNPLXRH6.cjs.map +1 -0
  17. package/dist/chunk-37ZI6VD4.mjs +12 -0
  18. package/dist/chunk-37ZI6VD4.mjs.map +1 -0
  19. package/dist/chunk-3HK2OE62.cjs +81 -0
  20. package/dist/chunk-3HK2OE62.cjs.map +1 -0
  21. package/dist/chunk-7DGDQVQW.cjs +591 -0
  22. package/dist/chunk-7DGDQVQW.cjs.map +1 -0
  23. package/dist/chunk-M6P2FU7L.mjs +572 -0
  24. package/dist/chunk-M6P2FU7L.mjs.map +1 -0
  25. package/dist/chunk-UQ3XI5MY.cjs +15 -0
  26. package/dist/chunk-UQ3XI5MY.cjs.map +1 -0
  27. package/dist/chunk-YFRNE2IR.mjs +79 -0
  28. package/dist/chunk-YFRNE2IR.mjs.map +1 -0
  29. package/dist/index.cjs +5042 -0
  30. package/dist/index.cjs.map +1 -0
  31. package/dist/index.d.cts +1591 -0
  32. package/dist/index.d.ts +1591 -0
  33. package/dist/index.mjs +4941 -0
  34. package/dist/index.mjs.map +1 -0
  35. package/package.json +86 -0
  36. package/src/components/markdown/MarkdownMessage.tsx +340 -0
  37. package/src/components/markdown/index.ts +5 -0
  38. package/src/index.ts +26 -0
  39. package/src/stores/index.ts +9 -0
  40. package/src/stores/mediaCache.ts +534 -0
  41. package/src/tools/AudioPlayer/README.md +206 -0
  42. package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +216 -0
  43. package/src/tools/AudioPlayer/components/HybridSimplePlayer.tsx +280 -0
  44. package/src/tools/AudioPlayer/components/HybridWaveform.tsx +279 -0
  45. package/src/tools/AudioPlayer/components/ReactiveCover/AudioReactiveCover.tsx +149 -0
  46. package/src/tools/AudioPlayer/components/ReactiveCover/effects/GlowEffect.tsx +110 -0
  47. package/src/tools/AudioPlayer/components/ReactiveCover/effects/MeshEffect.tsx +58 -0
  48. package/src/tools/AudioPlayer/components/ReactiveCover/effects/OrbsEffect.tsx +45 -0
  49. package/src/tools/AudioPlayer/components/ReactiveCover/effects/SpotlightEffect.tsx +82 -0
  50. package/src/tools/AudioPlayer/components/ReactiveCover/effects/index.ts +8 -0
  51. package/src/tools/AudioPlayer/components/ReactiveCover/index.ts +6 -0
  52. package/src/tools/AudioPlayer/components/index.ts +22 -0
  53. package/src/tools/AudioPlayer/context/HybridAudioProvider.tsx +158 -0
  54. package/src/tools/AudioPlayer/context/index.ts +16 -0
  55. package/src/tools/AudioPlayer/effects/index.ts +412 -0
  56. package/src/tools/AudioPlayer/hooks/index.ts +35 -0
  57. package/src/tools/AudioPlayer/hooks/useHybridAudio.ts +387 -0
  58. package/src/tools/AudioPlayer/hooks/useHybridAudioAnalysis.ts +95 -0
  59. package/src/tools/AudioPlayer/hooks/useVisualization.tsx +207 -0
  60. package/src/tools/AudioPlayer/index.ts +133 -0
  61. package/src/tools/AudioPlayer/types/effects.ts +73 -0
  62. package/src/tools/AudioPlayer/types/index.ts +27 -0
  63. package/src/tools/AudioPlayer/utils/debug.ts +14 -0
  64. package/src/tools/AudioPlayer/utils/formatTime.ts +10 -0
  65. package/src/tools/AudioPlayer/utils/index.ts +6 -0
  66. package/src/tools/ImageViewer/@refactoring/00-PLAN.md +71 -0
  67. package/src/tools/ImageViewer/@refactoring/01-TYPES.md +121 -0
  68. package/src/tools/ImageViewer/@refactoring/02-UTILS.md +143 -0
  69. package/src/tools/ImageViewer/@refactoring/03-HOOKS.md +261 -0
  70. package/src/tools/ImageViewer/@refactoring/04-COMPONENTS.md +427 -0
  71. package/src/tools/ImageViewer/@refactoring/05-EXECUTION-CHECKLIST.md +126 -0
  72. package/src/tools/ImageViewer/README.md +200 -0
  73. package/src/tools/ImageViewer/components/ImageInfo.tsx +44 -0
  74. package/src/tools/ImageViewer/components/ImageToolbar.tsx +145 -0
  75. package/src/tools/ImageViewer/components/ImageViewer.tsx +241 -0
  76. package/src/tools/ImageViewer/components/index.ts +7 -0
  77. package/src/tools/ImageViewer/hooks/index.ts +9 -0
  78. package/src/tools/ImageViewer/hooks/useImageLoading.ts +204 -0
  79. package/src/tools/ImageViewer/hooks/useImageTransform.ts +101 -0
  80. package/src/tools/ImageViewer/index.ts +60 -0
  81. package/src/tools/ImageViewer/types.ts +81 -0
  82. package/src/tools/ImageViewer/utils/constants.ts +59 -0
  83. package/src/tools/ImageViewer/utils/debug.ts +14 -0
  84. package/src/tools/ImageViewer/utils/index.ts +17 -0
  85. package/src/tools/ImageViewer/utils/lqip.ts +47 -0
  86. package/src/tools/JsonForm/JsonSchemaForm.tsx +197 -0
  87. package/src/tools/JsonForm/examples/BotConfigExample.tsx +249 -0
  88. package/src/tools/JsonForm/examples/RealBotConfigExample.tsx +161 -0
  89. package/src/tools/JsonForm/index.ts +46 -0
  90. package/src/tools/JsonForm/templates/ArrayFieldItemTemplate.tsx +47 -0
  91. package/src/tools/JsonForm/templates/ArrayFieldTemplate.tsx +74 -0
  92. package/src/tools/JsonForm/templates/BaseInputTemplate.tsx +107 -0
  93. package/src/tools/JsonForm/templates/ErrorListTemplate.tsx +35 -0
  94. package/src/tools/JsonForm/templates/FieldTemplate.tsx +62 -0
  95. package/src/tools/JsonForm/templates/ObjectFieldTemplate.tsx +116 -0
  96. package/src/tools/JsonForm/templates/index.ts +12 -0
  97. package/src/tools/JsonForm/types.ts +83 -0
  98. package/src/tools/JsonForm/utils.ts +213 -0
  99. package/src/tools/JsonForm/widgets/CheckboxWidget.tsx +37 -0
  100. package/src/tools/JsonForm/widgets/ColorWidget.tsx +219 -0
  101. package/src/tools/JsonForm/widgets/NumberWidget.tsx +89 -0
  102. package/src/tools/JsonForm/widgets/SelectWidget.tsx +97 -0
  103. package/src/tools/JsonForm/widgets/SliderWidget.tsx +148 -0
  104. package/src/tools/JsonForm/widgets/SwitchWidget.tsx +35 -0
  105. package/src/tools/JsonForm/widgets/TextWidget.tsx +96 -0
  106. package/src/tools/JsonForm/widgets/index.ts +14 -0
  107. package/src/tools/JsonTree/index.tsx +243 -0
  108. package/src/tools/LottiePlayer/LottiePlayer.client.tsx +213 -0
  109. package/src/tools/LottiePlayer/index.tsx +56 -0
  110. package/src/tools/LottiePlayer/types.ts +108 -0
  111. package/src/tools/LottiePlayer/useLottie.ts +164 -0
  112. package/src/tools/Mermaid/Mermaid.client.tsx +82 -0
  113. package/src/tools/Mermaid/components/MermaidCodeViewer.tsx +95 -0
  114. package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +103 -0
  115. package/src/tools/Mermaid/hooks/index.ts +4 -0
  116. package/src/tools/Mermaid/hooks/useMermaidCleanup.ts +73 -0
  117. package/src/tools/Mermaid/hooks/useMermaidFullscreen.ts +46 -0
  118. package/src/tools/Mermaid/hooks/useMermaidRenderer.ts +226 -0
  119. package/src/tools/Mermaid/hooks/useMermaidValidation.ts +29 -0
  120. package/src/tools/Mermaid/index.tsx +44 -0
  121. package/src/tools/Mermaid/utils/mermaid-helpers.ts +33 -0
  122. package/src/tools/OpenapiViewer/components/EndpointInfo.tsx +149 -0
  123. package/src/tools/OpenapiViewer/components/EndpointsLibrary.tsx +263 -0
  124. package/src/tools/OpenapiViewer/components/PlaygroundLayout.tsx +125 -0
  125. package/src/tools/OpenapiViewer/components/PlaygroundStepper.tsx +100 -0
  126. package/src/tools/OpenapiViewer/components/RequestBuilder.tsx +157 -0
  127. package/src/tools/OpenapiViewer/components/RequestParametersForm.tsx +253 -0
  128. package/src/tools/OpenapiViewer/components/ResponseViewer.tsx +173 -0
  129. package/src/tools/OpenapiViewer/components/VersionSelector.tsx +68 -0
  130. package/src/tools/OpenapiViewer/components/index.ts +14 -0
  131. package/src/tools/OpenapiViewer/constants.ts +39 -0
  132. package/src/tools/OpenapiViewer/context/PlaygroundContext.tsx +337 -0
  133. package/src/tools/OpenapiViewer/hooks/index.ts +8 -0
  134. package/src/tools/OpenapiViewer/hooks/useMobile.ts +10 -0
  135. package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +199 -0
  136. package/src/tools/OpenapiViewer/index.tsx +37 -0
  137. package/src/tools/OpenapiViewer/types.ts +151 -0
  138. package/src/tools/OpenapiViewer/utils/apiKeyManager.ts +149 -0
  139. package/src/tools/OpenapiViewer/utils/formatters.ts +71 -0
  140. package/src/tools/OpenapiViewer/utils/index.ts +9 -0
  141. package/src/tools/OpenapiViewer/utils/versionManager.ts +161 -0
  142. package/src/tools/PrettyCode/PrettyCode.client.tsx +208 -0
  143. package/src/tools/PrettyCode/index.tsx +47 -0
  144. package/src/tools/VideoPlayer/@refactoring/00-PLAN.md +91 -0
  145. package/src/tools/VideoPlayer/@refactoring/01-TYPES.md +284 -0
  146. package/src/tools/VideoPlayer/@refactoring/02-UTILS.md +141 -0
  147. package/src/tools/VideoPlayer/@refactoring/03-HOOKS.md +178 -0
  148. package/src/tools/VideoPlayer/@refactoring/04-COMPONENTS.md +95 -0
  149. package/src/tools/VideoPlayer/@refactoring/05-EXECUTION-CHECKLIST.md +139 -0
  150. package/src/tools/VideoPlayer/README.md +264 -0
  151. package/src/tools/VideoPlayer/components/VideoControls.tsx +138 -0
  152. package/src/tools/VideoPlayer/components/VideoErrorFallback.tsx +172 -0
  153. package/src/tools/VideoPlayer/components/VideoPlayer.tsx +201 -0
  154. package/src/tools/VideoPlayer/components/index.ts +14 -0
  155. package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +52 -0
  156. package/src/tools/VideoPlayer/context/index.ts +8 -0
  157. package/src/tools/VideoPlayer/hooks/index.ts +12 -0
  158. package/src/tools/VideoPlayer/hooks/useVideoPlayerSettings.ts +70 -0
  159. package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +116 -0
  160. package/src/tools/VideoPlayer/index.ts +77 -0
  161. package/src/tools/VideoPlayer/providers/NativeProvider.tsx +284 -0
  162. package/src/tools/VideoPlayer/providers/StreamProvider.tsx +505 -0
  163. package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +400 -0
  164. package/src/tools/VideoPlayer/providers/index.ts +8 -0
  165. package/src/tools/VideoPlayer/types/index.ts +38 -0
  166. package/src/tools/VideoPlayer/types/player.ts +116 -0
  167. package/src/tools/VideoPlayer/types/provider.ts +93 -0
  168. package/src/tools/VideoPlayer/types/sources.ts +97 -0
  169. package/src/tools/VideoPlayer/utils/debug.ts +14 -0
  170. package/src/tools/VideoPlayer/utils/fileSource.ts +78 -0
  171. package/src/tools/VideoPlayer/utils/index.ts +12 -0
  172. package/src/tools/VideoPlayer/utils/resolvers.ts +75 -0
  173. package/src/tools/_shared.ts +29 -0
  174. package/src/tools/index.ts +172 -0
@@ -0,0 +1,996 @@
1
+ import { usePlaygroundContext, deduplicateEndpoints, getStatusColor, JsonTree_default, isValidJson, PrettyCode_default, getVersionById, getVersionStats, API_VERSIONS, getMethodColor, findApiKeyById, parseRequestHeaders } from './chunk-M6P2FU7L.mjs';
2
+ import { __name } from './chunk-37ZI6VD4.mjs';
3
+ import { Menu, X, FileText, Send, Code, Check, ChevronLeft, ChevronRight, List, Grid3X3, Filter, Search, Download, XCircle, Key, Loader2, GitBranch, Info, Settings, BarChart3, Database, Users, Shield, ChevronDown, AlertCircle, HelpCircle } from 'lucide-react';
4
+ import { Sheet, SheetTrigger, Button, SheetContent, Skeleton, Card, CardContent, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Input, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, CardHeader, CardTitle, CopyButton, Badge, Textarea, Collapsible, CollapsibleTrigger, CollapsibleContent, TooltipProvider, Tabs, TabsList, TabsTrigger, TabsContent, Accordion, AccordionItem, AccordionTrigger, AccordionContent, Label, Tooltip, TooltipTrigger, TooltipContent } from '@djangocfg/ui-core/components';
5
+ import { useIsMobile } from '@djangocfg/ui-core/hooks';
6
+ import React, { useState, useMemo, useEffect, useCallback } from 'react';
7
+ import consola from 'consola';
8
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
+
10
+ var useMobile = /* @__PURE__ */ __name(() => {
11
+ const isMobile = useIsMobile();
12
+ return {
13
+ isMobile,
14
+ isDesktop: !isMobile
15
+ };
16
+ }, "useMobile");
17
+ var extractEndpoints = /* @__PURE__ */ __name((schema) => {
18
+ const endpointMap = /* @__PURE__ */ new Map();
19
+ if (!schema.paths) return [];
20
+ const baseUrl = schema.servers && schema.servers.length > 0 ? schema.servers[0].url : "";
21
+ for (const [path, methods] of Object.entries(schema.paths)) {
22
+ const getOperation = methods.get;
23
+ if (!getOperation) continue;
24
+ const op = getOperation;
25
+ const description = op.description || op.summary || `GET ${path}`;
26
+ const category = op.tags?.[0] || "Other";
27
+ const parameters = [];
28
+ if (op.parameters) {
29
+ for (const param of op.parameters) {
30
+ parameters.push({
31
+ name: param.name,
32
+ type: param.schema?.type || "string",
33
+ required: param.required || false,
34
+ description: param.description
35
+ });
36
+ }
37
+ }
38
+ const responses = [];
39
+ if (op.responses) {
40
+ for (const [code, response] of Object.entries(op.responses)) {
41
+ responses.push({
42
+ code,
43
+ description: response.description || `Response ${code}`
44
+ });
45
+ }
46
+ }
47
+ const endpoint = {
48
+ name: path.split("/").pop() || path,
49
+ method: "GET",
50
+ path: baseUrl + path,
51
+ // Combine baseUrl with path
52
+ description,
53
+ category,
54
+ parameters: parameters.length > 0 ? parameters : void 0,
55
+ requestBody: void 0,
56
+ // GET requests don't have request body
57
+ responses: responses.length > 0 ? responses : void 0
58
+ };
59
+ endpointMap.set(path, endpoint);
60
+ }
61
+ return Array.from(endpointMap.values());
62
+ }, "extractEndpoints");
63
+ var getCategories = /* @__PURE__ */ __name((endpoints) => {
64
+ const categories = /* @__PURE__ */ new Set();
65
+ endpoints.forEach((endpoint) => categories.add(endpoint.category));
66
+ return Array.from(categories).sort();
67
+ }, "getCategories");
68
+ var fetchSchema = /* @__PURE__ */ __name(async (url) => {
69
+ const response = await fetch(url, {
70
+ headers: {
71
+ "Accept": "application/json"
72
+ }
73
+ });
74
+ if (!response.ok) {
75
+ throw new Error(`Failed to fetch schema: ${response.statusText}`);
76
+ }
77
+ return response.json();
78
+ }, "fetchSchema");
79
+ function useOpenApiSchema({
80
+ schemas,
81
+ defaultSchemaId
82
+ }) {
83
+ const [loading, setLoading] = useState(true);
84
+ const [error, setError] = useState(null);
85
+ const [currentSchemaId, setCurrentSchemaId] = useState(
86
+ defaultSchemaId || schemas[0]?.id
87
+ );
88
+ const [loadedSchemas, setLoadedSchemas] = useState(
89
+ /* @__PURE__ */ new Map()
90
+ );
91
+ const currentSchema = useMemo(
92
+ () => schemas.find((s) => s.id === currentSchemaId) || null,
93
+ [schemas, currentSchemaId]
94
+ );
95
+ const currentOpenApiSchema = useMemo(
96
+ () => currentSchemaId ? loadedSchemas.get(currentSchemaId) : null,
97
+ [loadedSchemas, currentSchemaId]
98
+ );
99
+ const endpoints = useMemo(
100
+ () => currentOpenApiSchema ? extractEndpoints(currentOpenApiSchema) : [],
101
+ [currentOpenApiSchema]
102
+ );
103
+ const categories = useMemo(() => getCategories(endpoints), [endpoints]);
104
+ useEffect(() => {
105
+ if (!currentSchema) return;
106
+ if (loadedSchemas.has(currentSchema.id)) {
107
+ setLoading(false);
108
+ return;
109
+ }
110
+ setLoading(true);
111
+ setError(null);
112
+ fetchSchema(currentSchema.url).then((schema) => {
113
+ setLoadedSchemas((prev) => new Map(prev).set(currentSchema.id, schema));
114
+ consola.success(`Schema loaded: ${currentSchema.name}`);
115
+ setLoading(false);
116
+ }).catch((err) => {
117
+ consola.error(`Error loading schema from ${currentSchema.url}:`, err);
118
+ setError(err instanceof Error ? err.message : "Failed to load schema");
119
+ setLoading(false);
120
+ });
121
+ }, [currentSchema, loadedSchemas]);
122
+ const setCurrentSchema = useCallback((schemaId) => {
123
+ setCurrentSchemaId(schemaId);
124
+ }, []);
125
+ const refresh = useCallback(() => {
126
+ if (!currentSchema) return;
127
+ setLoading(true);
128
+ setError(null);
129
+ setLoadedSchemas((prev) => {
130
+ const next = new Map(prev);
131
+ next.delete(currentSchema.id);
132
+ return next;
133
+ });
134
+ fetchSchema(currentSchema.url).then((schema) => {
135
+ setLoadedSchemas((prev) => new Map(prev).set(currentSchema.id, schema));
136
+ consola.success(`Schema refreshed: ${currentSchema.name}`);
137
+ setLoading(false);
138
+ }).catch((err) => {
139
+ consola.error(`Error refreshing schema from ${currentSchema.url}:`, err);
140
+ setError(err instanceof Error ? err.message : "Failed to refresh schema");
141
+ setLoading(false);
142
+ });
143
+ }, [currentSchema]);
144
+ return {
145
+ loading,
146
+ error,
147
+ endpoints,
148
+ categories,
149
+ schemas,
150
+ currentSchema,
151
+ setCurrentSchema,
152
+ refresh
153
+ };
154
+ }
155
+ __name(useOpenApiSchema, "useOpenApiSchema");
156
+ var VersionSelector = /* @__PURE__ */ __name(() => {
157
+ const { state, config, setSelectedVersion } = usePlaygroundContext();
158
+ const { endpoints } = useOpenApiSchema({
159
+ schemas: config.schemas,
160
+ defaultSchemaId: config.defaultSchemaId
161
+ });
162
+ const currentVersion = getVersionById(state.selectedVersion);
163
+ const versionStats = getVersionStats(endpoints);
164
+ const handleVersionChange = /* @__PURE__ */ __name((versionId) => {
165
+ setSelectedVersion(versionId);
166
+ }, "handleVersionChange");
167
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3", children: [
168
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
169
+ /* @__PURE__ */ jsx(GitBranch, { className: "h-4 w-4 text-muted-foreground" }),
170
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: "API Version:" })
171
+ ] }),
172
+ /* @__PURE__ */ jsxs(Select, { value: state.selectedVersion, onValueChange: handleVersionChange, children: [
173
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-48", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
174
+ /* @__PURE__ */ jsx(SelectContent, { children: API_VERSIONS.map((version) => /* @__PURE__ */ jsx(SelectItem, { value: version.id, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between w-full", children: [
175
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
176
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: version.name }),
177
+ version.isDefault && /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: "Default" })
178
+ ] }),
179
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground ml-2", children: [
180
+ versionStats[version.id] || 0,
181
+ " endpoints"
182
+ ] })
183
+ ] }) }, version.id)) })
184
+ ] }),
185
+ currentVersion && /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-1 text-xs text-muted-foreground", children: [
186
+ /* @__PURE__ */ jsx(Info, { className: "h-3 w-3" }),
187
+ /* @__PURE__ */ jsx("span", { children: currentVersion.description })
188
+ ] })
189
+ ] });
190
+ }, "VersionSelector");
191
+ var categoryIcons = {
192
+ "Authentication": /* @__PURE__ */ jsx(Shield, { className: "h-4 w-4" }),
193
+ "Users": /* @__PURE__ */ jsx(Users, { className: "h-4 w-4" }),
194
+ "Data": /* @__PURE__ */ jsx(Database, { className: "h-4 w-4" }),
195
+ "Analytics": /* @__PURE__ */ jsx(BarChart3, { className: "h-4 w-4" }),
196
+ "Files": /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" }),
197
+ "Settings": /* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }),
198
+ "Other": /* @__PURE__ */ jsx(Code, { className: "h-4 w-4" })
199
+ };
200
+ var EndpointsLibrary = /* @__PURE__ */ __name(() => {
201
+ const { state, config, setSelectedEndpoint, setSelectedCategory, setSearchTerm } = usePlaygroundContext();
202
+ const { endpoints, categories, loading, error } = useOpenApiSchema({
203
+ schemas: config.schemas,
204
+ defaultSchemaId: config.defaultSchemaId
205
+ });
206
+ const [viewMode, setViewMode] = React.useState("table");
207
+ const getRelativePath = /* @__PURE__ */ __name((fullPath) => {
208
+ try {
209
+ const url = new URL(fullPath);
210
+ return url.pathname;
211
+ } catch {
212
+ return fullPath;
213
+ }
214
+ }, "getRelativePath");
215
+ const filteredEndpoints = useMemo(() => {
216
+ let filtered = deduplicateEndpoints(endpoints, state.selectedVersion);
217
+ if (state.selectedCategory && state.selectedCategory !== "All") {
218
+ filtered = filtered.filter((endpoint) => endpoint.category === state.selectedCategory);
219
+ }
220
+ if (state.searchTerm) {
221
+ const searchLower = state.searchTerm.toLowerCase();
222
+ filtered = filtered.filter(
223
+ (endpoint) => endpoint.name.toLowerCase().includes(searchLower) || endpoint.description.toLowerCase().includes(searchLower) || endpoint.path.toLowerCase().includes(searchLower)
224
+ );
225
+ }
226
+ return filtered;
227
+ }, [endpoints, state.selectedCategory, state.searchTerm, state.selectedVersion]);
228
+ const handleEndpointSelect = /* @__PURE__ */ __name((endpoint) => {
229
+ setSelectedEndpoint(endpoint);
230
+ }, "handleEndpointSelect");
231
+ const getMethodBadges = /* @__PURE__ */ __name((methods) => {
232
+ return methods.split(", ").map((method) => /* @__PURE__ */ jsx(Badge, { variant: getMethodColor(method) === "success" ? "default" : "secondary", className: "text-xs", children: method }, method));
233
+ }, "getMethodBadges");
234
+ if (loading) {
235
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
236
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
237
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: "API Endpoints" }),
238
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
239
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-32" }),
240
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-48" })
241
+ ] })
242
+ ] }),
243
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-20 w-full" }, i)) })
244
+ ] });
245
+ }
246
+ if (error) {
247
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
248
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: "API Endpoints" }) }),
249
+ /* @__PURE__ */ jsx(Card, { className: "bg-destructive/10 border-destructive/20", children: /* @__PURE__ */ jsx(CardContent, { className: "p-4", children: /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
250
+ "Error loading endpoints: ",
251
+ error
252
+ ] }) }) })
253
+ ] });
254
+ }
255
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
256
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
257
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between gap-4", children: [
258
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: "API Endpoints" }),
259
+ /* @__PURE__ */ jsx(VersionSelector, {})
260
+ ] }),
261
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
262
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center border rounded-md", children: [
263
+ /* @__PURE__ */ jsx(
264
+ Button,
265
+ {
266
+ variant: viewMode === "table" ? "default" : "ghost",
267
+ size: "sm",
268
+ onClick: () => setViewMode("table"),
269
+ className: "rounded-r-none",
270
+ children: /* @__PURE__ */ jsx(List, { className: "h-4 w-4" })
271
+ }
272
+ ),
273
+ /* @__PURE__ */ jsx(
274
+ Button,
275
+ {
276
+ variant: viewMode === "grid" ? "default" : "ghost",
277
+ size: "sm",
278
+ onClick: () => setViewMode("grid"),
279
+ className: "rounded-l-none",
280
+ children: /* @__PURE__ */ jsx(Grid3X3, { className: "h-4 w-4" })
281
+ }
282
+ )
283
+ ] }),
284
+ /* @__PURE__ */ jsxs(Select, { value: state.selectedCategory, onValueChange: setSelectedCategory, children: [
285
+ /* @__PURE__ */ jsxs(SelectTrigger, { className: "w-32", children: [
286
+ /* @__PURE__ */ jsx(Filter, { className: "h-4 w-4 mr-2" }),
287
+ /* @__PURE__ */ jsx(SelectValue, {})
288
+ ] }),
289
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
290
+ /* @__PURE__ */ jsx(SelectItem, { value: "All", children: "All" }),
291
+ categories.map((category) => /* @__PURE__ */ jsx(SelectItem, { value: category, children: category }, category))
292
+ ] })
293
+ ] }),
294
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
295
+ /* @__PURE__ */ jsx(Search, { className: "absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
296
+ /* @__PURE__ */ jsx(
297
+ Input,
298
+ {
299
+ placeholder: "Search endpoints...",
300
+ value: state.searchTerm,
301
+ onChange: (e) => setSearchTerm(e.target.value),
302
+ className: "w-48 pl-8"
303
+ }
304
+ )
305
+ ] })
306
+ ] }) })
307
+ ] }),
308
+ viewMode === "table" ? /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(Table, { children: [
309
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
310
+ /* @__PURE__ */ jsx(TableHead, { className: "text-foreground", children: "Methods" }),
311
+ /* @__PURE__ */ jsx(TableHead, { className: "text-foreground", children: "Path" }),
312
+ /* @__PURE__ */ jsx(TableHead, { className: "text-foreground", children: "Description" })
313
+ ] }) }),
314
+ /* @__PURE__ */ jsx(TableBody, { children: filteredEndpoints.length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 3, className: "text-center py-8 text-muted-foreground", children: "No endpoints found" }) }) : filteredEndpoints.map((endpoint) => /* @__PURE__ */ jsxs(
315
+ TableRow,
316
+ {
317
+ className: `cursor-pointer transition-colors hover:bg-muted/50 ${state.selectedEndpoint?.path === endpoint.path ? "bg-primary/10" : ""}`,
318
+ onClick: () => handleEndpointSelect(endpoint),
319
+ children: [
320
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx("div", { className: "flex space-x-1", children: getMethodBadges(endpoint.method) }) }),
321
+ /* @__PURE__ */ jsx(TableCell, { className: "font-mono text-sm text-muted-foreground", children: getRelativePath(endpoint.path) }),
322
+ /* @__PURE__ */ jsx(TableCell, { className: "text-sm text-muted-foreground max-w-xs truncate", children: endpoint.description })
323
+ ]
324
+ },
325
+ `${endpoint.method}-${endpoint.path}`
326
+ )) })
327
+ ] }) }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: filteredEndpoints.length === 0 ? /* @__PURE__ */ jsx("div", { className: "col-span-full text-center py-8 text-muted-foreground", children: "No endpoints found" }) : filteredEndpoints.map((endpoint) => /* @__PURE__ */ jsxs(
328
+ Card,
329
+ {
330
+ className: `cursor-pointer transition-all hover:shadow-md ${state.selectedEndpoint?.path === endpoint.path ? "ring-2 ring-primary" : ""}`,
331
+ onClick: () => handleEndpointSelect(endpoint),
332
+ children: [
333
+ /* @__PURE__ */ jsx(CardHeader, { className: "pb-3", children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between text-sm", children: [
334
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
335
+ categoryIcons[endpoint.category] || /* @__PURE__ */ jsx(Code, { className: "h-4 w-4" }),
336
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: endpoint.name })
337
+ ] }),
338
+ /* @__PURE__ */ jsx("div", { className: "flex space-x-1", children: getMethodBadges(endpoint.method) })
339
+ ] }) }),
340
+ /* @__PURE__ */ jsxs(CardContent, { className: "space-y-2", children: [
341
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-mono text-muted-foreground break-all", children: getRelativePath(endpoint.path) }),
342
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground line-clamp-2", children: endpoint.description })
343
+ ] })
344
+ ]
345
+ },
346
+ `${endpoint.method}-${endpoint.path}`
347
+ )) })
348
+ ] });
349
+ }, "EndpointsLibrary");
350
+ var stepConfig = {
351
+ endpoints: {
352
+ title: "Endpoints",
353
+ icon: Code,
354
+ description: "Select API endpoint"
355
+ },
356
+ request: {
357
+ title: "Request",
358
+ icon: Send,
359
+ description: "Configure request"
360
+ },
361
+ response: {
362
+ title: "Response",
363
+ icon: FileText,
364
+ description: "View response"
365
+ }
366
+ };
367
+ var PlaygroundStepper = /* @__PURE__ */ __name(() => {
368
+ const { state, setCurrentStep, goToNextStep, goToPreviousStep } = usePlaygroundContext();
369
+ const { currentStep, steps } = state;
370
+ const currentIndex = steps.indexOf(currentStep);
371
+ const canGoNext = currentIndex < steps.length - 1;
372
+ const canGoPrevious = currentIndex > 0;
373
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 border-b", children: [
374
+ /* @__PURE__ */ jsx("div", { className: "flex items-center space-x-4", children: steps.map((step, index) => {
375
+ const config = stepConfig[step];
376
+ const Icon = config.icon;
377
+ const isActive = step === currentStep;
378
+ const isCompleted = index < currentIndex;
379
+ const isClickable = index <= currentIndex + 1;
380
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
381
+ /* @__PURE__ */ jsxs(
382
+ Button,
383
+ {
384
+ variant: isActive ? "default" : "ghost",
385
+ size: "sm",
386
+ onClick: () => isClickable && setCurrentStep(step),
387
+ className: `flex items-center space-x-2 ${isClickable ? "cursor-pointer" : "cursor-not-allowed opacity-50"}`,
388
+ disabled: !isClickable,
389
+ children: [
390
+ isCompleted ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
391
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: config.title })
392
+ ]
393
+ }
394
+ ),
395
+ index < steps.length - 1 && /* @__PURE__ */ jsx("div", { className: "w-8 h-px bg-border" })
396
+ ] }, step);
397
+ }) }),
398
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
399
+ /* @__PURE__ */ jsxs(
400
+ Button,
401
+ {
402
+ variant: "outline",
403
+ size: "sm",
404
+ onClick: goToPreviousStep,
405
+ disabled: !canGoPrevious,
406
+ className: "flex items-center space-x-1",
407
+ children: [
408
+ /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }),
409
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Previous" })
410
+ ]
411
+ }
412
+ ),
413
+ /* @__PURE__ */ jsxs(
414
+ Button,
415
+ {
416
+ variant: "outline",
417
+ size: "sm",
418
+ onClick: goToNextStep,
419
+ disabled: !canGoNext,
420
+ className: "flex items-center space-x-1",
421
+ children: [
422
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Next" }),
423
+ /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
424
+ ]
425
+ }
426
+ )
427
+ ] })
428
+ ] });
429
+ }, "PlaygroundStepper");
430
+ var EndpointInfo = /* @__PURE__ */ __name(() => {
431
+ const { state } = usePlaygroundContext();
432
+ const { selectedEndpoint } = state;
433
+ const endpointJson = useMemo(() => {
434
+ if (!selectedEndpoint) return "";
435
+ return JSON.stringify({
436
+ name: selectedEndpoint.name,
437
+ method: selectedEndpoint.method,
438
+ path: selectedEndpoint.path,
439
+ description: selectedEndpoint.description,
440
+ parameters: selectedEndpoint.parameters,
441
+ requestBody: selectedEndpoint.requestBody,
442
+ responses: selectedEndpoint.responses
443
+ }, null, 2);
444
+ }, [selectedEndpoint]);
445
+ if (!selectedEndpoint) {
446
+ return null;
447
+ }
448
+ const getMethodBadges = /* @__PURE__ */ __name((methods) => {
449
+ return methods.split(", ").map((method) => /* @__PURE__ */ jsx(Badge, { variant: getMethodColor(method) === "success" ? "default" : "secondary", className: "text-xs", children: method }, method));
450
+ }, "getMethodBadges");
451
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
452
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
453
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: "Selected Endpoint" }),
454
+ /* @__PURE__ */ jsx(CopyButton, { value: endpointJson, variant: "outline", size: "sm", children: "Copy" })
455
+ ] }),
456
+ /* @__PURE__ */ jsxs(Card, { children: [
457
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center justify-between text-sm text-foreground", children: [
458
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
459
+ /* @__PURE__ */ jsx(Code, { className: "h-4 w-4" }),
460
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: selectedEndpoint.name })
461
+ ] }),
462
+ /* @__PURE__ */ jsx("div", { className: "flex space-x-1", children: getMethodBadges(selectedEndpoint.method) })
463
+ ] }) }),
464
+ /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
465
+ /* @__PURE__ */ jsxs("div", { children: [
466
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-mono text-muted-foreground break-all", children: selectedEndpoint.path }),
467
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: selectedEndpoint.description })
468
+ ] }),
469
+ selectedEndpoint.parameters && selectedEndpoint.parameters.length > 0 && /* @__PURE__ */ jsxs(Collapsible, { children: [
470
+ /* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "flex items-center space-x-2 text-sm font-medium text-foreground", children: [
471
+ /* @__PURE__ */ jsx(Database, { className: "h-4 w-4" }),
472
+ /* @__PURE__ */ jsxs("span", { children: [
473
+ "Parameters (",
474
+ selectedEndpoint.parameters.length,
475
+ ")"
476
+ ] }),
477
+ /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" })
478
+ ] }),
479
+ /* @__PURE__ */ jsx(CollapsibleContent, { className: "mt-2 space-y-2", children: selectedEndpoint.parameters.map((param, index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2 text-xs", children: [
480
+ /* @__PURE__ */ jsx(Badge, { variant: param.required ? "destructive" : "secondary", className: "text-xs", children: param.required ? "Required" : "Optional" }),
481
+ /* @__PURE__ */ jsxs("span", { className: "font-mono text-muted-foreground", children: [
482
+ param.name,
483
+ ": ",
484
+ param.type
485
+ ] }),
486
+ param.description && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
487
+ "- ",
488
+ param.description
489
+ ] })
490
+ ] }, index)) })
491
+ ] }),
492
+ selectedEndpoint.requestBody && /* @__PURE__ */ jsxs(Collapsible, { children: [
493
+ /* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "flex items-center space-x-2 text-sm font-medium text-foreground", children: [
494
+ /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" }),
495
+ /* @__PURE__ */ jsx("span", { children: "Request Body" }),
496
+ /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" })
497
+ ] }),
498
+ /* @__PURE__ */ jsx(CollapsibleContent, { className: "mt-2", children: /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
499
+ /* @__PURE__ */ jsxs("p", { children: [
500
+ "Type: ",
501
+ selectedEndpoint.requestBody.type
502
+ ] }),
503
+ selectedEndpoint.requestBody.description && /* @__PURE__ */ jsx("p", { className: "mt-1", children: selectedEndpoint.requestBody.description })
504
+ ] }) })
505
+ ] }),
506
+ selectedEndpoint.responses && selectedEndpoint.responses.length > 0 && /* @__PURE__ */ jsxs(Collapsible, { children: [
507
+ /* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "flex items-center space-x-2 text-sm font-medium text-foreground", children: [
508
+ /* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
509
+ /* @__PURE__ */ jsxs("span", { children: [
510
+ "Responses (",
511
+ selectedEndpoint.responses.length,
512
+ ")"
513
+ ] }),
514
+ /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" })
515
+ ] }),
516
+ /* @__PURE__ */ jsx(CollapsibleContent, { className: "mt-2 space-y-2", children: selectedEndpoint.responses.map((response, index) => {
517
+ const statusColor = getStatusColor(parseInt(response.code));
518
+ const badgeVariant = statusColor === "success" ? "default" : statusColor === "error" ? "destructive" : "secondary";
519
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2 text-xs", children: [
520
+ /* @__PURE__ */ jsx(Badge, { variant: badgeVariant, className: "text-xs", children: response.code }),
521
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: response.description })
522
+ ] }, index);
523
+ }) })
524
+ ] })
525
+ ] })
526
+ ] })
527
+ ] });
528
+ }, "EndpointInfo");
529
+ var RequestParametersForm = /* @__PURE__ */ __name(() => {
530
+ const { state, setParameters } = usePlaygroundContext();
531
+ const [formData, setFormData] = useState({});
532
+ const [activeTab, setActiveTab] = useState("required");
533
+ useEffect(() => {
534
+ if (state.selectedEndpoint?.parameters) {
535
+ const initialData = {};
536
+ state.selectedEndpoint.parameters.forEach((param) => {
537
+ initialData[param.name] = "";
538
+ });
539
+ setFormData(initialData);
540
+ }
541
+ }, [state.selectedEndpoint?.path, state.selectedEndpoint?.parameters]);
542
+ const handleInputChange = /* @__PURE__ */ __name((name, value) => {
543
+ const newFormData = {
544
+ ...formData,
545
+ [name]: value
546
+ };
547
+ setFormData(newFormData);
548
+ setParameters(newFormData);
549
+ }, "handleInputChange");
550
+ const handleClearForm = /* @__PURE__ */ __name(() => {
551
+ setFormData({});
552
+ setParameters({});
553
+ }, "handleClearForm");
554
+ const handleGenerateJson = /* @__PURE__ */ __name(() => {
555
+ const hasData = Object.values(formData).some((value) => value !== "" && value !== null && value !== void 0);
556
+ if (hasData) {
557
+ const jsonString = JSON.stringify(formData, null, 2);
558
+ navigator.clipboard.writeText(jsonString);
559
+ }
560
+ }, "handleGenerateJson");
561
+ if (!state.selectedEndpoint) return null;
562
+ const requiredParams = state.selectedEndpoint.parameters?.filter((param) => param.required) || [];
563
+ const optionalParams = state.selectedEndpoint.parameters?.filter((param) => !param.required) || [];
564
+ const hasParameters = (state.selectedEndpoint.parameters?.length || 0) > 0;
565
+ if (!hasParameters) {
566
+ return null;
567
+ }
568
+ const hasFormData = Object.values(formData).some((value) => value !== "" && value !== null && value !== void 0);
569
+ const ParameterField = /* @__PURE__ */ __name(({ param }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
570
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-1", children: [
571
+ /* @__PURE__ */ jsxs(Label, { htmlFor: param.name, className: "text-xs font-medium text-foreground", children: [
572
+ param.name,
573
+ param.required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
574
+ ] }),
575
+ param.description && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
576
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(HelpCircle, { className: "h-3 w-3 text-muted-foreground hover:text-foreground cursor-help" }) }),
577
+ /* @__PURE__ */ jsx(TooltipContent, { side: "top", className: "max-w-xs", children: /* @__PURE__ */ jsx("p", { className: "text-xs", children: param.description }) })
578
+ ] }) })
579
+ ] }),
580
+ /* @__PURE__ */ jsx(
581
+ Input,
582
+ {
583
+ id: param.name,
584
+ value: formData[param.name] || "",
585
+ onChange: (e) => handleInputChange(param.name, e.target.value),
586
+ placeholder: `Enter ${param.name}${param.required ? "" : " (optional)"}`,
587
+ className: "text-sm"
588
+ }
589
+ )
590
+ ] }), "ParameterField");
591
+ const ParametersGrid = /* @__PURE__ */ __name(({ params, title, badgeVariant }) => {
592
+ if (params.length === 0) return null;
593
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
594
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
595
+ /* @__PURE__ */ jsx(Badge, { variant: badgeVariant, className: "text-xs", children: title }),
596
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
597
+ params.length,
598
+ " parameter",
599
+ params.length !== 1 ? "s" : ""
600
+ ] })
601
+ ] }) }),
602
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: params.map((param) => /* @__PURE__ */ jsx(ParameterField, { param }, param.name)) })
603
+ ] });
604
+ }, "ParametersGrid");
605
+ return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Card, { children: [
606
+ /* @__PURE__ */ jsx(CardHeader, { className: "pb-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
607
+ /* @__PURE__ */ jsx(CardTitle, { className: "text-sm text-foreground", children: "Request Parameters" }),
608
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
609
+ hasFormData && /* @__PURE__ */ jsx(
610
+ Button,
611
+ {
612
+ variant: "default",
613
+ size: "sm",
614
+ onClick: handleGenerateJson,
615
+ className: "text-xs",
616
+ children: "Copy JSON"
617
+ }
618
+ ),
619
+ /* @__PURE__ */ jsx(
620
+ Button,
621
+ {
622
+ variant: "outline",
623
+ size: "sm",
624
+ onClick: handleClearForm,
625
+ className: "text-xs",
626
+ children: "Clear"
627
+ }
628
+ )
629
+ ] })
630
+ ] }) }),
631
+ /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
632
+ requiredParams.length + optionalParams.length > 10 ? /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, children: [
633
+ /* @__PURE__ */ jsxs(TabsList, { className: "grid w-full grid-cols-2", children: [
634
+ /* @__PURE__ */ jsxs(TabsTrigger, { value: "required", className: "text-xs", children: [
635
+ "Required (",
636
+ requiredParams.length,
637
+ ")"
638
+ ] }),
639
+ /* @__PURE__ */ jsxs(TabsTrigger, { value: "optional", className: "text-xs", children: [
640
+ "Optional (",
641
+ optionalParams.length,
642
+ ")"
643
+ ] })
644
+ ] }),
645
+ /* @__PURE__ */ jsx(TabsContent, { value: "required", className: "space-y-4", children: /* @__PURE__ */ jsx(
646
+ ParametersGrid,
647
+ {
648
+ params: requiredParams,
649
+ title: "Required",
650
+ badgeVariant: "destructive"
651
+ }
652
+ ) }),
653
+ /* @__PURE__ */ jsx(TabsContent, { value: "optional", className: "space-y-4", children: /* @__PURE__ */ jsx(
654
+ ParametersGrid,
655
+ {
656
+ params: optionalParams,
657
+ title: "Optional",
658
+ badgeVariant: "secondary"
659
+ }
660
+ ) })
661
+ ] }) : (
662
+ /* Use Accordion for smaller parameter sets */
663
+ /* @__PURE__ */ jsxs(Accordion, { type: "multiple", defaultValue: requiredParams.length > 0 ? ["required"] : ["optional"], children: [
664
+ requiredParams.length > 0 && /* @__PURE__ */ jsxs(AccordionItem, { value: "required", children: [
665
+ /* @__PURE__ */ jsx(AccordionTrigger, { className: "text-sm text-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
666
+ /* @__PURE__ */ jsx(Badge, { variant: "destructive", className: "text-xs", children: "Required" }),
667
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
668
+ requiredParams.length,
669
+ " parameter",
670
+ requiredParams.length !== 1 ? "s" : ""
671
+ ] })
672
+ ] }) }),
673
+ /* @__PURE__ */ jsx(AccordionContent, { children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 pt-2", children: requiredParams.map((param) => /* @__PURE__ */ jsx(ParameterField, { param }, param.name)) }) })
674
+ ] }),
675
+ optionalParams.length > 0 && /* @__PURE__ */ jsxs(AccordionItem, { value: "optional", children: [
676
+ /* @__PURE__ */ jsx(AccordionTrigger, { className: "text-sm text-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
677
+ /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: "Optional" }),
678
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
679
+ optionalParams.length,
680
+ " parameter",
681
+ optionalParams.length !== 1 ? "s" : ""
682
+ ] })
683
+ ] }) }),
684
+ /* @__PURE__ */ jsx(AccordionContent, { children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 pt-2", children: optionalParams.map((param) => /* @__PURE__ */ jsx(ParameterField, { param }, param.name)) }) })
685
+ ] })
686
+ ] })
687
+ ),
688
+ hasFormData && /* @__PURE__ */ jsxs("div", { className: "space-y-2 mt-6 pt-4 border-t", children: [
689
+ /* @__PURE__ */ jsx(Label, { className: "text-xs text-foreground", children: "Generated JSON" }),
690
+ /* @__PURE__ */ jsx(
691
+ Textarea,
692
+ {
693
+ value: JSON.stringify(formData, null, 2),
694
+ readOnly: true,
695
+ className: "text-xs font-mono",
696
+ rows: 4
697
+ }
698
+ ),
699
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: 'Click "Copy JSON" to copy this to clipboard, then paste it into the Request Body field above.' })
700
+ ] })
701
+ ] })
702
+ ] }) });
703
+ }, "RequestParametersForm");
704
+ var RequestBuilder = /* @__PURE__ */ __name(() => {
705
+ const {
706
+ state,
707
+ apiKeys,
708
+ setRequestBody,
709
+ setManualApiToken,
710
+ sendRequest
711
+ } = usePlaygroundContext();
712
+ const isJsonValid = state.requestBody ? isValidJson(state.requestBody) : true;
713
+ const generateCurlCommand = /* @__PURE__ */ __name(() => {
714
+ if (!state.requestUrl) return "";
715
+ const apiKey = state.selectedApiKey ? findApiKeyById(apiKeys, state.selectedApiKey) : null;
716
+ const headers = parseRequestHeaders(state.requestHeaders);
717
+ if (apiKey) {
718
+ headers["X-API-Key"] = apiKey.id || "";
719
+ }
720
+ let curl = `curl -X ${state.requestMethod} "${state.requestUrl}"`;
721
+ Object.entries(headers).forEach(([key, value]) => {
722
+ curl += ` \\
723
+ -H "${key}: ${value}"`;
724
+ });
725
+ if (state.requestBody && state.requestMethod !== "GET" && isJsonValid) {
726
+ curl += ` \\
727
+ -d '${state.requestBody}'`;
728
+ }
729
+ return curl;
730
+ }, "generateCurlCommand");
731
+ const curlCommand = generateCurlCommand();
732
+ const handleSendRequest = useCallback(async () => {
733
+ await sendRequest();
734
+ }, [sendRequest]);
735
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
736
+ state.selectedEndpoint && /* @__PURE__ */ jsx(EndpointInfo, {}),
737
+ state.selectedEndpoint && /* @__PURE__ */ jsx(RequestParametersForm, {}),
738
+ state.requestMethod !== "GET" && /* @__PURE__ */ jsxs(Card, { className: "", children: [
739
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { className: "text-sm text-foreground", children: "Request Body" }) }),
740
+ /* @__PURE__ */ jsxs(CardContent, { children: [
741
+ /* @__PURE__ */ jsx(
742
+ Textarea,
743
+ {
744
+ placeholder: '{\\n "key": "value"\\n}',
745
+ value: state.requestBody,
746
+ onChange: (e) => setRequestBody(e.target.value),
747
+ className: `font-mono text-sm ${!isJsonValid ? "border-destructive" : ""}`,
748
+ rows: 6
749
+ }
750
+ ),
751
+ !isJsonValid && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-destructive", children: "Invalid JSON format" })
752
+ ] })
753
+ ] }),
754
+ /* @__PURE__ */ jsxs(Card, { className: "", children: [
755
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center space-x-2 text-sm text-foreground", children: [
756
+ /* @__PURE__ */ jsx(Key, { className: "h-4 w-4" }),
757
+ /* @__PURE__ */ jsx("span", { children: "Bearer Token" })
758
+ ] }) }),
759
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center gap-2", children: [
760
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
761
+ /* @__PURE__ */ jsx(
762
+ Input,
763
+ {
764
+ type: "password",
765
+ placeholder: "Enter Bearer token (optional, uses JWT if empty)",
766
+ value: state.manualApiToken,
767
+ onChange: (e) => setManualApiToken(e.target.value),
768
+ className: "font-mono text-sm"
769
+ }
770
+ ),
771
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Leave empty to use JWT token from localStorage" })
772
+ ] }),
773
+ /* @__PURE__ */ jsx(
774
+ Button,
775
+ {
776
+ onClick: handleSendRequest,
777
+ disabled: state.loading || !state.requestUrl || !isJsonValid,
778
+ className: "bg-primary hover:bg-primary/90 text-primary-foreground flex items-center gap-2",
779
+ children: state.loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
780
+ /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
781
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Sending..." })
782
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
783
+ /* @__PURE__ */ jsx(Send, { className: "h-4 w-4" }),
784
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Send Request" })
785
+ ] })
786
+ }
787
+ )
788
+ ] }) })
789
+ ] }),
790
+ curlCommand && /* @__PURE__ */ jsxs(Card, { children: [
791
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
792
+ /* @__PURE__ */ jsx(CardTitle, { className: "text-sm text-foreground", children: "cURL Command" }),
793
+ /* @__PURE__ */ jsx(
794
+ CopyButton,
795
+ {
796
+ value: curlCommand,
797
+ variant: "outline",
798
+ size: "sm",
799
+ children: "Copy cURL"
800
+ }
801
+ )
802
+ ] }) }),
803
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(PrettyCode_default, { data: curlCommand, language: "bash" }) })
804
+ ] })
805
+ ] });
806
+ }, "RequestBuilder");
807
+ var ResponseViewer = /* @__PURE__ */ __name(() => {
808
+ const { state } = usePlaygroundContext();
809
+ const { response } = state;
810
+ const responseText = useMemo(() => {
811
+ if (!response?.data) return "";
812
+ return typeof response.data === "string" ? response.data : JSON.stringify(response.data, null, 2);
813
+ }, [response?.data]);
814
+ const handleDownloadResponse = useCallback(() => {
815
+ if (!responseText) return;
816
+ const blob = new Blob([responseText], { type: "application/json" });
817
+ const url = URL.createObjectURL(blob);
818
+ const a = document.createElement("a");
819
+ a.href = url;
820
+ a.download = "response.json";
821
+ document.body.appendChild(a);
822
+ a.click();
823
+ document.body.removeChild(a);
824
+ URL.revokeObjectURL(url);
825
+ }, [responseText]);
826
+ if (!response) {
827
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
828
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: "Response" }) }),
829
+ /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No response yet. Send a request to see the response here." }) }) })
830
+ ] });
831
+ }
832
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
833
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
834
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: "Response" }),
835
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
836
+ /* @__PURE__ */ jsx(CopyButton, { value: responseText, variant: "outline", size: "sm", children: "Copy" }),
837
+ /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: handleDownloadResponse, children: [
838
+ /* @__PURE__ */ jsx(Download, { className: "h-4 w-4" }),
839
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Download" })
840
+ ] })
841
+ ] })
842
+ ] }),
843
+ /* @__PURE__ */ jsxs(Card, { children: [
844
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { className: "text-sm text-foreground", children: "Response Information" }) }),
845
+ /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
846
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: [
847
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
848
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
849
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: "Status Code:" }),
850
+ /* @__PURE__ */ jsx(
851
+ Badge,
852
+ {
853
+ variant: getStatusColor(response.status || 0) === "success" ? "default" : getStatusColor(response.status || 0) === "error" ? "destructive" : "secondary",
854
+ className: "text-xs",
855
+ children: response.status
856
+ }
857
+ )
858
+ ] }),
859
+ response.statusText && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
860
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: "Status Text:" }),
861
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: response.statusText })
862
+ ] })
863
+ ] }),
864
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
865
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
866
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: "Response Type:" }),
867
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: typeof response.data === "string" ? "Text" : "JSON" })
868
+ ] }),
869
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
870
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: "Data Size:" }),
871
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
872
+ typeof response.data === "string" ? response.data.length : JSON.stringify(response.data).length,
873
+ " chars"
874
+ ] })
875
+ ] })
876
+ ] })
877
+ ] }),
878
+ response.error && /* @__PURE__ */ jsx("div", { className: "bg-destructive/10 border border-destructive/20 rounded p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
879
+ /* @__PURE__ */ jsx(XCircle, { className: "h-4 w-4 text-destructive" }),
880
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: response.error })
881
+ ] }) })
882
+ ] })
883
+ ] }),
884
+ /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { className: "p-0", children: (() => {
885
+ const is404 = response.status === 404;
886
+ const isNonJson = typeof response.data === "string";
887
+ if (is404 || isNonJson) {
888
+ return /* @__PURE__ */ jsx("div", { className: "p-8 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: is404 ? "Response body hidden for 404 Not Found status" : "Response body hidden for non-JSON responses" }) });
889
+ }
890
+ if (response.data) {
891
+ return /* @__PURE__ */ jsx(
892
+ JsonTree_default,
893
+ {
894
+ title: "Response Body",
895
+ data: response.data,
896
+ config: {
897
+ // Smart defaults for API responses
898
+ maxAutoExpandDepth: 2,
899
+ maxAutoExpandArrayItems: 10,
900
+ maxAutoExpandObjectKeys: 5,
901
+ maxStringLength: 200,
902
+ collectionLimit: 50,
903
+ showCollectionInfo: true,
904
+ showExpandControls: true,
905
+ showActionButtons: false,
906
+ // We have our own copy/download buttons above
907
+ preserveKeyOrder: true,
908
+ className: "border-0 rounded-none"
909
+ }
910
+ }
911
+ );
912
+ }
913
+ return /* @__PURE__ */ jsx("div", { className: "p-8 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No response body available" }) });
914
+ })() }) })
915
+ ] });
916
+ }, "ResponseViewer");
917
+ var PlaygroundLayout = /* @__PURE__ */ __name(() => {
918
+ const { state, setSidebarOpen } = usePlaygroundContext();
919
+ const { isMobile } = useMobile();
920
+ const renderStepContent = /* @__PURE__ */ __name(() => {
921
+ switch (state.currentStep) {
922
+ case "endpoints":
923
+ return /* @__PURE__ */ jsx(EndpointsLibrary, {});
924
+ case "request":
925
+ return /* @__PURE__ */ jsx(RequestBuilder, {});
926
+ case "response":
927
+ return /* @__PURE__ */ jsx(ResponseViewer, {});
928
+ default:
929
+ return /* @__PURE__ */ jsx(EndpointsLibrary, {});
930
+ }
931
+ }, "renderStepContent");
932
+ const getStepTitle = /* @__PURE__ */ __name(() => {
933
+ switch (state.currentStep) {
934
+ case "endpoints":
935
+ return "API Endpoints";
936
+ case "request":
937
+ return "Request Builder";
938
+ case "response":
939
+ return "Response Viewer";
940
+ default:
941
+ return "API Playground";
942
+ }
943
+ }, "getStepTitle");
944
+ return /* @__PURE__ */ jsxs("div", { className: "min-h-screen", children: [
945
+ /* @__PURE__ */ jsx("div", { className: "border-b", children: /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
946
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-4", children: [
947
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-bold text-foreground", children: "API Playground" }),
948
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground hidden sm:block", children: "Test and explore API endpoints" })
949
+ ] }),
950
+ isMobile && /* @__PURE__ */ jsxs(Sheet, { open: state.sidebarOpen, onOpenChange: setSidebarOpen, children: [
951
+ /* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", children: /* @__PURE__ */ jsx(Menu, { className: "h-4 w-4" }) }) }),
952
+ /* @__PURE__ */ jsx(SheetContent, { side: "left", className: "w-80", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
953
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
954
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: "Navigation" }),
955
+ /* @__PURE__ */ jsx(
956
+ Button,
957
+ {
958
+ variant: "ghost",
959
+ size: "sm",
960
+ onClick: () => setSidebarOpen(false),
961
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
962
+ }
963
+ )
964
+ ] }),
965
+ /* @__PURE__ */ jsx(PlaygroundStepper, {})
966
+ ] }) })
967
+ ] })
968
+ ] }) }) }),
969
+ !isMobile && /* @__PURE__ */ jsx(PlaygroundStepper, {}),
970
+ /* @__PURE__ */ jsxs("div", { className: "container mx-auto px-6 py-6", children: [
971
+ /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
972
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold text-foreground", children: getStepTitle() }),
973
+ /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground mt-1", children: [
974
+ state.currentStep === "endpoints" && "Browse and select API endpoints",
975
+ state.currentStep === "request" && "Configure your API request",
976
+ state.currentStep === "response" && "View API response and details"
977
+ ] })
978
+ ] }),
979
+ /* @__PURE__ */ jsx("div", { className: "space-y-6", children: renderStepContent() })
980
+ ] }),
981
+ isMobile && state.currentStep === "request" && /* @__PURE__ */ jsx("div", { className: "fixed bottom-4 right-4 z-50", children: /* @__PURE__ */ jsx(
982
+ Button,
983
+ {
984
+ size: "lg",
985
+ className: "rounded-full shadow-lg",
986
+ onClick: () => {
987
+ },
988
+ children: "Send Request"
989
+ }
990
+ ) })
991
+ ] });
992
+ }, "PlaygroundLayout");
993
+
994
+ export { PlaygroundLayout };
995
+ //# sourceMappingURL=PlaygroundLayout-4DYBORAS.mjs.map
996
+ //# sourceMappingURL=PlaygroundLayout-4DYBORAS.mjs.map