@sybilion/uilib 1.3.82 → 1.3.83

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.
@@ -15,7 +15,7 @@ import { filterToTextAttachments, isAttachmentsDropzoneEnabled, buildAcceptAttr
15
15
  import { extractChatAttachmentItems } from '../chatAttachmentExtract.js';
16
16
  import S from './ChatChrome.styl.js';
17
17
 
18
- function ChatChrome({ variant = 'default', showResizeHandle, resizeHandle, onClose, isEmpty, renderPresets, messages, onQuickReply, suppressedQuickReplyKeys, isLoading, loadingLabel, scriptContinueLabel, onScriptContinue, renderMessageChart, renderSystemMessage, showSyntheticBranchButtons, unusedBranchKeys, showInlinePresets, isLastMessageFromUser, scrollRef, effectiveScopeId, onPromptSubmit, onChatDeleted, onNewChat, promptPrefill, footerClassName, emptyState, allowedAttachments, allowPdfAttachments = false, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, promptPlaceholder, hideChatSelector = false, }) {
18
+ function ChatChrome({ variant = 'default', showResizeHandle, resizeHandle, onClose, isEmpty, renderPresets, messages, onQuickReply, suppressedQuickReplyKeys, isLoading, loadingLabel, scriptContinueLabel, onScriptContinue, renderMessageChart, renderSystemMessage, showSyntheticBranchButtons, unusedBranchKeys, showInlinePresets, isLastMessageFromUser, scrollRef, effectiveScopeId, onPromptSubmit, onChatDeleted, onNewChat, promptPrefill, footerClassName, messageClassNames, messageTextClassNames, emptyState, allowedAttachments, allowPdfAttachments = false, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, promptPlaceholder, hideChatSelector = false, }) {
19
19
  const filteredAllowedAttachments = useMemo(() => filterToTextAttachments(allowedAttachments), [allowedAttachments]);
20
20
  const attachmentsDropzoneEnabled = isAttachmentsDropzoneEnabled(allowedAttachments, allowPdfAttachments);
21
21
  const attachmentAccept = useMemo(() => buildAcceptAttr(filteredAllowedAttachments, allowPdfAttachments), [filteredAllowedAttachments, allowPdfAttachments]);
@@ -79,7 +79,21 @@ function ChatChrome({ variant = 'default', showResizeHandle, resizeHandle, onClo
79
79
  const isClean = variant === 'clean';
80
80
  return (jsxs("div", { className: cn(S.root, isClean && S.rootClean), children: [showResizeHandle && resizeHandle ? (jsx(PanelResizeHandle, { edge: "leading", isActive: resizeHandle.isActive, startWidthPx: resizeHandle.startWidthPx, getShellWidth: resizeHandle.getShellWidth, onDragWidth: resizeHandle.onDragWidth, onDragComplete: resizeHandle.onDragComplete, className: cn(SidebarStem.sidebarResizeHandle, S.chatResizeHandle) })) : null, jsx("div", { className: S.panelHeader, children: onClose ? (jsx(Button, { type: "button", variant: "ghost", icon: true, className: S.panelClose, "aria-label": "Close chat", onClick: onClose, children: jsx(X, { className: "size-4" }) })) : null }), jsxs("div", { className: S.content, children: [attachmentsDropzoneEnabled ? (jsx(DropZone, { accept: attachmentAccept, label: "Drop text files to attach", multiple: true, ghost: true, overlayScope: "container", disabled: promptDisabled, className: S.attachmentDropzone, onFiles: handleAttachmentFiles })) : null, jsxs(Chat, { className: isClean ? S.chatClean : undefined, isEmpty: isEmpty, scopeId: effectiveScopeId, onChatDeleted: onChatDeleted, onNewChat: onNewChat, hideChatSelector: hideChatSelector, children: [isEmpty ? (jsx("div", { className: S.emptyBody, children: jsx(Chat.EmptyState, { ...emptyState }) })) : (jsx("div", { className: S.scrollWrapper, children: jsxs(Scroll, { y: true, yScrollbarClassName: S.scrollbar, className: S.scroll, innerClassName: S.scrollInner, offset: { y: { before: 56, after: 24 } }, fadeSize: "m", autoHide: true, ref: scrollRef, children: [messages.map((msg, index, arr) => {
81
81
  const isLast = index === arr.length - 1;
82
- return (jsx(Chat.Message, { message: msg, role: msg.role, text: msg.text, inProgress: msg.inProgress, userTextFileAttachments: msg.userTextFileAttachments, onQuickReply: onQuickReply, suppressedQuickReplyKeys: suppressedQuickReplyKeys, quickReplyDisabled: isLoading, quickReplyHidden: Boolean(loadingLabel), isLastMessage: isLast, scriptContinue: isLast && scriptContinueLabel
82
+ const messageClassName = messageClassNames
83
+ ? {
84
+ [MessageRole.USER]: messageClassNames.user,
85
+ [MessageRole.ASSISTANT]: messageClassNames.assistant,
86
+ [MessageRole.SYSTEM]: messageClassNames.system,
87
+ }[msg.role]
88
+ : undefined;
89
+ const messageTextClassName = messageTextClassNames
90
+ ? {
91
+ [MessageRole.USER]: messageTextClassNames.user,
92
+ [MessageRole.ASSISTANT]: messageTextClassNames.assistant,
93
+ [MessageRole.SYSTEM]: messageTextClassNames.system,
94
+ }[msg.role]
95
+ : undefined;
96
+ return (jsx(Chat.Message, { message: msg, className: messageClassName, textClassName: messageTextClassName, role: msg.role, text: msg.text, inProgress: msg.inProgress, userTextFileAttachments: msg.userTextFileAttachments, onQuickReply: onQuickReply, suppressedQuickReplyKeys: suppressedQuickReplyKeys, quickReplyDisabled: isLoading, quickReplyHidden: Boolean(loadingLabel), isLastMessage: isLast, scriptContinue: isLast && scriptContinueLabel
83
97
  ? { label: scriptContinueLabel }
84
98
  : undefined, onScriptContinue: isLast && scriptContinueLabel
85
99
  ? onScriptContinue
@@ -88,8 +102,7 @@ function ChatChrome({ variant = 'default', showResizeHandle, resizeHandle, onClo
88
102
  const label = displayLabelForBranchKeyFromMessages(key, messages) ??
89
103
  humanizeBranchKey(key);
90
104
  return (jsx("span", { className: S.branchBtnWrap, children: jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: isLoading, onClick: () => onQuickReply(key, label), children: [jsx(PaperPlaneRightIcon, {}), label] }) }, key));
91
- }) })) : null, showInlinePresets &&
92
- renderPresets('inline', { variant }), isLoading &&
105
+ }) })) : null, showInlinePresets && renderPresets('inline', { variant }), isLoading &&
93
106
  !hasInProgressSystemMessage &&
94
107
  (isLastMessageFromUser || loadingLabel) && (jsx(TextShimmer, { duration: 1, spread: 5, className: S.loader, children: loadingLabel ?? 'Thinking...' }))] }) })), isEmpty ? (jsx("div", { className: S.fixedPresets, children: renderPresets('fixed', { variant }) })) : null, isEmpty ? (jsx("div", { className: S.notice, children: "Forecast Assistant can make mistakes." })) : null, jsx("div", { className: cn(S.footer, isClean && S.footerClean, footerClassName), children: jsx(Chat.Prompt, { className: isClean ? S.promptClean : undefined, onSubmit: handlePromptSubmitWithAttachments, disabled: promptDisabled, attachments: pendingAttachments, onRemoveAttachment: handleRemoveAttachment, prefillMessage: promptPrefill ?? undefined, placeholder: promptPlaceholder, slashCommandItems: slashCommandItems, onSlashItemCommand: onSlashItemCommand, attachmentAccept: attachmentsDropzoneEnabled ? attachmentAccept : undefined, onAttachmentFiles: attachmentsDropzoneEnabled ? handleAttachmentFiles : undefined }) })] })] })] }));
95
108
  }
@@ -1,4 +1,5 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import cn from 'classnames';
2
3
  import { useState, useMemo } from 'react';
3
4
  import { Button } from '../../Button/Button.js';
4
5
  import { InteractiveContent } from '../../InteractiveContent/InteractiveContent.js';
@@ -13,7 +14,7 @@ import S from './ChatMessage.styl.js';
13
14
  import { DocIcon } from './icons/DocIcon.js';
14
15
  import { XlsIcon } from './icons/XlsIcon.js';
15
16
 
16
- function AgentMessageContent({ text, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage = true, scriptContinue, onScriptContinue, renderMessageChart, }) {
17
+ function AgentMessageContent({ text, textClassName, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage = true, scriptContinue, onScriptContinue, renderMessageChart, }) {
17
18
  const [showRaw, setShowRaw] = useState(false);
18
19
  const parts = useMemo(() => {
19
20
  // Convert markdown tables to HTML first
@@ -125,7 +126,7 @@ function AgentMessageContent({ text, onQuickReply, suppressedQuickReplyKeys, qui
125
126
  isLastMessage,
126
127
  renderMessageChart,
127
128
  ]);
128
- return (jsxs("div", { className: S.text, children: [showRaw ? text : parts, !showRaw &&
129
+ return (jsxs("div", { className: cn(S.text, textClassName), children: [showRaw ? text : parts, !showRaw &&
129
130
  !quickReplyHidden &&
130
131
  isLastMessage &&
131
132
  scriptContinue &&
@@ -10,13 +10,13 @@ import { AgentMessageContent } from './AgentMessageContent.js';
10
10
  import S from './ChatMessage.styl.js';
11
11
  import { UserTextFileAttachmentBubble } from './UserTextFileAttachmentBubble.js';
12
12
 
13
- function ChatMessage({ role, text, inProgress, userTextFileAttachments, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage = true, scriptContinue, onScriptContinue, renderMessageChart, message, renderSystemMessage, }) {
13
+ function ChatMessage({ role, text, inProgress, userTextFileAttachments, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage = true, scriptContinue, onScriptContinue, renderMessageChart, message, renderSystemMessage, className, textClassName, }) {
14
14
  const fileAttachments = userTextFileAttachmentsFromMessage({
15
15
  userTextFileAttachments,
16
16
  });
17
17
  const isAssistant = role === MessageRole.ASSISTANT;
18
18
  const isSystem = role === MessageRole.SYSTEM;
19
- return (jsx("div", { className: cn(S.root, S[`role-${role}`]), children: isSystem ? (jsx("div", { className: S.text, children: inProgress ? (jsx(TextShimmer, { as: "span", children: text })) : renderSystemMessage && message ? (renderSystemMessage(message)) : (text) })) : isAssistant ? (jsx(AgentMessageContent, { text: text, onQuickReply: onQuickReply, suppressedQuickReplyKeys: suppressedQuickReplyKeys, quickReplyDisabled: quickReplyDisabled, quickReplyHidden: quickReplyHidden, isLastMessage: isLastMessage, scriptContinue: scriptContinue, onScriptContinue: onScriptContinue, renderMessageChart: renderMessageChart })) : (jsxs("div", { className: S.userColumn, children: [jsx("div", { className: S.text, children: jsx(InteractiveContent, { text: text }) }), fileAttachments.map(attachment => (jsx(UserTextFileAttachmentBubble, { attachment: attachment }, `${attachment.displayName}:${attachment.filename}`)))] })) }));
19
+ return (jsx("div", { className: cn(S.root, S[`role-${role}`], className), children: isSystem ? (jsx("div", { className: cn(S.text, textClassName), children: inProgress ? (jsx(TextShimmer, { as: "span", children: text })) : renderSystemMessage && message ? (renderSystemMessage(message)) : (text) })) : isAssistant ? (jsx(AgentMessageContent, { text: text, textClassName: textClassName, onQuickReply: onQuickReply, suppressedQuickReplyKeys: suppressedQuickReplyKeys, quickReplyDisabled: quickReplyDisabled, quickReplyHidden: quickReplyHidden, isLastMessage: isLastMessage, scriptContinue: scriptContinue, onScriptContinue: onScriptContinue, renderMessageChart: renderMessageChart })) : (jsxs("div", { className: S.userColumn, children: [jsx("div", { className: cn(S.text, textClassName && S.textCustom, textClassName), children: jsx(InteractiveContent, { text: text }) }), fileAttachments.map(attachment => (jsx(UserTextFileAttachmentBubble, { attachment: attachment }, `${attachment.displayName}:${attachment.filename}`)))] })) }));
20
20
  }
21
21
 
22
22
  export { ChatMessage };
@@ -1,7 +1,7 @@
1
1
  import styleInject from 'style-inject';
2
2
 
3
- var css_248z = ".ChatMessage_root__6rnsF{background:var(--bg-secondary);display:flex;flex-direction:column;gap:var(--p-1);padding:var(--p-4);padding-bottom:var(--p-1)}.ChatMessage_text__Y1XNR{color:var(--text-secondary);font-size:var(--text-sm);max-width:100%;min-width:0;overflow-wrap:anywhere;-webkit-user-select:text;-moz-user-select:text;user-select:text;width:-moz-fit-content;width:fit-content;word-break:break-word}.ChatMessage_role-assistant__wketE+.ChatMessage_role-assistant__wketE,.ChatMessage_role-system__g13OP+.ChatMessage_role-system__g13OP,.ChatMessage_role-user__u4JPV+.ChatMessage_role-user__u4JPV{padding-top:var(--p-1)}.ChatMessage_role-user__u4JPV{align-items:flex-end;max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_userColumn__cQM6-{align-items:flex-end;display:flex;flex-direction:column;gap:var(--p-2);max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{background-color:var(--sb-slate-100);border-radius:var(--p-4);border-bottom-right-radius:0;box-sizing:border-box;overflow:hidden;padding:var(--p-3) var(--p-4);white-space:pre-wrap}.dark .ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{background-color:var(--sb-gray-900)}.ChatMessage_role-system__g13OP{align-items:center}.ChatMessage_role-system__g13OP .ChatMessage_text__Y1XNR{color:var(--muted-foreground);width:100%}.ChatMessage_role-assistant__wketE .ChatMessage_text__Y1XNR{width:100%}.ChatMessage_role-assistant__wketE h3{line-height:2.4}.ChatMessage_role-assistant__wketE h4{font-size:1.1em;font-weight:600;line-height:2.2}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq{display:inline-block;margin-left:4px;margin-right:6px}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq:before{color:var(--text-secondary);content:\"•\";display:inline-block}.ChatMessage_role-assistant__wketE .ChatMessage_scrollHorizontal__Rms9n{max-width:100%}.ChatMessage_role-assistant__wketE table{border:1px solid var(--border);border-collapse:collapse;border-radius:var(--p-2);border-spacing:0;margin:var(--p-4) 0;overflow:hidden}.ChatMessage_role-assistant__wketE table td,.ChatMessage_role-assistant__wketE table th{border:1px solid var(--border);min-width:100px;padding:var(--p-1)}.ChatMessage_role-assistant__wketE table th{text-align:left}.ChatMessage_role-assistant__wketE ol,.ChatMessage_role-assistant__wketE ul{padding-left:var(--p-4)}.ChatMessage_role-assistant__wketE ul{list-style-type:disc}.ChatMessage_role-assistant__wketE ol{list-style-type:decimal}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{align-items:center;border:1px dashed var(--sb-slate-300);border-radius:8px;color:var(--foreground);display:inline-flex;font-size:var(--text-xs);gap:6px;margin:1px;max-width:100%;padding:2px 6px 2px 4px;text-decoration:none;vertical-align:middle}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-slate-50);border-color:var(--sb-slate-400);border-style:solid}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{border-color:var(--sb-gray-600)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-gray-900)}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLinkLabel__PMU7e{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ChatMessage_role-assistant__wketE .ChatMessage_quickReplyWrap__1UFyD{display:inline-block;margin:var(--p-1) var(--p-1) var(--p-1) 0;vertical-align:middle;width:100%}.ChatMessage_role-assistant__wketE .ChatMessage_downloadButtons__RygM-{display:flex;gap:var(--p-2);margin-top:var(--p-4)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{align-items:center;background-color:var(--background);border-radius:var(--p-3);box-shadow:0 0 0 1px var(--border);cursor:pointer;display:flex;gap:var(--p-4);margin-top:var(--p-3);padding:var(--p-3);padding-right:var(--p-4);transition:all .15s;width:-moz-fit-content;width:fit-content}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-50);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{background-color:var(--sb-gray-900);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-800)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardIcon__jkxDJ{align-items:center;border-radius:var(--p-2);display:flex;flex-shrink:0;height:32px;justify-content:center;width:32px}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardContent__PTPwz{display:flex;flex:1;flex-direction:column;min-width:0}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardTitle__K1wqr{font-size:var(--text-base);font-weight:600;line-height:1.4}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardSubtitle__fVeF2{color:var(--muted-foreground);font-size:var(--text-sm);line-height:1.4}";
4
- var S = {"root":"ChatMessage_root__6rnsF","text":"ChatMessage_text__Y1XNR","role-user":"ChatMessage_role-user__u4JPV","role-assistant":"ChatMessage_role-assistant__wketE","role-system":"ChatMessage_role-system__g13OP","userColumn":"ChatMessage_userColumn__cQM6-","bullet":"ChatMessage_bullet__6vAhq","scrollHorizontal":"ChatMessage_scrollHorizontal__Rms9n","datasetAppLink":"ChatMessage_datasetAppLink__Pxy-T","datasetAppLinkLabel":"ChatMessage_datasetAppLinkLabel__PMU7e","quickReplyWrap":"ChatMessage_quickReplyWrap__1UFyD","downloadButtons":"ChatMessage_downloadButtons__RygM-","downloadCard":"ChatMessage_downloadCard__NsNRa","downloadCardIcon":"ChatMessage_downloadCardIcon__jkxDJ","downloadCardContent":"ChatMessage_downloadCardContent__PTPwz","downloadCardTitle":"ChatMessage_downloadCardTitle__K1wqr","downloadCardSubtitle":"ChatMessage_downloadCardSubtitle__fVeF2"};
3
+ var css_248z = ".ChatMessage_root__6rnsF{background:var(--bg-secondary);display:flex;flex-direction:column;gap:var(--p-1);padding:var(--p-4);padding-bottom:var(--p-1)}.ChatMessage_text__Y1XNR{color:var(--text-secondary);font-size:var(--text-sm);max-width:100%;min-width:0;overflow-wrap:anywhere;-webkit-user-select:text;-moz-user-select:text;user-select:text;width:-moz-fit-content;width:fit-content;word-break:break-word}.ChatMessage_role-assistant__wketE+.ChatMessage_role-assistant__wketE,.ChatMessage_role-system__g13OP+.ChatMessage_role-system__g13OP,.ChatMessage_role-user__u4JPV+.ChatMessage_role-user__u4JPV{padding-top:var(--p-1)}.ChatMessage_role-user__u4JPV{align-items:flex-end;max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_userColumn__cQM6-{align-items:flex-end;display:flex;flex-direction:column;gap:var(--p-2);max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{border-radius:var(--p-4);border-bottom-right-radius:0;box-sizing:border-box;overflow:hidden;padding:var(--p-3) var(--p-4);white-space:pre-wrap}.ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR:not(.ChatMessage_textCustom__C8Tts){background-color:var(--sb-slate-100)}.dark .ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR:not(.ChatMessage_textCustom__C8Tts){background-color:var(--sb-gray-900)}.ChatMessage_role-system__g13OP{align-items:center}.ChatMessage_role-system__g13OP .ChatMessage_text__Y1XNR{color:var(--muted-foreground);width:100%}.ChatMessage_role-assistant__wketE .ChatMessage_text__Y1XNR{width:100%}.ChatMessage_role-assistant__wketE h3{line-height:2.4}.ChatMessage_role-assistant__wketE h4{font-size:1.1em;font-weight:600;line-height:2.2}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq{display:inline-block;margin-left:4px;margin-right:6px}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq:before{color:var(--text-secondary);content:\"•\";display:inline-block}.ChatMessage_role-assistant__wketE .ChatMessage_scrollHorizontal__Rms9n{max-width:100%}.ChatMessage_role-assistant__wketE table{border:1px solid var(--border);border-collapse:collapse;border-radius:var(--p-2);border-spacing:0;margin:var(--p-4) 0;overflow:hidden}.ChatMessage_role-assistant__wketE table td,.ChatMessage_role-assistant__wketE table th{border:1px solid var(--border);min-width:100px;padding:var(--p-1)}.ChatMessage_role-assistant__wketE table th{text-align:left}.ChatMessage_role-assistant__wketE ol,.ChatMessage_role-assistant__wketE ul{padding-left:var(--p-4)}.ChatMessage_role-assistant__wketE ul{list-style-type:disc}.ChatMessage_role-assistant__wketE ol{list-style-type:decimal}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{align-items:center;border:1px dashed var(--sb-slate-300);border-radius:8px;color:var(--foreground);display:inline-flex;font-size:var(--text-xs);gap:6px;margin:1px;max-width:100%;padding:2px 6px 2px 4px;text-decoration:none;vertical-align:middle}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-slate-50);border-color:var(--sb-slate-400);border-style:solid}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{border-color:var(--sb-gray-600)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-gray-900)}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLinkLabel__PMU7e{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ChatMessage_role-assistant__wketE .ChatMessage_quickReplyWrap__1UFyD{display:inline-block;margin:var(--p-1) var(--p-1) var(--p-1) 0;vertical-align:middle;width:100%}.ChatMessage_role-assistant__wketE .ChatMessage_downloadButtons__RygM-{display:flex;gap:var(--p-2);margin-top:var(--p-4)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{align-items:center;background-color:var(--background);border-radius:var(--p-3);box-shadow:0 0 0 1px var(--border);cursor:pointer;display:flex;gap:var(--p-4);margin-top:var(--p-3);padding:var(--p-3);padding-right:var(--p-4);transition:all .15s;width:-moz-fit-content;width:fit-content}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-50);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{background-color:var(--sb-gray-900);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-800)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardIcon__jkxDJ{align-items:center;border-radius:var(--p-2);display:flex;flex-shrink:0;height:32px;justify-content:center;width:32px}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardContent__PTPwz{display:flex;flex:1;flex-direction:column;min-width:0}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardTitle__K1wqr{font-size:var(--text-base);font-weight:600;line-height:1.4}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardSubtitle__fVeF2{color:var(--muted-foreground);font-size:var(--text-sm);line-height:1.4}";
4
+ var S = {"root":"ChatMessage_root__6rnsF","text":"ChatMessage_text__Y1XNR","role-user":"ChatMessage_role-user__u4JPV","role-assistant":"ChatMessage_role-assistant__wketE","role-system":"ChatMessage_role-system__g13OP","userColumn":"ChatMessage_userColumn__cQM6-","textCustom":"ChatMessage_textCustom__C8Tts","bullet":"ChatMessage_bullet__6vAhq","scrollHorizontal":"ChatMessage_scrollHorizontal__Rms9n","datasetAppLink":"ChatMessage_datasetAppLink__Pxy-T","datasetAppLinkLabel":"ChatMessage_datasetAppLinkLabel__PMU7e","quickReplyWrap":"ChatMessage_quickReplyWrap__1UFyD","downloadButtons":"ChatMessage_downloadButtons__RygM-","downloadCard":"ChatMessage_downloadCard__NsNRa","downloadCardIcon":"ChatMessage_downloadCardIcon__jkxDJ","downloadCardContent":"ChatMessage_downloadCardContent__PTPwz","downloadCardTitle":"ChatMessage_downloadCardTitle__K1wqr","downloadCardSubtitle":"ChatMessage_downloadCardSubtitle__fVeF2"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { S as default };
@@ -97,9 +97,23 @@ export interface ChatPromptProps {
97
97
  /** Custom slash pick handler; return true to skip default mention insert and insert via composer API. */
98
98
  onSlashItemCommand?: SlashOnItemCommand;
99
99
  }
100
+ export type ChatMessageClassNames = {
101
+ user?: string;
102
+ assistant?: string;
103
+ system?: string;
104
+ };
105
+ export type ChatMessageTextClassNames = {
106
+ user?: string;
107
+ assistant?: string;
108
+ system?: string;
109
+ };
100
110
  export interface ChatMessageProps {
101
111
  role: MessageRole;
102
112
  text: string;
113
+ /** Extra class on the message root wrapper (role layout + defaults still apply). */
114
+ className?: string;
115
+ /** Extra class on the inner text bubble (merged with built-in `.text` styles). */
116
+ textClassName?: string;
103
117
  inProgress?: boolean;
104
118
  userTextFileAttachments?: UserTextFileAttachment[];
105
119
  onQuickReply?: (branchKey: string, displayLabel: string) => void;
@@ -1,2 +1,2 @@
1
1
  import type { ChatChromeProps } from './ChatChrome.types';
2
- export declare function ChatChrome({ variant, showResizeHandle, resizeHandle, onClose, isEmpty, renderPresets, messages, onQuickReply, suppressedQuickReplyKeys, isLoading, loadingLabel, scriptContinueLabel, onScriptContinue, renderMessageChart, renderSystemMessage, showSyntheticBranchButtons, unusedBranchKeys, showInlinePresets, isLastMessageFromUser, scrollRef, effectiveScopeId, onPromptSubmit, onChatDeleted, onNewChat, promptPrefill, footerClassName, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, promptPlaceholder, hideChatSelector, }: ChatChromeProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function ChatChrome({ variant, showResizeHandle, resizeHandle, onClose, isEmpty, renderPresets, messages, onQuickReply, suppressedQuickReplyKeys, isLoading, loadingLabel, scriptContinueLabel, onScriptContinue, renderMessageChart, renderSystemMessage, showSyntheticBranchButtons, unusedBranchKeys, showInlinePresets, isLastMessageFromUser, scrollRef, effectiveScopeId, onPromptSubmit, onChatDeleted, onNewChat, promptPrefill, footerClassName, messageClassNames, messageTextClassNames, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, promptPlaceholder, hideChatSelector, }: ChatChromeProps): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import type { RefObject } from 'react';
2
- import type { ChatAttachmentDropItem, Message } from '#uilib/components/ui/Chat/Chat.types';
2
+ import type { ChatAttachmentDropItem, ChatMessageClassNames, ChatMessageTextClassNames, Message } from '#uilib/components/ui/Chat/Chat.types';
3
3
  import type { ChatEmptyStateProps } from '#uilib/components/ui/Chat/ChatEmptyState/ChatEmptyState.types';
4
4
  import type { ChatPresetsLayout } from '#uilib/components/ui/Chat/ChatPresets';
5
5
  import type { SlashCommandItem, SlashOnItemCommand } from '#uilib/tiptap/slash-mention/types';
@@ -48,6 +48,10 @@ export interface ChatChromeProps {
48
48
  /** `?prompt=` deep link text for one-shot composer pre-fill. */
49
49
  promptPrefill?: string | null;
50
50
  footerClassName?: string;
51
+ /** Per-role extra classes on message root wrappers (merged with built-in role styles). */
52
+ messageClassNames?: ChatMessageClassNames;
53
+ /** Per-role extra classes on inner text bubbles (merged with built-in `.text` styles). */
54
+ messageTextClassNames?: ChatMessageTextClassNames;
51
55
  emptyState?: ChatEmptyStateProps;
52
56
  /** MIME types / extensions (filtered to text-only allowlist). Enables dropzone when non-empty. */
53
57
  allowedAttachments?: readonly string[];
@@ -1,6 +1,7 @@
1
1
  import { type ReactNode } from 'react';
2
- export declare function AgentMessageContent({ text, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage, scriptContinue, onScriptContinue, renderMessageChart, }: {
2
+ export declare function AgentMessageContent({ text, textClassName, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage, scriptContinue, onScriptContinue, renderMessageChart, }: {
3
3
  text: string;
4
+ textClassName?: string;
4
5
  onQuickReply?: (branchKey: string, displayLabel: string) => void;
5
6
  suppressedQuickReplyKeys?: ReadonlySet<string>;
6
7
  quickReplyDisabled?: boolean;
@@ -1,2 +1,2 @@
1
1
  import { type ChatMessageProps } from '../Chat.types';
2
- export declare function ChatMessage({ role, text, inProgress, userTextFileAttachments, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage, scriptContinue, onScriptContinue, renderMessageChart, message, renderSystemMessage, }: ChatMessageProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function ChatMessage({ role, text, inProgress, userTextFileAttachments, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage, scriptContinue, onScriptContinue, renderMessageChart, message, renderSystemMessage, className, textClassName, }: ChatMessageProps): import("react/jsx-runtime").JSX.Element;
@@ -18,7 +18,7 @@ export { CHAT_PROMPT_COMMAND_CHIP_CLASS, chatPromptChipHtml, createChatPromptCom
18
18
  export type { ChatPromptComposerInsertOptions } from './ChatPrompt/ChatPromptComposer.types';
19
19
  export { ChatPresets } from './ChatPresets';
20
20
  export type { ChatEmptyStateConfig, ChatEmptyStateContext, ChatEmptyStateProps, } from './ChatEmptyState/ChatEmptyState.types';
21
- export type { Chat as ChatType, ChatAttachmentDropItem, ChatMeta, ChatMetaValue, ChatSendMessagePayload, ChatProps, ChatPreset as ChatPresetType, Message, UserTextFileAttachment, } from './Chat.types';
21
+ export type { Chat as ChatType, ChatAttachmentDropItem, ChatMessageClassNames, ChatMessageTextClassNames, ChatMeta, ChatMetaValue, ChatSendMessagePayload, ChatMessageProps, ChatProps, ChatPreset as ChatPresetType, Message, UserTextFileAttachment, } from './Chat.types';
22
22
  export { MessageRole } from './Chat.types';
23
23
  export type { SlashCommandItem, SlashItemCommandContext, SlashOnItemCommand, } from '#uilib/tiptap/slash-mention/types';
24
24
  export { CsvIcon } from '../../icons/CsvIcon/CsvIcon';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sybilion/uilib",
3
- "version": "1.3.82",
3
+ "version": "1.3.83",
4
4
  "description": "Sybilion Design System — React UI components (Webpack + Stylus)",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -114,9 +114,25 @@ export interface ChatPromptProps {
114
114
  onSlashItemCommand?: SlashOnItemCommand;
115
115
  }
116
116
 
117
+ export type ChatMessageClassNames = {
118
+ user?: string;
119
+ assistant?: string;
120
+ system?: string;
121
+ };
122
+
123
+ export type ChatMessageTextClassNames = {
124
+ user?: string;
125
+ assistant?: string;
126
+ system?: string;
127
+ };
128
+
117
129
  export interface ChatMessageProps {
118
130
  role: MessageRole;
119
131
  text: string;
132
+ /** Extra class on the message root wrapper (role layout + defaults still apply). */
133
+ className?: string;
134
+ /** Extra class on the inner text bubble (merged with built-in `.text` styles). */
135
+ textClassName?: string;
120
136
  inProgress?: boolean;
121
137
  userTextFileAttachments?: UserTextFileAttachment[];
122
138
  onQuickReply?: (branchKey: string, displayLabel: string) => void;
@@ -51,6 +51,8 @@ export function ChatChrome({
51
51
  onNewChat,
52
52
  promptPrefill,
53
53
  footerClassName,
54
+ messageClassNames,
55
+ messageTextClassNames,
54
56
  emptyState,
55
57
  allowedAttachments,
56
58
  allowPdfAttachments = false,
@@ -219,10 +221,27 @@ export function ChatChrome({
219
221
  >
220
222
  {messages.map((msg, index, arr) => {
221
223
  const isLast = index === arr.length - 1;
224
+ const messageClassName = messageClassNames
225
+ ? {
226
+ [MessageRole.USER]: messageClassNames.user,
227
+ [MessageRole.ASSISTANT]: messageClassNames.assistant,
228
+ [MessageRole.SYSTEM]: messageClassNames.system,
229
+ }[msg.role]
230
+ : undefined;
231
+ const messageTextClassName = messageTextClassNames
232
+ ? {
233
+ [MessageRole.USER]: messageTextClassNames.user,
234
+ [MessageRole.ASSISTANT]:
235
+ messageTextClassNames.assistant,
236
+ [MessageRole.SYSTEM]: messageTextClassNames.system,
237
+ }[msg.role]
238
+ : undefined;
222
239
  return (
223
240
  <Chat.Message
224
241
  key={msg.id}
225
242
  message={msg}
243
+ className={messageClassName}
244
+ textClassName={messageTextClassName}
226
245
  role={msg.role}
227
246
  text={msg.text}
228
247
  inProgress={msg.inProgress}
@@ -272,8 +291,7 @@ export function ChatChrome({
272
291
  </div>
273
292
  ) : null}
274
293
 
275
- {showInlinePresets &&
276
- renderPresets('inline', { variant })}
294
+ {showInlinePresets && renderPresets('inline', { variant })}
277
295
 
278
296
  {isLoading &&
279
297
  !hasInProgressSystemMessage &&
@@ -298,7 +316,9 @@ export function ChatChrome({
298
316
  </div>
299
317
  ) : null}
300
318
 
301
- <div className={cn(S.footer, isClean && S.footerClean, footerClassName)}>
319
+ <div
320
+ className={cn(S.footer, isClean && S.footerClean, footerClassName)}
321
+ >
302
322
  <Chat.Prompt
303
323
  className={isClean ? S.promptClean : undefined}
304
324
  onSubmit={handlePromptSubmitWithAttachments}
@@ -2,6 +2,8 @@ import type { RefObject } from 'react';
2
2
 
3
3
  import type {
4
4
  ChatAttachmentDropItem,
5
+ ChatMessageClassNames,
6
+ ChatMessageTextClassNames,
5
7
  Message,
6
8
  } from '#uilib/components/ui/Chat/Chat.types';
7
9
  import type { ChatEmptyStateProps } from '#uilib/components/ui/Chat/ChatEmptyState/ChatEmptyState.types';
@@ -66,6 +68,10 @@ export interface ChatChromeProps {
66
68
  /** `?prompt=` deep link text for one-shot composer pre-fill. */
67
69
  promptPrefill?: string | null;
68
70
  footerClassName?: string;
71
+ /** Per-role extra classes on message root wrappers (merged with built-in role styles). */
72
+ messageClassNames?: ChatMessageClassNames;
73
+ /** Per-role extra classes on inner text bubbles (merged with built-in `.text` styles). */
74
+ messageTextClassNames?: ChatMessageTextClassNames;
69
75
  emptyState?: ChatEmptyStateProps;
70
76
  /** MIME types / extensions (filtered to text-only allowlist). Enables dropzone when non-empty. */
71
77
  allowedAttachments?: readonly string[];
@@ -1,3 +1,4 @@
1
+ import cn from 'classnames';
1
2
  import { type ReactNode, useMemo, useState } from 'react';
2
3
 
3
4
  import { Button } from '#uilib/components/ui/Button';
@@ -15,6 +16,7 @@ import { XlsIcon } from './icons/XlsIcon';
15
16
 
16
17
  export function AgentMessageContent({
17
18
  text,
19
+ textClassName,
18
20
  onQuickReply,
19
21
  suppressedQuickReplyKeys,
20
22
  quickReplyDisabled,
@@ -25,6 +27,7 @@ export function AgentMessageContent({
25
27
  renderMessageChart,
26
28
  }: {
27
29
  text: string;
30
+ textClassName?: string;
28
31
  onQuickReply?: (branchKey: string, displayLabel: string) => void;
29
32
  suppressedQuickReplyKeys?: ReadonlySet<string>;
30
33
  quickReplyDisabled?: boolean;
@@ -211,7 +214,7 @@ export function AgentMessageContent({
211
214
 
212
215
  return (
213
216
  <div
214
- className={S.text}
217
+ className={cn(S.text, textClassName)}
215
218
  // onClick={() => setShowRaw(!showRaw)}
216
219
  >
217
220
  {showRaw ? text : parts}
@@ -39,7 +39,6 @@
39
39
  .text
40
40
  padding var(--p-3) var(--p-4)
41
41
 
42
- background-color var(--sb-slate-100)
43
42
  border-radius var(--p-4)
44
43
  border-bottom-right-radius 0
45
44
 
@@ -47,8 +46,11 @@
47
46
  overflow hidden
48
47
  box-sizing border-box
49
48
 
50
- :global(.dark) &
51
- background-color var(--sb-gray-900)
49
+ &:not(.textCustom)
50
+ background-color var(--sb-slate-100)
51
+
52
+ :global(.dark) &
53
+ background-color var(--sb-gray-900)
52
54
 
53
55
  .role-system
54
56
  align-items center
@@ -17,6 +17,7 @@ interface CssExports {
17
17
  'root': string;
18
18
  'scrollHorizontal': string;
19
19
  'text': string;
20
+ 'textCustom': string;
20
21
  'userColumn': string;
21
22
  }
22
23
  export const cssExports: CssExports;
@@ -24,6 +24,8 @@ export function ChatMessage({
24
24
  renderMessageChart,
25
25
  message,
26
26
  renderSystemMessage,
27
+ className,
28
+ textClassName,
27
29
  }: ChatMessageProps) {
28
30
  const fileAttachments = userTextFileAttachmentsFromMessage({
29
31
  userTextFileAttachments,
@@ -32,9 +34,9 @@ export function ChatMessage({
32
34
  const isSystem = role === MessageRole.SYSTEM;
33
35
 
34
36
  return (
35
- <div className={cn(S.root, S[`role-${role}`])}>
37
+ <div className={cn(S.root, S[`role-${role}`], className)}>
36
38
  {isSystem ? (
37
- <div className={S.text}>
39
+ <div className={cn(S.text, textClassName)}>
38
40
  {inProgress ? (
39
41
  <TextShimmer as="span">{text}</TextShimmer>
40
42
  ) : renderSystemMessage && message ? (
@@ -46,6 +48,7 @@ export function ChatMessage({
46
48
  ) : isAssistant ? (
47
49
  <AgentMessageContent
48
50
  text={text}
51
+ textClassName={textClassName}
49
52
  onQuickReply={onQuickReply}
50
53
  suppressedQuickReplyKeys={suppressedQuickReplyKeys}
51
54
  quickReplyDisabled={quickReplyDisabled}
@@ -57,7 +60,9 @@ export function ChatMessage({
57
60
  />
58
61
  ) : (
59
62
  <div className={S.userColumn}>
60
- <div className={S.text}>
63
+ <div
64
+ className={cn(S.text, textClassName && S.textCustom, textClassName)}
65
+ >
61
66
  <InteractiveContent text={text} />
62
67
  </div>
63
68
  {fileAttachments.map(attachment => (
@@ -48,9 +48,12 @@ export type {
48
48
  export type {
49
49
  Chat as ChatType,
50
50
  ChatAttachmentDropItem,
51
+ ChatMessageClassNames,
52
+ ChatMessageTextClassNames,
51
53
  ChatMeta,
52
54
  ChatMetaValue,
53
55
  ChatSendMessagePayload,
56
+ ChatMessageProps,
54
57
  ChatProps,
55
58
  ChatPreset as ChatPresetType,
56
59
  Message,