@djangocfg/ui-tools 2.1.268 → 2.1.270

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