@djangocfg/ui-nextjs 2.1.89 → 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 (161) hide show
  1. package/README.md +6 -15
  2. package/package.json +6 -25
  3. package/src/blocks/SplitHero/SplitHeroMedia.tsx +1 -1
  4. package/src/components/index.ts +0 -40
  5. package/src/hooks/index.ts +0 -6
  6. package/src/index.ts +2 -11
  7. package/src/components/button-download.tsx +0 -277
  8. package/src/components/markdown/MarkdownMessage.tsx +0 -340
  9. package/src/components/markdown/index.ts +0 -5
  10. package/src/components/menubar.tsx +0 -275
  11. package/src/components/multi-select-pro/async.tsx +0 -598
  12. package/src/components/multi-select-pro/helpers.tsx +0 -84
  13. package/src/components/multi-select-pro/index.tsx +0 -612
  14. package/src/components/navigation-menu.tsx +0 -154
  15. package/src/components/otp/index.tsx +0 -197
  16. package/src/components/otp/types.ts +0 -133
  17. package/src/components/otp/use-otp-input.ts +0 -225
  18. package/src/components/phone-input.tsx +0 -277
  19. package/src/components/sonner.tsx +0 -32
  20. package/src/hooks/useLocalStorage.ts +0 -300
  21. package/src/hooks/useSessionStorage.ts +0 -290
  22. package/src/lib/index.ts +0 -5
  23. package/src/lib/logger/index.ts +0 -10
  24. package/src/lib/logger/logStore.ts +0 -122
  25. package/src/lib/logger/logger.ts +0 -175
  26. package/src/lib/logger/types.ts +0 -82
  27. package/src/stores/index.ts +0 -8
  28. package/src/stores/mediaCache.ts +0 -534
  29. package/src/tools/AudioPlayer/README.md +0 -206
  30. package/src/tools/AudioPlayer/components/HybridAudioPlayer.tsx +0 -216
  31. package/src/tools/AudioPlayer/components/HybridSimplePlayer.tsx +0 -280
  32. package/src/tools/AudioPlayer/components/HybridWaveform.tsx +0 -279
  33. package/src/tools/AudioPlayer/components/ReactiveCover/AudioReactiveCover.tsx +0 -149
  34. package/src/tools/AudioPlayer/components/ReactiveCover/effects/GlowEffect.tsx +0 -110
  35. package/src/tools/AudioPlayer/components/ReactiveCover/effects/MeshEffect.tsx +0 -58
  36. package/src/tools/AudioPlayer/components/ReactiveCover/effects/OrbsEffect.tsx +0 -45
  37. package/src/tools/AudioPlayer/components/ReactiveCover/effects/SpotlightEffect.tsx +0 -82
  38. package/src/tools/AudioPlayer/components/ReactiveCover/effects/index.ts +0 -8
  39. package/src/tools/AudioPlayer/components/ReactiveCover/index.ts +0 -6
  40. package/src/tools/AudioPlayer/components/index.ts +0 -22
  41. package/src/tools/AudioPlayer/context/HybridAudioProvider.tsx +0 -158
  42. package/src/tools/AudioPlayer/context/index.ts +0 -16
  43. package/src/tools/AudioPlayer/effects/index.ts +0 -412
  44. package/src/tools/AudioPlayer/hooks/index.ts +0 -35
  45. package/src/tools/AudioPlayer/hooks/useHybridAudio.ts +0 -387
  46. package/src/tools/AudioPlayer/hooks/useHybridAudioAnalysis.ts +0 -95
  47. package/src/tools/AudioPlayer/hooks/useVisualization.tsx +0 -207
  48. package/src/tools/AudioPlayer/index.ts +0 -133
  49. package/src/tools/AudioPlayer/types/effects.ts +0 -73
  50. package/src/tools/AudioPlayer/types/index.ts +0 -27
  51. package/src/tools/AudioPlayer/utils/debug.ts +0 -14
  52. package/src/tools/AudioPlayer/utils/formatTime.ts +0 -10
  53. package/src/tools/AudioPlayer/utils/index.ts +0 -6
  54. package/src/tools/ImageViewer/@refactoring/00-PLAN.md +0 -71
  55. package/src/tools/ImageViewer/@refactoring/01-TYPES.md +0 -121
  56. package/src/tools/ImageViewer/@refactoring/02-UTILS.md +0 -143
  57. package/src/tools/ImageViewer/@refactoring/03-HOOKS.md +0 -261
  58. package/src/tools/ImageViewer/@refactoring/04-COMPONENTS.md +0 -427
  59. package/src/tools/ImageViewer/@refactoring/05-EXECUTION-CHECKLIST.md +0 -126
  60. package/src/tools/ImageViewer/README.md +0 -200
  61. package/src/tools/ImageViewer/components/ImageInfo.tsx +0 -44
  62. package/src/tools/ImageViewer/components/ImageToolbar.tsx +0 -150
  63. package/src/tools/ImageViewer/components/ImageViewer.tsx +0 -241
  64. package/src/tools/ImageViewer/components/index.ts +0 -7
  65. package/src/tools/ImageViewer/hooks/index.ts +0 -9
  66. package/src/tools/ImageViewer/hooks/useImageLoading.ts +0 -204
  67. package/src/tools/ImageViewer/hooks/useImageTransform.ts +0 -101
  68. package/src/tools/ImageViewer/index.ts +0 -60
  69. package/src/tools/ImageViewer/types.ts +0 -81
  70. package/src/tools/ImageViewer/utils/constants.ts +0 -59
  71. package/src/tools/ImageViewer/utils/debug.ts +0 -14
  72. package/src/tools/ImageViewer/utils/index.ts +0 -17
  73. package/src/tools/ImageViewer/utils/lqip.ts +0 -47
  74. package/src/tools/JsonForm/JsonSchemaForm.tsx +0 -197
  75. package/src/tools/JsonForm/examples/BotConfigExample.tsx +0 -249
  76. package/src/tools/JsonForm/examples/RealBotConfigExample.tsx +0 -161
  77. package/src/tools/JsonForm/index.ts +0 -46
  78. package/src/tools/JsonForm/templates/ArrayFieldItemTemplate.tsx +0 -47
  79. package/src/tools/JsonForm/templates/ArrayFieldTemplate.tsx +0 -74
  80. package/src/tools/JsonForm/templates/BaseInputTemplate.tsx +0 -107
  81. package/src/tools/JsonForm/templates/ErrorListTemplate.tsx +0 -35
  82. package/src/tools/JsonForm/templates/FieldTemplate.tsx +0 -62
  83. package/src/tools/JsonForm/templates/ObjectFieldTemplate.tsx +0 -116
  84. package/src/tools/JsonForm/templates/index.ts +0 -12
  85. package/src/tools/JsonForm/types.ts +0 -83
  86. package/src/tools/JsonForm/utils.ts +0 -213
  87. package/src/tools/JsonForm/widgets/CheckboxWidget.tsx +0 -37
  88. package/src/tools/JsonForm/widgets/ColorWidget.tsx +0 -219
  89. package/src/tools/JsonForm/widgets/NumberWidget.tsx +0 -89
  90. package/src/tools/JsonForm/widgets/SelectWidget.tsx +0 -97
  91. package/src/tools/JsonForm/widgets/SliderWidget.tsx +0 -148
  92. package/src/tools/JsonForm/widgets/SwitchWidget.tsx +0 -35
  93. package/src/tools/JsonForm/widgets/TextWidget.tsx +0 -96
  94. package/src/tools/JsonForm/widgets/index.ts +0 -14
  95. package/src/tools/JsonTree/index.tsx +0 -243
  96. package/src/tools/LottiePlayer/LottiePlayer.client.tsx +0 -213
  97. package/src/tools/LottiePlayer/index.tsx +0 -55
  98. package/src/tools/LottiePlayer/types.ts +0 -108
  99. package/src/tools/LottiePlayer/useLottie.ts +0 -164
  100. package/src/tools/Mermaid/Mermaid.client.tsx +0 -82
  101. package/src/tools/Mermaid/components/MermaidCodeViewer.tsx +0 -95
  102. package/src/tools/Mermaid/components/MermaidFullscreenModal.tsx +0 -103
  103. package/src/tools/Mermaid/hooks/index.ts +0 -4
  104. package/src/tools/Mermaid/hooks/useMermaidCleanup.ts +0 -73
  105. package/src/tools/Mermaid/hooks/useMermaidFullscreen.ts +0 -46
  106. package/src/tools/Mermaid/hooks/useMermaidRenderer.ts +0 -226
  107. package/src/tools/Mermaid/hooks/useMermaidValidation.ts +0 -29
  108. package/src/tools/Mermaid/index.tsx +0 -41
  109. package/src/tools/Mermaid/utils/mermaid-helpers.ts +0 -33
  110. package/src/tools/OpenapiViewer/components/EndpointInfo.tsx +0 -149
  111. package/src/tools/OpenapiViewer/components/EndpointsLibrary.tsx +0 -263
  112. package/src/tools/OpenapiViewer/components/PlaygroundLayout.tsx +0 -125
  113. package/src/tools/OpenapiViewer/components/PlaygroundStepper.tsx +0 -100
  114. package/src/tools/OpenapiViewer/components/RequestBuilder.tsx +0 -157
  115. package/src/tools/OpenapiViewer/components/RequestParametersForm.tsx +0 -253
  116. package/src/tools/OpenapiViewer/components/ResponseViewer.tsx +0 -173
  117. package/src/tools/OpenapiViewer/components/VersionSelector.tsx +0 -68
  118. package/src/tools/OpenapiViewer/components/index.ts +0 -14
  119. package/src/tools/OpenapiViewer/constants.ts +0 -39
  120. package/src/tools/OpenapiViewer/context/PlaygroundContext.tsx +0 -337
  121. package/src/tools/OpenapiViewer/hooks/index.ts +0 -8
  122. package/src/tools/OpenapiViewer/hooks/useMobile.ts +0 -10
  123. package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +0 -199
  124. package/src/tools/OpenapiViewer/index.tsx +0 -38
  125. package/src/tools/OpenapiViewer/types.ts +0 -151
  126. package/src/tools/OpenapiViewer/utils/apiKeyManager.ts +0 -149
  127. package/src/tools/OpenapiViewer/utils/formatters.ts +0 -71
  128. package/src/tools/OpenapiViewer/utils/index.ts +0 -9
  129. package/src/tools/OpenapiViewer/utils/versionManager.ts +0 -161
  130. package/src/tools/PrettyCode/PrettyCode.client.tsx +0 -208
  131. package/src/tools/PrettyCode/index.tsx +0 -45
  132. package/src/tools/VideoPlayer/@refactoring/00-PLAN.md +0 -91
  133. package/src/tools/VideoPlayer/@refactoring/01-TYPES.md +0 -284
  134. package/src/tools/VideoPlayer/@refactoring/02-UTILS.md +0 -141
  135. package/src/tools/VideoPlayer/@refactoring/03-HOOKS.md +0 -178
  136. package/src/tools/VideoPlayer/@refactoring/04-COMPONENTS.md +0 -95
  137. package/src/tools/VideoPlayer/@refactoring/05-EXECUTION-CHECKLIST.md +0 -139
  138. package/src/tools/VideoPlayer/README.md +0 -264
  139. package/src/tools/VideoPlayer/components/VideoControls.tsx +0 -138
  140. package/src/tools/VideoPlayer/components/VideoErrorFallback.tsx +0 -174
  141. package/src/tools/VideoPlayer/components/VideoPlayer.tsx +0 -201
  142. package/src/tools/VideoPlayer/components/index.ts +0 -14
  143. package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +0 -52
  144. package/src/tools/VideoPlayer/context/index.ts +0 -8
  145. package/src/tools/VideoPlayer/hooks/index.ts +0 -12
  146. package/src/tools/VideoPlayer/hooks/useVideoPlayerSettings.ts +0 -70
  147. package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +0 -116
  148. package/src/tools/VideoPlayer/index.ts +0 -77
  149. package/src/tools/VideoPlayer/providers/NativeProvider.tsx +0 -284
  150. package/src/tools/VideoPlayer/providers/StreamProvider.tsx +0 -505
  151. package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +0 -400
  152. package/src/tools/VideoPlayer/providers/index.ts +0 -8
  153. package/src/tools/VideoPlayer/types/index.ts +0 -38
  154. package/src/tools/VideoPlayer/types/player.ts +0 -116
  155. package/src/tools/VideoPlayer/types/provider.ts +0 -93
  156. package/src/tools/VideoPlayer/types/sources.ts +0 -97
  157. package/src/tools/VideoPlayer/utils/debug.ts +0 -14
  158. package/src/tools/VideoPlayer/utils/fileSource.ts +0 -78
  159. package/src/tools/VideoPlayer/utils/index.ts +0 -12
  160. package/src/tools/VideoPlayer/utils/resolvers.ts +0 -75
  161. package/src/tools/index.ts +0 -170
