@djangocfg/ui-tools 2.1.349 → 2.1.351
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-2KT32NFJ.cjs +14 -0
- package/dist/{ChatRoot-CZMOJOGD.mjs.map → ChatRoot-2KT32NFJ.cjs.map} +1 -1
- package/dist/ChatRoot-VSIBJLE2.mjs +5 -0
- package/dist/{ChatRoot-VTYANC7M.cjs.map → ChatRoot-VSIBJLE2.mjs.map} +1 -1
- package/dist/{chunk-XYGB26BY.cjs → chunk-2SXDCXLK.cjs} +56 -14
- package/dist/chunk-2SXDCXLK.cjs.map +1 -0
- package/dist/{chunk-QCKJVSJF.mjs → chunk-XJ7CXHSU.mjs} +56 -14
- package/dist/chunk-XJ7CXHSU.mjs.map +1 -0
- package/dist/index.cjs +77 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -18
- package/dist/index.d.ts +45 -18
- package/dist/index.mjs +34 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/tools/Chat/Chat.story.tsx +33 -0
- package/src/tools/Chat/components/AudioToggle.tsx +78 -0
- package/src/tools/Chat/components/ChatRoot.tsx +5 -1
- package/src/tools/Chat/components/Composer.tsx +66 -13
- package/src/tools/Chat/components/index.ts +1 -0
- package/src/tools/Chat/context/ChatProvider.tsx +14 -2
- package/src/tools/Chat/index.ts +2 -0
- package/dist/ChatRoot-CZMOJOGD.mjs +0 -5
- package/dist/ChatRoot-VTYANC7M.cjs +0 -14
- package/dist/chunk-QCKJVSJF.mjs.map +0 -1
- package/dist/chunk-XYGB26BY.cjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ui-tools",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.351",
|
|
4
4
|
"description": "Heavy React tools with lazy loading - for Electron, Vite, CRA, Next.js apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ui-tools",
|
|
@@ -101,8 +101,8 @@
|
|
|
101
101
|
"check": "tsc --noEmit"
|
|
102
102
|
},
|
|
103
103
|
"peerDependencies": {
|
|
104
|
-
"@djangocfg/i18n": "^2.1.
|
|
105
|
-
"@djangocfg/ui-core": "^2.1.
|
|
104
|
+
"@djangocfg/i18n": "^2.1.351",
|
|
105
|
+
"@djangocfg/ui-core": "^2.1.351",
|
|
106
106
|
"consola": "^3.4.2",
|
|
107
107
|
"lodash-es": "^4.18.1",
|
|
108
108
|
"lucide-react": "^0.545.0",
|
|
@@ -155,10 +155,10 @@
|
|
|
155
155
|
"material-file-icons": "^2.4.0"
|
|
156
156
|
},
|
|
157
157
|
"devDependencies": {
|
|
158
|
-
"@djangocfg/i18n": "^2.1.
|
|
158
|
+
"@djangocfg/i18n": "^2.1.351",
|
|
159
159
|
"@djangocfg/playground": "workspace:*",
|
|
160
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
161
|
-
"@djangocfg/ui-core": "^2.1.
|
|
160
|
+
"@djangocfg/typescript-config": "^2.1.351",
|
|
161
|
+
"@djangocfg/ui-core": "^2.1.351",
|
|
162
162
|
"@types/lodash-es": "^4.17.12",
|
|
163
163
|
"@types/mapbox__mapbox-gl-draw": "^1.4.8",
|
|
164
164
|
"@types/node": "^24.7.2",
|
|
@@ -101,6 +101,39 @@ export const Default = () => {
|
|
|
101
101
|
);
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// 1b) ComposerSizes — sm / md / lg side-by-side
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
|
|
108
|
+
export const ComposerSizes = () => {
|
|
109
|
+
const make = () =>
|
|
110
|
+
createMockTransport({
|
|
111
|
+
replies: ['I scale with the composer size — try `lg` on a primary surface.'],
|
|
112
|
+
latencyMs: 25,
|
|
113
|
+
});
|
|
114
|
+
const cells: Array<{ size: 'sm' | 'md' | 'lg'; label: string }> = [
|
|
115
|
+
{ size: 'sm', label: 'sm — 32px (compact)' },
|
|
116
|
+
{ size: 'md', label: 'md — 36px (default)' },
|
|
117
|
+
{ size: 'lg', label: 'lg — 48px (primary surface)' },
|
|
118
|
+
];
|
|
119
|
+
return (
|
|
120
|
+
<div className="grid h-[640px] grid-cols-3 gap-3">
|
|
121
|
+
{cells.map(({ size, label }) => (
|
|
122
|
+
<Frame key={size} h={620}>
|
|
123
|
+
<ChatRoot
|
|
124
|
+
transport={make()}
|
|
125
|
+
config={{
|
|
126
|
+
greeting: label,
|
|
127
|
+
placeholder: 'Type a message…',
|
|
128
|
+
}}
|
|
129
|
+
composerSize={size}
|
|
130
|
+
/>
|
|
131
|
+
</Frame>
|
|
132
|
+
))}
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
104
137
|
// ---------------------------------------------------------------------------
|
|
105
138
|
// 2) WithToolCalls — scripted tool invocations
|
|
106
139
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mute / unmute toggle for chat audio events.
|
|
5
|
+
*
|
|
6
|
+
* Reads the current ``muted`` state from the active chat context and
|
|
7
|
+
* persists changes through ``useChatAudioPrefs`` (cross-tab safe). The
|
|
8
|
+
* button auto-hides when no ``audio.sounds`` config is provided —
|
|
9
|
+
* showing a mute toggle for a chat with no sounds is just clutter.
|
|
10
|
+
*
|
|
11
|
+
* Drop into a ChatRoot ``header`` slot or anywhere inside a chat
|
|
12
|
+
* provider:
|
|
13
|
+
*
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <ChatRoot
|
|
16
|
+
* header={<AudioToggle />}
|
|
17
|
+
* audio={{ sounds: { messageReceived: '/ping.mp3' } }}
|
|
18
|
+
* ...
|
|
19
|
+
* />
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { Volume2, VolumeX } from 'lucide-react';
|
|
24
|
+
|
|
25
|
+
import { Button } from '@djangocfg/ui-core/components';
|
|
26
|
+
import { cn } from '@djangocfg/ui-core/lib';
|
|
27
|
+
|
|
28
|
+
import { useChatContextOptional } from '../context';
|
|
29
|
+
import { useChatAudioPrefs } from '../core/audio/preferences';
|
|
30
|
+
|
|
31
|
+
export interface AudioToggleProps {
|
|
32
|
+
/** Visual size — matches Button sizes. Default: ``icon``. */
|
|
33
|
+
size?: 'sm' | 'icon';
|
|
34
|
+
/** Variant passed to the underlying Button. Default: ``ghost``. */
|
|
35
|
+
variant?: 'ghost' | 'outline' | 'secondary';
|
|
36
|
+
/** Force-show even when no audio config is wired (e.g. for stories). */
|
|
37
|
+
alwaysShow?: boolean;
|
|
38
|
+
className?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function AudioToggle({
|
|
42
|
+
size = 'icon',
|
|
43
|
+
variant = 'ghost',
|
|
44
|
+
alwaysShow = false,
|
|
45
|
+
className,
|
|
46
|
+
}: AudioToggleProps) {
|
|
47
|
+
// Read straight from the persist store so the toggle works even
|
|
48
|
+
// when rendered OUTSIDE the ChatRoot (e.g. in a parent header). The
|
|
49
|
+
// chat audio bus reads the same store, so a click here flips the
|
|
50
|
+
// "muted" state for any sibling ChatRoot in the same tab and
|
|
51
|
+
// mirrors across tabs via the storage event.
|
|
52
|
+
const muted = useChatAudioPrefs((s) => s.muted);
|
|
53
|
+
const setMuted = useChatAudioPrefs((s) => s.setMuted);
|
|
54
|
+
|
|
55
|
+
// If a ChatRoot is in scope, hide unless it actually wired sounds —
|
|
56
|
+
// otherwise the button is a no-op for that surface. When rendered
|
|
57
|
+
// standalone (no context), default to visible.
|
|
58
|
+
const ctx = useChatContextOptional();
|
|
59
|
+
if (ctx && !ctx.hasAudio && !alwaysShow) return null;
|
|
60
|
+
|
|
61
|
+
const Icon = muted ? VolumeX : Volume2;
|
|
62
|
+
const label = muted ? 'Unmute chat sounds' : 'Mute chat sounds';
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Button
|
|
66
|
+
type="button"
|
|
67
|
+
variant={variant}
|
|
68
|
+
size={size}
|
|
69
|
+
onClick={() => setMuted(!muted)}
|
|
70
|
+
aria-label={label}
|
|
71
|
+
aria-pressed={muted}
|
|
72
|
+
title={label}
|
|
73
|
+
className={cn(size === 'icon' ? 'h-9 w-9' : '', className)}
|
|
74
|
+
>
|
|
75
|
+
<Icon aria-hidden className="size-4" />
|
|
76
|
+
</Button>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
@@ -10,7 +10,7 @@ import { ChatProvider, useChatContext, type ChatContextValue } from '../context'
|
|
|
10
10
|
import { useChatComposer, type UseChatComposerReturn } from '../hooks/useChatComposer';
|
|
11
11
|
import { useChatScroll } from '../hooks/useChatScroll';
|
|
12
12
|
import { useChatHistory } from '../hooks/useChatHistory';
|
|
13
|
-
import { Composer } from './Composer';
|
|
13
|
+
import { Composer, type ComposerSize } from './Composer';
|
|
14
14
|
import { EmptyState } from './EmptyState';
|
|
15
15
|
import { ErrorBanner } from './ErrorBanner';
|
|
16
16
|
import { JumpToLatest } from './JumpToLatest';
|
|
@@ -75,6 +75,9 @@ export interface ChatRootProps {
|
|
|
75
75
|
onPickFiles?: () => void;
|
|
76
76
|
/** Hide the composer input area entirely (e.g. while waiting for human approval). */
|
|
77
77
|
hideComposer?: boolean;
|
|
78
|
+
/** Composer size variant. Default ``md`` (36px slot). Use ``lg`` for primary
|
|
79
|
+
* surfaces (onboarding, full-page chat), ``sm`` for dense sidebars. */
|
|
80
|
+
composerSize?: ComposerSize;
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
export function ChatRoot(props: ChatRootProps) {
|
|
@@ -195,6 +198,7 @@ function ChatRootShell({ className, slots }: ChatRootShellProps) {
|
|
|
195
198
|
toolbarStart={slots.composerToolbarStart}
|
|
196
199
|
toolbarEnd={slots.composerToolbarEnd}
|
|
197
200
|
attachmentTray={slots.composerAttachmentTray}
|
|
201
|
+
size={slots.composerSize}
|
|
198
202
|
/>
|
|
199
203
|
)}
|
|
200
204
|
{slots.footer ?? null}
|
|
@@ -10,6 +10,8 @@ import { useChatContextOptional } from '../context';
|
|
|
10
10
|
import type { UseChatComposerReturn } from '../hooks/useChatComposer';
|
|
11
11
|
import { Attachments } from './Attachments';
|
|
12
12
|
|
|
13
|
+
export type ComposerSize = 'sm' | 'md' | 'lg';
|
|
14
|
+
|
|
13
15
|
export interface ComposerProps {
|
|
14
16
|
composer: UseChatComposerReturn;
|
|
15
17
|
placeholder?: string;
|
|
@@ -21,11 +23,57 @@ export interface ComposerProps {
|
|
|
21
23
|
attachmentTray?: ReactNode;
|
|
22
24
|
className?: string;
|
|
23
25
|
textareaClassName?: string;
|
|
26
|
+
/** Visual size — controls textarea height + button slot size.
|
|
27
|
+
*
|
|
28
|
+
* - ``sm`` — 32px slot, dense compact composer (admin sidebars, etc).
|
|
29
|
+
* - ``md`` — 36px slot, default. Same as the legacy fixed size.
|
|
30
|
+
* - ``lg`` — 48px slot, generous textarea. Use when the chat is
|
|
31
|
+
* the page's primary surface (onboarding, support).
|
|
32
|
+
*/
|
|
33
|
+
size?: ComposerSize;
|
|
24
34
|
/** Show "Stop" button instead of "Send" while streaming. */
|
|
25
35
|
isStreaming?: boolean;
|
|
26
36
|
onCancel?: () => void;
|
|
27
37
|
}
|
|
28
38
|
|
|
39
|
+
const SIZE_CLASSES: Record<ComposerSize, {
|
|
40
|
+
slot: string;
|
|
41
|
+
button: string;
|
|
42
|
+
iconButton: string;
|
|
43
|
+
textarea: string;
|
|
44
|
+
text: string;
|
|
45
|
+
padding: string;
|
|
46
|
+
containerPadding: string;
|
|
47
|
+
}> = {
|
|
48
|
+
sm: {
|
|
49
|
+
slot: '[&>:not(textarea)]:h-8',
|
|
50
|
+
button: 'h-8 w-8',
|
|
51
|
+
iconButton: 'size-3.5',
|
|
52
|
+
textarea: 'min-h-8 max-h-48 px-3 py-1.5',
|
|
53
|
+
text: 'text-sm',
|
|
54
|
+
padding: 'gap-1.5',
|
|
55
|
+
containerPadding: 'px-2 pt-1.5 pb-[max(0.375rem,env(safe-area-inset-bottom))]',
|
|
56
|
+
},
|
|
57
|
+
md: {
|
|
58
|
+
slot: '[&>:not(textarea)]:h-9',
|
|
59
|
+
button: 'h-9 w-9',
|
|
60
|
+
iconButton: 'size-4',
|
|
61
|
+
textarea: 'min-h-9 max-h-60 px-3.5 py-2',
|
|
62
|
+
text: 'text-base sm:text-sm',
|
|
63
|
+
padding: 'gap-1.5',
|
|
64
|
+
containerPadding: 'px-2.5 pt-2 pb-[max(0.5rem,env(safe-area-inset-bottom))]',
|
|
65
|
+
},
|
|
66
|
+
lg: {
|
|
67
|
+
slot: '[&>:not(textarea)]:h-12',
|
|
68
|
+
button: 'h-12 w-12',
|
|
69
|
+
iconButton: 'size-5',
|
|
70
|
+
textarea: 'min-h-12 max-h-72 px-4 py-3',
|
|
71
|
+
text: 'text-base',
|
|
72
|
+
padding: 'gap-2',
|
|
73
|
+
containerPadding: 'px-3.5 pt-3 pb-[max(0.875rem,env(safe-area-inset-bottom))]',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
29
77
|
export const Composer = forwardRef<HTMLDivElement, ComposerProps>(function Composer(
|
|
30
78
|
{
|
|
31
79
|
composer,
|
|
@@ -38,6 +86,7 @@ export const Composer = forwardRef<HTMLDivElement, ComposerProps>(function Compo
|
|
|
38
86
|
attachmentTray,
|
|
39
87
|
className,
|
|
40
88
|
textareaClassName,
|
|
89
|
+
size = 'md',
|
|
41
90
|
isStreaming: isStreamingProp,
|
|
42
91
|
onCancel: onCancelProp,
|
|
43
92
|
},
|
|
@@ -47,12 +96,14 @@ export const Composer = forwardRef<HTMLDivElement, ComposerProps>(function Compo
|
|
|
47
96
|
const isStreaming = isStreamingProp ?? ctx?.isStreaming ?? false;
|
|
48
97
|
const onCancel = onCancelProp ?? ctx?.cancelStream;
|
|
49
98
|
const isDisabled = disabled ?? isStreaming;
|
|
99
|
+
const sz = SIZE_CLASSES[size];
|
|
50
100
|
|
|
51
101
|
return (
|
|
52
102
|
<div
|
|
53
103
|
ref={ref}
|
|
54
104
|
className={cn(
|
|
55
|
-
'border-t border-border bg-background/95
|
|
105
|
+
'border-t border-border bg-background/95',
|
|
106
|
+
sz.containerPadding,
|
|
56
107
|
className,
|
|
57
108
|
)}
|
|
58
109
|
>
|
|
@@ -67,11 +118,11 @@ export const Composer = forwardRef<HTMLDivElement, ComposerProps>(function Compo
|
|
|
67
118
|
</div>
|
|
68
119
|
) : null}
|
|
69
120
|
|
|
70
|
-
{/*
|
|
71
|
-
* buttons line up with the
|
|
72
|
-
* Toolbar slots that want to opt out can
|
|
73
|
-
* like `!h-auto`. */}
|
|
74
|
-
<div className=
|
|
121
|
+
{/* Size-aware slot row. ``[&>:not(textarea)]:h-{N}`` enforces a
|
|
122
|
+
* consistent slot height so toolbar buttons line up with the
|
|
123
|
+
* textarea baseline. Toolbar slots that want to opt out can
|
|
124
|
+
* pass an explicit class like `!h-auto`. */}
|
|
125
|
+
<div className={cn('flex items-end [&>:not(textarea)]:shrink-0', sz.padding, sz.slot)}>
|
|
75
126
|
{showAttachmentButton ? (
|
|
76
127
|
<Button
|
|
77
128
|
type="button"
|
|
@@ -80,9 +131,9 @@ export const Composer = forwardRef<HTMLDivElement, ComposerProps>(function Compo
|
|
|
80
131
|
onClick={onPickFiles}
|
|
81
132
|
aria-label="Attach files"
|
|
82
133
|
disabled={isDisabled}
|
|
83
|
-
className=
|
|
134
|
+
className={sz.button}
|
|
84
135
|
>
|
|
85
|
-
<Paperclip aria-hidden className=
|
|
136
|
+
<Paperclip aria-hidden className={sz.iconButton} />
|
|
86
137
|
</Button>
|
|
87
138
|
) : null}
|
|
88
139
|
|
|
@@ -96,7 +147,9 @@ export const Composer = forwardRef<HTMLDivElement, ComposerProps>(function Compo
|
|
|
96
147
|
aria-multiline="true"
|
|
97
148
|
disabled={isDisabled}
|
|
98
149
|
className={cn(
|
|
99
|
-
'
|
|
150
|
+
'flex-1 resize-none rounded-2xl',
|
|
151
|
+
sz.textarea,
|
|
152
|
+
sz.text,
|
|
100
153
|
textareaClassName,
|
|
101
154
|
)}
|
|
102
155
|
/>
|
|
@@ -111,9 +164,9 @@ export const Composer = forwardRef<HTMLDivElement, ComposerProps>(function Compo
|
|
|
111
164
|
onClick={onCancel}
|
|
112
165
|
aria-label="Stop"
|
|
113
166
|
aria-keyshortcuts="Escape"
|
|
114
|
-
className=
|
|
167
|
+
className={sz.button}
|
|
115
168
|
>
|
|
116
|
-
<Square aria-hidden className=
|
|
169
|
+
<Square aria-hidden className={sz.iconButton} />
|
|
117
170
|
</Button>
|
|
118
171
|
) : (
|
|
119
172
|
<Button
|
|
@@ -123,9 +176,9 @@ export const Composer = forwardRef<HTMLDivElement, ComposerProps>(function Compo
|
|
|
123
176
|
disabled={!composer.canSubmit}
|
|
124
177
|
aria-label="Send"
|
|
125
178
|
aria-keyshortcuts="Enter"
|
|
126
|
-
className=
|
|
179
|
+
className={sz.button}
|
|
127
180
|
>
|
|
128
|
-
<Send aria-hidden className=
|
|
181
|
+
<Send aria-hidden className={sz.iconButton} />
|
|
129
182
|
</Button>
|
|
130
183
|
)}
|
|
131
184
|
</div>
|
|
@@ -22,3 +22,4 @@ export { EmptyState, type EmptyStateProps } from './EmptyState';
|
|
|
22
22
|
export { ErrorBanner, type ErrorBannerProps } from './ErrorBanner';
|
|
23
23
|
export { JumpToLatest, type JumpToLatestProps } from './JumpToLatest';
|
|
24
24
|
export { StreamingIndicator, type StreamingIndicatorProps } from './StreamingIndicator';
|
|
25
|
+
export { AudioToggle, type AudioToggleProps } from './AudioToggle';
|
|
@@ -22,6 +22,10 @@ export interface ChatContextValue extends UseChatReturn {
|
|
|
22
22
|
config: ChatConfig;
|
|
23
23
|
labels: ChatLabels;
|
|
24
24
|
audio: UseChatAudioReturn;
|
|
25
|
+
/** True iff the host wired at least one ``audio.sounds[event]`` URL.
|
|
26
|
+
* Components like ``AudioToggle`` use this to auto-hide when there
|
|
27
|
+
* is nothing to mute. */
|
|
28
|
+
hasAudio: boolean;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
const Ctx = createContext<ChatContextValue | null>(null);
|
|
@@ -101,9 +105,17 @@ export function ChatProvider({
|
|
|
101
105
|
[config.labels],
|
|
102
106
|
);
|
|
103
107
|
|
|
108
|
+
const hasAudio = useMemo<boolean>(() => {
|
|
109
|
+
const sounds = audio?.sounds;
|
|
110
|
+
if (!sounds) return false;
|
|
111
|
+
return Object.values(sounds).some(
|
|
112
|
+
(v) => typeof v === 'string' && v.length > 0,
|
|
113
|
+
);
|
|
114
|
+
}, [audio]);
|
|
115
|
+
|
|
104
116
|
const value = useMemo<ChatContextValue>(
|
|
105
|
-
() => ({ ...chat, layout, config, labels, audio: audioApi }),
|
|
106
|
-
[chat, layout, config, labels, audioApi],
|
|
117
|
+
() => ({ ...chat, layout, config, labels, audio: audioApi, hasAudio }),
|
|
118
|
+
[chat, layout, config, labels, audioApi, hasAudio],
|
|
107
119
|
);
|
|
108
120
|
|
|
109
121
|
return (
|
package/src/tools/Chat/index.ts
CHANGED
|
@@ -137,6 +137,7 @@ export {
|
|
|
137
137
|
ErrorBanner,
|
|
138
138
|
JumpToLatest,
|
|
139
139
|
StreamingIndicator,
|
|
140
|
+
AudioToggle,
|
|
140
141
|
type ChatRootProps,
|
|
141
142
|
type MessageListProps,
|
|
142
143
|
type MessageBubbleProps,
|
|
@@ -155,6 +156,7 @@ export {
|
|
|
155
156
|
type ErrorBannerProps,
|
|
156
157
|
type JumpToLatestProps,
|
|
157
158
|
type StreamingIndicatorProps,
|
|
159
|
+
type AudioToggleProps,
|
|
158
160
|
} from './components';
|
|
159
161
|
|
|
160
162
|
// Lazy preset
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunkXYGB26BY_cjs = require('./chunk-XYGB26BY.cjs');
|
|
4
|
-
require('./chunk-B5AWZOHJ.cjs');
|
|
5
|
-
require('./chunk-OLISEQHS.cjs');
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Object.defineProperty(exports, "ChatRoot", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: function () { return chunkXYGB26BY_cjs.ChatRoot; }
|
|
12
|
-
});
|
|
13
|
-
//# sourceMappingURL=ChatRoot-VTYANC7M.cjs.map
|
|
14
|
-
//# sourceMappingURL=ChatRoot-VTYANC7M.cjs.map
|