@gravity-ui/aikit 0.2.0 → 0.2.2

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.
@@ -19,7 +19,7 @@ const b = block('chat-container');
19
19
  */
20
20
  export function ChatContainer(props) {
21
21
  var _a, _b;
22
- const { chats = [], messages = [], onSendMessage, onDeleteChat, onCancel, onRetry, status = 'ready', error = null, showActionsOnHover = false, contextItems = [], transformOptions, headerProps = {}, contentProps = {}, emptyContainerProps = {}, promptInputProps = {}, historyProps = {}, welcomeConfig, i18nConfig = {}, className, qa, } = props;
22
+ const { chats = [], messages = [], onSendMessage, onDeleteChat, onCancel, onRetry, status = 'ready', error = null, showActionsOnHover = false, contextItems = [], transformOptions, headerProps = {}, contentProps = {}, emptyContainerProps = {}, promptInputProps = {}, historyProps = {}, welcomeConfig, i18nConfig = {}, className, headerClassName, contentClassName, footerClassName, qa, } = props;
23
23
  const hookState = useChatContainer(props);
24
24
  // Collect i18n texts with overrides
25
25
  const headerTitle = useMemo(() => {
@@ -41,24 +41,15 @@ export function ChatContainer(props) {
41
41
  ]);
42
42
  // Build props for EmptyContainer
43
43
  const finalEmptyContainerProps = useMemo(() => {
44
- var _a, _b, _c, _d, _e;
45
- // Map suggestions from WelcomeConfig to SuggestionsItem format
46
- const defaultSuggestions = (_a = welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.suggestions) === null || _a === void 0 ? void 0 : _a.map((s) => ({
47
- id: s.id,
48
- title: s.label || s.content, // Use label or content as button title
49
- }));
50
- return Object.assign(Object.assign({}, emptyContainerProps), { image: welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.image, title: (welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.title) || ((_b = i18nConfig.emptyState) === null || _b === void 0 ? void 0 : _b.title) || i18n('empty-state-title'), description: (welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.description) ||
51
- ((_c = i18nConfig.emptyState) === null || _c === void 0 ? void 0 : _c.description) ||
44
+ var _a, _b, _c, _d;
45
+ return Object.assign(Object.assign({}, emptyContainerProps), { image: welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.image, title: (welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.title) || ((_a = i18nConfig.emptyState) === null || _a === void 0 ? void 0 : _a.title) || i18n('empty-state-title'), description: (welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.description) ||
46
+ ((_b = i18nConfig.emptyState) === null || _b === void 0 ? void 0 : _b.description) ||
52
47
  i18n('empty-state-description'), suggestionTitle: (welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.suggestionTitle) ||
53
- ((_d = i18nConfig.emptyState) === null || _d === void 0 ? void 0 : _d.suggestionsTitle) ||
54
- i18n('empty-state-suggestions-title'), suggestions: defaultSuggestions, showMore: welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.showMore, showMoreText: (welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.showMoreText) ||
55
- ((_e = i18nConfig.emptyState) === null || _e === void 0 ? void 0 : _e.showMoreText) ||
48
+ ((_c = i18nConfig.emptyState) === null || _c === void 0 ? void 0 : _c.suggestionsTitle) ||
49
+ i18n('empty-state-suggestions-title'), suggestions: welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.suggestions, alignment: welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.alignment, wrapText: welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.wrapText, showMore: welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.showMore, showMoreText: (welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.showMoreText) ||
50
+ ((_d = i18nConfig.emptyState) === null || _d === void 0 ? void 0 : _d.showMoreText) ||
56
51
  i18n('empty-state-show-more'), onSuggestionClick: async (clickedTitle) => {
57
- var _a;
58
- // Find original suggestion by title to get content
59
- const originalSuggestion = (_a = welcomeConfig === null || welcomeConfig === void 0 ? void 0 : welcomeConfig.suggestions) === null || _a === void 0 ? void 0 : _a.find((s) => (s.label || s.content) === clickedTitle);
60
- const contentToSend = (originalSuggestion === null || originalSuggestion === void 0 ? void 0 : originalSuggestion.content) || clickedTitle;
61
- await onSendMessage({ content: contentToSend });
52
+ await onSendMessage({ content: clickedTitle });
62
53
  } });
63
54
  }, [welcomeConfig, i18nConfig.emptyState, emptyContainerProps, onSendMessage]);
64
55
  // Build props for MessageList
@@ -106,5 +97,5 @@ export function ChatContainer(props) {
106
97
  historyProps,
107
98
  ]);
108
99
  const showFooter = finalPromptInputProps || disclaimerProps;
109
- return (_jsxs("div", { className: b(null, className), "data-qa": qa, children: [_jsx("div", { className: b('header'), children: _jsx(Header, Object.assign({}, finalHeaderProps)) }), _jsx("div", { className: b('content'), children: _jsx(ChatContent, Object.assign({}, finalContentProps)) }), showFooter && (_jsxs("div", { className: b('footer'), children: [finalPromptInputProps && _jsx(PromptInput, Object.assign({}, finalPromptInputProps)), disclaimerProps && _jsx(Disclaimer, Object.assign({}, disclaimerProps))] })), _jsx(History, Object.assign({}, finalHistoryProps))] }));
100
+ return (_jsxs("div", { className: b(null, className), "data-qa": qa, children: [_jsx("div", { className: b('header', headerClassName), children: _jsx(Header, Object.assign({}, finalHeaderProps)) }), _jsx("div", { className: b('content', { view: hookState.chatContentView }, contentClassName), children: _jsx(ChatContent, Object.assign({}, finalContentProps)) }), showFooter && (_jsxs("div", { className: b('footer', { view: hookState.chatContentView }, footerClassName), children: [finalPromptInputProps && _jsx(PromptInput, Object.assign({}, finalPromptInputProps)), disclaimerProps && _jsx(Disclaimer, Object.assign({}, disclaimerProps))] })), _jsx(History, Object.assign({}, finalHistoryProps))] }));
110
101
  }
@@ -32,6 +32,14 @@
32
32
  flex: 1 0 0;
33
33
  }
34
34
 
35
+ &__content_view_empty {
36
+ background: var(--g-aikit-chat-container-content-empty-background);
37
+ }
38
+
39
+ &__content_view_chat {
40
+ background: var(--g-aikit-chat-container-content-chat-background);
41
+ }
42
+
35
43
  &__footer {
36
44
  display: flex;
37
45
  padding: var(--g-aikit-layout-base-padding-m);
@@ -41,4 +49,12 @@
41
49
  align-self: stretch;
42
50
  background: var(--g-aikit-chat-container-footer-background);
43
51
  }
52
+
53
+ &__footer_view_empty {
54
+ background: var(--g-aikit-chat-container-footer-empty-background);
55
+ }
56
+
57
+ &__footer_view_chat {
58
+ background: var(--g-aikit-chat-container-footer-chat-background);
59
+ }
44
60
  }