@@ -1,337 +0,0 @@
1
- 'use client';
2
-
3
- import consola from 'consola';
4
- import React, {
5
- createContext, ReactNode, useCallback, useContext, useEffect, useState
6
- } from 'react';
7
-
8
- import type {
9
- ApiEndpoint, ApiResponse, PlaygroundConfig, PlaygroundContextType, PlaygroundState,
10
- PlaygroundStep
11
- } from '../types';
12
- import { parseRequestHeaders, substituteUrlParameters } from '../utils';
13
- import { getDefaultVersion } from '../utils/versionManager';
14
-
15
- const createInitialState = (): PlaygroundState => ({
16
- // Step management
17
- currentStep: 'endpoints',
18
- steps: ['endpoints', 'request', 'response'],
19
-
20
- // Endpoint selection
21
- selectedEndpoint: null,
22
- selectedCategory: 'All',
23
- searchTerm: '',
24
- selectedVersion: getDefaultVersion().id,
25
-
26
- // Request configuration
27
- requestUrl: '',
28
- requestMethod: 'GET',
29
- requestHeaders: '{\n "Content-Type": "application/json"\n}',
30
- requestBody: '',
31
- selectedApiKey: null,
32
- manualApiToken: '',
33
- parameters: {},
34
-
35
- // Response
36
- response: null,
37
- loading: false,
38
-
39
- // UI state
40
- sidebarOpen: false,
41
- });
42
-
43
- const PlaygroundContext = createContext<PlaygroundContextType | undefined>(undefined);
44
-
45
- export const usePlaygroundContext = () => {
46
- const context = useContext(PlaygroundContext);
47
- if (!context) {
48
- throw new Error('usePlaygroundContext must be used within a PlaygroundProvider');
49
- }
50
- return context;
51
- };
52
-
53
- interface PlaygroundProviderProps {
54
- children: ReactNode;
55
- config: PlaygroundConfig;
56
- }
57
-
58
- export const PlaygroundProvider: React.FC<PlaygroundProviderProps> = ({ children, config }) => {
59
- const [state, setState] = useState<PlaygroundState>(() => createInitialState());
60
-
61
- // TODO: Get API keys from CFG context - temporarily disabled
62
- // const { apiKeys: apiKeysResponse, isLoadingApiKeys } = useApiKeysContext();
63
- // const apiKeys = (apiKeysResponse && apiKeysResponse.results) ? apiKeysResponse.results : [];
64
- const apiKeys = React.useMemo(() => [], []);
65
- const isLoadingApiKeys = false;
66
-
67
- const updateState = (updates: Partial<PlaygroundState>) => {
68
- setState((prev) => ({ ...prev, ...updates }));
69
- };
70
-
71
- // Auto-select first API key when available
72
- useEffect(() => {
73
- if (!isLoadingApiKeys && apiKeys.length > 0 && !state.selectedApiKey) {
74
- updateState({ selectedApiKey: apiKeys[0]?.id || null });
75
- }
76
- }, [apiKeys, isLoadingApiKeys, state.selectedApiKey]);
77
-
78
- // Update headers when API key changes
79
- useEffect(() => {
80
- try {
81
- setState(prev => {
82
- const headers = parseRequestHeaders(prev.requestHeaders);
83
- let hasChanged = false;
84
-
85
- if (prev.selectedApiKey) {
86
- const apiKey = apiKeys.find(k => k.id === prev.selectedApiKey);
87
-
88
- if (apiKey) {
89
- // Add API key to headers only if it changed
90
- if (headers['X-API-Key'] !== apiKey.id) {
91
- headers['X-API-Key'] = apiKey.id;
92
- hasChanged = true;
93
- }
94
- } else {
95
- // Selected API key no longer exists, clear selection
96
- return { ...prev, selectedApiKey: null };
97
- }
98
- } else {
99
- // Remove API key from headers if no key is selected
100
- if (headers['X-API-Key']) {
101
- delete headers['X-API-Key'];
102
- hasChanged = true;
103
- }
104
- }
105
-
106
- // Only update if headers actually changed
107
- if (hasChanged) {
108
- const updatedHeaders = JSON.stringify(headers, null, 2);
109
- return { ...prev, requestHeaders: updatedHeaders };
110
- }
111
-
112
- return prev;
113
- });
114
- } catch (error) {
115
- consola.error('Error updating headers:', error);
116
- }
117
- }, [state.selectedApiKey, apiKeys]); // Removed state.requestHeaders dependency
118
-
119
- // Update URL when parameters change
120
- useEffect(() => {
121
- if (state.selectedEndpoint && state.parameters) {
122
- // Path is already a full URL from the endpoint
123
- const updatedUrl = substituteUrlParameters(state.selectedEndpoint.path, state.parameters);
124
-
125
- // Only update if URL actually changed to avoid infinite loop
126
- if (updatedUrl !== state.requestUrl) {
127
- updateState({ requestUrl: updatedUrl });
128
- }
129
- }
130
- }, [state.parameters, state.selectedEndpoint, state.requestUrl]);
131
-
132
- // Step management
133
- const setCurrentStep = (step: PlaygroundStep) => {
134
- updateState({ currentStep: step });
135
- };
136
-
137
- const goToNextStep = () => {
138
- const currentIndex = state.steps.indexOf(state.currentStep);
139
- if (currentIndex < state.steps.length - 1) {
140
- updateState({ currentStep: state.steps[currentIndex + 1] });
141
- }
142
- };
143
-
144
- const goToPreviousStep = () => {
145
- const currentIndex = state.steps.indexOf(state.currentStep);
146
- if (currentIndex > 0) {
147
- updateState({ currentStep: state.steps[currentIndex - 1] });
148
- }
149
- };
150
-
151
- // Endpoint management
152
- const setSelectedEndpoint = (endpoint: ApiEndpoint | null) => {
153
- if (endpoint) {
154
- // All endpoints are GET only
155
- // Path is already a full URL from the endpoint
156
- updateState({
157
- selectedEndpoint: endpoint,
158
- requestMethod: 'GET',
159
- requestUrl: endpoint.path,
160
- parameters: {}, // Reset parameters when endpoint changes
161
- currentStep: 'request'
162
- });
163
- } else {
164
- updateState({ selectedEndpoint: endpoint });
165
- }
166
- };
167
-
168
- const setSelectedCategory = (category: string) => {
169
- updateState({ selectedCategory: category });
170
- };
171
-
172
- const setSearchTerm = (term: string) => {
173
- updateState({ searchTerm: term });
174
- };
175
-
176
- const setSelectedVersion = (version: string) => {
177
- updateState({ selectedVersion: version });
178
- };
179
-
180
- // Request management
181
- const setRequestUrl = (url: string) => {
182
- updateState({ requestUrl: url });
183
- };
184
-
185
- const setRequestMethod = (method: string) => {
186
- updateState({ requestMethod: method });
187
- };
188
-
189
- const setRequestHeaders = (headers: string) => {
190
- updateState({ requestHeaders: headers });
191
- };
192
-
193
- const setRequestBody = (body: string) => {
194
- updateState({ requestBody: body });
195
- };
196
-
197
- const setSelectedApiKey = (apiKeyId: string | null) => {
198
- updateState({ selectedApiKey: apiKeyId });
199
- };
200
-
201
- const setManualApiToken = (manualApiToken: string) => {
202
- updateState({ manualApiToken });
203
- };
204
-
205
- const setParameters = (parameters: Record<string, string>) => {
206
- updateState({ parameters });
207
- };
208
-
209
- // Response management
210
- const setResponse = (response: ApiResponse | null) => {
211
- updateState({ response });
212
- };
213
-
214
- const setLoading = (loading: boolean) => {
215
- updateState({ loading });
216
- };
217
-
218
- // UI management
219
- const setSidebarOpen = (sidebarOpen: boolean) => {
220
- updateState({ sidebarOpen });
221
- };
222
-
223
- // Actions
224
- const clearAll = useCallback(() => {
225
- setState(createInitialState());
226
- }, []);
227
-
228
- const sendRequest = useCallback(async () => {
229
- if (!state.requestUrl) {
230
- consola.error('No URL provided');
231
- return;
232
- }
233
-
234
- setLoading(true);
235
- setResponse(null);
236
-
237
- try {
238
- const headers = parseRequestHeaders(state.requestHeaders);
239
-
240
- // Bearer token priority: manual token → JWT token from localStorage
241
- let bearerToken: string | null = null;
242
-
243
- if (state.manualApiToken) {
244
- // Use manual token if provided
245
- bearerToken = state.manualApiToken;
246
- } else {
247
- // Try to get JWT token from localStorage
248
- if (typeof window !== 'undefined') {
249
- bearerToken = window.localStorage.getItem('auth_token');
250
- }
251
- }
252
-
253
- if (bearerToken) {
254
- headers['Authorization'] = `Bearer ${bearerToken}`;
255
- }
256
-
257
- const requestOptions: RequestInit = {
258
- method: state.requestMethod,
259
- headers,
260
- };
261
-
262
- if (state.requestBody && state.requestMethod !== 'GET') {
263
- requestOptions.body = state.requestBody;
264
- }
265
-
266
- const response = await fetch(state.requestUrl, requestOptions);
267
- const responseText = await response.text();
268
-
269
- let responseData;
270
- try {
271
- responseData = JSON.parse(responseText);
272
- } catch {
273
- responseData = responseText;
274
- }
275
-
276
- setResponse({
277
- status: response.status,
278
- statusText: response.statusText,
279
- headers: Object.fromEntries(response.headers.entries()),
280
- data: responseData,
281
- });
282
-
283
- consola.success(`Request successful: ${state.requestMethod} ${state.requestUrl}`);
284
-
285
- // Auto-advance to response step
286
- updateState({ currentStep: 'response' });
287
- } catch (error) {
288
- consola.error('Request failed:', error);
289
- setResponse({
290
- error: error instanceof Error ? error.message : 'Request failed',
291
- });
292
- } finally {
293
- setLoading(false);
294
- }
295
- }, [state, setLoading, setResponse]);
296
-
297
- const contextValue: PlaygroundContextType = {
298
- // State
299
- state,
300
- config,
301
- apiKeys,
302
- apiKeysLoading: isLoadingApiKeys,
303
-
304
- // Step management
305
- setCurrentStep,
306
- goToNextStep,
307
- goToPreviousStep,
308
-
309
- // Endpoint management
310
- setSelectedEndpoint,
311
- setSelectedCategory,
312
- setSearchTerm,
313
- setSelectedVersion,
314
-
315
- // Request management
316
- setRequestUrl,
317
- setRequestMethod,
318
- setRequestHeaders,
319
- setRequestBody,
320
- setSelectedApiKey,
321
- setManualApiToken,
322
- setParameters,
323
-
324
- // Response management
325
- setResponse,
326
- setLoading,
327
-
328
- // UI management
329
- setSidebarOpen,
330
-
331
- // Actions
332
- clearAll,
333
- sendRequest,
334
- };
335
-
336
- return <PlaygroundContext.Provider value={contextValue}>{children}</PlaygroundContext.Provider>;
337
- };
@@ -1,8 +0,0 @@
1
- /**
2
- * Playground Hooks
3
- *
4
- * Centralized exports for all playground hooks
5
- */
6
-
7
- export { default as useOpenApiSchema } from './useOpenApiSchema';
8
- export { useMobile } from './useMobile';
@@ -1,10 +0,0 @@
1
- import { useIsMobile } from '@djangocfg/ui-core/hooks';
2
-
3
- export const useMobile = () => {
4
- const isMobile = useIsMobile();
5
-
6
- return {
7
- isMobile,
8
- isDesktop: !isMobile,
9
- };
10
- };
@@ -1,199 +0,0 @@
1
- 'use client';
2
-
3
- import consola from 'consola';
4
- import { useCallback, useEffect, useMemo, useState } from 'react';
5
-
6
- import { ApiEndpoint, OpenApiSchema, SchemaSource, UseOpenApiSchemaReturn } from '../types';
7
-
8
- // Extract endpoints from OpenAPI schema (GET only)
9
- const extractEndpoints = (schema: OpenApiSchema): ApiEndpoint[] => {
10
- const endpointMap = new Map<string, ApiEndpoint>();
11
-
12
- if (!schema.paths) return [];
13
-
14
- // Get base URL from servers
15
- const baseUrl = schema.servers && schema.servers.length > 0 ? schema.servers[0].url : '';
16
-
17
- for (const [path, methods] of Object.entries(schema.paths)) {
18
- // Only process GET methods
19
- const getOperation = (methods as any).get;
20
- if (!getOperation) continue;
21
-
22
- const op = getOperation as any;
23
- const description = op.description || op.summary || `GET ${path}`;
24
- const category = op.tags?.[0] || 'Other';
25
-
26
- const parameters: Array<{
27
- name: string;
28
- type: string;
29
- required: boolean;
30
- description?: string;
31
- }> = [];
32
-
33
- // Collect parameters
34
- if (op.parameters) {
35
- for (const param of op.parameters) {
36
- parameters.push({
37
- name: param.name,
38
- type: param.schema?.type || 'string',
39
- required: param.required || false,
40
- description: param.description,
41
- });
42
- }
43
- }
44
-
45
- // Collect responses
46
- const responses: Array<{
47
- code: string;
48
- description: string;
49
- }> = [];
50
-
51
- if (op.responses) {
52
- for (const [code, response] of Object.entries(op.responses)) {
53
- responses.push({
54
- code,
55
- description: (response as any).description || `Response ${code}`,
56
- });
57
- }
58
- }
59
-
60
- // Create endpoint (GET only) with full URL
61
- const endpoint: ApiEndpoint = {
62
- name: path.split('/').pop() || path,
63
- method: 'GET',
64
- path: baseUrl + path, // Combine baseUrl with path
65
- description,
66
- category,
67
- parameters: parameters.length > 0 ? parameters : undefined,
68
- requestBody: undefined, // GET requests don't have request body
69
- responses: responses.length > 0 ? responses : undefined,
70
- };
71
-
72
- endpointMap.set(path, endpoint);
73
- }
74
-
75
- return Array.from(endpointMap.values());
76
- };
77
-
78
- // Get unique categories from endpoints
79
- const getCategories = (endpoints: ApiEndpoint[]): string[] => {
80
- const categories = new Set<string>();
81
- endpoints.forEach((endpoint) => categories.add(endpoint.category));
82
- return Array.from(categories).sort();
83
- };
84
-
85
- // Fetch schema from URL
86
- const fetchSchema = async (url: string): Promise<OpenApiSchema> => {
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
- };
97
-
98
- interface UseOpenApiSchemaProps {
99
- schemas: SchemaSource[];
100
- defaultSchemaId?: string;
101
- }
102
-
103
- export default function useOpenApiSchema({
104
- schemas,
105
- defaultSchemaId,
106
- }: UseOpenApiSchemaProps): UseOpenApiSchemaReturn {
107
- const [loading, setLoading] = useState(true);
108
- const [error, setError] = useState<string | null>(null);
109
- const [currentSchemaId, setCurrentSchemaId] = useState<string>(
110
- defaultSchemaId || schemas[0]?.id
111
- );
112
- const [loadedSchemas, setLoadedSchemas] = useState<Map<string, OpenApiSchema>>(
113
- new Map()
114
- );
115
-
116
- const currentSchema = useMemo(
117
- () => schemas.find((s) => s.id === currentSchemaId) || null,
118
- [schemas, currentSchemaId]
119
- );
120
-
121
- const currentOpenApiSchema = useMemo(
122
- () => (currentSchemaId ? loadedSchemas.get(currentSchemaId) : null),
123
- [loadedSchemas, currentSchemaId]
124
- );
125
-
126
- const endpoints = useMemo(
127
- () => (currentOpenApiSchema ? extractEndpoints(currentOpenApiSchema) : []),
128
- [currentOpenApiSchema]
129
- );
130
-
131
- const categories = useMemo(() => getCategories(endpoints), [endpoints]);
132
-
133
- // Load schema when current schema changes
134
- useEffect(() => {
135
- if (!currentSchema) return;
136
-
137
- // Skip if already loaded
138
- if (loadedSchemas.has(currentSchema.id)) {
139
- setLoading(false);
140
- return;
141
- }
142
-
143
- setLoading(true);
144
- setError(null);
145
-
146
- fetchSchema(currentSchema.url)
147
- .then((schema) => {
148
- setLoadedSchemas((prev) => new Map(prev).set(currentSchema.id, schema));
149
- consola.success(`Schema loaded: ${currentSchema.name}`);
150
- setLoading(false);
151
- })
152
- .catch((err) => {
153
- consola.error(`Error loading schema from ${currentSchema.url}:`, err);
154
- setError(err instanceof Error ? err.message : 'Failed to load schema');
155
- setLoading(false);
156
- });
157
- }, [currentSchema, loadedSchemas]);
158
-
159
- const setCurrentSchema = useCallback((schemaId: string) => {
160
- setCurrentSchemaId(schemaId);
161
- }, []);
162
-
163
- const refresh = useCallback(() => {
164
- if (!currentSchema) return;
165
-
166
- setLoading(true);
167
- setError(null);
168
-
169
- // Remove from cache to force reload
170
- setLoadedSchemas((prev) => {
171
- const next = new Map(prev);
172
- next.delete(currentSchema.id);
173
- return next;
174
- });
175
-
176
- fetchSchema(currentSchema.url)
177
- .then((schema) => {
178
- setLoadedSchemas((prev) => new Map(prev).set(currentSchema.id, schema));
179
- consola.success(`Schema refreshed: ${currentSchema.name}`);
180
- setLoading(false);
181
- })
182
- .catch((err) => {
183
- consola.error(`Error refreshing schema from ${currentSchema.url}:`, err);
184
- setError(err instanceof Error ? err.message : 'Failed to refresh schema');
185
- setLoading(false);
186
- });
187
- }, [currentSchema]);
188
-
189
- return {
190
- loading,
191
- error,
192
- endpoints,
193
- categories,
194
- schemas,
195
- currentSchema,
196
- setCurrentSchema,
197
- refresh,
198
- };
199
- }
@@ -1,38 +0,0 @@
1
- 'use client';
2
-
3
- import dynamic from 'next/dynamic';
4
- import React from 'react';
5
-
6
- import { PlaygroundProvider } from './context/PlaygroundContext';
7
-
8
- import type { PlaygroundConfig } from './types';
9
-
10
- const PlaygroundLayout = dynamic(
11
- () => import('./components/PlaygroundLayout').then((mod) => ({ default: mod.PlaygroundLayout })),
12
- {
13
- ssr: false,
14
- loading: () => (
15
- <div className="flex items-center justify-center min-h-[400px]">
16
- <div className="text-muted-foreground">Loading API Playground...</div>
17
- </div>
18
- ),
19
- }
20
- );
21
-
22
- export interface PlaygroundProps {
23
- config: PlaygroundConfig;
24
- }
25
-
26
- export const Playground: React.FC<PlaygroundProps> = ({ config }) => {
27
- return (
28
- <PlaygroundProvider config={config}>
29
- <PlaygroundLayout />
30
- </PlaygroundProvider>
31
- );
32
- };
33
-
34
- // Re-export types for convenience
35
- export type { PlaygroundConfig, SchemaSource } from './types';
36
-
37
- // Default export for dynamic import
38
- export default Playground;