@melony/react 0.1.23 → 0.1.25
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/index.cjs +682 -390
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +174 -43
- package/dist/index.d.ts +174 -43
- package/dist/index.js +613 -346
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React11 = require('react');
|
|
4
4
|
var react = require('nuqs/adapters/react');
|
|
5
5
|
var reactQuery = require('@tanstack/react-query');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -10,12 +10,12 @@ var clsx = require('clsx');
|
|
|
10
10
|
var tailwindMerge = require('tailwind-merge');
|
|
11
11
|
var button = require('@base-ui/react/button');
|
|
12
12
|
var classVarianceAuthority = require('class-variance-authority');
|
|
13
|
+
var mergeProps = require('@base-ui/react/merge-props');
|
|
14
|
+
var useRender = require('@base-ui/react/use-render');
|
|
13
15
|
var ICONS = require('@tabler/icons-react');
|
|
14
16
|
var menu = require('@base-ui/react/menu');
|
|
15
17
|
var separator = require('@base-ui/react/separator');
|
|
16
18
|
var dialog = require('@base-ui/react/dialog');
|
|
17
|
-
var mergeProps = require('@base-ui/react/merge-props');
|
|
18
|
-
var useRender = require('@base-ui/react/use-render');
|
|
19
19
|
var input = require('@base-ui/react/input');
|
|
20
20
|
var select = require('@base-ui/react/select');
|
|
21
21
|
var reactDom = require('react-dom');
|
|
@@ -40,7 +40,7 @@ function _interopNamespace(e) {
|
|
|
40
40
|
return Object.freeze(n);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
var
|
|
43
|
+
var React11__namespace = /*#__PURE__*/_interopNamespace(React11);
|
|
44
44
|
var ICONS__namespace = /*#__PURE__*/_interopNamespace(ICONS);
|
|
45
45
|
|
|
46
46
|
// src/providers/melony-provider.tsx
|
|
@@ -69,7 +69,7 @@ function groupEventsToMessages(events) {
|
|
|
69
69
|
}
|
|
70
70
|
return messages;
|
|
71
71
|
}
|
|
72
|
-
var MelonyContext =
|
|
72
|
+
var MelonyContext = React11.createContext(
|
|
73
73
|
void 0
|
|
74
74
|
);
|
|
75
75
|
var defaultQueryClient = new reactQuery.QueryClient({
|
|
@@ -84,41 +84,78 @@ var MelonyContextProviderInner = ({
|
|
|
84
84
|
children,
|
|
85
85
|
client,
|
|
86
86
|
initialEvents,
|
|
87
|
-
configApi,
|
|
88
87
|
setContextValue
|
|
89
88
|
}) => {
|
|
90
|
-
const [state, setState] =
|
|
89
|
+
const [state, setState] = React11.useState(client.getState());
|
|
91
90
|
const { data: config } = reactQuery.useQuery({
|
|
92
|
-
queryKey: ["melony-config",
|
|
93
|
-
queryFn: () => client.getConfig(
|
|
94
|
-
enabled: !!configApi,
|
|
91
|
+
queryKey: ["melony-config", client.url],
|
|
92
|
+
queryFn: () => client.getConfig(),
|
|
95
93
|
staleTime: Infinity
|
|
96
94
|
});
|
|
97
|
-
|
|
95
|
+
React11.useEffect(() => {
|
|
98
96
|
if (initialEvents && initialEvents.length > 0 && client.getState().events.length === 0) {
|
|
99
97
|
client.reset(initialEvents);
|
|
100
98
|
}
|
|
101
99
|
}, [client, initialEvents]);
|
|
102
|
-
|
|
100
|
+
React11.useEffect(() => {
|
|
103
101
|
setState(client.getState());
|
|
104
102
|
const unsubscribe = client.subscribe(setState);
|
|
105
103
|
return () => {
|
|
106
104
|
unsubscribe();
|
|
107
105
|
};
|
|
108
106
|
}, [client]);
|
|
109
|
-
const
|
|
107
|
+
const reset = React11.useCallback(
|
|
108
|
+
(events) => client.reset(events),
|
|
109
|
+
[client]
|
|
110
|
+
);
|
|
111
|
+
const dispatchClientAction = React11.useCallback(
|
|
112
|
+
async (event) => {
|
|
113
|
+
if (!event.type.startsWith("client:")) return false;
|
|
114
|
+
switch (event.type) {
|
|
115
|
+
case "client:navigate": {
|
|
116
|
+
const url = event.data?.url;
|
|
117
|
+
if (url) {
|
|
118
|
+
window.history.pushState(null, "", url);
|
|
119
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
case "client:open-url": {
|
|
124
|
+
const { url, target = "_blank" } = event.data || {};
|
|
125
|
+
if (url) {
|
|
126
|
+
window.open(url, target);
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
case "client:copy": {
|
|
131
|
+
const { text } = event.data || {};
|
|
132
|
+
if (text) {
|
|
133
|
+
await navigator.clipboard.writeText(text);
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
case "client:reset": {
|
|
138
|
+
reset([]);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
default:
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
[client, reset]
|
|
146
|
+
);
|
|
147
|
+
const sendEvent = React11.useCallback(
|
|
110
148
|
async (event, options) => {
|
|
149
|
+
const handled = await dispatchClientAction(event);
|
|
150
|
+
if (handled) return;
|
|
111
151
|
const generator = client.sendEvent(event, options);
|
|
112
|
-
for await (const
|
|
152
|
+
for await (const incomingEvent of generator) {
|
|
153
|
+
await dispatchClientAction(incomingEvent);
|
|
113
154
|
}
|
|
114
155
|
},
|
|
115
|
-
[client]
|
|
156
|
+
[client, dispatchClientAction]
|
|
116
157
|
);
|
|
117
|
-
const
|
|
118
|
-
(events) => client.reset(events),
|
|
119
|
-
[client]
|
|
120
|
-
);
|
|
121
|
-
const value = React10.useMemo(
|
|
158
|
+
const value = React11.useMemo(
|
|
122
159
|
() => ({
|
|
123
160
|
...state,
|
|
124
161
|
messages: groupEventsToMessages(state.events),
|
|
@@ -129,7 +166,7 @@ var MelonyContextProviderInner = ({
|
|
|
129
166
|
}),
|
|
130
167
|
[state, sendEvent, reset, client, config]
|
|
131
168
|
);
|
|
132
|
-
|
|
169
|
+
React11.useEffect(() => {
|
|
133
170
|
setContextValue(value);
|
|
134
171
|
}, [value, setContextValue]);
|
|
135
172
|
return /* @__PURE__ */ jsxRuntime.jsx(react.NuqsAdapter, { children });
|
|
@@ -138,31 +175,29 @@ var MelonyClientProvider = ({
|
|
|
138
175
|
children,
|
|
139
176
|
client,
|
|
140
177
|
initialEvents,
|
|
141
|
-
queryClient = defaultQueryClient
|
|
142
|
-
configApi
|
|
178
|
+
queryClient = defaultQueryClient
|
|
143
179
|
}) => {
|
|
144
|
-
const [contextValue, setContextValue] =
|
|
180
|
+
const [contextValue, setContextValue] = React11.useState(void 0);
|
|
145
181
|
return /* @__PURE__ */ jsxRuntime.jsx(MelonyContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
146
182
|
MelonyContextProviderInner,
|
|
147
183
|
{
|
|
148
184
|
client,
|
|
149
185
|
initialEvents,
|
|
150
|
-
configApi,
|
|
151
186
|
setContextValue,
|
|
152
187
|
children
|
|
153
188
|
}
|
|
154
189
|
) }) });
|
|
155
190
|
};
|
|
156
|
-
var AuthContext =
|
|
191
|
+
var AuthContext = React11.createContext(
|
|
157
192
|
void 0
|
|
158
193
|
);
|
|
159
194
|
var AuthProvider = ({
|
|
160
195
|
children,
|
|
161
196
|
service
|
|
162
197
|
}) => {
|
|
163
|
-
const [user, setUser] =
|
|
164
|
-
const [isLoading, setIsLoading] =
|
|
165
|
-
const fetchMe =
|
|
198
|
+
const [user, setUser] = React11.useState(null);
|
|
199
|
+
const [isLoading, setIsLoading] = React11.useState(true);
|
|
200
|
+
const fetchMe = React11.useCallback(async () => {
|
|
166
201
|
setIsLoading(true);
|
|
167
202
|
try {
|
|
168
203
|
const userData = await service.getMe();
|
|
@@ -174,13 +209,13 @@ var AuthProvider = ({
|
|
|
174
209
|
setIsLoading(false);
|
|
175
210
|
}
|
|
176
211
|
}, [service]);
|
|
177
|
-
|
|
212
|
+
React11.useEffect(() => {
|
|
178
213
|
fetchMe();
|
|
179
214
|
}, [fetchMe]);
|
|
180
|
-
const login =
|
|
215
|
+
const login = React11.useCallback(() => {
|
|
181
216
|
service.login();
|
|
182
217
|
}, [service]);
|
|
183
|
-
const logout =
|
|
218
|
+
const logout = React11.useCallback(async () => {
|
|
184
219
|
try {
|
|
185
220
|
await service.logout();
|
|
186
221
|
setUser(null);
|
|
@@ -216,7 +251,7 @@ var AuthProvider = ({
|
|
|
216
251
|
}
|
|
217
252
|
return /* @__PURE__ */ jsxRuntime.jsx(AuthContext.Provider, { value, children });
|
|
218
253
|
};
|
|
219
|
-
var ThreadContext =
|
|
254
|
+
var ThreadContext = React11.createContext(
|
|
220
255
|
void 0
|
|
221
256
|
);
|
|
222
257
|
var ThreadProvider = ({
|
|
@@ -225,7 +260,7 @@ var ThreadProvider = ({
|
|
|
225
260
|
initialThreadId: providedInitialThreadId
|
|
226
261
|
}) => {
|
|
227
262
|
const queryClient = reactQuery.useQueryClient();
|
|
228
|
-
const defaultInitialThreadId =
|
|
263
|
+
const defaultInitialThreadId = React11.useMemo(() => client.generateId(), []);
|
|
229
264
|
const initialThreadId = providedInitialThreadId || defaultInitialThreadId;
|
|
230
265
|
const [activeThreadId, setActiveThreadId] = nuqs.useQueryState(
|
|
231
266
|
"threadId",
|
|
@@ -266,22 +301,22 @@ var ThreadProvider = ({
|
|
|
266
301
|
}
|
|
267
302
|
}
|
|
268
303
|
});
|
|
269
|
-
const selectThread =
|
|
304
|
+
const selectThread = React11.useCallback(
|
|
270
305
|
(threadId) => {
|
|
271
306
|
setActiveThreadId(threadId);
|
|
272
307
|
},
|
|
273
308
|
[setActiveThreadId]
|
|
274
309
|
);
|
|
275
|
-
const createThread =
|
|
310
|
+
const createThread = React11.useCallback(async () => {
|
|
276
311
|
return createMutation.mutateAsync();
|
|
277
312
|
}, [createMutation]);
|
|
278
|
-
const deleteThread =
|
|
313
|
+
const deleteThread = React11.useCallback(
|
|
279
314
|
async (threadId) => {
|
|
280
315
|
return deleteMutation.mutateAsync(threadId);
|
|
281
316
|
},
|
|
282
317
|
[deleteMutation]
|
|
283
318
|
);
|
|
284
|
-
const value =
|
|
319
|
+
const value = React11.useMemo(
|
|
285
320
|
() => ({
|
|
286
321
|
threads,
|
|
287
322
|
activeThreadId,
|
|
@@ -311,11 +346,11 @@ var ThreadProvider = ({
|
|
|
311
346
|
);
|
|
312
347
|
return /* @__PURE__ */ jsxRuntime.jsx(ThreadContext.Provider, { value, children });
|
|
313
348
|
};
|
|
314
|
-
var ThemeContext =
|
|
349
|
+
var ThemeContext = React11.createContext(void 0);
|
|
315
350
|
function ThemeProvider({ children }) {
|
|
316
|
-
const [theme, setThemeState] =
|
|
317
|
-
const [resolvedTheme, setResolvedTheme] =
|
|
318
|
-
|
|
351
|
+
const [theme, setThemeState] = React11.useState("system");
|
|
352
|
+
const [resolvedTheme, setResolvedTheme] = React11.useState("light");
|
|
353
|
+
React11.useEffect(() => {
|
|
319
354
|
if (typeof window !== "undefined") {
|
|
320
355
|
const stored = localStorage.getItem("theme");
|
|
321
356
|
if (stored) {
|
|
@@ -323,7 +358,7 @@ function ThemeProvider({ children }) {
|
|
|
323
358
|
}
|
|
324
359
|
}
|
|
325
360
|
}, []);
|
|
326
|
-
|
|
361
|
+
React11.useEffect(() => {
|
|
327
362
|
if (typeof window !== "undefined") {
|
|
328
363
|
if (theme === "system") {
|
|
329
364
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
@@ -338,7 +373,7 @@ function ThemeProvider({ children }) {
|
|
|
338
373
|
}
|
|
339
374
|
}
|
|
340
375
|
}, [theme]);
|
|
341
|
-
|
|
376
|
+
React11.useEffect(() => {
|
|
342
377
|
if (typeof window !== "undefined") {
|
|
343
378
|
const root = document.documentElement;
|
|
344
379
|
if (resolvedTheme === "dark") {
|
|
@@ -357,21 +392,21 @@ function ThemeProvider({ children }) {
|
|
|
357
392
|
return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: { theme, setTheme, resolvedTheme }, children });
|
|
358
393
|
}
|
|
359
394
|
function useTheme() {
|
|
360
|
-
const context =
|
|
395
|
+
const context = React11.useContext(ThemeContext);
|
|
361
396
|
if (context === void 0) {
|
|
362
397
|
throw new Error("useTheme must be used within a ThemeProvider");
|
|
363
398
|
}
|
|
364
399
|
return context;
|
|
365
400
|
}
|
|
366
401
|
var useMelony = (options) => {
|
|
367
|
-
const context =
|
|
402
|
+
const context = React11.useContext(MelonyContext);
|
|
368
403
|
if (context === void 0) {
|
|
369
404
|
throw new Error("useMelony must be used within a MelonyClientProvider");
|
|
370
405
|
}
|
|
371
406
|
const { client, reset } = context;
|
|
372
407
|
const { initialEvents } = options || {};
|
|
373
|
-
const prevInitialEventsRef =
|
|
374
|
-
|
|
408
|
+
const prevInitialEventsRef = React11.useRef(void 0);
|
|
409
|
+
React11.useEffect(() => {
|
|
375
410
|
const currentSerialized = initialEvents ? JSON.stringify(initialEvents) : void 0;
|
|
376
411
|
if (currentSerialized !== prevInitialEventsRef.current) {
|
|
377
412
|
if (initialEvents) {
|
|
@@ -385,19 +420,60 @@ var useMelony = (options) => {
|
|
|
385
420
|
return context;
|
|
386
421
|
};
|
|
387
422
|
var useAuth = () => {
|
|
388
|
-
const context =
|
|
423
|
+
const context = React11.useContext(AuthContext);
|
|
389
424
|
if (context === void 0) {
|
|
390
425
|
throw new Error("useAuth must be used within an AuthProvider");
|
|
391
426
|
}
|
|
392
427
|
return context;
|
|
393
428
|
};
|
|
394
429
|
var useThreads = () => {
|
|
395
|
-
const context =
|
|
430
|
+
const context = React11.useContext(ThreadContext);
|
|
396
431
|
if (context === void 0) {
|
|
397
432
|
throw new Error("useThreads must be used within a ThreadProvider");
|
|
398
433
|
}
|
|
399
434
|
return context;
|
|
400
435
|
};
|
|
436
|
+
function useScreenSize(mobileBreakpoint = 768, tabletBreakpoint = 1024) {
|
|
437
|
+
const [screenSize, setScreenSize] = React11.useState(() => {
|
|
438
|
+
if (typeof window === "undefined") {
|
|
439
|
+
return {
|
|
440
|
+
width: 1024,
|
|
441
|
+
height: 768,
|
|
442
|
+
isMobile: false,
|
|
443
|
+
isTablet: false,
|
|
444
|
+
isDesktop: true
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
const width = window.innerWidth;
|
|
448
|
+
return {
|
|
449
|
+
width,
|
|
450
|
+
height: window.innerHeight,
|
|
451
|
+
isMobile: width < mobileBreakpoint,
|
|
452
|
+
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
453
|
+
isDesktop: width >= tabletBreakpoint
|
|
454
|
+
};
|
|
455
|
+
});
|
|
456
|
+
React11.useEffect(() => {
|
|
457
|
+
if (typeof window === "undefined") return;
|
|
458
|
+
const updateScreenSize = () => {
|
|
459
|
+
const width = window.innerWidth;
|
|
460
|
+
const height = window.innerHeight;
|
|
461
|
+
setScreenSize({
|
|
462
|
+
width,
|
|
463
|
+
height,
|
|
464
|
+
isMobile: width < mobileBreakpoint,
|
|
465
|
+
isTablet: width >= mobileBreakpoint && width < tabletBreakpoint,
|
|
466
|
+
isDesktop: width >= tabletBreakpoint
|
|
467
|
+
});
|
|
468
|
+
};
|
|
469
|
+
updateScreenSize();
|
|
470
|
+
window.addEventListener("resize", updateScreenSize);
|
|
471
|
+
return () => {
|
|
472
|
+
window.removeEventListener("resize", updateScreenSize);
|
|
473
|
+
};
|
|
474
|
+
}, [mobileBreakpoint, tabletBreakpoint]);
|
|
475
|
+
return screenSize;
|
|
476
|
+
}
|
|
401
477
|
function cn(...inputs) {
|
|
402
478
|
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
403
479
|
}
|
|
@@ -458,6 +534,45 @@ function Textarea({ className, ...props }) {
|
|
|
458
534
|
}
|
|
459
535
|
);
|
|
460
536
|
}
|
|
537
|
+
var badgeVariants = classVarianceAuthority.cva(
|
|
538
|
+
"h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge",
|
|
539
|
+
{
|
|
540
|
+
variants: {
|
|
541
|
+
variant: {
|
|
542
|
+
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
543
|
+
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
544
|
+
destructive: "bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20",
|
|
545
|
+
outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/30",
|
|
546
|
+
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
|
547
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
548
|
+
}
|
|
549
|
+
},
|
|
550
|
+
defaultVariants: {
|
|
551
|
+
variant: "default"
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
);
|
|
555
|
+
function Badge({
|
|
556
|
+
className,
|
|
557
|
+
variant = "default",
|
|
558
|
+
render,
|
|
559
|
+
...props
|
|
560
|
+
}) {
|
|
561
|
+
return useRender.useRender({
|
|
562
|
+
defaultTagName: "span",
|
|
563
|
+
props: mergeProps.mergeProps(
|
|
564
|
+
{
|
|
565
|
+
className: cn(badgeVariants({ className, variant }))
|
|
566
|
+
},
|
|
567
|
+
props
|
|
568
|
+
),
|
|
569
|
+
render,
|
|
570
|
+
state: {
|
|
571
|
+
slot: "badge",
|
|
572
|
+
variant
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
}
|
|
461
576
|
function DropdownMenu({ ...props }) {
|
|
462
577
|
return /* @__PURE__ */ jsxRuntime.jsx(menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
463
578
|
}
|
|
@@ -584,11 +699,18 @@ function Composer({
|
|
|
584
699
|
className,
|
|
585
700
|
options = [],
|
|
586
701
|
autoFocus = false,
|
|
587
|
-
defaultSelectedIds = []
|
|
702
|
+
defaultSelectedIds = [],
|
|
703
|
+
fileAttachments
|
|
588
704
|
}) {
|
|
589
|
-
const
|
|
705
|
+
const enabled = fileAttachments?.enabled || false;
|
|
706
|
+
const accept = fileAttachments?.accept;
|
|
707
|
+
const maxFiles = fileAttachments?.maxFiles ?? 10;
|
|
708
|
+
const maxFileSize = fileAttachments?.maxFileSize ?? 10 * 1024 * 1024;
|
|
709
|
+
const [selectedOptions, setSelectedOptions] = React11__namespace.default.useState(
|
|
590
710
|
() => new Set(defaultSelectedIds)
|
|
591
711
|
);
|
|
712
|
+
const [attachedFiles, setAttachedFiles] = React11__namespace.default.useState([]);
|
|
713
|
+
const fileInputRef = React11__namespace.default.useRef(null);
|
|
592
714
|
const toggleOption = (id, groupOptions, type = "multiple") => {
|
|
593
715
|
const next = new Set(selectedOptions);
|
|
594
716
|
if (type === "single") {
|
|
@@ -608,7 +730,38 @@ function Composer({
|
|
|
608
730
|
}
|
|
609
731
|
setSelectedOptions(next);
|
|
610
732
|
};
|
|
611
|
-
const
|
|
733
|
+
const handleFileSelect = (e) => {
|
|
734
|
+
const files = Array.from(e.target.files || []);
|
|
735
|
+
const validFiles = files.filter((file) => {
|
|
736
|
+
if (file.size > maxFileSize) {
|
|
737
|
+
console.warn(
|
|
738
|
+
`File ${file.name} exceeds maximum size of ${maxFileSize} bytes`
|
|
739
|
+
);
|
|
740
|
+
return false;
|
|
741
|
+
}
|
|
742
|
+
return true;
|
|
743
|
+
});
|
|
744
|
+
const remainingSlots = maxFiles - attachedFiles.length;
|
|
745
|
+
const filesToAdd = validFiles.slice(0, remainingSlots);
|
|
746
|
+
if (filesToAdd.length < validFiles.length) {
|
|
747
|
+
console.warn(
|
|
748
|
+
`Only ${filesToAdd.length} files can be added (max: ${maxFiles})`
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
setAttachedFiles((prev) => [...prev, ...filesToAdd]);
|
|
752
|
+
if (fileInputRef.current) {
|
|
753
|
+
fileInputRef.current.value = "";
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
const handleRemoveFile = (index) => {
|
|
757
|
+
setAttachedFiles((prev) => prev.filter((_, i) => i !== index));
|
|
758
|
+
};
|
|
759
|
+
const formatFileSize = (bytes) => {
|
|
760
|
+
if (bytes < 1024) return bytes + " B";
|
|
761
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
|
762
|
+
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
|
763
|
+
};
|
|
764
|
+
const handleInternalSubmit = async () => {
|
|
612
765
|
const state = {};
|
|
613
766
|
options.forEach((group) => {
|
|
614
767
|
const selectedInGroup = group.options.filter(
|
|
@@ -625,12 +778,52 @@ function Composer({
|
|
|
625
778
|
}
|
|
626
779
|
}
|
|
627
780
|
});
|
|
781
|
+
if (attachedFiles.length > 0) {
|
|
782
|
+
const filePromises = attachedFiles.map((file) => {
|
|
783
|
+
return new Promise((resolve, reject) => {
|
|
784
|
+
const reader = new FileReader();
|
|
785
|
+
reader.onload = () => {
|
|
786
|
+
try {
|
|
787
|
+
const base64 = reader.result;
|
|
788
|
+
if (!base64) {
|
|
789
|
+
reject(new Error("FileReader returned empty result"));
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
resolve({
|
|
793
|
+
name: file.name,
|
|
794
|
+
type: file.type,
|
|
795
|
+
size: file.size,
|
|
796
|
+
data: base64
|
|
797
|
+
});
|
|
798
|
+
} catch (error) {
|
|
799
|
+
reject(error);
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
reader.onerror = (error) => {
|
|
803
|
+
reject(new Error(`Failed to read file ${file.name}: ${error}`));
|
|
804
|
+
};
|
|
805
|
+
reader.onabort = () => {
|
|
806
|
+
reject(new Error(`File read aborted for ${file.name}`));
|
|
807
|
+
};
|
|
808
|
+
reader.readAsDataURL(file);
|
|
809
|
+
});
|
|
810
|
+
});
|
|
811
|
+
try {
|
|
812
|
+
const convertedFiles = await Promise.all(filePromises);
|
|
813
|
+
if (convertedFiles.length > 0) {
|
|
814
|
+
state.files = convertedFiles;
|
|
815
|
+
}
|
|
816
|
+
} catch (error) {
|
|
817
|
+
console.error("Failed to convert files to base64:", error);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
628
820
|
onSubmit(state);
|
|
821
|
+
setAttachedFiles([]);
|
|
629
822
|
};
|
|
630
823
|
const handleKeyDown = (e) => {
|
|
631
824
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
632
825
|
e.preventDefault();
|
|
633
|
-
handleInternalSubmit();
|
|
826
|
+
handleInternalSubmit().catch(console.error);
|
|
634
827
|
}
|
|
635
828
|
};
|
|
636
829
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative flex flex-col w-full", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col w-full border-input border-[1.5px] rounded-3xl bg-background shadow-sm focus-within:border-ring transition-all p-2", children: [
|
|
@@ -646,59 +839,171 @@ function Composer({
|
|
|
646
839
|
}
|
|
647
840
|
),
|
|
648
841
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center px-1", children: [
|
|
649
|
-
/* @__PURE__ */ jsxRuntime.
|
|
650
|
-
|
|
651
|
-
(o) => selectedOptions.has(o.id)
|
|
652
|
-
);
|
|
653
|
-
const label = selectedInGroup.length === 0 ? group.label : selectedInGroup.length === 1 ? selectedInGroup[0].label : `${group.label} (${selectedInGroup.length})`;
|
|
654
|
-
const isSingle = group.type === "single";
|
|
655
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
842
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
843
|
+
enabled && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
656
844
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
657
|
-
|
|
845
|
+
"input",
|
|
658
846
|
{
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
),
|
|
667
|
-
children: [
|
|
668
|
-
label,
|
|
669
|
-
/* @__PURE__ */ jsxRuntime.jsx(ICONS.IconChevronDown, { className: "h-3 w-3 opacity-50" })
|
|
670
|
-
]
|
|
671
|
-
}
|
|
672
|
-
)
|
|
847
|
+
ref: fileInputRef,
|
|
848
|
+
type: "file",
|
|
849
|
+
multiple: true,
|
|
850
|
+
accept,
|
|
851
|
+
onChange: handleFileSelect,
|
|
852
|
+
className: "hidden",
|
|
853
|
+
disabled: isLoading || attachedFiles.length >= maxFiles
|
|
673
854
|
}
|
|
674
855
|
),
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
856
|
+
attachedFiles.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
857
|
+
Button,
|
|
858
|
+
{
|
|
859
|
+
type: "button",
|
|
860
|
+
variant: "ghost",
|
|
861
|
+
size: "sm",
|
|
862
|
+
onClick: () => fileInputRef.current?.click(),
|
|
863
|
+
disabled: isLoading,
|
|
864
|
+
className: "text-muted-foreground",
|
|
865
|
+
title: "Attach file",
|
|
866
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPaperclip, { className: "h-4 w-4" })
|
|
867
|
+
}
|
|
868
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
869
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
870
|
+
DropdownMenuTrigger,
|
|
680
871
|
{
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
872
|
+
render: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
873
|
+
Button,
|
|
874
|
+
{
|
|
875
|
+
type: "button",
|
|
876
|
+
variant: "ghost",
|
|
877
|
+
size: "sm",
|
|
878
|
+
className: "text-muted-foreground gap-2",
|
|
879
|
+
title: `${attachedFiles.length} files attached`,
|
|
880
|
+
children: [
|
|
881
|
+
/* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPaperclip, { className: "h-4 w-4" }),
|
|
882
|
+
/* @__PURE__ */ jsxRuntime.jsx(Badge, { className: "h-[18px] min-w-[18px] px-1.5 text-[10px]", children: attachedFiles.length })
|
|
883
|
+
]
|
|
884
|
+
}
|
|
885
|
+
)
|
|
886
|
+
}
|
|
887
|
+
),
|
|
888
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "start", className: "w-64", children: [
|
|
889
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuGroup, { children: [
|
|
890
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuLabel, { children: [
|
|
891
|
+
"Attached Files (",
|
|
892
|
+
attachedFiles.length,
|
|
893
|
+
"/",
|
|
894
|
+
maxFiles,
|
|
895
|
+
")"
|
|
896
|
+
] }),
|
|
897
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
898
|
+
attachedFiles.map((file, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
899
|
+
DropdownMenuItem,
|
|
900
|
+
{
|
|
901
|
+
className: "flex items-center justify-between group",
|
|
902
|
+
onSelect: (e) => e.preventDefault(),
|
|
903
|
+
children: [
|
|
904
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
905
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
906
|
+
"span",
|
|
907
|
+
{
|
|
908
|
+
className: "truncate text-sm",
|
|
909
|
+
title: file.name,
|
|
910
|
+
children: file.name
|
|
911
|
+
}
|
|
912
|
+
),
|
|
913
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground", children: formatFileSize(file.size) })
|
|
914
|
+
] }),
|
|
915
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
916
|
+
Button,
|
|
917
|
+
{
|
|
918
|
+
type: "button",
|
|
919
|
+
variant: "ghost",
|
|
920
|
+
size: "icon",
|
|
921
|
+
className: "h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
922
|
+
onClick: () => handleRemoveFile(index),
|
|
923
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconX, { className: "h-3 w-3" })
|
|
924
|
+
}
|
|
925
|
+
)
|
|
926
|
+
]
|
|
927
|
+
},
|
|
928
|
+
index
|
|
929
|
+
))
|
|
930
|
+
] }),
|
|
931
|
+
attachedFiles.length < maxFiles && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
932
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
933
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
934
|
+
DropdownMenuItem,
|
|
935
|
+
{
|
|
936
|
+
onSelect: (e) => {
|
|
937
|
+
e.preventDefault();
|
|
938
|
+
fileInputRef.current?.click();
|
|
939
|
+
},
|
|
940
|
+
className: "text-primary focus:text-primary",
|
|
941
|
+
children: [
|
|
942
|
+
/* @__PURE__ */ jsxRuntime.jsx(ICONS.IconPlus, { className: "mr-2 h-4 w-4" }),
|
|
943
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Add more files" })
|
|
944
|
+
]
|
|
945
|
+
}
|
|
946
|
+
)
|
|
947
|
+
] })
|
|
948
|
+
] })
|
|
949
|
+
] })
|
|
950
|
+
] }),
|
|
951
|
+
options.map((group) => {
|
|
952
|
+
const selectedInGroup = group.options.filter(
|
|
953
|
+
(o) => selectedOptions.has(o.id)
|
|
954
|
+
);
|
|
955
|
+
const label = selectedInGroup.length === 0 ? group.label : selectedInGroup.length === 1 ? selectedInGroup[0].label : group.label;
|
|
956
|
+
const isSingle = group.type === "single";
|
|
957
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
|
|
958
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
959
|
+
DropdownMenuTrigger,
|
|
960
|
+
{
|
|
961
|
+
render: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
962
|
+
Button,
|
|
963
|
+
{
|
|
964
|
+
variant: "ghost",
|
|
965
|
+
size: "sm",
|
|
966
|
+
className: cn(
|
|
967
|
+
"gap-2",
|
|
968
|
+
selectedInGroup.length > 0 ? "text-foreground bg-muted/50" : "text-muted-foreground"
|
|
969
|
+
),
|
|
970
|
+
children: [
|
|
971
|
+
label,
|
|
972
|
+
selectedInGroup.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { className: "h-[18px] min-w-[18px] px-1.5 text-[10px]", children: selectedInGroup.length }),
|
|
973
|
+
/* @__PURE__ */ jsxRuntime.jsx(ICONS.IconChevronDown, { className: "h-3 w-3 opacity-50" })
|
|
974
|
+
]
|
|
975
|
+
}
|
|
976
|
+
)
|
|
977
|
+
}
|
|
978
|
+
),
|
|
979
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuContent, { align: "start", className: "w-56", children: /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuGroup, { children: [
|
|
980
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuLabel, { children: group.label }),
|
|
981
|
+
/* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
|
|
982
|
+
group.options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
983
|
+
DropdownMenuCheckboxItem,
|
|
984
|
+
{
|
|
985
|
+
checked: selectedOptions.has(option.id),
|
|
986
|
+
onCheckedChange: () => toggleOption(
|
|
987
|
+
option.id,
|
|
988
|
+
group.options,
|
|
989
|
+
isSingle ? "single" : "multiple"
|
|
990
|
+
),
|
|
991
|
+
onSelect: (e) => e.preventDefault(),
|
|
992
|
+
children: option.label
|
|
993
|
+
},
|
|
994
|
+
option.id
|
|
995
|
+
))
|
|
996
|
+
] }) })
|
|
997
|
+
] }, group.id);
|
|
998
|
+
})
|
|
999
|
+
] }),
|
|
695
1000
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
696
1001
|
Button,
|
|
697
1002
|
{
|
|
698
1003
|
type: "submit",
|
|
699
|
-
disabled: !value.trim() && !isLoading || isLoading,
|
|
1004
|
+
disabled: !value.trim() && attachedFiles.length === 0 && !isLoading || isLoading,
|
|
700
1005
|
size: "icon-lg",
|
|
701
|
-
onClick: handleInternalSubmit,
|
|
1006
|
+
onClick: () => handleInternalSubmit().catch(console.error),
|
|
702
1007
|
children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLoader2, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconArrowUp, { className: "h-5 w-5" })
|
|
703
1008
|
}
|
|
704
1009
|
)
|
|
@@ -835,8 +1140,6 @@ var Col = ({
|
|
|
835
1140
|
gap = "sm",
|
|
836
1141
|
align = "start",
|
|
837
1142
|
justify = "start",
|
|
838
|
-
wrap = "nowrap",
|
|
839
|
-
flex = 1,
|
|
840
1143
|
width,
|
|
841
1144
|
height,
|
|
842
1145
|
padding,
|
|
@@ -886,13 +1189,11 @@ var Col = ({
|
|
|
886
1189
|
gapClasses[gap] || "gap-2",
|
|
887
1190
|
alignClasses[align] || "items-start",
|
|
888
1191
|
justifyClasses[justify] || "justify-start",
|
|
889
|
-
wrap === "wrap" ? "flex-wrap" : "flex-nowrap",
|
|
890
1192
|
overflow && overflowClasses[overflow],
|
|
891
1193
|
position && positionClasses[position],
|
|
892
1194
|
className
|
|
893
1195
|
),
|
|
894
1196
|
style: {
|
|
895
|
-
flex,
|
|
896
1197
|
width,
|
|
897
1198
|
height,
|
|
898
1199
|
padding,
|
|
@@ -1200,9 +1501,9 @@ var Image = ({
|
|
|
1200
1501
|
className,
|
|
1201
1502
|
style
|
|
1202
1503
|
}) => {
|
|
1203
|
-
const [hasError, setHasError] =
|
|
1204
|
-
const [isLoading, setIsLoading] =
|
|
1205
|
-
const [open, setOpen] =
|
|
1504
|
+
const [hasError, setHasError] = React11.useState(false);
|
|
1505
|
+
const [isLoading, setIsLoading] = React11.useState(true);
|
|
1506
|
+
const [open, setOpen] = React11.useState(false);
|
|
1206
1507
|
const sizes = {
|
|
1207
1508
|
sm: "h-11",
|
|
1208
1509
|
md: "h-22",
|
|
@@ -1326,45 +1627,6 @@ var Icon = ({
|
|
|
1326
1627
|
}
|
|
1327
1628
|
);
|
|
1328
1629
|
};
|
|
1329
|
-
var badgeVariants = classVarianceAuthority.cva(
|
|
1330
|
-
"h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-colors overflow-hidden group/badge",
|
|
1331
|
-
{
|
|
1332
|
-
variants: {
|
|
1333
|
-
variant: {
|
|
1334
|
-
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
|
1335
|
-
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
|
1336
|
-
destructive: "bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20",
|
|
1337
|
-
outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground bg-input/30",
|
|
1338
|
-
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
|
1339
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
1340
|
-
}
|
|
1341
|
-
},
|
|
1342
|
-
defaultVariants: {
|
|
1343
|
-
variant: "default"
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
);
|
|
1347
|
-
function Badge({
|
|
1348
|
-
className,
|
|
1349
|
-
variant = "default",
|
|
1350
|
-
render,
|
|
1351
|
-
...props
|
|
1352
|
-
}) {
|
|
1353
|
-
return useRender.useRender({
|
|
1354
|
-
defaultTagName: "span",
|
|
1355
|
-
props: mergeProps.mergeProps(
|
|
1356
|
-
{
|
|
1357
|
-
className: cn(badgeVariants({ className, variant }))
|
|
1358
|
-
},
|
|
1359
|
-
props
|
|
1360
|
-
),
|
|
1361
|
-
render,
|
|
1362
|
-
state: {
|
|
1363
|
-
slot: "badge",
|
|
1364
|
-
variant
|
|
1365
|
-
}
|
|
1366
|
-
});
|
|
1367
|
-
}
|
|
1368
1630
|
var Badge2 = ({
|
|
1369
1631
|
label,
|
|
1370
1632
|
variant = "primary",
|
|
@@ -1400,7 +1662,7 @@ var Chart = ({
|
|
|
1400
1662
|
className,
|
|
1401
1663
|
style
|
|
1402
1664
|
}) => {
|
|
1403
|
-
const [tooltip, setTooltip] =
|
|
1665
|
+
const [tooltip, setTooltip] = React11.useState(null);
|
|
1404
1666
|
if (!Array.isArray(data)) {
|
|
1405
1667
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-destructive border border-destructive/20 rounded-md bg-destructive/5", children: "Error: Chart data must be an array" });
|
|
1406
1668
|
}
|
|
@@ -1953,9 +2215,9 @@ var Select2 = ({
|
|
|
1953
2215
|
defaultValue,
|
|
1954
2216
|
value,
|
|
1955
2217
|
disabled,
|
|
1956
|
-
onValueChange: handleValueChange,
|
|
2218
|
+
onValueChange: (value2) => handleValueChange(value2 || ""),
|
|
1957
2219
|
children: [
|
|
1958
|
-
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, {
|
|
2220
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, {}) }),
|
|
1959
2221
|
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
1960
2222
|
]
|
|
1961
2223
|
}
|
|
@@ -1985,7 +2247,6 @@ var Label2 = ({
|
|
|
1985
2247
|
var Checkbox = ({
|
|
1986
2248
|
label,
|
|
1987
2249
|
name,
|
|
1988
|
-
value = "on",
|
|
1989
2250
|
checked,
|
|
1990
2251
|
defaultChecked,
|
|
1991
2252
|
disabled,
|
|
@@ -2000,46 +2261,37 @@ var Checkbox = ({
|
|
|
2000
2261
|
...onChangeAction,
|
|
2001
2262
|
data: {
|
|
2002
2263
|
name: name || "",
|
|
2003
|
-
value,
|
|
2004
2264
|
checked: e.target.checked
|
|
2005
2265
|
}
|
|
2006
2266
|
});
|
|
2007
2267
|
}
|
|
2008
2268
|
};
|
|
2009
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
{
|
|
2032
|
-
htmlFor: name,
|
|
2033
|
-
value: label,
|
|
2034
|
-
className: cn(
|
|
2035
|
-
"cursor-pointer select-none text-sm font-medium leading-none",
|
|
2036
|
-
disabled && "cursor-not-allowed opacity-50"
|
|
2037
|
-
)
|
|
2038
|
-
}
|
|
2269
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2", className), style, children: [
|
|
2270
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2271
|
+
"input",
|
|
2272
|
+
{
|
|
2273
|
+
type: "checkbox",
|
|
2274
|
+
name,
|
|
2275
|
+
id: name,
|
|
2276
|
+
checked,
|
|
2277
|
+
defaultChecked,
|
|
2278
|
+
disabled,
|
|
2279
|
+
onChange: handleChange,
|
|
2280
|
+
className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary disabled:cursor-not-allowed disabled:opacity-50"
|
|
2281
|
+
}
|
|
2282
|
+
),
|
|
2283
|
+
label && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2284
|
+
Label2,
|
|
2285
|
+
{
|
|
2286
|
+
htmlFor: name,
|
|
2287
|
+
value: label,
|
|
2288
|
+
className: cn(
|
|
2289
|
+
"cursor-pointer select-none text-sm font-medium leading-none",
|
|
2290
|
+
disabled && "cursor-not-allowed opacity-50"
|
|
2039
2291
|
)
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
);
|
|
2292
|
+
}
|
|
2293
|
+
)
|
|
2294
|
+
] });
|
|
2043
2295
|
};
|
|
2044
2296
|
var RadioGroup = ({
|
|
2045
2297
|
name,
|
|
@@ -2156,7 +2408,7 @@ var Button2 = ({
|
|
|
2156
2408
|
};
|
|
2157
2409
|
var Form = ({ children, onSubmitAction, className, style }) => {
|
|
2158
2410
|
const { sendEvent } = useMelony();
|
|
2159
|
-
const [isSubmitted, setIsSubmitted] =
|
|
2411
|
+
const [isSubmitted, setIsSubmitted] = React11.useState(false);
|
|
2160
2412
|
const handleSubmit = (e) => {
|
|
2161
2413
|
e.preventDefault();
|
|
2162
2414
|
if (isSubmitted) return;
|
|
@@ -2303,7 +2555,7 @@ function MessageBubble({ message }) {
|
|
|
2303
2555
|
);
|
|
2304
2556
|
}
|
|
2305
2557
|
function LoadingIndicator({ status }) {
|
|
2306
|
-
const [isExpanded, setIsExpanded] =
|
|
2558
|
+
const [isExpanded, setIsExpanded] = React11.useState(false);
|
|
2307
2559
|
const message = status?.message || "Processing...";
|
|
2308
2560
|
const details = status?.details;
|
|
2309
2561
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
@@ -2335,7 +2587,7 @@ function MessageList({
|
|
|
2335
2587
|
if (messages.length === 0) {
|
|
2336
2588
|
return null;
|
|
2337
2589
|
}
|
|
2338
|
-
const isTextStreaming =
|
|
2590
|
+
const isTextStreaming = React11.useMemo(() => {
|
|
2339
2591
|
if (messages.length === 0 || !isLoading) return false;
|
|
2340
2592
|
const lastMessage = messages[messages.length - 1];
|
|
2341
2593
|
return lastMessage.content.some((event) => event.type === "text-delta");
|
|
@@ -2362,28 +2614,31 @@ function Thread({
|
|
|
2362
2614
|
});
|
|
2363
2615
|
const starterPrompts = localStarterPrompts ?? config?.starterPrompts;
|
|
2364
2616
|
const options = localOptions ?? config?.options;
|
|
2365
|
-
const
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
) ?? [];
|
|
2617
|
+
const fileAttachments = config?.fileAttachments;
|
|
2618
|
+
const allDefaultSelectedIds = React11.useMemo(() => {
|
|
2619
|
+
const defaultSelectedIdsFromOptions = options?.flatMap((group) => group.defaultSelectedIds ?? []) ?? [];
|
|
2369
2620
|
return [
|
|
2370
|
-
.../* @__PURE__ */ new Set([
|
|
2621
|
+
.../* @__PURE__ */ new Set([
|
|
2622
|
+
...defaultSelectedIdsFromOptions,
|
|
2623
|
+
...defaultSelectedIds ?? []
|
|
2624
|
+
])
|
|
2371
2625
|
];
|
|
2372
2626
|
}, [options, defaultSelectedIds]);
|
|
2373
|
-
const [input, setInput] =
|
|
2374
|
-
const messagesEndRef =
|
|
2375
|
-
|
|
2627
|
+
const [input, setInput] = React11.useState("");
|
|
2628
|
+
const messagesEndRef = React11.useRef(null);
|
|
2629
|
+
React11.useEffect(() => {
|
|
2376
2630
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
2377
2631
|
}, [messages]);
|
|
2378
2632
|
const handleSubmit = async (state, overrideInput) => {
|
|
2379
2633
|
const text = (overrideInput ?? input).trim();
|
|
2380
|
-
|
|
2634
|
+
const hasFiles = state?.files && Array.isArray(state.files) && state.files.length > 0;
|
|
2635
|
+
if (!text && !hasFiles || isLoading) return;
|
|
2381
2636
|
if (!overrideInput) setInput("");
|
|
2382
2637
|
await sendEvent(
|
|
2383
2638
|
{
|
|
2384
2639
|
type: "text",
|
|
2385
2640
|
role: "user",
|
|
2386
|
-
data: { content: text }
|
|
2641
|
+
data: { content: text || "" }
|
|
2387
2642
|
},
|
|
2388
2643
|
{ state: { ...state, threadId: activeThreadId ?? void 0 } }
|
|
2389
2644
|
);
|
|
@@ -2441,7 +2696,8 @@ function Thread({
|
|
|
2441
2696
|
isLoading,
|
|
2442
2697
|
options,
|
|
2443
2698
|
autoFocus,
|
|
2444
|
-
defaultSelectedIds: allDefaultSelectedIds
|
|
2699
|
+
defaultSelectedIds: allDefaultSelectedIds,
|
|
2700
|
+
fileAttachments
|
|
2445
2701
|
}
|
|
2446
2702
|
) }) })
|
|
2447
2703
|
]
|
|
@@ -2449,20 +2705,36 @@ function Thread({
|
|
|
2449
2705
|
);
|
|
2450
2706
|
}
|
|
2451
2707
|
function ChatHeader({
|
|
2452
|
-
title,
|
|
2453
2708
|
leftContent,
|
|
2454
2709
|
rightContent,
|
|
2455
2710
|
className,
|
|
2456
|
-
titleClassName,
|
|
2457
2711
|
children
|
|
2458
2712
|
}) {
|
|
2459
2713
|
if (children) {
|
|
2460
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2714
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2715
|
+
"div",
|
|
2716
|
+
{
|
|
2717
|
+
className: cn(
|
|
2718
|
+
"px-2 border-b border-border h-14 flex items-center shrink-0",
|
|
2719
|
+
className
|
|
2720
|
+
),
|
|
2721
|
+
children
|
|
2722
|
+
}
|
|
2723
|
+
);
|
|
2461
2724
|
}
|
|
2462
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2725
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2726
|
+
"div",
|
|
2727
|
+
{
|
|
2728
|
+
className: cn(
|
|
2729
|
+
"px-2 border-b border-border h-14 flex items-center justify-between shrink-0",
|
|
2730
|
+
className
|
|
2731
|
+
),
|
|
2732
|
+
children: [
|
|
2733
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: leftContent }),
|
|
2734
|
+
rightContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1 shrink-0 ml-2", children: rightContent })
|
|
2735
|
+
]
|
|
2736
|
+
}
|
|
2737
|
+
);
|
|
2466
2738
|
}
|
|
2467
2739
|
var ThreadList = ({
|
|
2468
2740
|
className,
|
|
@@ -2513,58 +2785,43 @@ var ThreadList = ({
|
|
|
2513
2785
|
if (diffDays < 7) return `${diffDays}d ago`;
|
|
2514
2786
|
return d.toLocaleDateString();
|
|
2515
2787
|
};
|
|
2516
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
2517
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2518
|
-
|
|
2788
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col h-full", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto", children: isLoading && threads.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLoader2, { className: "size-5 animate-spin text-muted-foreground" }) }) : threads.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-center text-muted-foreground", children: emptyState || /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
2789
|
+
/* @__PURE__ */ jsxRuntime.jsx(ICONS.IconMessage, { className: "size-8 mx-auto opacity-50" }),
|
|
2790
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No threads yet" }),
|
|
2791
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", onClick: handleNewThread, children: "Start a conversation" })
|
|
2792
|
+
] }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 space-y-1", children: threads.map((thread) => {
|
|
2793
|
+
const isActive = thread.id === activeThreadId;
|
|
2794
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2795
|
+
"div",
|
|
2519
2796
|
{
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2797
|
+
onClick: () => handleThreadClick(thread.id),
|
|
2798
|
+
className: cn(
|
|
2799
|
+
"group relative flex items-center gap-3 px-3 py-1.5 rounded-lg cursor-pointer transition-colors",
|
|
2800
|
+
isActive ? "bg-muted" : "hover:bg-muted"
|
|
2801
|
+
),
|
|
2524
2802
|
children: [
|
|
2525
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2526
|
-
|
|
2803
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2804
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-sm font-medium truncate"), children: thread.title || `Thread ${thread.id.slice(0, 8)}` }),
|
|
2805
|
+
thread.updatedAt && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs shrink-0"), children: formatDate(thread.updatedAt) })
|
|
2806
|
+
] }) }),
|
|
2807
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2808
|
+
Button,
|
|
2809
|
+
{
|
|
2810
|
+
variant: "ghost",
|
|
2811
|
+
size: "icon-xs",
|
|
2812
|
+
onClick: (e) => handleDelete(e, thread.id),
|
|
2813
|
+
className: cn(
|
|
2814
|
+
"opacity-0 group-hover:opacity-100 transition-opacity shrink-0",
|
|
2815
|
+
isActive && "hover:bg-primary-foreground/20"
|
|
2816
|
+
),
|
|
2817
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconTrash, { className: "size-3" })
|
|
2818
|
+
}
|
|
2819
|
+
)
|
|
2527
2820
|
]
|
|
2528
|
-
}
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "No threads yet" }),
|
|
2533
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", onClick: handleNewThread, children: "Start a conversation" })
|
|
2534
|
-
] }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 space-y-1", children: threads.map((thread) => {
|
|
2535
|
-
const isActive = thread.id === activeThreadId;
|
|
2536
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2537
|
-
"div",
|
|
2538
|
-
{
|
|
2539
|
-
onClick: () => handleThreadClick(thread.id),
|
|
2540
|
-
className: cn(
|
|
2541
|
-
"group relative flex items-center gap-3 px-3 py-1.5 rounded-lg cursor-pointer transition-colors",
|
|
2542
|
-
isActive ? "bg-muted" : "hover:bg-muted"
|
|
2543
|
-
),
|
|
2544
|
-
children: [
|
|
2545
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2546
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-sm font-medium truncate"), children: thread.title || `Thread ${thread.id.slice(0, 8)}` }),
|
|
2547
|
-
thread.updatedAt && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs shrink-0"), children: formatDate(thread.updatedAt) })
|
|
2548
|
-
] }) }),
|
|
2549
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2550
|
-
Button,
|
|
2551
|
-
{
|
|
2552
|
-
variant: "ghost",
|
|
2553
|
-
size: "icon-xs",
|
|
2554
|
-
onClick: (e) => handleDelete(e, thread.id),
|
|
2555
|
-
className: cn(
|
|
2556
|
-
"opacity-0 group-hover:opacity-100 transition-opacity shrink-0",
|
|
2557
|
-
isActive && "hover:bg-primary-foreground/20"
|
|
2558
|
-
),
|
|
2559
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconTrash, { className: "size-3" })
|
|
2560
|
-
}
|
|
2561
|
-
)
|
|
2562
|
-
]
|
|
2563
|
-
},
|
|
2564
|
-
thread.id
|
|
2565
|
-
);
|
|
2566
|
-
}) }) })
|
|
2567
|
-
] });
|
|
2821
|
+
},
|
|
2822
|
+
thread.id
|
|
2823
|
+
);
|
|
2824
|
+
}) }) }) });
|
|
2568
2825
|
};
|
|
2569
2826
|
function ChatPopup({
|
|
2570
2827
|
title = "Chat",
|
|
@@ -2575,8 +2832,8 @@ function ChatPopup({
|
|
|
2575
2832
|
headerProps,
|
|
2576
2833
|
defaultSelectedIds
|
|
2577
2834
|
}) {
|
|
2578
|
-
const [isOpen, setIsOpen] =
|
|
2579
|
-
const [view, setView] =
|
|
2835
|
+
const [isOpen, setIsOpen] = React11.useState(defaultOpen);
|
|
2836
|
+
const [view, setView] = React11.useState("chat");
|
|
2580
2837
|
const { createThread } = useThreads();
|
|
2581
2838
|
const handleNewChat = async () => {
|
|
2582
2839
|
try {
|
|
@@ -2693,6 +2950,16 @@ function ChatSidebar({
|
|
|
2693
2950
|
) })
|
|
2694
2951
|
] });
|
|
2695
2952
|
}
|
|
2953
|
+
var ChatSidebarContext = React11.createContext(
|
|
2954
|
+
void 0
|
|
2955
|
+
);
|
|
2956
|
+
function useChatSidebar() {
|
|
2957
|
+
const context = React11.useContext(ChatSidebarContext);
|
|
2958
|
+
if (context === void 0) {
|
|
2959
|
+
throw new Error("useChatSidebar must be used within a ChatSidebarProvider");
|
|
2960
|
+
}
|
|
2961
|
+
return context;
|
|
2962
|
+
}
|
|
2696
2963
|
function ChatFull({
|
|
2697
2964
|
title = "Chat",
|
|
2698
2965
|
placeholder = "Message the AI",
|
|
@@ -2704,134 +2971,134 @@ function ChatFull({
|
|
|
2704
2971
|
rightSidebar,
|
|
2705
2972
|
leftSidebarClassName,
|
|
2706
2973
|
rightSidebarClassName,
|
|
2707
|
-
leftSidebarCollapsible = false,
|
|
2708
|
-
rightSidebarCollapsible = false,
|
|
2709
|
-
defaultLeftSidebarCollapsed = false,
|
|
2710
|
-
defaultRightSidebarCollapsed = false,
|
|
2711
|
-
leftSidebarCollapsed: controlledLeftCollapsed,
|
|
2712
|
-
rightSidebarCollapsed: controlledRightCollapsed,
|
|
2713
|
-
onLeftSidebarCollapseChange,
|
|
2714
|
-
onRightSidebarCollapseChange,
|
|
2715
2974
|
autoFocus = false,
|
|
2716
2975
|
defaultSelectedIds
|
|
2717
2976
|
}) {
|
|
2718
|
-
const
|
|
2719
|
-
|
|
2720
|
-
)
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
);
|
|
2724
|
-
const leftCollapsed = controlledLeftCollapsed !== void 0 ? controlledLeftCollapsed : internalLeftCollapsed;
|
|
2725
|
-
const rightCollapsed = controlledRightCollapsed !== void 0 ? controlledRightCollapsed : internalRightCollapsed;
|
|
2726
|
-
const handleLeftToggle = () => {
|
|
2727
|
-
const newCollapsed = !leftCollapsed;
|
|
2728
|
-
if (controlledLeftCollapsed === void 0) {
|
|
2729
|
-
setInternalLeftCollapsed(newCollapsed);
|
|
2977
|
+
const { isMobile, isTablet } = useScreenSize();
|
|
2978
|
+
const isSmallScreen = isMobile || isTablet;
|
|
2979
|
+
const [internalLeftCollapsed, setInternalLeftCollapsed] = React11.useState(() => {
|
|
2980
|
+
if (typeof window !== "undefined") {
|
|
2981
|
+
return window.innerWidth < 1024;
|
|
2730
2982
|
}
|
|
2731
|
-
|
|
2732
|
-
};
|
|
2733
|
-
const
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
setInternalRightCollapsed(newCollapsed);
|
|
2983
|
+
return false;
|
|
2984
|
+
});
|
|
2985
|
+
const [internalRightCollapsed, setInternalRightCollapsed] = React11.useState(() => {
|
|
2986
|
+
if (typeof window !== "undefined") {
|
|
2987
|
+
return window.innerWidth < 1024;
|
|
2737
2988
|
}
|
|
2738
|
-
|
|
2739
|
-
};
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2989
|
+
return false;
|
|
2990
|
+
});
|
|
2991
|
+
React11.useEffect(() => {
|
|
2992
|
+
if (isSmallScreen) {
|
|
2993
|
+
setInternalLeftCollapsed(true);
|
|
2994
|
+
setInternalRightCollapsed(true);
|
|
2995
|
+
}
|
|
2996
|
+
}, [isSmallScreen]);
|
|
2997
|
+
const leftCollapsed = internalLeftCollapsed;
|
|
2998
|
+
const rightCollapsed = internalRightCollapsed;
|
|
2999
|
+
const handleLeftToggle = React11.useCallback((collapsed) => {
|
|
3000
|
+
setInternalLeftCollapsed(collapsed);
|
|
3001
|
+
}, []);
|
|
3002
|
+
const handleRightToggle = React11.useCallback((collapsed) => {
|
|
3003
|
+
setInternalRightCollapsed(collapsed);
|
|
3004
|
+
}, []);
|
|
3005
|
+
const contextValue = React11.useMemo(
|
|
3006
|
+
() => ({
|
|
3007
|
+
leftCollapsed,
|
|
3008
|
+
rightCollapsed,
|
|
3009
|
+
setLeftCollapsed: handleLeftToggle,
|
|
3010
|
+
setRightCollapsed: handleRightToggle,
|
|
3011
|
+
leftCollapsible: true,
|
|
3012
|
+
rightCollapsible: true
|
|
3013
|
+
}),
|
|
3014
|
+
[leftCollapsed, rightCollapsed, handleLeftToggle, handleRightToggle]
|
|
3015
|
+
);
|
|
3016
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ChatSidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3017
|
+
"div",
|
|
3018
|
+
{
|
|
3019
|
+
className: cn("flex flex-col h-full w-full bg-background", className),
|
|
3020
|
+
children: [
|
|
3021
|
+
title && /* @__PURE__ */ jsxRuntime.jsx(ChatHeader, { title, ...headerProps }),
|
|
3022
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-hidden flex relative", children: [
|
|
3023
|
+
leftSidebar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3024
|
+
"div",
|
|
3025
|
+
{
|
|
3026
|
+
className: cn(
|
|
3027
|
+
"flex-shrink-0 border-r border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
3028
|
+
leftCollapsed ? "w-0 border-r-0 min-w-0" : "",
|
|
3029
|
+
!leftCollapsed && leftSidebarClassName
|
|
3030
|
+
),
|
|
3031
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: leftSidebar })
|
|
3032
|
+
}
|
|
3033
|
+
),
|
|
3034
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3035
|
+
Thread,
|
|
3036
|
+
{
|
|
3037
|
+
placeholder,
|
|
3038
|
+
starterPrompts,
|
|
3039
|
+
options,
|
|
3040
|
+
autoFocus,
|
|
3041
|
+
defaultSelectedIds
|
|
3042
|
+
}
|
|
3043
|
+
) }),
|
|
3044
|
+
rightSidebar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3045
|
+
"div",
|
|
3046
|
+
{
|
|
3047
|
+
className: cn(
|
|
3048
|
+
"flex-shrink-0 border-l border-border bg-background transition-all duration-300 ease-in-out overflow-hidden flex flex-col",
|
|
3049
|
+
rightCollapsed ? "w-0 border-l-0 min-w-0" : "",
|
|
3050
|
+
!rightCollapsed && rightSidebarClassName
|
|
3051
|
+
),
|
|
3052
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden min-h-0", children: rightSidebar })
|
|
3053
|
+
}
|
|
3054
|
+
)
|
|
3055
|
+
] })
|
|
3056
|
+
]
|
|
3057
|
+
}
|
|
3058
|
+
) });
|
|
3059
|
+
}
|
|
3060
|
+
function SidebarToggle({ side, className }) {
|
|
3061
|
+
const {
|
|
3062
|
+
leftCollapsed,
|
|
3063
|
+
rightCollapsed,
|
|
3064
|
+
setLeftCollapsed,
|
|
3065
|
+
setRightCollapsed,
|
|
3066
|
+
leftCollapsible,
|
|
3067
|
+
rightCollapsible
|
|
3068
|
+
} = useChatSidebar();
|
|
3069
|
+
if (side === "left") {
|
|
3070
|
+
if (!leftCollapsible) return null;
|
|
3071
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3072
|
+
Button,
|
|
3073
|
+
{
|
|
3074
|
+
variant: "ghost",
|
|
3075
|
+
onClick: () => setLeftCollapsed(!leftCollapsed),
|
|
3076
|
+
"aria-label": leftCollapsed ? "Expand left sidebar" : "Collapse left sidebar",
|
|
3077
|
+
className: cn("", className),
|
|
3078
|
+
children: leftCollapsed ? /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLayoutSidebarLeftExpand, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLayoutSidebarLeftCollapse, { className: "h-4 w-4" })
|
|
3079
|
+
}
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3082
|
+
if (side === "right") {
|
|
3083
|
+
if (!rightCollapsible) return null;
|
|
3084
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3085
|
+
Button,
|
|
3086
|
+
{
|
|
3087
|
+
variant: "ghost",
|
|
3088
|
+
onClick: () => setRightCollapsed(!rightCollapsed),
|
|
3089
|
+
"aria-label": rightCollapsed ? "Expand right sidebar" : "Collapse right sidebar",
|
|
3090
|
+
className: cn("", className),
|
|
3091
|
+
children: rightCollapsed ? /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLayoutSidebarRightExpand, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(ICONS.IconLayoutSidebarRightCollapse, { className: "h-4 w-4" })
|
|
3092
|
+
}
|
|
3093
|
+
);
|
|
3094
|
+
}
|
|
3095
|
+
return null;
|
|
2829
3096
|
}
|
|
2830
|
-
var PopoverContext =
|
|
3097
|
+
var PopoverContext = React11__namespace.createContext(
|
|
2831
3098
|
void 0
|
|
2832
3099
|
);
|
|
2833
3100
|
function usePopoverContext() {
|
|
2834
|
-
const context =
|
|
3101
|
+
const context = React11__namespace.useContext(PopoverContext);
|
|
2835
3102
|
if (!context) {
|
|
2836
3103
|
throw new Error("Popover components must be used within a Popover");
|
|
2837
3104
|
}
|
|
@@ -2843,10 +3110,10 @@ function Popover({
|
|
|
2843
3110
|
open: controlledOpen,
|
|
2844
3111
|
onOpenChange
|
|
2845
3112
|
}) {
|
|
2846
|
-
const [internalOpen, setInternalOpen] =
|
|
2847
|
-
const triggerRef =
|
|
3113
|
+
const [internalOpen, setInternalOpen] = React11__namespace.useState(defaultOpen);
|
|
3114
|
+
const triggerRef = React11__namespace.useRef(null);
|
|
2848
3115
|
const open = controlledOpen ?? internalOpen;
|
|
2849
|
-
const setOpen =
|
|
3116
|
+
const setOpen = React11__namespace.useCallback(
|
|
2850
3117
|
(newOpen) => {
|
|
2851
3118
|
if (controlledOpen === void 0) {
|
|
2852
3119
|
setInternalOpen(newOpen);
|
|
@@ -2855,7 +3122,7 @@ function Popover({
|
|
|
2855
3122
|
},
|
|
2856
3123
|
[controlledOpen, onOpenChange]
|
|
2857
3124
|
);
|
|
2858
|
-
const value =
|
|
3125
|
+
const value = React11__namespace.useMemo(
|
|
2859
3126
|
() => ({
|
|
2860
3127
|
open,
|
|
2861
3128
|
setOpen,
|
|
@@ -2865,15 +3132,15 @@ function Popover({
|
|
|
2865
3132
|
);
|
|
2866
3133
|
return /* @__PURE__ */ jsxRuntime.jsx(PopoverContext.Provider, { value, children });
|
|
2867
3134
|
}
|
|
2868
|
-
var PopoverTrigger =
|
|
3135
|
+
var PopoverTrigger = React11__namespace.forwardRef(
|
|
2869
3136
|
({ asChild, className, children, ...props }, ref) => {
|
|
2870
3137
|
const { setOpen, triggerRef } = usePopoverContext();
|
|
2871
3138
|
const handleClick = (e) => {
|
|
2872
3139
|
setOpen(true);
|
|
2873
3140
|
props.onClick?.(e);
|
|
2874
3141
|
};
|
|
2875
|
-
if (asChild &&
|
|
2876
|
-
return
|
|
3142
|
+
if (asChild && React11__namespace.isValidElement(children)) {
|
|
3143
|
+
return React11__namespace.cloneElement(children, {
|
|
2877
3144
|
ref: (node) => {
|
|
2878
3145
|
triggerRef.current = node;
|
|
2879
3146
|
if (typeof children.ref === "function") {
|
|
@@ -2905,7 +3172,7 @@ var PopoverTrigger = React10__namespace.forwardRef(
|
|
|
2905
3172
|
}
|
|
2906
3173
|
);
|
|
2907
3174
|
PopoverTrigger.displayName = "PopoverTrigger";
|
|
2908
|
-
var PopoverContent =
|
|
3175
|
+
var PopoverContent = React11__namespace.forwardRef(
|
|
2909
3176
|
({
|
|
2910
3177
|
className,
|
|
2911
3178
|
side = "bottom",
|
|
@@ -2916,9 +3183,9 @@ var PopoverContent = React10__namespace.forwardRef(
|
|
|
2916
3183
|
...props
|
|
2917
3184
|
}, ref) => {
|
|
2918
3185
|
const { open, setOpen, triggerRef } = usePopoverContext();
|
|
2919
|
-
const [position, setPosition] =
|
|
2920
|
-
const contentRef =
|
|
2921
|
-
|
|
3186
|
+
const [position, setPosition] = React11__namespace.useState({ top: 0, left: 0 });
|
|
3187
|
+
const contentRef = React11__namespace.useRef(null);
|
|
3188
|
+
React11__namespace.useEffect(() => {
|
|
2922
3189
|
if (!open || !triggerRef.current) return;
|
|
2923
3190
|
const updatePosition = () => {
|
|
2924
3191
|
if (!triggerRef.current || !contentRef.current) return;
|
|
@@ -2979,7 +3246,7 @@ var PopoverContent = React10__namespace.forwardRef(
|
|
|
2979
3246
|
window.removeEventListener("scroll", updatePosition, true);
|
|
2980
3247
|
};
|
|
2981
3248
|
}, [open, side, align, sideOffset, alignOffset, triggerRef]);
|
|
2982
|
-
|
|
3249
|
+
React11__namespace.useEffect(() => {
|
|
2983
3250
|
if (!open) return;
|
|
2984
3251
|
const handleClickOutside = (event) => {
|
|
2985
3252
|
if (contentRef.current && !contentRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
|
|
@@ -3035,7 +3302,7 @@ var ThreadPopover = ({
|
|
|
3035
3302
|
emptyState,
|
|
3036
3303
|
onThreadSelect
|
|
3037
3304
|
}) => {
|
|
3038
|
-
const [isOpen, setIsOpen] =
|
|
3305
|
+
const [isOpen, setIsOpen] = React11__namespace.useState(false);
|
|
3039
3306
|
reactHotkeysHook.useHotkeys(
|
|
3040
3307
|
"h",
|
|
3041
3308
|
(e) => {
|
|
@@ -3090,7 +3357,7 @@ var CreateThreadButton = ({
|
|
|
3090
3357
|
onThreadCreated
|
|
3091
3358
|
}) => {
|
|
3092
3359
|
const { createThread } = useThreads();
|
|
3093
|
-
const [isCreating, setIsCreating] =
|
|
3360
|
+
const [isCreating, setIsCreating] = React11__namespace.useState(false);
|
|
3094
3361
|
const handleCreateThread = async () => {
|
|
3095
3362
|
if (isCreating) return;
|
|
3096
3363
|
try {
|
|
@@ -3216,10 +3483,10 @@ var AccountDialog = ({
|
|
|
3216
3483
|
size
|
|
3217
3484
|
}) => {
|
|
3218
3485
|
const { isLoading, isAuthenticated, user, login, logout } = useAuth();
|
|
3219
|
-
const [open, setOpen] =
|
|
3220
|
-
const [accountInfoOpen, setAccountInfoOpen] =
|
|
3221
|
-
const [error, setError] =
|
|
3222
|
-
const initials =
|
|
3486
|
+
const [open, setOpen] = React11__namespace.useState(false);
|
|
3487
|
+
const [accountInfoOpen, setAccountInfoOpen] = React11__namespace.useState(false);
|
|
3488
|
+
const [error, setError] = React11__namespace.useState(null);
|
|
3489
|
+
const initials = React11__namespace.useMemo(() => {
|
|
3223
3490
|
const name = user?.displayName || user?.name;
|
|
3224
3491
|
if (!name) return "";
|
|
3225
3492
|
return name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2);
|
|
@@ -3395,14 +3662,37 @@ function ThemeToggle() {
|
|
|
3395
3662
|
exports.AccountDialog = AccountDialog;
|
|
3396
3663
|
exports.AuthContext = AuthContext;
|
|
3397
3664
|
exports.AuthProvider = AuthProvider;
|
|
3665
|
+
exports.Badge = Badge2;
|
|
3666
|
+
exports.Box = Box;
|
|
3667
|
+
exports.Button = Button2;
|
|
3668
|
+
exports.Card = Card2;
|
|
3669
|
+
exports.Chart = Chart;
|
|
3398
3670
|
exports.ChatFull = ChatFull;
|
|
3399
3671
|
exports.ChatHeader = ChatHeader;
|
|
3400
3672
|
exports.ChatPopup = ChatPopup;
|
|
3401
3673
|
exports.ChatSidebar = ChatSidebar;
|
|
3674
|
+
exports.ChatSidebarContext = ChatSidebarContext;
|
|
3675
|
+
exports.Checkbox = Checkbox;
|
|
3676
|
+
exports.Col = Col;
|
|
3402
3677
|
exports.Composer = Composer;
|
|
3403
3678
|
exports.CreateThreadButton = CreateThreadButton;
|
|
3679
|
+
exports.Divider = Divider;
|
|
3680
|
+
exports.Form = Form;
|
|
3681
|
+
exports.Heading = Heading;
|
|
3682
|
+
exports.Image = Image;
|
|
3683
|
+
exports.Input = Input2;
|
|
3684
|
+
exports.Label = Label2;
|
|
3685
|
+
exports.List = List;
|
|
3686
|
+
exports.ListItem = ListItem;
|
|
3404
3687
|
exports.MelonyClientProvider = MelonyClientProvider;
|
|
3405
3688
|
exports.MelonyContext = MelonyContext;
|
|
3689
|
+
exports.RadioGroup = RadioGroup;
|
|
3690
|
+
exports.Row = Row;
|
|
3691
|
+
exports.Select = Select2;
|
|
3692
|
+
exports.SidebarToggle = SidebarToggle;
|
|
3693
|
+
exports.Spacer = Spacer;
|
|
3694
|
+
exports.Text = Text;
|
|
3695
|
+
exports.Textarea = Textarea2;
|
|
3406
3696
|
exports.ThemeProvider = ThemeProvider;
|
|
3407
3697
|
exports.ThemeToggle = ThemeToggle;
|
|
3408
3698
|
exports.Thread = Thread;
|
|
@@ -3413,7 +3703,9 @@ exports.ThreadProvider = ThreadProvider;
|
|
|
3413
3703
|
exports.UIRenderer = UIRenderer;
|
|
3414
3704
|
exports.groupEventsToMessages = groupEventsToMessages;
|
|
3415
3705
|
exports.useAuth = useAuth;
|
|
3706
|
+
exports.useChatSidebar = useChatSidebar;
|
|
3416
3707
|
exports.useMelony = useMelony;
|
|
3708
|
+
exports.useScreenSize = useScreenSize;
|
|
3417
3709
|
exports.useTheme = useTheme;
|
|
3418
3710
|
exports.useThreads = useThreads;
|
|
3419
3711
|
//# sourceMappingURL=index.cjs.map
|