@@ -1,10 +1,11 @@
1
1
  import type { OptionsType } from '@diplodoc/transform/lib/typings';
2
2
  import type { ChatStatus, ChatType, TChatMessage, TSubmitData } from '../../../types';
3
3
  import type { ContextItemConfig } from '../../molecules/PromptInputHeader';
4
+ import type { SuggestionsItem } from '../../molecules/Suggestions';
4
5
  import type { HeaderProps } from '../../organisms/Header';
5
6
  import type { PromptInputProps } from '../../organisms/PromptInput';
6
7
  import type { ChatContentProps } from '../../templates/ChatContent';
7
- import type { EmptyContainerProps } from '../../templates/EmptyContainer';
8
+ import type { AlignmentConfig, EmptyContainerProps } from '../../templates/EmptyContainer';
8
9
  import type { HistoryProps } from '../../templates/History';
9
10
  /**
10
11
  * I18n configuration for all text labels in ChatContainer
@@ -60,21 +61,18 @@ export interface ChatContainerI18nConfig {
60
61
  export interface WelcomeConfig {
61
62
  /** Image or icon to display */
62
63
  image?: React.ReactNode;
63
- /** Title text */
64
- title?: string;
65
- /** Description text */
66
- description?: string;
64
+ /** Title text or custom React element */
65
+ title?: string | React.ReactNode;
66
+ /** Description text or custom React element */
67
+ description?: string | React.ReactNode;
67
68
  /** Suggestions section title */
