@djangocfg/ui-tools 2.1.382 → 2.1.384
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ChatRoot-JVR3M3H2.mjs +5 -0
- package/dist/{ChatRoot-6IZFM5HM.mjs.map → ChatRoot-JVR3M3H2.mjs.map} +1 -1
- package/dist/ChatRoot-LXIUBOXF.cjs +14 -0
- package/dist/{ChatRoot-LW4XNIKP.cjs.map → ChatRoot-LXIUBOXF.cjs.map} +1 -1
- package/dist/DictationField-U25MEYAL.mjs +4 -0
- package/dist/{DictationField-2ZLQWLYV.mjs.map → DictationField-U25MEYAL.mjs.map} +1 -1
- package/dist/DictationField-XWR5VOID.cjs +13 -0
- package/dist/{DictationField-IPPJ54CU.cjs.map → DictationField-XWR5VOID.cjs.map} +1 -1
- package/dist/{chunk-KMSBGNVC.cjs → chunk-4PFW7MIJ.cjs} +4 -2
- package/dist/chunk-4PFW7MIJ.cjs.map +1 -0
- package/dist/{chunk-4LXG3NBV.mjs → chunk-C2YN6WEO.mjs} +3 -3
- package/dist/chunk-C2YN6WEO.mjs.map +1 -0
- package/dist/{chunk-OZAU3QWD.cjs → chunk-HPK3EWBF.cjs} +8 -8
- package/dist/chunk-HPK3EWBF.cjs.map +1 -0
- package/dist/{chunk-UWVP6LCW.mjs → chunk-PEKBT75W.mjs} +8 -8
- package/dist/chunk-PEKBT75W.mjs.map +1 -0
- package/dist/index.cjs +192 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -6
- package/dist/index.d.ts +78 -6
- package/dist/index.mjs +143 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -13
- package/src/tools/Chat/core/audio/defaults.ts +16 -11
- package/src/tools/Chat/core/audio/sounds/error.ts +3 -0
- package/src/tools/Chat/core/audio/sounds/mention.ts +3 -0
- package/src/tools/Chat/core/audio/sounds/notification.ts +3 -0
- package/src/tools/Chat/core/audio/sounds/received.ts +3 -0
- package/src/tools/Chat/core/audio/sounds/sent.ts +3 -0
- package/src/tools/Chat/core/audio/sounds/start.ts +3 -0
- package/src/tools/Chat/index.ts +15 -0
- package/src/tools/SpeechRecognition/core/audio/defaults.ts +4 -4
- package/dist/ChatRoot-6IZFM5HM.mjs +0 -5
- package/dist/ChatRoot-LW4XNIKP.cjs +0 -14
- package/dist/DictationField-2ZLQWLYV.mjs +0 -4
- package/dist/DictationField-IPPJ54CU.cjs +0 -13
- package/dist/chunk-4LXG3NBV.mjs.map +0 -1
- package/dist/chunk-KMSBGNVC.cjs.map +0 -1
- package/dist/chunk-OZAU3QWD.cjs.map +0 -1
- package/dist/chunk-UWVP6LCW.mjs.map +0 -1
- package/src/audio-assets.d.ts +0 -8
- package/src/components/markdown/MarkdownMessage/MarkdownMessage.story.tsx +0 -771
- package/src/stories/index.ts +0 -63
- package/src/tools/AudioPlayer/AudioPlayer.story.tsx +0 -481
- package/src/tools/Chat/core/audio/sounds/error.mp3 +0 -0
- package/src/tools/Chat/core/audio/sounds/mention.mp3 +0 -0
- package/src/tools/Chat/core/audio/sounds/notification.mp3 +0 -0
- package/src/tools/Chat/core/audio/sounds/received.mp3 +0 -0
- package/src/tools/Chat/core/audio/sounds/sent.mp3 +0 -0
- package/src/tools/Chat/core/audio/sounds/start.mp3 +0 -0
- package/src/tools/Chat/stories/01-basic.story.tsx +0 -64
- package/src/tools/Chat/stories/02-bubbles.story.tsx +0 -21
- package/src/tools/Chat/stories/03-tool-calls.story.tsx +0 -59
- package/src/tools/Chat/stories/04-personas.story.tsx +0 -78
- package/src/tools/Chat/stories/05-launcher.story.tsx +0 -321
- package/src/tools/Chat/stories/06-header.story.tsx +0 -147
- package/src/tools/Chat/stories/07-audio-actions.story.tsx +0 -112
- package/src/tools/Chat/stories/shared/Frame.tsx +0 -21
- package/src/tools/Chat/stories/shared/index.ts +0 -5
- package/src/tools/Chat/stories/shared/messages.ts +0 -39
- package/src/tools/Chat/stories/shared/personas.ts +0 -13
- package/src/tools/Chat/stories/shared/seeds.ts +0 -92
- package/src/tools/Chat/stories/shared/transports.ts +0 -36
- package/src/tools/CodeEditor/CodeEditor.story.tsx +0 -202
- package/src/tools/CronScheduler/CronScheduler.story.tsx +0 -300
- package/src/tools/Gallery/Gallery.story.tsx +0 -237
- package/src/tools/ImageViewer/ImageViewer.story.tsx +0 -85
- package/src/tools/JsonForm/JsonForm.story.tsx +0 -350
- package/src/tools/JsonTree/JsonTree.story.tsx +0 -141
- package/src/tools/LottiePlayer/LottiePlayer.story.tsx +0 -95
- package/src/tools/Map/Map.story.tsx +0 -458
- package/src/tools/MarkdownEditor/MarkdownEditor.story.tsx +0 -225
- package/src/tools/Mermaid/Mermaid.story.tsx +0 -251
- package/src/tools/OpenapiViewer/OpenapiViewer.story.tsx +0 -230
- package/src/tools/PrettyCode/PrettyCode.story.tsx +0 -304
- package/src/tools/SpeechRecognition/stories/01-basic.story.tsx +0 -32
- package/src/tools/SpeechRecognition/stories/02-dictation-field.story.tsx +0 -32
- package/src/tools/SpeechRecognition/stories/03-push-to-talk.story.tsx +0 -27
- package/src/tools/SpeechRecognition/stories/04-mic-meter.story.tsx +0 -35
- package/src/tools/SpeechRecognition/stories/05-custom-engine-http.story.tsx +0 -40
- package/src/tools/SpeechRecognition/stories/06-custom-engine-ws.story.tsx +0 -48
- package/src/tools/SpeechRecognition/stories/07-language-device.story.tsx +0 -57
- package/src/tools/SpeechRecognition/stories/08-errors-permissions.story.tsx +0 -25
- package/src/tools/SpeechRecognition/stories/09-chat-voice.story.tsx +0 -90
- package/src/tools/SpeechRecognition/stories/shared.tsx +0 -123
- package/src/tools/Tour/Tour.story.tsx +0 -279
- package/src/tools/Tree/Tree.story.tsx +0 -620
- package/src/tools/Uploader/Uploader.story.tsx +0 -415
- package/src/tools/VideoPlayer/VideoPlayer.story.tsx +0 -87
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import { defineStory, useSelect, useBoolean } from '@djangocfg/playground';
|
|
2
|
-
import Mermaid, {
|
|
3
|
-
FlowDiagram,
|
|
4
|
-
SequenceDiagram,
|
|
5
|
-
JourneyDiagram,
|
|
6
|
-
useStylePresets,
|
|
7
|
-
useBoxColors,
|
|
8
|
-
} from './index';
|
|
9
|
-
|
|
10
|
-
export default defineStory({
|
|
11
|
-
title: 'Tools/Mermaid',
|
|
12
|
-
component: Mermaid,
|
|
13
|
-
description: 'Mermaid diagram renderer with declarative type-safe builders.',
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
// ============================================================================
|
|
17
|
-
// Diagram Generators
|
|
18
|
-
// ============================================================================
|
|
19
|
-
|
|
20
|
-
function useFlowDiagram() {
|
|
21
|
-
type Nodes = 'start' | 'check' | 'success' | 'debug' | 'finish';
|
|
22
|
-
const flow = FlowDiagram<Nodes>({ direction: 'TB' });
|
|
23
|
-
const presets = useStylePresets();
|
|
24
|
-
|
|
25
|
-
flow.node('start').rect('Start');
|
|
26
|
-
flow.node('check').rhombus('Is it working?');
|
|
27
|
-
flow.node('success').rect('Great!');
|
|
28
|
-
flow.node('debug').rect('Debug');
|
|
29
|
-
flow.node('finish').stadium('End');
|
|
30
|
-
|
|
31
|
-
flow.edge('start').to('check').solid();
|
|
32
|
-
flow.edge('check').to('success').solid('Yes');
|
|
33
|
-
flow.edge('check').to('debug').solid('No');
|
|
34
|
-
flow.edge('debug').to('check').dotted();
|
|
35
|
-
flow.edge('success').to('finish').solid();
|
|
36
|
-
|
|
37
|
-
flow.style.define('success', presets.success);
|
|
38
|
-
flow.style.define('primary', presets.primary);
|
|
39
|
-
flow.style.apply('success', 'success', 'finish');
|
|
40
|
-
flow.style.apply('primary', 'start');
|
|
41
|
-
|
|
42
|
-
return flow.toString();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function useSequenceDiagram() {
|
|
46
|
-
const boxes = useBoxColors();
|
|
47
|
-
|
|
48
|
-
const { d, rect, alt, loop, blank, toString } = SequenceDiagram({
|
|
49
|
-
User: 'actor',
|
|
50
|
-
App: 'participant',
|
|
51
|
-
Auth: 'participant',
|
|
52
|
-
DB: 'participant',
|
|
53
|
-
}, { autoNumber: true });
|
|
54
|
-
|
|
55
|
-
rect(boxes.primary, () => {
|
|
56
|
-
d.User.sync.App.msg('Enter credentials');
|
|
57
|
-
d.App.sync.Auth.msg('Validate credentials');
|
|
58
|
-
|
|
59
|
-
alt('Valid credentials', () => {
|
|
60
|
-
d.Auth.sync.DB.msg('Get user profile');
|
|
61
|
-
d.DB.syncReply.Auth.msg('Profile data');
|
|
62
|
-
d.Auth.syncReply.App.msg('Auth token');
|
|
63
|
-
d.App.syncReply.User.msg('Welcome!');
|
|
64
|
-
}).else('Invalid credentials', () => {
|
|
65
|
-
d.Auth.syncReply.App.msg('Auth failed');
|
|
66
|
-
d.App.syncReply.User.msg('Error message');
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
blank();
|
|
71
|
-
|
|
72
|
-
loop('Every 15 minutes', () => {
|
|
73
|
-
d.App.async.Auth.msg('Refresh token');
|
|
74
|
-
d.Auth.asyncReply.App.msg('New token');
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
return toString();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function useJourneyDiagram() {
|
|
81
|
-
const journey = JourneyDiagram({ title: 'User Onboarding' });
|
|
82
|
-
|
|
83
|
-
journey.section('Discovery')
|
|
84
|
-
.task('Visit landing page', 5, 'User')
|
|
85
|
-
.task('Read features', 4, 'User');
|
|
86
|
-
|
|
87
|
-
journey.section('Sign Up')
|
|
88
|
-
.task('Click Sign Up', 5, 'User')
|
|
89
|
-
.task('Fill form', 2, 'User')
|
|
90
|
-
.task('Verify email', 4, ['User', 'System']);
|
|
91
|
-
|
|
92
|
-
journey.section('Onboarding')
|
|
93
|
-
.task('Complete profile', 3, 'User')
|
|
94
|
-
.task('Create first project', 5, 'User');
|
|
95
|
-
|
|
96
|
-
return journey.toString();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Example using dynamic methods for runtime participant names
|
|
101
|
-
* Useful when participants are not known at compile time
|
|
102
|
-
*/
|
|
103
|
-
function useDynamicSequenceDiagram() {
|
|
104
|
-
const boxes = useBoxColors();
|
|
105
|
-
|
|
106
|
-
// Participants from dynamic data (e.g., from API)
|
|
107
|
-
const participants = ['Alice', 'Bob', 'Charlie'];
|
|
108
|
-
const participantsObj: Record<string, 'participant'> = {};
|
|
109
|
-
participants.forEach(p => { participantsObj[p] = 'participant'; });
|
|
110
|
-
|
|
111
|
-
const seq = SequenceDiagram(participantsObj, { autoNumber: true });
|
|
112
|
-
|
|
113
|
-
// Using dynamic methods - no type assertions needed
|
|
114
|
-
seq.rect(boxes.primary, () => {
|
|
115
|
-
seq.noteOver('Alice', 'Starting conversation');
|
|
116
|
-
seq.message('Alice', 'Bob', 'Hello Bob!');
|
|
117
|
-
seq.message('Bob', 'Alice', 'Hi Alice!', 'syncReply');
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
seq.blank();
|
|
121
|
-
|
|
122
|
-
seq.rect(boxes.success, () => {
|
|
123
|
-
seq.noteOverSpan('Alice', 'Charlie', 'Group discussion');
|
|
124
|
-
seq.message('Alice', 'Charlie', 'Hey Charlie!');
|
|
125
|
-
seq.message('Charlie', 'Bob', 'Bob, join us!');
|
|
126
|
-
seq.message('Bob', 'Charlie', 'On my way!', 'async');
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
return seq.toString();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function useArchitectureDiagram() {
|
|
133
|
-
type Nodes = 'client' | 'nginx' | 'api1' | 'api2' | 'db' | 'cache' | 'queue';
|
|
134
|
-
const flow = FlowDiagram<Nodes>({ direction: 'TB' });
|
|
135
|
-
const presets = useStylePresets();
|
|
136
|
-
|
|
137
|
-
flow.subgraph('Frontend', (sub) => {
|
|
138
|
-
sub.direction('LR');
|
|
139
|
-
sub.node('client').round('Browser');
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
flow.subgraph('Load Balancer', (sub) => {
|
|
143
|
-
sub.node('nginx').hexagon('Nginx');
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
flow.subgraph('API Servers', (sub) => {
|
|
147
|
-
sub.direction('LR');
|
|
148
|
-
sub.node('api1').rect('API Server 1');
|
|
149
|
-
sub.node('api2').rect('API Server 2');
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
flow.subgraph('Data Layer', (sub) => {
|
|
153
|
-
sub.direction('LR');
|
|
154
|
-
sub.node('db').cylinder('PostgreSQL');
|
|
155
|
-
sub.node('cache').cylinder('Redis');
|
|
156
|
-
sub.node('queue').cylinder('RabbitMQ');
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
flow.edge('client').to('nginx').solid();
|
|
160
|
-
flow.edge('nginx').to('api1').solid();
|
|
161
|
-
flow.edge('nginx').to('api2').solid();
|
|
162
|
-
flow.edge('api1').to('db').solid();
|
|
163
|
-
flow.edge('api2').to('db').solid();
|
|
164
|
-
flow.edge('api1').to('cache').dotted();
|
|
165
|
-
flow.edge('api2').to('cache').dotted();
|
|
166
|
-
flow.edge('api1').to('queue').dotted();
|
|
167
|
-
|
|
168
|
-
flow.style.define('frontend', presets.info);
|
|
169
|
-
flow.style.define('backend', presets.success);
|
|
170
|
-
flow.style.define('data', presets.warning);
|
|
171
|
-
flow.style.apply('frontend', 'client', 'nginx');
|
|
172
|
-
flow.style.apply('backend', 'api1', 'api2');
|
|
173
|
-
flow.style.apply('data', 'db', 'cache', 'queue');
|
|
174
|
-
|
|
175
|
-
return flow.toString();
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// ============================================================================
|
|
179
|
-
// Stories
|
|
180
|
-
// ============================================================================
|
|
181
|
-
|
|
182
|
-
export const Interactive = () => {
|
|
183
|
-
const [diagramType] = useSelect('diagramType', {
|
|
184
|
-
options: ['flow', 'sequence', 'sequenceDynamic', 'journey', 'architecture'] as const,
|
|
185
|
-
defaultValue: 'flow',
|
|
186
|
-
label: 'Diagram Type',
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
const [fullscreen] = useBoolean('fullscreen', {
|
|
190
|
-
defaultValue: false,
|
|
191
|
-
label: 'Enable Fullscreen',
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
const flowChart = useFlowDiagram();
|
|
195
|
-
const sequenceChart = useSequenceDiagram();
|
|
196
|
-
const sequenceDynamicChart = useDynamicSequenceDiagram();
|
|
197
|
-
const journeyChart = useJourneyDiagram();
|
|
198
|
-
const architectureChart = useArchitectureDiagram();
|
|
199
|
-
|
|
200
|
-
const charts = {
|
|
201
|
-
flow: flowChart,
|
|
202
|
-
sequence: sequenceChart,
|
|
203
|
-
sequenceDynamic: sequenceDynamicChart,
|
|
204
|
-
journey: journeyChart,
|
|
205
|
-
architecture: architectureChart,
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
const chart = charts[diagramType];
|
|
209
|
-
|
|
210
|
-
return (
|
|
211
|
-
<div className="space-y-4">
|
|
212
|
-
<Mermaid chart={chart} fullscreen={fullscreen} />
|
|
213
|
-
<details className="text-xs">
|
|
214
|
-
<summary className="cursor-pointer text-muted-foreground">Generated Mermaid code</summary>
|
|
215
|
-
<pre className="mt-2 p-3 bg-muted rounded overflow-auto">{chart}</pre>
|
|
216
|
-
</details>
|
|
217
|
-
</div>
|
|
218
|
-
);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
export const Flow = () => {
|
|
222
|
-
const chart = useFlowDiagram();
|
|
223
|
-
return <Mermaid chart={chart} />;
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
export const Sequence = () => {
|
|
227
|
-
const chart = useSequenceDiagram();
|
|
228
|
-
return <Mermaid chart={chart} />;
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
export const Journey = () => {
|
|
232
|
-
const chart = useJourneyDiagram();
|
|
233
|
-
return <Mermaid chart={chart} />;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
export const Architecture = () => {
|
|
237
|
-
const chart = useArchitectureDiagram();
|
|
238
|
-
return <Mermaid chart={chart} />;
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
export const WithFullscreen = () => {
|
|
242
|
-
const chart = useFlowDiagram();
|
|
243
|
-
return (
|
|
244
|
-
<div className="space-y-2">
|
|
245
|
-
<p className="text-sm text-muted-foreground">
|
|
246
|
-
Click the expand button to open fullscreen
|
|
247
|
-
</p>
|
|
248
|
-
<Mermaid chart={chart} fullscreen />
|
|
249
|
-
</div>
|
|
250
|
-
);
|
|
251
|
-
};
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import { defineStory, useSelect, useValue, useBoolean } from '@djangocfg/playground';
|
|
2
|
-
import { Playground } from './index';
|
|
3
|
-
import { LazyOpenapiViewer } from './lazy';
|
|
4
|
-
import type { PlaygroundConfig } from './types';
|
|
5
|
-
|
|
6
|
-
export default defineStory({
|
|
7
|
-
title: 'Tools/OpenapiViewer',
|
|
8
|
-
component: Playground,
|
|
9
|
-
description:
|
|
10
|
-
'Interactive OpenAPI schema viewer. Sidebar + docs longread with a slide-in two-column playground (Request + Response) when an endpoint is selected.',
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
// ============================================================================
|
|
14
|
-
// Schema fixtures
|
|
15
|
-
// ============================================================================
|
|
16
|
-
|
|
17
|
-
// Petstore's own ``servers[0].url`` is just ``/api/v3`` (relative),
|
|
18
|
-
// which makes code samples look like they target ``localhost`` when
|
|
19
|
-
// viewed from the playground. Override with the canonical public host
|
|
20
|
-
// so the generated curl/fetch/etc snippets are runnable as-is.
|
|
21
|
-
const PETSTORE_SCHEMA = {
|
|
22
|
-
id: 'petstore',
|
|
23
|
-
name: 'Petstore API',
|
|
24
|
-
url: 'https://petstore3.swagger.io/api/v3/openapi.json',
|
|
25
|
-
baseUrl: 'https://petstore3.swagger.io/api/v3',
|
|
26
|
-
} as const;
|
|
27
|
-
|
|
28
|
-
const HTTPBIN_SCHEMA = {
|
|
29
|
-
id: 'httpbin',
|
|
30
|
-
name: 'HTTPBin API',
|
|
31
|
-
url: 'https://httpbin.org/spec.json',
|
|
32
|
-
} as const;
|
|
33
|
-
|
|
34
|
-
const MULTI_SCHEMAS = [PETSTORE_SCHEMA, HTTPBIN_SCHEMA] as const;
|
|
35
|
-
|
|
36
|
-
// Simulates a real multi-group setup (like cmdop with 5+ API groups).
|
|
37
|
-
// All clones share the canonical Petstore host so code samples
|
|
38
|
-
// render with a real runnable URL.
|
|
39
|
-
const PETSTORE_BASE = 'https://petstore3.swagger.io/api/v3';
|
|
40
|
-
const MANY_SCHEMAS = [
|
|
41
|
-
PETSTORE_SCHEMA,
|
|
42
|
-
HTTPBIN_SCHEMA,
|
|
43
|
-
{ id: 'machines', name: 'Machines API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
|
|
44
|
-
{ id: 'terminal', name: 'Terminal API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
|
|
45
|
-
{ id: 'skills', name: 'Skills API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
|
|
46
|
-
{ id: 'system', name: 'System API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
|
|
47
|
-
{ id: 'site', name: 'Site API', url: 'https://petstore3.swagger.io/api/v3/openapi.json', baseUrl: PETSTORE_BASE },
|
|
48
|
-
] as const;
|
|
49
|
-
|
|
50
|
-
// ============================================================================
|
|
51
|
-
// Stories
|
|
52
|
-
// ============================================================================
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Default — single-schema mode with the most common configuration knobs
|
|
56
|
-
* exposed as toggles. Replaces the earlier Interactive / SingleSchema /
|
|
57
|
-
* WithBaseUrl / NoDefault / CustomUrl stories, which were all "this
|
|
58
|
-
* component with different props" variations.
|
|
59
|
-
*/
|
|
60
|
-
export const Default = () => {
|
|
61
|
-
const [schemaUrl] = useValue('schemaUrl', {
|
|
62
|
-
defaultValue: PETSTORE_SCHEMA.url,
|
|
63
|
-
label: 'Schema URL',
|
|
64
|
-
description: 'Any OpenAPI 3.x JSON endpoint',
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const [baseUrl] = useValue('baseUrl', {
|
|
68
|
-
defaultValue: '',
|
|
69
|
-
label: 'Base URL override',
|
|
70
|
-
description: 'Empty = use servers[0].url from the schema',
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
const [autoSelect] = useBoolean('autoSelectDefault', {
|
|
74
|
-
defaultValue: true,
|
|
75
|
-
label: 'Auto-select default schema',
|
|
76
|
-
description: 'When off, tests the "no defaultSchemaId" code path',
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const config: PlaygroundConfig = {
|
|
80
|
-
schemas: [{ id: 'custom', name: 'Schema', url: schemaUrl }],
|
|
81
|
-
defaultSchemaId: autoSelect ? 'custom' : undefined,
|
|
82
|
-
baseUrl: baseUrl || undefined,
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<div className="min-h-[600px]">
|
|
87
|
-
<Playground config={config} />
|
|
88
|
-
</div>
|
|
89
|
-
);
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* MultiSchema — multiple schemas with the Combobox switcher. Count
|
|
94
|
-
* is adjustable to exercise both the short-list layout and the
|
|
95
|
-
* long-list behaviour (cmdop-style setups with 7+ APIs).
|
|
96
|
-
*/
|
|
97
|
-
export const MultiSchema = () => {
|
|
98
|
-
const [count] = useSelect('count', {
|
|
99
|
-
options: ['2', '7'] as const,
|
|
100
|
-
defaultValue: '2',
|
|
101
|
-
label: 'Schema count',
|
|
102
|
-
description: '2 uses Petstore+HTTPBin; 7 stress-tests the Combobox',
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
const config: PlaygroundConfig = {
|
|
106
|
-
schemas: count === '2' ? [...MULTI_SCHEMAS] : [...MANY_SCHEMAS],
|
|
107
|
-
defaultSchemaId: 'petstore',
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<div className="min-h-[600px]">
|
|
112
|
-
<Playground config={config} />
|
|
113
|
-
</div>
|
|
114
|
-
);
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* SectionsGrouping — alternate layout: every schema's endpoints get
|
|
119
|
-
* rendered on the same page as top-level sections, with a sidebar
|
|
120
|
-
* that stacks them. URL hash sync writes ``#<schemaId>/<anchor>``
|
|
121
|
-
* as the user scrolls so deep-linking keeps working.
|
|
122
|
-
*/
|
|
123
|
-
export const SectionsGrouping = () => {
|
|
124
|
-
const [urlSync] = useBoolean('urlSync', {
|
|
125
|
-
defaultValue: true,
|
|
126
|
-
label: 'URL hash sync',
|
|
127
|
-
description: 'Writes #<schemaId>/<anchor> as you scroll',
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const config: PlaygroundConfig = {
|
|
131
|
-
schemas: [...MULTI_SCHEMAS],
|
|
132
|
-
defaultSchemaId: 'petstore',
|
|
133
|
-
schemaGrouping: 'sections',
|
|
134
|
-
urlSync,
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
return (
|
|
138
|
-
<div className="min-h-[600px]">
|
|
139
|
-
<Playground config={config} />
|
|
140
|
-
</div>
|
|
141
|
-
);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Errors — consolidated failure paths. Pick a scenario via the toggle:
|
|
146
|
-
* - ``broken``: single schema that 404s → full-panel error state.
|
|
147
|
-
* - ``mixed``: valid + broken side-by-side → tests switching between.
|
|
148
|
-
* - ``empty``: no schemas configured at all → empty-state UI.
|
|
149
|
-
*/
|
|
150
|
-
export const Errors = () => {
|
|
151
|
-
const [scenario] = useSelect('scenario', {
|
|
152
|
-
options: ['broken', 'mixed', 'empty'] as const,
|
|
153
|
-
defaultValue: 'broken',
|
|
154
|
-
label: 'Failure scenario',
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
const config: PlaygroundConfig = (() => {
|
|
158
|
-
switch (scenario) {
|
|
159
|
-
case 'broken':
|
|
160
|
-
return {
|
|
161
|
-
schemas: [{ id: 'broken', name: 'Broken API', url: 'https://httpbin.org/status/404' }],
|
|
162
|
-
defaultSchemaId: 'broken',
|
|
163
|
-
};
|
|
164
|
-
case 'mixed':
|
|
165
|
-
return {
|
|
166
|
-
schemas: [
|
|
167
|
-
PETSTORE_SCHEMA,
|
|
168
|
-
{ id: 'broken', name: 'Broken API (404)', url: 'https://httpbin.org/status/404' },
|
|
169
|
-
],
|
|
170
|
-
defaultSchemaId: 'petstore',
|
|
171
|
-
};
|
|
172
|
-
case 'empty':
|
|
173
|
-
return { schemas: [] };
|
|
174
|
-
}
|
|
175
|
-
})();
|
|
176
|
-
|
|
177
|
-
return (
|
|
178
|
-
<div className="min-h-[600px]">
|
|
179
|
-
<Playground config={config} />
|
|
180
|
-
</div>
|
|
181
|
-
);
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* UnfilledPathParams — regression guard for the ``%7Bid%7D`` bug.
|
|
186
|
-
*
|
|
187
|
-
* When a path template like ``/pet/{petId}`` is rendered before the
|
|
188
|
-
* user types a value, the path stays a template — not a percent-
|
|
189
|
-
* encoded string. Previously the URL parser turned ``{`` / ``}`` into
|
|
190
|
-
* ``%7B`` / ``%7D``, and the same encoded form leaked into every
|
|
191
|
-
* generated code sample (curl, axios, python, …) via the HAR
|
|
192
|
-
* intermediate.
|
|
193
|
-
*
|
|
194
|
-
* To verify visually:
|
|
195
|
-
* 1. Open any endpoint with a path param, e.g. ``GET /pet/{petId}``,
|
|
196
|
-
* ``GET /store/order/{orderId}``, or ``GET /user/{username}``.
|
|
197
|
-
* 2. Without filling the parameter, look at the header path and
|
|
198
|
-
* every Code Samples tab.
|
|
199
|
-
* 3. All occurrences must read ``{petId}``, never ``%7BpetId%7D``.
|
|
200
|
-
*/
|
|
201
|
-
export const UnfilledPathParams = () => {
|
|
202
|
-
const config: PlaygroundConfig = {
|
|
203
|
-
schemas: [PETSTORE_SCHEMA],
|
|
204
|
-
defaultSchemaId: 'petstore',
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
return (
|
|
208
|
-
<div className="min-h-[600px]">
|
|
209
|
-
<Playground config={config} />
|
|
210
|
-
</div>
|
|
211
|
-
);
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Lazy — production lazy-loaded variant. Shows the loading spinner
|
|
216
|
-
* while the ~400 KB OpenAPI viewer chunk is fetched. Only path you
|
|
217
|
-
* should use in an actual app bundle.
|
|
218
|
-
*/
|
|
219
|
-
export const Lazy = () => {
|
|
220
|
-
const config: PlaygroundConfig = {
|
|
221
|
-
schemas: [...MULTI_SCHEMAS],
|
|
222
|
-
defaultSchemaId: 'petstore',
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
return (
|
|
226
|
-
<div className="min-h-[600px]">
|
|
227
|
-
<LazyOpenapiViewer config={config} />
|
|
228
|
-
</div>
|
|
229
|
-
);
|
|
230
|
-
};
|