@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,112 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
|
|
3
|
-
import { defineStory } from '@djangocfg/playground';
|
|
4
|
-
import { DialogProvider } from '@djangocfg/ui-core/lib';
|
|
5
|
-
|
|
6
|
-
import { ChatRoot } from '../components/ChatRoot';
|
|
7
|
-
import { useChatAudio } from '../hooks/useChatAudio';
|
|
8
|
-
import { ChatDock } from '../launcher/ChatDock';
|
|
9
|
-
import { ChatHeaderAudioToggle } from '../launcher/ChatHeaderAudioToggle';
|
|
10
|
-
import { ChatHeaderResetButton } from '../launcher/ChatHeaderResetButton';
|
|
11
|
-
import { ChatLauncher } from '../launcher/ChatLauncher';
|
|
12
|
-
import { SEED_BASIC, makeBasicTransport } from './shared';
|
|
13
|
-
|
|
14
|
-
export default defineStory({
|
|
15
|
-
title: 'Tools/Chat/Audio & Actions',
|
|
16
|
-
component: ChatHeaderAudioToggle,
|
|
17
|
-
description:
|
|
18
|
-
'Header audio toggle (auto-injected when `audio` is passed) and header reset action with `window.dialog.confirm`. Wrap stories in `<DialogProvider>` so confirm prompts render.',
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// ── Audio toggle ──────────────────────────────────────────────────────────
|
|
22
|
-
|
|
23
|
-
function AudioLauncher() {
|
|
24
|
-
const transport = useMemo(() => makeBasicTransport(SEED_BASIC), []);
|
|
25
|
-
// A real notification sound — bundle your own assets in production.
|
|
26
|
-
// No `sounds` prop — uses bundled DEFAULT_CHAT_SOUNDS automatically.
|
|
27
|
-
const audio = useChatAudio();
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<ChatLauncher
|
|
31
|
-
audio={audio}
|
|
32
|
-
hotkey={{ key: '/', meta: true }}
|
|
33
|
-
fab={{ ariaLabel: 'Open chat', tooltip: 'Open chat' }}
|
|
34
|
-
dock={{ title: 'Assistant', height: 600 }}
|
|
35
|
-
>
|
|
36
|
-
<ChatRoot transport={transport} />
|
|
37
|
-
</ChatLauncher>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const AudioToggleAutoInjected = () => <AudioLauncher />;
|
|
42
|
-
|
|
43
|
-
// ── Reset with confirm ────────────────────────────────────────────────────
|
|
44
|
-
|
|
45
|
-
function ResetLauncher() {
|
|
46
|
-
const transport = useMemo(() => makeBasicTransport(SEED_BASIC), []);
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<DialogProvider>
|
|
50
|
-
<ChatLauncher
|
|
51
|
-
hotkey={{ key: '/', meta: true }}
|
|
52
|
-
fab={{ ariaLabel: 'Open chat', tooltip: 'Open chat' }}
|
|
53
|
-
dock={{
|
|
54
|
-
title: 'CRM Assistant',
|
|
55
|
-
height: 600,
|
|
56
|
-
headerActions: (
|
|
57
|
-
<ChatHeaderResetButton
|
|
58
|
-
onReset={async () => {
|
|
59
|
-
await new Promise((r) => setTimeout(r, 600));
|
|
60
|
-
return true;
|
|
61
|
-
}}
|
|
62
|
-
onSuccess={() => alert('Context cleared.')}
|
|
63
|
-
/>
|
|
64
|
-
),
|
|
65
|
-
}}
|
|
66
|
-
>
|
|
67
|
-
<ChatRoot transport={transport} />
|
|
68
|
-
</ChatLauncher>
|
|
69
|
-
</DialogProvider>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* `ChatHeaderResetButton` prompts `window.dialog.confirm` (destructive
|
|
75
|
-
* variant) before running the backend reset. `DialogProvider` from
|
|
76
|
-
* `@djangocfg/ui-core` installs that API.
|
|
77
|
-
*/
|
|
78
|
-
export const ResetWithConfirm = () => <ResetLauncher />;
|
|
79
|
-
|
|
80
|
-
// ── Both together ────────────────────────────────────────────────────────
|
|
81
|
-
|
|
82
|
-
function FullLauncher() {
|
|
83
|
-
const transport = useMemo(() => makeBasicTransport(SEED_BASIC), []);
|
|
84
|
-
// No `sounds` prop — uses bundled DEFAULT_CHAT_SOUNDS automatically.
|
|
85
|
-
const audio = useChatAudio();
|
|
86
|
-
return (
|
|
87
|
-
<DialogProvider>
|
|
88
|
-
<ChatLauncher
|
|
89
|
-
audio={audio}
|
|
90
|
-
hotkey={{ key: '/', meta: true }}
|
|
91
|
-
fab={{ ariaLabel: 'Open chat', tooltip: 'Open chat' }}
|
|
92
|
-
dock={{
|
|
93
|
-
title: 'CRM Assistant',
|
|
94
|
-
height: 600,
|
|
95
|
-
headerActions: (
|
|
96
|
-
<ChatHeaderResetButton
|
|
97
|
-
onReset={async () => {
|
|
98
|
-
await new Promise((r) => setTimeout(r, 600));
|
|
99
|
-
return true;
|
|
100
|
-
}}
|
|
101
|
-
onSuccess={() => alert('Context cleared.')}
|
|
102
|
-
/>
|
|
103
|
-
),
|
|
104
|
-
}}
|
|
105
|
-
>
|
|
106
|
-
<ChatRoot transport={transport} />
|
|
107
|
-
</ChatLauncher>
|
|
108
|
-
</DialogProvider>
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export const AudioPlusReset = () => <FullLauncher />;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
/** Fixed-size container so chat stories have a viewport to live in. */
|
|
4
|
-
export function Frame({
|
|
5
|
-
children,
|
|
6
|
-
h = 560,
|
|
7
|
-
w = 480,
|
|
8
|
-
}: {
|
|
9
|
-
children: ReactNode;
|
|
10
|
-
h?: number | string;
|
|
11
|
-
w?: number | string;
|
|
12
|
-
}) {
|
|
13
|
-
return (
|
|
14
|
-
<div
|
|
15
|
-
className="overflow-hidden rounded-lg border border-border bg-background shadow-sm"
|
|
16
|
-
style={{ height: h, width: w }}
|
|
17
|
-
>
|
|
18
|
-
{children}
|
|
19
|
-
</div>
|
|
20
|
-
);
|
|
21
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export { Frame } from './Frame';
|
|
2
|
-
export { makeBasicTransport, makeToolCallsTransport } from './transports';
|
|
3
|
-
export { BUBBLE_GALLERY } from './messages';
|
|
4
|
-
export { USER_ANNA, ASSISTANT_AURA } from './personas';
|
|
5
|
-
export { SEED_BASIC, SEED_TOOL_CALLS, SEED_JSON_PAYLOAD } from './seeds';
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { ChatMessage } from '../../types';
|
|
2
|
-
|
|
3
|
-
/** Compact transcript that exercises every bubble state for visual review. */
|
|
4
|
-
export const BUBBLE_GALLERY: ChatMessage[] = [
|
|
5
|
-
{
|
|
6
|
-
id: 'u-1',
|
|
7
|
-
role: 'user',
|
|
8
|
-
content: 'How do I add a new persona?',
|
|
9
|
-
createdAt: Date.now() - 5 * 60_000,
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
id: 'a-1',
|
|
13
|
-
role: 'assistant',
|
|
14
|
-
content:
|
|
15
|
-
'Set `config.assistant = { name, avatarUrl }`. You can also override per message via `message.sender`.\n\nMore info: [docs](https://example.com/docs/personas).',
|
|
16
|
-
createdAt: Date.now() - 4 * 60_000,
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
id: 'u-2',
|
|
20
|
-
role: 'user',
|
|
21
|
-
content: 'And errors? What if the turn fails?',
|
|
22
|
-
createdAt: Date.now() - 3 * 60_000,
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
id: 'a-err',
|
|
26
|
-
role: 'assistant',
|
|
27
|
-
content: 'Network blew up — try again in a moment.',
|
|
28
|
-
isError: true,
|
|
29
|
-
createdAt: Date.now() - 2 * 60_000,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
id: 'a-streaming',
|
|
33
|
-
role: 'assistant',
|
|
34
|
-
content: 'Live reply tokens arrive here',
|
|
35
|
-
isStreaming: true,
|
|
36
|
-
createdAt: Date.now() - 60_000,
|
|
37
|
-
toolActivity: 'Searching knowledge base…',
|
|
38
|
-
},
|
|
39
|
-
];
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ChatAssistantContext, ChatUserContext } from '../../types';
|
|
2
|
-
|
|
3
|
-
export const USER_ANNA: ChatUserContext = {
|
|
4
|
-
name: 'Anna',
|
|
5
|
-
email: 'anna@example.com',
|
|
6
|
-
avatarUrl: 'https://i.pravatar.cc/64?img=5',
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const ASSISTANT_AURA: ChatAssistantContext = {
|
|
10
|
-
name: 'Aura',
|
|
11
|
-
avatarUrl: 'https://i.pravatar.cc/64?img=11',
|
|
12
|
-
model: 'gpt-4o',
|
|
13
|
-
};
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import type { ChatMessage, ChatToolCall } from '../../types';
|
|
2
|
-
|
|
3
|
-
const now = Date.now();
|
|
4
|
-
|
|
5
|
-
/** Two-turn transcript exercising markdown + plain reply. Used in Basic stories. */
|
|
6
|
-
export const SEED_BASIC: ChatMessage[] = [
|
|
7
|
-
{
|
|
8
|
-
id: 'seed-u-1',
|
|
9
|
-
role: 'user',
|
|
10
|
-
content: 'Give me a markdown sample with a list and a code snippet.',
|
|
11
|
-
createdAt: now - 4 * 60_000,
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
id: 'seed-a-1',
|
|
15
|
-
role: 'assistant',
|
|
16
|
-
content:
|
|
17
|
-
'**Sure!** Here is a list:\n\n- alpha\n- beta\n- gamma\n\nAnd a snippet:\n\n```ts\nconst answer = 42;\n```',
|
|
18
|
-
createdAt: now - 3 * 60_000,
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
id: 'seed-u-2',
|
|
22
|
-
role: 'user',
|
|
23
|
-
content: 'How does streaming work?',
|
|
24
|
-
createdAt: now - 2 * 60_000,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
id: 'seed-a-2',
|
|
28
|
-
role: 'assistant',
|
|
29
|
-
content:
|
|
30
|
-
'Each token arrives separately over SSE. The UI sticks to the bottom while the stream is in flight and shows a streaming indicator until `message_end` fires.',
|
|
31
|
-
createdAt: now - 60_000,
|
|
32
|
-
},
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
/** A completed tool-call so the panel is visible without sending anything. */
|
|
36
|
-
const SEED_TOOL_CALL: ChatToolCall = {
|
|
37
|
-
id: 'tc-seed-1',
|
|
38
|
-
name: 'search_docs',
|
|
39
|
-
input: { query: 'streaming protocol' },
|
|
40
|
-
output: { hits: 3, top: 'streaming.md' },
|
|
41
|
-
status: 'success',
|
|
42
|
-
startedAt: now - 90_000,
|
|
43
|
-
endedAt: now - 89_000,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const SEED_TOOL_CALLS: ChatMessage[] = [
|
|
47
|
-
{
|
|
48
|
-
id: 'seed-u-tool',
|
|
49
|
-
role: 'user',
|
|
50
|
-
content: 'Find docs about streaming.',
|
|
51
|
-
createdAt: now - 2 * 60_000,
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
id: 'seed-a-tool',
|
|
55
|
-
role: 'assistant',
|
|
56
|
-
content: 'Let me check the docs for you.\n\nFound 3 relevant chunks. Here is a summary…',
|
|
57
|
-
createdAt: now - 60_000,
|
|
58
|
-
toolCalls: [SEED_TOOL_CALL],
|
|
59
|
-
},
|
|
60
|
-
];
|
|
61
|
-
|
|
62
|
-
/** Tool-call with a richer JSON payload — drives the JsonTree dispatcher story. */
|
|
63
|
-
const SEED_JSON_TOOL_CALL: ChatToolCall = {
|
|
64
|
-
id: 'tc-seed-json',
|
|
65
|
-
name: 'fetch_user',
|
|
66
|
-
input: { id: 'usr_42', fields: ['email', 'roles', 'metadata'] },
|
|
67
|
-
output: {
|
|
68
|
-
id: 'usr_42',
|
|
69
|
-
email: 'mark@example.com',
|
|
70
|
-
roles: ['admin', 'editor'],
|
|
71
|
-
metadata: { plan: 'pro', seats: 5, trial: false },
|
|
72
|
-
},
|
|
73
|
-
status: 'success',
|
|
74
|
-
startedAt: now - 90_000,
|
|
75
|
-
endedAt: now - 89_000,
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export const SEED_JSON_PAYLOAD: ChatMessage[] = [
|
|
79
|
-
{
|
|
80
|
-
id: 'seed-u-json',
|
|
81
|
-
role: 'user',
|
|
82
|
-
content: 'Fetch user 42.',
|
|
83
|
-
createdAt: now - 2 * 60_000,
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: 'seed-a-json',
|
|
87
|
-
role: 'assistant',
|
|
88
|
-
content: 'Open the tool panel to inspect the payload.',
|
|
89
|
-
createdAt: now - 60_000,
|
|
90
|
-
toolCalls: [SEED_JSON_TOOL_CALL],
|
|
91
|
-
},
|
|
92
|
-
];
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { createMockTransport } from '../../core/transport/mock';
|
|
2
|
-
import type { ChatMessage, ChatStreamEvent } from '../../types';
|
|
3
|
-
|
|
4
|
-
/** Scripted-replies transport. Pass `seed` to pre-populate the bubble area. */
|
|
5
|
-
export function makeBasicTransport(seed: ChatMessage[] = []) {
|
|
6
|
-
return createMockTransport({
|
|
7
|
-
initialMessages: seed,
|
|
8
|
-
replies: [
|
|
9
|
-
'Hello! I am a mock assistant. Ask me anything — I will reply with scripted text.',
|
|
10
|
-
'**Sure!** Here is a list:\n\n- alpha\n- beta\n- gamma\n\nAnd a snippet:\n\n```ts\nconst answer = 42;\n```',
|
|
11
|
-
'Streaming chunked text works too. Each token arrives separately and the UI sticks to the bottom while the stream is in flight.',
|
|
12
|
-
],
|
|
13
|
-
latencyMs: 35,
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/** Transport with an inline tool_call + result on send. Seedable. */
|
|
18
|
-
export function makeToolCallsTransport(seed: ChatMessage[] = []) {
|
|
19
|
-
const toolTurn: ChatStreamEvent[] = [
|
|
20
|
-
{ type: 'chunk', delta: 'Let me check the docs for you.\n\n' },
|
|
21
|
-
{
|
|
22
|
-
type: 'tool_call_start',
|
|
23
|
-
toolId: 'search-live',
|
|
24
|
-
name: 'search_docs',
|
|
25
|
-
input: { query: 'streaming protocol' },
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
type: 'tool_call_end',
|
|
29
|
-
toolId: 'search-live',
|
|
30
|
-
status: 'success',
|
|
31
|
-
output: { hits: 3, top: 'streaming.md' },
|
|
32
|
-
},
|
|
33
|
-
{ type: 'chunk', delta: 'Found 3 relevant chunks. Here is a summary…' },
|
|
34
|
-
];
|
|
35
|
-
return createMockTransport({ initialMessages: seed, replies: [toolTurn], latencyMs: 25 });
|
|
36
|
-
}
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { defineStory, useSelect, useBoolean } from '@djangocfg/playground';
|
|
2
|
-
import { Editor, DiffEditor } from './components';
|
|
3
|
-
|
|
4
|
-
export default defineStory({
|
|
5
|
-
title: 'Tools/Code Editor',
|
|
6
|
-
component: Editor,
|
|
7
|
-
description: 'Monaco-based code editor with syntax highlighting, diff view, and full IDE features.',
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
const SAMPLE_CODE = {
|
|
11
|
-
typescript: `import { useState, useCallback, useMemo } from 'react';
|
|
12
|
-
|
|
13
|
-
interface User {
|
|
14
|
-
id: string;
|
|
15
|
-
name: string;
|
|
16
|
-
email: string;
|
|
17
|
-
role: 'admin' | 'user' | 'viewer';
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function useUsers() {
|
|
21
|
-
const [users, setUsers] = useState<User[]>([]);
|
|
22
|
-
|
|
23
|
-
const addUser = useCallback((user: Omit<User, 'id'>) => {
|
|
24
|
-
setUsers(prev => [...prev, { ...user, id: crypto.randomUUID() }]);
|
|
25
|
-
}, []);
|
|
26
|
-
|
|
27
|
-
const admins = useMemo(
|
|
28
|
-
() => users.filter(u => u.role === 'admin'),
|
|
29
|
-
[users],
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
return { users, admins, addUser };
|
|
33
|
-
}`,
|
|
34
|
-
|
|
35
|
-
python: `from __future__ import annotations
|
|
36
|
-
|
|
37
|
-
from dataclasses import dataclass
|
|
38
|
-
from datetime import datetime
|
|
39
|
-
from typing import AsyncIterator
|
|
40
|
-
|
|
41
|
-
import httpx
|
|
42
|
-
from pydantic import BaseModel, Field
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class User(BaseModel):
|
|
46
|
-
id: str
|
|
47
|
-
name: str
|
|
48
|
-
email: str
|
|
49
|
-
role: str = "user"
|
|
50
|
-
created_at: datetime = Field(default_factory=datetime.utcnow)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@dataclass
|
|
54
|
-
class UserService:
|
|
55
|
-
base_url: str
|
|
56
|
-
client: httpx.AsyncClient | None = None
|
|
57
|
-
|
|
58
|
-
async def list_users(self, page: int = 1) -> list[User]:
|
|
59
|
-
async with httpx.AsyncClient(base_url=self.base_url) as client:
|
|
60
|
-
response = await client.get("/users", params={"page": page})
|
|
61
|
-
response.raise_for_status()
|
|
62
|
-
return [User(**u) for u in response.json()["data"]]`,
|
|
63
|
-
|
|
64
|
-
json: `{
|
|
65
|
-
"name": "@djangocfg/ui-tools",
|
|
66
|
-
"version": "2.1.0",
|
|
67
|
-
"description": "Heavy React tools with lazy loading",
|
|
68
|
-
"dependencies": {
|
|
69
|
-
"monaco-editor": "^0.55.1",
|
|
70
|
-
"react": "^19.1.0"
|
|
71
|
-
},
|
|
72
|
-
"exports": {
|
|
73
|
-
".": "./src/index.ts",
|
|
74
|
-
"./code-editor": "./src/tools/CodeEditor/index.ts"
|
|
75
|
-
}
|
|
76
|
-
}`,
|
|
77
|
-
|
|
78
|
-
css: `/* Design tokens */
|
|
79
|
-
:root {
|
|
80
|
-
--radius: 0.5rem;
|
|
81
|
-
--shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.editor-container {
|
|
85
|
-
position: relative;
|
|
86
|
-
border-radius: var(--radius);
|
|
87
|
-
border: 1px solid hsl(var(--border));
|
|
88
|
-
overflow: hidden;
|
|
89
|
-
|
|
90
|
-
&:focus-within {
|
|
91
|
-
outline: 2px solid hsl(var(--ring));
|
|
92
|
-
outline-offset: 2px;
|
|
93
|
-
}
|
|
94
|
-
}`,
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const DIFF_ORIGINAL = `function greet(name: string) {
|
|
98
|
-
console.log("Hello, " + name);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
greet("World");`;
|
|
102
|
-
|
|
103
|
-
const DIFF_MODIFIED = `function greet(name: string, greeting = "Hello") {
|
|
104
|
-
console.log(\`\${greeting}, \${name}!\`);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function farewell(name: string) {
|
|
108
|
-
console.log(\`Goodbye, \${name}!\`);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
greet("World");
|
|
112
|
-
farewell("World");`;
|
|
113
|
-
|
|
114
|
-
export const Interactive = () => {
|
|
115
|
-
const [language] = useSelect('language', {
|
|
116
|
-
options: ['typescript', 'python', 'json', 'css'] as const,
|
|
117
|
-
defaultValue: 'typescript',
|
|
118
|
-
label: 'Language',
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
const [readOnly] = useBoolean('readOnly', {
|
|
122
|
-
defaultValue: false,
|
|
123
|
-
label: 'Read Only',
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
const [minimap] = useBoolean('minimap', {
|
|
127
|
-
defaultValue: false,
|
|
128
|
-
label: 'Minimap',
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
const [autoHeight] = useBoolean('autoHeight', {
|
|
132
|
-
defaultValue: false,
|
|
133
|
-
label: 'Auto Height',
|
|
134
|
-
description: 'Resize editor to fit content',
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
return autoHeight ? (
|
|
138
|
-
<Editor
|
|
139
|
-
value={SAMPLE_CODE[language]}
|
|
140
|
-
language={language}
|
|
141
|
-
autoHeight
|
|
142
|
-
minHeight={100}
|
|
143
|
-
maxHeight={500}
|
|
144
|
-
options={{ readOnly, minimap, fontSize: 14 }}
|
|
145
|
-
/>
|
|
146
|
-
) : (
|
|
147
|
-
<div style={{ height: 400 }}>
|
|
148
|
-
<Editor
|
|
149
|
-
value={SAMPLE_CODE[language]}
|
|
150
|
-
language={language}
|
|
151
|
-
options={{ readOnly, minimap, fontSize: 14 }}
|
|
152
|
-
/>
|
|
153
|
-
</div>
|
|
154
|
-
);
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
export const TypeScript = () => (
|
|
158
|
-
<div style={{ height: 350 }}>
|
|
159
|
-
<Editor value={SAMPLE_CODE.typescript} language="typescript" />
|
|
160
|
-
</div>
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
export const Python = () => (
|
|
164
|
-
<div style={{ height: 350 }}>
|
|
165
|
-
<Editor value={SAMPLE_CODE.python} language="python" />
|
|
166
|
-
</div>
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
export const ReadOnly = () => (
|
|
170
|
-
<div style={{ height: 300 }}>
|
|
171
|
-
<Editor
|
|
172
|
-
value={SAMPLE_CODE.json}
|
|
173
|
-
language="json"
|
|
174
|
-
options={{ readOnly: true, lineNumbers: 'on' }}
|
|
175
|
-
/>
|
|
176
|
-
</div>
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
export const AutoHeight = () => (
|
|
180
|
-
<div className="flex flex-col gap-4 max-w-3xl">
|
|
181
|
-
<p className="text-sm text-muted-foreground">
|
|
182
|
-
Editor grows with content (min 100px, max 400px). Try typing new lines.
|
|
183
|
-
</p>
|
|
184
|
-
<Editor
|
|
185
|
-
value={`const x = 1;\nconst y = 2;\nconst z = x + y;`}
|
|
186
|
-
language="typescript"
|
|
187
|
-
autoHeight
|
|
188
|
-
minHeight={100}
|
|
189
|
-
maxHeight={400}
|
|
190
|
-
/>
|
|
191
|
-
</div>
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
export const DiffView = () => (
|
|
195
|
-
<div style={{ height: 400 }}>
|
|
196
|
-
<DiffEditor
|
|
197
|
-
original={DIFF_ORIGINAL}
|
|
198
|
-
modified={DIFF_MODIFIED}
|
|
199
|
-
language="typescript"
|
|
200
|
-
/>
|
|
201
|
-
</div>
|
|
202
|
-
);
|