68
69
  suggestionTitle?: string;
69
- /** Array of suggestions */
70
- suggestions?: Array<{
71
- /** Unique identifier for the suggestion */
72
- id: string;
73
- /** Suggestion text content that will be sent as message */
74
- content: string;
75
- /** Display title for the suggestion button (defaults to content if not provided) */
76
- label?: string;
77
- }>;
70
+ /** Array of suggestions (title will be used as message content) */
71
+ suggestions?: SuggestionsItem[];
72
+ /** Alignment configuration for image, title, and description */
73
+ alignment?: AlignmentConfig;
74
+ /** Enable text wrapping inside suggestion buttons instead of ellipsis */
75
+ wrapText?: boolean;
78
76
  /** Show more suggestions callback */
79
77
  showMore?: () => void;
80
78
  /** Show more button text */
@@ -138,6 +136,12 @@ export interface ChatContainerProps {
138
136
  showClose?: boolean;
139
137
  /** Additional CSS class */
140
138
  className?: string;
139
+ /** Additional CSS class for header section */
140
+ headerClassName?: string;
141
+ /** Additional CSS class for content section */
142
+ contentClassName?: string;
143
+ /** Additional CSS class for footer section */
144
+ footerClassName?: string;
141
145
  /** QA/test identifier */
142
146
  qa?: string;
143
147
  }
