@clubmed/usg-chat-ui 1.3.0 → 1.4.0
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/assets/style.css +1 -1
- package/config/chatLabels.d.ts +40 -0
- package/organisms/chat/Chat.js +65 -64
- package/organisms/chat/Chat.js.map +1 -1
- package/organisms/chat/ChatHeader.d.ts +1 -2
- package/organisms/chat/ChatHeader.js +15 -20
- package/organisms/chat/ChatHeader.js.map +1 -1
- package/organisms/chat/ChatHeader.test.js +12 -12
- package/organisms/chat/ChatHeader.test.js.map +1 -1
- package/organisms/chat/ChatSettingsButton.js +6 -5
- package/organisms/chat/ChatSettingsButton.js.map +1 -1
- package/organisms/chat/ConversationSidebar.js +8 -8
- package/organisms/chat/ConversationSidebar.js.map +1 -1
- package/organisms/chat/MessageActions.js +157 -133
- package/organisms/chat/MessageActions.js.map +1 -1
- package/organisms/chat/PromptComposer.js +19 -14
- package/organisms/chat/PromptComposer.js.map +1 -1
- package/organisms/chat/SidebarToggleButton.d.ts +2 -1
- package/organisms/chat/SidebarToggleButton.js +13 -12
- package/organisms/chat/SidebarToggleButton.js.map +1 -1
- package/package.json +1 -1
package/config/chatLabels.d.ts
CHANGED
|
@@ -39,5 +39,45 @@ export interface ChatLabelsConfig {
|
|
|
39
39
|
branchNextAriaLabel: string;
|
|
40
40
|
/** Example: "Submit" */
|
|
41
41
|
promptSubmitAriaLabel: string;
|
|
42
|
+
/** Example: "Décrivez votre besoin ou tapez /help pour l'aide..." */
|
|
43
|
+
promptComposerPlaceholder: string;
|
|
44
|
+
/** Example: "Copier" */
|
|
45
|
+
messageCopyButtonText: string;
|
|
46
|
+
/** Example: "Copié" */
|
|
47
|
+
messageCopySuccessText: string;
|
|
48
|
+
/** Example: "Copié" */
|
|
49
|
+
messageCopyToastTitle: string;
|
|
50
|
+
/** Example: "Message copié dans le presse-papiers" */
|
|
51
|
+
messageCopyToastDescription: string;
|
|
52
|
+
/** Example: "Erreur" */
|
|
53
|
+
messageCopyErrorTitle: string;
|
|
54
|
+
/** Example: "Impossible de copier le message" */
|
|
55
|
+
messageCopyErrorDescription: string;
|
|
56
|
+
/** Example: "Régénérer" */
|
|
57
|
+
messageRegenerateButtonText: string;
|
|
58
|
+
/** Example: "Ouvrir Canva" */
|
|
59
|
+
messageOpenCanvasButtonText: string;
|
|
60
|
+
/** Example: "Merci pour votre feedback !" */
|
|
61
|
+
messageFeedbackPositiveTitle: string;
|
|
62
|
+
/** Example: "Aidez-nous à nous améliorer" */
|
|
63
|
+
messageFeedbackNegativeTitle: string;
|
|
64
|
+
/** Example: "Un commentaire pour nous aider ?" */
|
|
65
|
+
messageFeedbackPromptText: string;
|
|
66
|
+
/** Example: "Votre commentaire (optionnel)..." */
|
|
67
|
+
messageFeedbackTextareaPlaceholder: string;
|
|
68
|
+
/** Example: "Passer" */
|
|
69
|
+
messageFeedbackSkipButtonText: string;
|
|
70
|
+
/** Example: "Envoyer" */
|
|
71
|
+
messageFeedbackSubmitButtonText: string;
|
|
72
|
+
/** Example: "Envoi..." */
|
|
73
|
+
messageFeedbackSubmittingText: string;
|
|
74
|
+
/** Example: "Merci !" */
|
|
75
|
+
messageFeedbackToastTitle: string;
|
|
76
|
+
/** Example: "Votre feedback a été enregistré" */
|
|
77
|
+
messageFeedbackToastDescription: string;
|
|
78
|
+
/** Example: "Erreur" */
|
|
79
|
+
messageFeedbackToastErrorTitle: string;
|
|
80
|
+
/** Example: "Impossible d'enregistrer le feedback" */
|
|
81
|
+
messageFeedbackToastErrorDescription: string;
|
|
42
82
|
}
|
|
43
83
|
export type ChatLabelOverrides = Partial<ChatLabelsConfig>;
|
package/organisms/chat/Chat.js
CHANGED
|
@@ -1,105 +1,106 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as e, jsxs as
|
|
3
|
-
import { cn as
|
|
4
|
-
import { ChatHeader as
|
|
5
|
-
import { SidebarToggleButton as
|
|
6
|
-
import { ConversationSidebar as
|
|
7
|
-
import { ChatMessageList as
|
|
8
|
-
import { PromptComposer as
|
|
2
|
+
import { jsx as e, jsxs as t } from "react/jsx-runtime";
|
|
3
|
+
import { cn as d } from "../../utils/cn.js";
|
|
4
|
+
import { ChatHeader as k } from "./ChatHeader.js";
|
|
5
|
+
import { SidebarToggleButton as z } from "./SidebarToggleButton.js";
|
|
6
|
+
import { ConversationSidebar as I } from "./ConversationSidebar.js";
|
|
7
|
+
import { ChatMessageList as T } from "./ChatMessageList.js";
|
|
8
|
+
import { PromptComposer as j } from "./PromptComposer.js";
|
|
9
9
|
import { CanvasLayout as A } from "../canvas/CanvasLayout.js";
|
|
10
10
|
import { StoryCanvas as F } from "../canvas/StoryCanvas.js";
|
|
11
|
-
import { ApiDocsCanvas as
|
|
12
|
-
import { ReleaseNoteCanvas as
|
|
13
|
-
import { SettingsModal as
|
|
14
|
-
import { useChat as
|
|
15
|
-
import { ChatSettingsButton as
|
|
11
|
+
import { ApiDocsCanvas as B } from "../canvas/ApiDocsCanvas.js";
|
|
12
|
+
import { ReleaseNoteCanvas as P } from "../canvas/ReleaseNoteCanvas.js";
|
|
13
|
+
import { SettingsModal as W } from "../settings/SettingsModal.js";
|
|
14
|
+
import { useChat as _ } from "./hooks/useChat.js";
|
|
15
|
+
import { ChatSettingsButton as p } from "./ChatSettingsButton.js";
|
|
16
16
|
import { ChatLabelsProvider as $ } from "../../contexts/ChatLabelsContext.js";
|
|
17
17
|
function te({
|
|
18
18
|
title: h = "ClubMed USG AI Assistant",
|
|
19
|
-
headerActions:
|
|
20
|
-
variant:
|
|
21
|
-
className:
|
|
22
|
-
labels:
|
|
19
|
+
headerActions: u,
|
|
20
|
+
variant: o = "full",
|
|
21
|
+
className: f,
|
|
22
|
+
labels: g
|
|
23
23
|
}) {
|
|
24
24
|
const {
|
|
25
|
-
chatMessages:
|
|
26
|
-
settingsOpen:
|
|
27
|
-
setSettingsOpen:
|
|
28
|
-
sidebarOpen:
|
|
29
|
-
setSidebarOpen:
|
|
30
|
-
sidebarRefreshTrigger:
|
|
25
|
+
chatMessages: C,
|
|
26
|
+
settingsOpen: x,
|
|
27
|
+
setSettingsOpen: s,
|
|
28
|
+
sidebarOpen: b,
|
|
29
|
+
setSidebarOpen: l,
|
|
30
|
+
sidebarRefreshTrigger: v,
|
|
31
31
|
currentConversationId: S,
|
|
32
32
|
loadConversation: w,
|
|
33
|
-
handleNewConversation:
|
|
34
|
-
isLoadingMessage:
|
|
35
|
-
canvasType:
|
|
36
|
-
isFullscreen:
|
|
37
|
-
canvasWidth:
|
|
38
|
-
isResizing:
|
|
39
|
-
resizeWidth:
|
|
33
|
+
handleNewConversation: N,
|
|
34
|
+
isLoadingMessage: r,
|
|
35
|
+
canvasType: n,
|
|
36
|
+
isFullscreen: i,
|
|
37
|
+
canvasWidth: a,
|
|
38
|
+
isResizing: m,
|
|
39
|
+
resizeWidth: c,
|
|
40
40
|
handleFollowupClick: y,
|
|
41
|
-
handleSubmit:
|
|
42
|
-
handleRegenerate:
|
|
43
|
-
localInput:
|
|
44
|
-
setLocalInput:
|
|
45
|
-
} =
|
|
46
|
-
return /* @__PURE__ */ e($, { labels:
|
|
47
|
-
/* @__PURE__ */
|
|
48
|
-
|
|
49
|
-
/* @__PURE__ */ e(
|
|
41
|
+
handleSubmit: L,
|
|
42
|
+
handleRegenerate: O,
|
|
43
|
+
localInput: M,
|
|
44
|
+
setLocalInput: R
|
|
45
|
+
} = _();
|
|
46
|
+
return /* @__PURE__ */ e($, { labels: g, children: /* @__PURE__ */ t("div", { className: d("usg-chat-ui", f), "data-testid": "chat", children: [
|
|
47
|
+
!(o != null && o.includes("no-header")) && /* @__PURE__ */ t(k, { title: h, variant: o, children: [
|
|
48
|
+
u,
|
|
49
|
+
/* @__PURE__ */ e(p, { onClick: () => s(!0) })
|
|
50
50
|
] }),
|
|
51
|
-
/* @__PURE__ */
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
/* @__PURE__ */ t("div", { className: "flex-1 flex overflow-hidden relative", children: [
|
|
52
|
+
/* @__PURE__ */ e(z, { className: "absolute left-4 z-10 top-4", onOpen: () => l(!0) }),
|
|
53
|
+
(o == null ? void 0 : o.includes("no-header")) && /* @__PURE__ */ e(p, { className: "absolute right-4 z-10 top-4", onClick: () => s(!0) }),
|
|
54
|
+
b && /* @__PURE__ */ e(
|
|
55
|
+
I,
|
|
55
56
|
{
|
|
56
57
|
currentConversationId: S,
|
|
57
58
|
onSelectConversation: w,
|
|
58
|
-
onNewConversation:
|
|
59
|
-
refreshTrigger:
|
|
60
|
-
onClose: () =>
|
|
59
|
+
onNewConversation: N,
|
|
60
|
+
refreshTrigger: v,
|
|
61
|
+
onClose: () => l(!1)
|
|
61
62
|
}
|
|
62
63
|
),
|
|
63
64
|
/* @__PURE__ */ e(
|
|
64
65
|
"main",
|
|
65
66
|
{
|
|
66
|
-
className:
|
|
67
|
+
className: d(
|
|
67
68
|
"flex-1 flex items-stretch justify-center overflow-hidden min-h-0",
|
|
68
|
-
|
|
69
|
-
!
|
|
69
|
+
i && "lg:w-0 lg:opacity-0 lg:pointer-events-none",
|
|
70
|
+
!m && "transition-all duration-300"
|
|
70
71
|
),
|
|
71
72
|
style: {
|
|
72
|
-
width:
|
|
73
|
+
width: i ? "0" : m && c !== null ? `calc(100% - ${c}px)` : a !== null ? `calc(100% - ${a}px)` : "50%"
|
|
73
74
|
},
|
|
74
|
-
children: /* @__PURE__ */
|
|
75
|
+
children: /* @__PURE__ */ t("div", { className: "w-full max-w-3xl flex flex-col h-full", children: [
|
|
75
76
|
/* @__PURE__ */ e(
|
|
76
|
-
|
|
77
|
+
T,
|
|
77
78
|
{
|
|
78
|
-
chatMessages:
|
|
79
|
-
isLoadingMessage:
|
|
79
|
+
chatMessages: C,
|
|
80
|
+
isLoadingMessage: r,
|
|
80
81
|
onFollowupClick: y,
|
|
81
|
-
onRegenerate:
|
|
82
|
+
onRegenerate: O
|
|
82
83
|
}
|
|
83
84
|
),
|
|
84
85
|
/* @__PURE__ */ e(
|
|
85
|
-
|
|
86
|
+
j,
|
|
86
87
|
{
|
|
87
|
-
value:
|
|
88
|
-
isLoading:
|
|
89
|
-
onChange:
|
|
90
|
-
onSubmit:
|
|
88
|
+
value: M,
|
|
89
|
+
isLoading: r,
|
|
90
|
+
onChange: R,
|
|
91
|
+
onSubmit: L
|
|
91
92
|
}
|
|
92
93
|
)
|
|
93
94
|
] })
|
|
94
95
|
}
|
|
95
96
|
),
|
|
96
|
-
/* @__PURE__ */
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
/* @__PURE__ */ t(A, { children: [
|
|
98
|
+
n === "story" && /* @__PURE__ */ e(F, {}),
|
|
99
|
+
n === "api_docs" && /* @__PURE__ */ e(B, {}),
|
|
100
|
+
n === "release_note" && /* @__PURE__ */ e(P, {})
|
|
100
101
|
] })
|
|
101
102
|
] }),
|
|
102
|
-
/* @__PURE__ */ e(
|
|
103
|
+
/* @__PURE__ */ e(W, { open: x, onOpenChange: s })
|
|
103
104
|
] }) });
|
|
104
105
|
}
|
|
105
106
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chat.js","sources":["../../../lib/organisms/chat/Chat.tsx"],"sourcesContent":["\"use client\";\n\nimport type {ReactNode} from \"react\";\n\nimport {cn} from \"../../utils/cn\";\nimport {ChatHeader, type ChatHeaderProps} from \"./ChatHeader\";\nimport {SidebarToggleButton} from \"./SidebarToggleButton\";\nimport {ConversationSidebar} from \"./ConversationSidebar\";\nimport {ChatMessageList} from \"./ChatMessageList\";\nimport {PromptComposer} from \"./PromptComposer\";\nimport {CanvasLayout} from \"../canvas/CanvasLayout\";\nimport {StoryCanvas} from \"../canvas/StoryCanvas\";\nimport {ApiDocsCanvas} from \"../canvas/ApiDocsCanvas\";\nimport {ReleaseNoteCanvas} from \"../canvas/ReleaseNoteCanvas\";\nimport {SettingsModal} from \"../settings/SettingsModal\";\nimport {useChat} from \"./hooks/useChat\";\nimport type {ChatLabelOverrides} from \"../../config/chatLabels\";\nimport {ChatSettingsButton} from \"@clubmed/usg-chat-ui/organisms/chat/ChatSettingsButton\";\nimport {ChatLabelsProvider} from \"../../contexts/ChatLabelsContext\";\n\nexport interface ChatProps {\n title?: string;\n className?: string;\n headerActions?: ReactNode;\n variant?: ChatHeaderProps[\"variant\"];\n labels?: ChatLabelOverrides;\n}\n\nexport function Chat({\n title = \"ClubMed USG AI Assistant\",\n headerActions,\n variant = \"full\",\n className,\n labels,\n }: ChatProps) {\n const {\n chatMessages,\n settingsOpen,\n setSettingsOpen,\n sidebarOpen,\n setSidebarOpen,\n sidebarRefreshTrigger,\n currentConversationId,\n loadConversation,\n handleNewConversation,\n isLoadingMessage,\n canvasType,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n handleFollowupClick,\n handleSubmit,\n handleRegenerate,\n localInput,\n setLocalInput,\n } = useChat();\n\n return (\n <ChatLabelsProvider labels={labels}>\n <div className={cn(\"usg-chat-ui\", className)} data-testid=\"chat\">\n <ChatHeader title={title}
|
|
1
|
+
{"version":3,"file":"Chat.js","sources":["../../../lib/organisms/chat/Chat.tsx"],"sourcesContent":["\"use client\";\n\nimport type {ReactNode} from \"react\";\n\nimport {cn} from \"../../utils/cn\";\nimport {ChatHeader, type ChatHeaderProps} from \"./ChatHeader\";\nimport {SidebarToggleButton} from \"./SidebarToggleButton\";\nimport {ConversationSidebar} from \"./ConversationSidebar\";\nimport {ChatMessageList} from \"./ChatMessageList\";\nimport {PromptComposer} from \"./PromptComposer\";\nimport {CanvasLayout} from \"../canvas/CanvasLayout\";\nimport {StoryCanvas} from \"../canvas/StoryCanvas\";\nimport {ApiDocsCanvas} from \"../canvas/ApiDocsCanvas\";\nimport {ReleaseNoteCanvas} from \"../canvas/ReleaseNoteCanvas\";\nimport {SettingsModal} from \"../settings/SettingsModal\";\nimport {useChat} from \"./hooks/useChat\";\nimport type {ChatLabelOverrides} from \"../../config/chatLabels\";\nimport {ChatSettingsButton} from \"@clubmed/usg-chat-ui/organisms/chat/ChatSettingsButton\";\nimport {ChatLabelsProvider} from \"../../contexts/ChatLabelsContext\";\n\nexport interface ChatProps {\n title?: string;\n className?: string;\n headerActions?: ReactNode;\n variant?: ChatHeaderProps[\"variant\"];\n labels?: ChatLabelOverrides;\n}\n\nexport function Chat({\n title = \"ClubMed USG AI Assistant\",\n headerActions,\n variant = \"full\",\n className,\n labels,\n }: ChatProps) {\n const {\n chatMessages,\n settingsOpen,\n setSettingsOpen,\n sidebarOpen,\n setSidebarOpen,\n sidebarRefreshTrigger,\n currentConversationId,\n loadConversation,\n handleNewConversation,\n isLoadingMessage,\n canvasType,\n isFullscreen,\n canvasWidth,\n isResizing,\n resizeWidth,\n handleFollowupClick,\n handleSubmit,\n handleRegenerate,\n localInput,\n setLocalInput,\n } = useChat();\n\n return (\n <ChatLabelsProvider labels={labels}>\n <div className={cn(\"usg-chat-ui\", className)} data-testid=\"chat\">\n {\n !variant?.includes(\"no-header\") && <ChatHeader title={title} variant={variant}>\n {headerActions}\n <ChatSettingsButton onClick={() => setSettingsOpen(true)}/>\n </ChatHeader>\n }\n\n <div className=\"flex-1 flex overflow-hidden relative\">\n <SidebarToggleButton className=\"absolute left-4 z-10 top-4\" onOpen={() => setSidebarOpen(true)}/>\n\n {variant?.includes(\"no-header\") && <ChatSettingsButton className=\"absolute right-4 z-10 top-4\" onClick={() => setSettingsOpen(true)}/>}\n\n {sidebarOpen && (\n <ConversationSidebar\n currentConversationId={currentConversationId}\n onSelectConversation={loadConversation}\n onNewConversation={handleNewConversation}\n refreshTrigger={sidebarRefreshTrigger}\n onClose={() => setSidebarOpen(false)}\n />\n )}\n\n <main\n className={cn(\n \"flex-1 flex items-stretch justify-center overflow-hidden min-h-0\",\n isFullscreen && \"lg:w-0 lg:opacity-0 lg:pointer-events-none\",\n !isResizing && \"transition-all duration-300\"\n )}\n style={{\n width: isFullscreen\n ? \"0\"\n : isResizing && resizeWidth !== null\n ? `calc(100% - ${resizeWidth}px)`\n : canvasWidth !== null\n ? `calc(100% - ${canvasWidth}px)`\n : \"50%\",\n }}\n >\n <div className=\"w-full max-w-3xl flex flex-col h-full\">\n <ChatMessageList\n chatMessages={chatMessages}\n isLoadingMessage={isLoadingMessage}\n onFollowupClick={handleFollowupClick}\n onRegenerate={handleRegenerate}\n />\n\n <PromptComposer\n value={localInput}\n isLoading={isLoadingMessage}\n onChange={setLocalInput}\n onSubmit={handleSubmit}\n />\n </div>\n </main>\n\n <CanvasLayout>\n {canvasType === \"story\" && <StoryCanvas/>}\n {canvasType === \"api_docs\" && <ApiDocsCanvas/>}\n {canvasType === \"release_note\" && <ReleaseNoteCanvas/>}\n </CanvasLayout>\n </div>\n\n <SettingsModal open={settingsOpen} onOpenChange={setSettingsOpen}/>\n </div>\n </ChatLabelsProvider>\n );\n}\n\nexport default Chat;\n"],"names":["Chat","title","headerActions","variant","className","labels","chatMessages","settingsOpen","setSettingsOpen","sidebarOpen","setSidebarOpen","sidebarRefreshTrigger","currentConversationId","loadConversation","handleNewConversation","isLoadingMessage","canvasType","isFullscreen","canvasWidth","isResizing","resizeWidth","handleFollowupClick","handleSubmit","handleRegenerate","localInput","setLocalInput","useChat","jsx","ChatLabelsProvider","jsxs","cn","ChatHeader","ChatSettingsButton","SidebarToggleButton","ConversationSidebar","ChatMessageList","PromptComposer","CanvasLayout","StoryCanvas","ApiDocsCanvas","ReleaseNoteCanvas","SettingsModal"],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
2
|
export interface ChatHeaderProps {
|
|
3
3
|
title: string;
|
|
4
|
-
conversationCount: number;
|
|
5
4
|
variant?: string;
|
|
6
5
|
}
|
|
7
|
-
export declare function ChatHeader({ title,
|
|
6
|
+
export declare function ChatHeader({ title, variant, children }: PropsWithChildren<ChatHeaderProps>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as r, jsx as
|
|
3
|
-
import { cn as
|
|
4
|
-
import { W as
|
|
5
|
-
function
|
|
2
|
+
import { jsxs as r, jsx as s, Fragment as l } from "react/jsx-runtime";
|
|
3
|
+
import { cn as d } from "../../utils/cn.js";
|
|
4
|
+
import { W as i } from "../../chunks/wand-sparkles.js";
|
|
5
|
+
function m({ title: o, variant: e = "", children: t }) {
|
|
6
6
|
return /* @__PURE__ */ r(
|
|
7
7
|
"div",
|
|
8
8
|
{
|
|
9
|
-
className:
|
|
10
|
-
"shadow-sm": !(
|
|
9
|
+
className: d("h-16 flex items-center justify-between px-4 sm:px-6 transition-colors", {
|
|
10
|
+
"shadow-sm": !(e != null && e.includes("no-shadow")),
|
|
11
|
+
"bg-card/95 border-b border-border backdrop-blur-xl": !(e != null && e.includes("no-border"))
|
|
11
12
|
}),
|
|
12
13
|
children: [
|
|
13
14
|
/* @__PURE__ */ r("div", { className: "flex items-center gap-3 sm:gap-4", children: [
|
|
14
|
-
/* @__PURE__ */
|
|
15
|
-
/* @__PURE__ */
|
|
16
|
-
"div",
|
|
17
|
-
{
|
|
18
|
-
className: "absolute inset-0 bg-foreground/10 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"
|
|
19
|
-
}
|
|
20
|
-
),
|
|
15
|
+
/* @__PURE__ */ s("div", { className: "relative group", children: !(e != null && e.includes("no-logo")) && /* @__PURE__ */ r(l, { children: [
|
|
16
|
+
/* @__PURE__ */ s("div", { className: "absolute inset-0 bg-foreground/10 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500" }),
|
|
21
17
|
/* @__PURE__ */ r(
|
|
22
18
|
"div",
|
|
23
19
|
{
|
|
@@ -27,21 +23,20 @@ function c({ title: a, conversationCount: t, variant: s = "", children: i }) {
|
|
|
27
23
|
boxShadow: "inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 4px 6px rgba(0, 0, 0, 0.3)"
|
|
28
24
|
},
|
|
29
25
|
children: [
|
|
30
|
-
/* @__PURE__ */
|
|
31
|
-
/* @__PURE__ */
|
|
26
|
+
/* @__PURE__ */ s("div", { className: "absolute inset-0 bg-gradient-to-br from-white/10 to-transparent pointer-events-none" }),
|
|
27
|
+
/* @__PURE__ */ s(i, { className: "h-4 w-4 sm:h-5 sm:w-5 text-white relative z-10", strokeWidth: 2 })
|
|
32
28
|
]
|
|
33
29
|
}
|
|
34
30
|
)
|
|
35
|
-
] }),
|
|
36
|
-
/* @__PURE__ */
|
|
37
|
-
t > 0 && /* @__PURE__ */ e("div", { className: "sm:hidden ml-2 px-2 py-1 rounded-full bg-muted text-xs font-medium text-foreground", children: t })
|
|
31
|
+
] }) }),
|
|
32
|
+
/* @__PURE__ */ s("div", { className: "flex flex-col", children: /* @__PURE__ */ s("h1", { className: "text-sm sm:text-base font-semibold text-foreground tracking-tight", children: o }) })
|
|
38
33
|
] }),
|
|
39
|
-
/* @__PURE__ */
|
|
34
|
+
/* @__PURE__ */ s("div", { className: "flex items-center gap-2 sm:gap-3", children: t })
|
|
40
35
|
]
|
|
41
36
|
}
|
|
42
37
|
);
|
|
43
38
|
}
|
|
44
39
|
export {
|
|
45
|
-
|
|
40
|
+
m as ChatHeader
|
|
46
41
|
};
|
|
47
42
|
//# sourceMappingURL=ChatHeader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatHeader.js","sources":["../../../lib/organisms/chat/ChatHeader.tsx"],"sourcesContent":["\"use client\";\n\nimport type {PropsWithChildren} from \"react\";\nimport {Wand2} from \"lucide-react\";\nimport {cn} from \"@clubmed/usg-chat-ui/utils/cn\";\n\nexport interface ChatHeaderProps {\n title: string;\n
|
|
1
|
+
{"version":3,"file":"ChatHeader.js","sources":["../../../lib/organisms/chat/ChatHeader.tsx"],"sourcesContent":["\"use client\";\n\nimport type {PropsWithChildren} from \"react\";\nimport {Wand2} from \"lucide-react\";\nimport {cn} from \"@clubmed/usg-chat-ui/utils/cn\";\n\nexport interface ChatHeaderProps {\n title: string;\n variant?: string;\n}\n\nexport function ChatHeader({title, variant = \"\", children}: PropsWithChildren<ChatHeaderProps>) {\n return (\n <div\n className={cn(\"h-16 flex items-center justify-between px-4 sm:px-6 transition-colors\", {\n \"shadow-sm\": !variant?.includes(\"no-shadow\"),\n \"bg-card/95 border-b border-border backdrop-blur-xl\": !variant?.includes(\"no-border\"),\n })}>\n <div className=\"flex items-center gap-3 sm:gap-4\">\n <div className=\"relative group\">\n {!variant?.includes(\"no-logo\") && (\n <>\n <div className=\"absolute inset-0 bg-foreground/10 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500\"/>\n <div\n className=\"relative flex h-10 w-10 sm:h-11 sm:w-11 items-center justify-center rounded-xl shadow-lg ring-1 ring-border/40 transition-transform group-hover:scale-105 duration-300 overflow-hidden\"\n style={{\n background: \"linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 50%, #0f0f0f 100%)\",\n boxShadow: \"inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 4px 6px rgba(0, 0, 0, 0.3)\",\n }}\n >\n <div className=\"absolute inset-0 bg-gradient-to-br from-white/10 to-transparent pointer-events-none\"/>\n <Wand2 className=\"h-4 w-4 sm:h-5 sm:w-5 text-white relative z-10\" strokeWidth={2}/>\n </div>\n </>\n )}\n </div>\n\n <div className=\"flex flex-col\">\n <h1 className=\"text-sm sm:text-base font-semibold text-foreground tracking-tight\">\n {title}\n </h1>\n </div>\n </div>\n\n <div className=\"flex items-center gap-2 sm:gap-3\">\n {children}\n </div>\n </div>\n );\n}\n"],"names":["ChatHeader","title","variant","children","jsxs","cn","jsx","Fragment","Wand2"],"mappings":";;;;AAWO,SAASA,EAAW,EAAC,OAAAC,GAAO,SAAAC,IAAU,IAAI,UAAAC,KAA+C;AAC9F,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,EAAG,yEAAyE;AAAA,QACrF,aAAa,EAACH,KAAA,QAAAA,EAAS,SAAS;AAAA,QAChC,sDAAsD,EAACA,KAAA,QAAAA,EAAS,SAAS;AAAA,MAAW,CACrF;AAAA,MACD,UAAA;AAAA,QAAA,gBAAAE,EAAC,OAAA,EAAI,WAAU,oCACb,UAAA;AAAA,UAAA,gBAAAE,EAAC,OAAA,EAAI,WAAU,kBACZ,UAAA,EAACJ,KAAA,QAAAA,EAAS,SAAS,eAClB,gBAAAE,EAAAG,GAAA,EACE,UAAA;AAAA,YAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,8GAAA,CAA6G;AAAA,YAC5H,gBAAAF;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA,kBACL,YAAY;AAAA,kBACZ,WAAW;AAAA,gBAAA;AAAA,gBAGb,UAAA;AAAA,kBAAA,gBAAAE,EAAC,OAAA,EAAI,WAAU,sFAAA,CAAqF;AAAA,kBACpG,gBAAAA,EAACE,GAAA,EAAM,WAAU,kDAAiD,aAAa,EAAA,CAAE;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UACnF,EAAA,CACF,EAAA,CAEJ;AAAA,UAEA,gBAAAF,EAAC,SAAI,WAAU,iBACb,4BAAC,MAAA,EAAG,WAAU,qEACX,UAAAL,EAAA,CACH,EAAA,CACF;AAAA,QAAA,GACF;AAAA,QAEA,gBAAAK,EAAC,OAAA,EAAI,WAAU,oCACZ,UAAAH,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { jsx as e } from "react/jsx-runtime";
|
|
2
|
-
import { a as
|
|
3
|
-
import { ChatHeader as
|
|
2
|
+
import { a as o, s as a } from "../../chunks/react.esm.js";
|
|
3
|
+
import { ChatHeader as s } from "./ChatHeader.js";
|
|
4
4
|
import { ChatLabelsProvider as r } from "../../contexts/ChatLabelsContext.js";
|
|
5
|
-
import { d as
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/* @__PURE__ */ e(r, { children: /* @__PURE__ */ e(
|
|
10
|
-
), t(
|
|
11
|
-
}),
|
|
12
|
-
const { container:
|
|
13
|
-
/* @__PURE__ */ e(r, { children: /* @__PURE__ */ e(
|
|
5
|
+
import { d as h, i, g as t } from "../../chunks/vi.2VT5v0um.js";
|
|
6
|
+
h("<ChatHeader />", () => {
|
|
7
|
+
i("renders title, actions", () => {
|
|
8
|
+
o(
|
|
9
|
+
/* @__PURE__ */ e(r, { children: /* @__PURE__ */ e(s, { title: "Assistant", children: /* @__PURE__ */ e("span", { children: "Action" }) }) })
|
|
10
|
+
), t(a.getByText("Assistant")).toBeInTheDocument(), t(a.getByText("Action")).toBeInTheDocument();
|
|
11
|
+
}), i("toggles shadow based on variant and hides badge", () => {
|
|
12
|
+
const { container: n, queryByText: d } = o(
|
|
13
|
+
/* @__PURE__ */ e(r, { children: /* @__PURE__ */ e(s, { title: "No Shadow", variant: "no-shadow" }) })
|
|
14
14
|
);
|
|
15
|
-
t(
|
|
15
|
+
t(n.firstChild).not.toHaveClass("shadow-sm"), t(d("0")).toBeNull();
|
|
16
16
|
});
|
|
17
17
|
});
|
|
18
18
|
//# sourceMappingURL=ChatHeader.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatHeader.test.js","sources":["../../../lib/organisms/chat/ChatHeader.test.tsx"],"sourcesContent":["import {render, screen} from \"@testing-library/react\";\nimport {describe, expect, it} from \"vitest\";\nimport {ChatHeader} from \"./ChatHeader\";\nimport {ChatLabelsProvider} from \"../../contexts/ChatLabelsContext\";\n\ndescribe(\"<ChatHeader />\", () => {\n it(\"renders title, actions
|
|
1
|
+
{"version":3,"file":"ChatHeader.test.js","sources":["../../../lib/organisms/chat/ChatHeader.test.tsx"],"sourcesContent":["import {render, screen} from \"@testing-library/react\";\nimport {describe, expect, it} from \"vitest\";\nimport {ChatHeader} from \"./ChatHeader\";\nimport {ChatLabelsProvider} from \"../../contexts/ChatLabelsContext\";\n\ndescribe(\"<ChatHeader />\", () => {\n it(\"renders title, actions\", () => {\n render(\n <ChatLabelsProvider>\n <ChatHeader title=\"Assistant\">\n <span>Action</span>\n </ChatHeader>\n </ChatLabelsProvider>\n );\n\n expect(screen.getByText(\"Assistant\")).toBeInTheDocument();\n expect(screen.getByText(\"Action\")).toBeInTheDocument();\n });\n\n it(\"toggles shadow based on variant and hides badge\", () => {\n const {container, queryByText} = render(\n <ChatLabelsProvider>\n <ChatHeader title=\"No Shadow\" variant=\"no-shadow\" />\n </ChatLabelsProvider>\n );\n\n expect(container.firstChild).not.toHaveClass(\"shadow-sm\");\n expect(queryByText(\"0\")).toBeNull();\n });\n});\n"],"names":["describe","it","render","jsx","ChatLabelsProvider","ChatHeader","expect","screen","container","queryByText"],"mappings":";;;;;AAKAA,EAAS,kBAAkB,MAAM;AAC/B,EAAAC,EAAG,0BAA0B,MAAM;AACjC,IAAAC;AAAA,MACE,gBAAAC,EAACC,GAAA,EACC,UAAA,gBAAAD,EAACE,GAAA,EAAW,OAAM,aAChB,UAAA,gBAAAF,EAAC,QAAA,EAAK,UAAA,SAAA,CAAM,EAAA,CACd,EAAA,CACF;AAAA,IAAA,GAGFG,EAAOC,EAAO,UAAU,WAAW,CAAC,EAAE,kBAAA,GACtCD,EAAOC,EAAO,UAAU,QAAQ,CAAC,EAAE,kBAAA;AAAA,EACrC,CAAC,GAEDN,EAAG,mDAAmD,MAAM;AAC1D,UAAM,EAAC,WAAAO,GAAW,aAAAC,EAAA,IAAeP;AAAA,MAC/B,gBAAAC,EAACC,KACC,UAAA,gBAAAD,EAACE,GAAA,EAAW,OAAM,aAAY,SAAQ,aAAY,EAAA,CACpD;AAAA,IAAA;AAGFC,IAAAA,EAAOE,EAAU,UAAU,EAAE,IAAI,YAAY,WAAW,GACxDF,EAAOG,EAAY,GAAG,CAAC,EAAE,SAAA;AAAA,EAC3B,CAAC;AACH,CAAC;"}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { jsx as r } from "react/jsx-runtime";
|
|
2
2
|
import { useChatLabels as n } from "../../contexts/ChatLabelsContext.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { cn as s } from "../../utils/cn.js";
|
|
4
|
+
import { S as a } from "../../chunks/settings.js";
|
|
5
|
+
function f(t) {
|
|
5
6
|
const { get: o } = n(), e = o("chatSettingsButtonAriaLabel", "Paramètres");
|
|
6
7
|
return /* @__PURE__ */ r(
|
|
7
8
|
"button",
|
|
8
9
|
{
|
|
9
10
|
...t,
|
|
10
11
|
"aria-label": e,
|
|
11
|
-
className: "group
|
|
12
|
+
className: s("group flex h-10 w-10 sm:h-11 sm:w-11 items-center justify-center bg-transparent hover:bg-muted transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background rounded-lg p-2", t.className),
|
|
12
13
|
children: /* @__PURE__ */ r(
|
|
13
|
-
|
|
14
|
+
a,
|
|
14
15
|
{
|
|
15
16
|
className: "h-4 w-4 sm:h-5 sm:w-5 text-muted-foreground group-hover:rotate-90 transition-transform duration-500"
|
|
16
17
|
}
|
|
@@ -19,6 +20,6 @@ function m(t) {
|
|
|
19
20
|
);
|
|
20
21
|
}
|
|
21
22
|
export {
|
|
22
|
-
|
|
23
|
+
f as ChatSettingsButton
|
|
23
24
|
};
|
|
24
25
|
//# sourceMappingURL=ChatSettingsButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatSettingsButton.js","sources":["../../../lib/organisms/chat/ChatSettingsButton.tsx"],"sourcesContent":["import {Settings as SettingsIcon} from \"lucide-react\";\nimport type {ButtonHTMLAttributes} from \"react\";\nimport {useChatLabels} from \"../../contexts/ChatLabelsContext\";\n\nexport function ChatSettingsButton(props: ButtonHTMLAttributes<HTMLButtonElement>) {\n const {get} = useChatLabels();\n const ariaLabel = get(\"chatSettingsButtonAriaLabel\", \"Paramètres\");\n\n return (\n <button\n {...props}\n aria-label={ariaLabel}\n className
|
|
1
|
+
{"version":3,"file":"ChatSettingsButton.js","sources":["../../../lib/organisms/chat/ChatSettingsButton.tsx"],"sourcesContent":["import {Settings as SettingsIcon} from \"lucide-react\";\nimport type {ButtonHTMLAttributes} from \"react\";\nimport {useChatLabels} from \"../../contexts/ChatLabelsContext\";\nimport {cn} from \"@clubmed/usg-chat-ui/utils/cn\";\n\nexport function ChatSettingsButton(props: ButtonHTMLAttributes<HTMLButtonElement>) {\n const {get} = useChatLabels();\n const ariaLabel = get(\"chatSettingsButtonAriaLabel\", \"Paramètres\");\n\n return (\n <button\n {...props}\n aria-label={ariaLabel}\n className={cn(\"group flex h-10 w-10 sm:h-11 sm:w-11 items-center justify-center bg-transparent hover:bg-muted transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background rounded-lg p-2\", props.className)}\n >\n <SettingsIcon\n className=\"h-4 w-4 sm:h-5 sm:w-5 text-muted-foreground group-hover:rotate-90 transition-transform duration-500\"\n />\n </button>\n );\n}\n"],"names":["ChatSettingsButton","props","get","useChatLabels","ariaLabel","jsx","cn","SettingsIcon"],"mappings":";;;;AAKO,SAASA,EAAmBC,GAAgD;AACjF,QAAM,EAAC,KAAAC,EAAA,IAAOC,EAAA,GACRC,IAAYF,EAAI,+BAA+B,YAAY;AAEjE,SACE,gBAAAG;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAGJ;AAAA,MACJ,cAAYG;AAAA,MACZ,WAAWE,EAAG,8PAA8PL,EAAM,SAAS;AAAA,MAE3R,UAAA,gBAAAI;AAAA,QAACE;AAAAA,QAAA;AAAA,UACC,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IACZ;AAAA,EAAA;AAGN;"}
|
|
@@ -41,11 +41,11 @@ const B = [
|
|
|
41
41
|
function re({
|
|
42
42
|
currentConversationId: h,
|
|
43
43
|
onSelectConversation: f,
|
|
44
|
-
onNewConversation:
|
|
45
|
-
refreshTrigger:
|
|
44
|
+
onNewConversation: z,
|
|
45
|
+
refreshTrigger: A,
|
|
46
46
|
onClose: l
|
|
47
47
|
}) {
|
|
48
|
-
const u = _(), { get: p } = $(),
|
|
48
|
+
const u = _(), { get: p } = $(), D = p("conversationRefreshAriaLabel", "Rafraîchir"), S = p("conversationCloseHistoryAriaLabel", "Fermer l'historique"), [g, v] = o([]), [c, b] = o(!0), [N, x] = o(null), [y, w] = o(null), d = async () => {
|
|
49
49
|
try {
|
|
50
50
|
b(!0), w(null), console.log("[ConversationSidebar] Fetching conversations (auth-based)");
|
|
51
51
|
const e = await u.listConversations();
|
|
@@ -58,7 +58,7 @@ function re({
|
|
|
58
58
|
};
|
|
59
59
|
q(() => {
|
|
60
60
|
d();
|
|
61
|
-
}, [
|
|
61
|
+
}, [A]);
|
|
62
62
|
const E = async (e, r) => {
|
|
63
63
|
if (r.stopPropagation(), !!confirm("Voulez-vous vraiment supprimer cette conversation ?"))
|
|
64
64
|
try {
|
|
@@ -74,7 +74,7 @@ function re({
|
|
|
74
74
|
}, R = () => {
|
|
75
75
|
l == null || l();
|
|
76
76
|
};
|
|
77
|
-
return /* @__PURE__ */ a("div", { className: "flex flex-col h-full w-64 border-r border-border bg-card relative", children: [
|
|
77
|
+
return /* @__PURE__ */ a("div", { className: "z-20 flex flex-col h-full w-64 border-r border-border bg-card relative", children: [
|
|
78
78
|
/* @__PURE__ */ a("div", { className: "flex items-center justify-between p-3 border-b border-border", children: [
|
|
79
79
|
/* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
|
|
80
80
|
/* @__PURE__ */ t(I, { className: "h-4 w-4 text-muted-foreground" }),
|
|
@@ -88,7 +88,7 @@ function re({
|
|
|
88
88
|
size: "icon",
|
|
89
89
|
onClick: () => d(),
|
|
90
90
|
className: "h-6 w-6",
|
|
91
|
-
"aria-label":
|
|
91
|
+
"aria-label": D,
|
|
92
92
|
disabled: c,
|
|
93
93
|
children: /* @__PURE__ */ t(F, { className: M("h-3 w-3", c && "animate-spin") })
|
|
94
94
|
}
|
|
@@ -100,7 +100,7 @@ function re({
|
|
|
100
100
|
size: "icon",
|
|
101
101
|
onClick: R,
|
|
102
102
|
className: "h-6 w-6",
|
|
103
|
-
"aria-label":
|
|
103
|
+
"aria-label": S,
|
|
104
104
|
children: /* @__PURE__ */ t(P, { className: "h-3 w-3" })
|
|
105
105
|
}
|
|
106
106
|
)
|
|
@@ -111,7 +111,7 @@ function re({
|
|
|
111
111
|
{
|
|
112
112
|
variant: "default",
|
|
113
113
|
size: "sm",
|
|
114
|
-
onClick:
|
|
114
|
+
onClick: z,
|
|
115
115
|
className: "w-full",
|
|
116
116
|
children: "Nouvelle conversation"
|
|
117
117
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationSidebar.js","sources":["../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/message-square.js","../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/trash-2.js","../../../lib/organisms/chat/ConversationSidebar.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z\",\n key: \"18887p\"\n }\n ]\n];\nconst MessageSquare = createLucideIcon(\"message-square\", __iconNode);\n\nexport { __iconNode, MessageSquare as default };\n//# sourceMappingURL=message-square.js.map\n","/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 11v6\", key: \"nco0om\" }],\n [\"path\", { d: \"M14 11v6\", key: \"outv1u\" }],\n [\"path\", { d: \"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\", key: \"miytrc\" }],\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\", key: \"e791ji\" }]\n];\nconst Trash2 = createLucideIcon(\"trash-2\", __iconNode);\n\nexport { __iconNode, Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","\"use client\";\n\nimport type {MouseEvent} from \"react\";\nimport {useEffect, useState} from \"react\";\nimport {Loader2, MessageSquare, PanelLeft, RefreshCw, Trash2} from \"lucide-react\";\nimport {Button} from \"@clubmed/usg-chat-ui/molecules/Buttons/Button\";\nimport {ScrollArea} from \"@clubmed/usg-chat-ui/molecules/ScrollAreas/ScrollArea\";\nimport {cn} from \"@clubmed/usg-chat-ui/utils/cn\";\nimport {useChatApiClient} from \"@clubmed/usg-chat-ui/contexts/ChatContext\";\nimport type {ConversationSummary} from \"@clubmed/usg-chat-ui/core/interfaces\";\nimport {useChatLabels} from \"../../contexts/ChatLabelsContext\";\n\ninterface ConversationSidebarProps {\n currentConversationId: string | null;\n onSelectConversation: (conversation: ConversationSummary | null) => void;\n onNewConversation: () => void;\n refreshTrigger?: number; // Trigger refresh when this changes\n onClose?: () => void; // Callback when sidebar is closed\n}\n\nexport function ConversationSidebar({\n currentConversationId,\n onSelectConversation,\n onNewConversation,\n refreshTrigger,\n onClose,\n}: ConversationSidebarProps) {\n const apiClient = useChatApiClient();\n const {get} = useChatLabels();\n const refreshLabel = get(\"conversationRefreshAriaLabel\", \"Rafraîchir\");\n const closeHistoryLabel = get(\"conversationCloseHistoryAriaLabel\", \"Fermer l'historique\");\n const [conversations, setConversations] = useState<ConversationSummary[]>([]);\n const [loading, setLoading] = useState(true);\n const [deletingId, setDeletingId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const loadConversations = async () => {\n try {\n setLoading(true);\n setError(null);\n\n console.log('[ConversationSidebar] Fetching conversations (auth-based)');\n const data = await apiClient.listConversations();\n console.log('[ConversationSidebar] Conversations received:', data, 'count:', data.length);\n\n setConversations(data);\n } catch (error) {\n setError(error instanceof Error ? error.message : \"Erreur lors du chargement\");\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n loadConversations();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refreshTrigger]);\n\n const handleDelete = async (\n conversationId: string,\n event: MouseEvent<HTMLButtonElement>\n ) => {\n event.stopPropagation();\n if (!confirm(\"Voulez-vous vraiment supprimer cette conversation ?\")) {\n return;\n }\n\n try {\n setDeletingId(conversationId);\n\n await apiClient.deleteConversation({conversationId});\n\n setConversations((prev) => prev.filter((c) => c.id !== conversationId));\n if (currentConversationId === conversationId) {\n onSelectConversation(null);\n }\n // Reload conversations to ensure consistency\n await loadConversations();\n } catch (error) {\n console.error(\"Error deleting conversation:\", error);\n alert(\"Erreur lors de la suppression\");\n } finally {\n setDeletingId(null);\n }\n };\n\n const formatDate = (dateString: string) => {\n const date = new Date(dateString);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return \"À l'instant\";\n if (diffMins < 60) return `Il y a ${diffMins} min`;\n if (diffHours < 24) return `Il y a ${diffHours}h`;\n if (diffDays < 7) return `Il y a ${diffDays}j`;\n return date.toLocaleDateString(\"fr-FR\", {day: \"numeric\", month: \"short\"});\n };\n\n const handleClose = () => {\n onClose?.();\n };\n\n return (\n <div className=\"flex flex-col h-full w-64 border-r border-border bg-card relative\">\n {/* Header */}\n <div className=\"flex items-center justify-between p-3 border-b border-border\">\n <div className=\"flex items-center gap-2\">\n <MessageSquare className=\"h-4 w-4 text-muted-foreground\"/>\n <h2 className=\"text-sm font-semibold text-foreground\">Historique</h2>\n </div>\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => loadConversations()}\n className=\"h-6 w-6\"\n aria-label={refreshLabel}\n disabled={loading}\n >\n <RefreshCw className={cn(\"h-3 w-3\", loading && \"animate-spin\")}/>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={handleClose}\n className=\"h-6 w-6\"\n aria-label={closeHistoryLabel}\n >\n <PanelLeft className=\"h-3 w-3\"/>\n </Button>\n </div>\n </div>\n\n {/* New Conversation Button */}\n <div className=\"p-2 border-b border-border\">\n <Button\n variant=\"default\"\n size=\"sm\"\n onClick={onNewConversation}\n className=\"w-full\"\n >\n Nouvelle conversation\n </Button>\n </div>\n\n {/* Conversations List */}\n <ScrollArea className=\"flex-1\">\n {loading ? (\n <div className=\"flex items-center justify-center p-4\">\n <Loader2 className=\"h-4 w-4 animate-spin text-muted-foreground\"/>\n </div>\n ) : error ? (\n <div className=\"p-4 text-center text-sm text-destructive\">\n {error}\n </div>\n ) : conversations.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-muted-foreground\">\n Aucune conversation\n </div>\n ) : (\n <div className=\"p-2\">\n {conversations.map((conversation) => (\n <div\n key={conversation.id}\n onClick={() => onSelectConversation(conversation)}\n className={cn(\n \"group relative p-3 rounded-lg cursor-pointer transition-colors mb-1\",\n currentConversationId === conversation.id\n ? \"bg-muted\"\n : \"hover:bg-muted/50\"\n )}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-sm font-medium text-foreground truncate\">\n {conversation.title || \"Sans titre\"}\n </h3>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {formatDate(conversation.updatedAt)}\n </p>\n </div>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event: MouseEvent<HTMLButtonElement>) =>\n handleDelete(conversation.id, event)\n }\n className=\"h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity shrink-0\"\n disabled={deletingId === conversation.id}\n >\n {deletingId === conversation.id ? (\n <Loader2 className=\"h-3 w-3 animate-spin\"/>\n ) : (\n <Trash2 className=\"h-3 w-3\"/>\n )}\n </Button>\n </div>\n </div>\n ))}\n </div>\n )}\n </ScrollArea>\n </div>\n );\n}\n"],"names":["__iconNode","MessageSquare","createLucideIcon","Trash2","ConversationSidebar","currentConversationId","onSelectConversation","onNewConversation","refreshTrigger","onClose","apiClient","useChatApiClient","get","useChatLabels","refreshLabel","closeHistoryLabel","conversations","setConversations","useState","loading","setLoading","deletingId","setDeletingId","error","setError","loadConversations","data","useEffect","handleDelete","conversationId","event","prev","c","formatDate","dateString","date","diffMs","diffMins","diffHours","diffDays","handleClose","jsxs","jsx","Button","RefreshCw","cn","PanelLeft","ScrollArea","Loader2","conversation"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"ConversationSidebar.js","sources":["../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/message-square.js","../../../../../node_modules/.pnpm/lucide-react@0.545.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/trash-2.js","../../../lib/organisms/chat/ConversationSidebar.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z\",\n key: \"18887p\"\n }\n ]\n];\nconst MessageSquare = createLucideIcon(\"message-square\", __iconNode);\n\nexport { __iconNode, MessageSquare as default };\n//# sourceMappingURL=message-square.js.map\n","/**\n * @license lucide-react v0.545.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 11v6\", key: \"nco0om\" }],\n [\"path\", { d: \"M14 11v6\", key: \"outv1u\" }],\n [\"path\", { d: \"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\", key: \"miytrc\" }],\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\", key: \"e791ji\" }]\n];\nconst Trash2 = createLucideIcon(\"trash-2\", __iconNode);\n\nexport { __iconNode, Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","\"use client\";\n\nimport type {MouseEvent} from \"react\";\nimport {useEffect, useState} from \"react\";\nimport {Loader2, MessageSquare, PanelLeft, RefreshCw, Trash2} from \"lucide-react\";\nimport {Button} from \"@clubmed/usg-chat-ui/molecules/Buttons/Button\";\nimport {ScrollArea} from \"@clubmed/usg-chat-ui/molecules/ScrollAreas/ScrollArea\";\nimport {cn} from \"@clubmed/usg-chat-ui/utils/cn\";\nimport {useChatApiClient} from \"@clubmed/usg-chat-ui/contexts/ChatContext\";\nimport type {ConversationSummary} from \"@clubmed/usg-chat-ui/core/interfaces\";\nimport {useChatLabels} from \"../../contexts/ChatLabelsContext\";\n\ninterface ConversationSidebarProps {\n currentConversationId: string | null;\n onSelectConversation: (conversation: ConversationSummary | null) => void;\n onNewConversation: () => void;\n refreshTrigger?: number; // Trigger refresh when this changes\n onClose?: () => void; // Callback when sidebar is closed\n}\n\nexport function ConversationSidebar({\n currentConversationId,\n onSelectConversation,\n onNewConversation,\n refreshTrigger,\n onClose,\n}: ConversationSidebarProps) {\n const apiClient = useChatApiClient();\n const {get} = useChatLabels();\n const refreshLabel = get(\"conversationRefreshAriaLabel\", \"Rafraîchir\");\n const closeHistoryLabel = get(\"conversationCloseHistoryAriaLabel\", \"Fermer l'historique\");\n const [conversations, setConversations] = useState<ConversationSummary[]>([]);\n const [loading, setLoading] = useState(true);\n const [deletingId, setDeletingId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const loadConversations = async () => {\n try {\n setLoading(true);\n setError(null);\n\n console.log('[ConversationSidebar] Fetching conversations (auth-based)');\n const data = await apiClient.listConversations();\n console.log('[ConversationSidebar] Conversations received:', data, 'count:', data.length);\n\n setConversations(data);\n } catch (error) {\n setError(error instanceof Error ? error.message : \"Erreur lors du chargement\");\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n loadConversations();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refreshTrigger]);\n\n const handleDelete = async (\n conversationId: string,\n event: MouseEvent<HTMLButtonElement>\n ) => {\n event.stopPropagation();\n if (!confirm(\"Voulez-vous vraiment supprimer cette conversation ?\")) {\n return;\n }\n\n try {\n setDeletingId(conversationId);\n\n await apiClient.deleteConversation({conversationId});\n\n setConversations((prev) => prev.filter((c) => c.id !== conversationId));\n if (currentConversationId === conversationId) {\n onSelectConversation(null);\n }\n // Reload conversations to ensure consistency\n await loadConversations();\n } catch (error) {\n console.error(\"Error deleting conversation:\", error);\n alert(\"Erreur lors de la suppression\");\n } finally {\n setDeletingId(null);\n }\n };\n\n const formatDate = (dateString: string) => {\n const date = new Date(dateString);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return \"À l'instant\";\n if (diffMins < 60) return `Il y a ${diffMins} min`;\n if (diffHours < 24) return `Il y a ${diffHours}h`;\n if (diffDays < 7) return `Il y a ${diffDays}j`;\n return date.toLocaleDateString(\"fr-FR\", {day: \"numeric\", month: \"short\"});\n };\n\n const handleClose = () => {\n onClose?.();\n };\n\n return (\n <div className=\"z-20 flex flex-col h-full w-64 border-r border-border bg-card relative\">\n {/* Header */}\n <div className=\"flex items-center justify-between p-3 border-b border-border\">\n <div className=\"flex items-center gap-2\">\n <MessageSquare className=\"h-4 w-4 text-muted-foreground\"/>\n <h2 className=\"text-sm font-semibold text-foreground\">Historique</h2>\n </div>\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => loadConversations()}\n className=\"h-6 w-6\"\n aria-label={refreshLabel}\n disabled={loading}\n >\n <RefreshCw className={cn(\"h-3 w-3\", loading && \"animate-spin\")}/>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={handleClose}\n className=\"h-6 w-6\"\n aria-label={closeHistoryLabel}\n >\n <PanelLeft className=\"h-3 w-3\"/>\n </Button>\n </div>\n </div>\n\n {/* New Conversation Button */}\n <div className=\"p-2 border-b border-border\">\n <Button\n variant=\"default\"\n size=\"sm\"\n onClick={onNewConversation}\n className=\"w-full\"\n >\n Nouvelle conversation\n </Button>\n </div>\n\n {/* Conversations List */}\n <ScrollArea className=\"flex-1\">\n {loading ? (\n <div className=\"flex items-center justify-center p-4\">\n <Loader2 className=\"h-4 w-4 animate-spin text-muted-foreground\"/>\n </div>\n ) : error ? (\n <div className=\"p-4 text-center text-sm text-destructive\">\n {error}\n </div>\n ) : conversations.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-muted-foreground\">\n Aucune conversation\n </div>\n ) : (\n <div className=\"p-2\">\n {conversations.map((conversation) => (\n <div\n key={conversation.id}\n onClick={() => onSelectConversation(conversation)}\n className={cn(\n \"group relative p-3 rounded-lg cursor-pointer transition-colors mb-1\",\n currentConversationId === conversation.id\n ? \"bg-muted\"\n : \"hover:bg-muted/50\"\n )}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"text-sm font-medium text-foreground truncate\">\n {conversation.title || \"Sans titre\"}\n </h3>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {formatDate(conversation.updatedAt)}\n </p>\n </div>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event: MouseEvent<HTMLButtonElement>) =>\n handleDelete(conversation.id, event)\n }\n className=\"h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity shrink-0\"\n disabled={deletingId === conversation.id}\n >\n {deletingId === conversation.id ? (\n <Loader2 className=\"h-3 w-3 animate-spin\"/>\n ) : (\n <Trash2 className=\"h-3 w-3\"/>\n )}\n </Button>\n </div>\n </div>\n ))}\n </div>\n )}\n </ScrollArea>\n </div>\n );\n}\n"],"names":["__iconNode","MessageSquare","createLucideIcon","Trash2","ConversationSidebar","currentConversationId","onSelectConversation","onNewConversation","refreshTrigger","onClose","apiClient","useChatApiClient","get","useChatLabels","refreshLabel","closeHistoryLabel","conversations","setConversations","useState","loading","setLoading","deletingId","setDeletingId","error","setError","loadConversations","data","useEffect","handleDelete","conversationId","event","prev","c","formatDate","dateString","date","diffMs","diffMins","diffHours","diffDays","handleClose","jsxs","jsx","Button","RefreshCw","cn","PanelLeft","ScrollArea","Loader2","conversation"],"mappings":"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","x_google_ignoreList":[0,1]}
|