@@ -26,10 +26,10 @@ export interface AlignmentConfig {
26
26
  export interface EmptyContainerProps {
27
27
  /** Image or icon to display at the top */
28
28
  image?: React.ReactNode;
29
- /** Title text for the welcome screen */
30
- title?: string;
31
- /** Description text explaining the functionality */
32
- description?: string;
29
+ /** Title text or custom React element for the welcome screen */
30
+ title?: string | React.ReactNode;
31
+ /** Description text or custom React element explaining the functionality */
32
+ description?: string | React.ReactNode;
33
33
  /** Title for the suggestions section */
34
34
  suggestionTitle?: string;
35
35
  /** Array of suggestion items */
@@ -38,6 +38,8 @@ export interface EmptyContainerProps {
38
38
  onSuggestionClick?: (content: string, id?: string) => void;
39
39
  /** Alignment configuration for image, title, and description */
40
40
  alignment?: AlignmentConfig;
41
+ /** Enable text wrapping inside suggestion buttons instead of ellipsis */
42
+ wrapText?: boolean;
41
43
  /** Callback for showing more suggestions */
42
44
  showMore?: () => void;
43
45
  /** Custom text for the show more button */
@@ -14,7 +14,7 @@ const b = block('empty-container');
14
14
  * @returns React component
15
15
  */
16
16
  export function EmptyContainer(props) {
17
- const { image, title, description, suggestionTitle, suggestions = [], onSuggestionClick, alignment, showMore, showMoreText, className, qa, } = props;
17
+ const { image, title, description, suggestionTitle, suggestions = [], onSuggestionClick, alignment, wrapText = false, showMore, showMoreText, className, qa, } = props;
18
18
  const hasContent = title || description || (suggestions && suggestions.length > 0);
19
19
  // Define alignment for each element
20
20
  const imageAlignment = (alignment === null || alignment === void 0 ? void 0 : alignment.image) || 'left';
@@ -22,5 +22,5 @@ export function EmptyContainer(props) {
22
22
  const descriptionAlignment = (alignment === null || alignment === void 0 ? void 0 : alignment.description) || 'left';
23
23
  // Define text for "Show more" button with localization support
24
24
  const showMoreButtonText = showMoreText || i18n('show-more-button');
25
- return (_jsx("div", { className: b(null, className), "data-qa": qa, children: _jsx("div", { className: b('content'), children: hasContent && (_jsxs(_Fragment, { children: [_jsxs("div", { className: b('welcome-section'), children: [image && (_jsx("div", { className: b('image-container', { align: imageAlignment }), children: image })), _jsxs("div", { className: b('text-container'), children: [title && (_jsx(Text, { variant: "header-2", className: b('title', { align: titleAlignment }), children: title })), description && (_jsx(Text, { variant: "body-2", color: "complementary", className: b('description', { align: descriptionAlignment }), children: description }))] })] }), suggestions && suggestions.length > 0 && onSuggestionClick && (_jsxs("div", { className: b('suggestions-section'), children: [suggestionTitle && (_jsx("div", { className: b('suggestions-title'), children: _jsx(Text, { variant: "subheader-3", color: "primary", children: suggestionTitle }) })), _jsx("div", { children: _jsx(Suggestions, { items: suggestions, onClick: onSuggestionClick, layout: "grid" }) }), showMore && (_jsx("div", { className: b('show-more'), children: _jsxs(Button, { view: "flat-secondary", size: "l", onClick: showMore, className: b('show-more-button'), children: [_jsx(Button.Icon, { children: _jsx(ArrowRotateRight, {}) }), showMoreButtonText] }) }))] }))] })) }) }));
25
+ return (_jsx("div", { className: b(null, className), "data-qa": qa, children: _jsx("div", { className: b('content'), children: hasContent && (_jsxs(_Fragment, { children: [_jsxs("div", { className: b('welcome-section'), children: [image && (_jsx("div", { className: b('image-container', { align: imageAlignment }), children: image })), _jsxs("div", { className: b('text-container'), children: [title && (_jsx(Text, { variant: "header-2", className: b('title', { align: titleAlignment }), children: title })), description && (_jsx(Text, { variant: "body-2", color: "complementary", className: b('description', { align: descriptionAlignment }), children: description }))] })] }), suggestions && suggestions.length > 0 && onSuggestionClick && (_jsxs("div", { className: b('suggestions-section'), children: [suggestionTitle && (_jsx("div", { className: b('suggestions-title'), children: _jsx(Text, { variant: "subheader-3", color: "primary", children: suggestionTitle }) })), _jsx("div", { children: _jsx(Suggestions, { items: suggestions, onClick: onSuggestionClick, layout: "grid", wrapText: wrapText }) }), showMore && (_jsx("div", { className: b('show-more'), children: _jsxs(Button, { view: "flat-secondary", size: "l", onClick: showMore, className: b('show-more-button'), children: [_jsx(Button.Icon, { children: _jsx(ArrowRotateRight, {}) }), showMoreButtonText] }) }))] }))] })) }) }));
26
26
  }
@@ -66,4 +66,8 @@
66
66
  --g-aikit-chat-container-content-background: var(--g-color-base-background);
67
67
  --g-aikit-chat-container-footer-background: var(--g-color-base-background);
68
68
  --g-aikit-chat-container-background: var(--g-color-base-background);
69
+ --g-aikit-chat-container-content-empty-background: var(--g-color-base-background);
70
+ --g-aikit-chat-container-content-chat-background: var(--g-color-base-background);
71
+ --g-aikit-chat-container-footer-empty-background: var(--g-color-base-background);
72
+ --g-aikit-chat-container-footer-chat-background: var(--g-color-base-background);
69
73
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/aikit",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Gravity UI base kit for building ai assistant chats",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",