@gravity-ui/aikit 0.3.0 → 0.3.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.
@@ -18,6 +18,14 @@ export interface SubmitButtonProps {
18
18
  * Button size
19
19
  */
20
20
  size?: ButtonButtonProps['size'];
21
+ /**
22
+ * Custom tooltip for enabled state
23
+ */
24
+ tooltipSend?: string;
25
+ /**
26
+ * Custom tooltip for cancelable state
27
+ */
28
+ tooltipCancel?: string;
21
29
  /**
22
30
  * QA/test identifier
23
31
  */
@@ -34,4 +42,4 @@ export interface SubmitButtonProps {
34
42
  *
35
43
  * @returns Submit button component
36
44
  */
37
- export declare function SubmitButton({ onClick, state, className, size, qa }: SubmitButtonProps): import("react/jsx-runtime").JSX.Element;
45
+ export declare function SubmitButton({ onClick, state, className, size, tooltipSend, tooltipCancel, qa, }: SubmitButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -18,7 +18,7 @@ const b = block('submit-button');
18
18
  *
19
19
  * @returns Submit button component
20
20
  */
21
- export function SubmitButton({ onClick, state, className, size = 'm', qa }) {
21
+ export function SubmitButton({ onClick, state, className, size = 'm', tooltipSend, tooltipCancel, qa, }) {
22
22
  const isCancelable = state === 'cancelable';
23
23
  const isLoading = state === 'loading';
24
24
  const isDisabled = state === 'disabled';
@@ -29,5 +29,19 @@ export function SubmitButton({ onClick, state, className, size = 'm', qa }) {
29
29
  }
30
30
  return Promise.resolve();
31
31
  }, [state, onClick]);
32
- return (_jsx(ActionButton, { view: "action", size: size, color: "brand", disabled: isDisabled, onClick: handleClick, className: b({ size, loading: isLoading, cancelable: isCancelable }, className), qa: qa, tooltipTitle: i18n('tooltip-send'), children: isLoading ? (_jsx("div", { className: b('loader'), children: _jsx(Spin, { className: b('spinner'), size: "xs" }) })) : (_jsx(Icon, { size: 16, data: iconData })) }));
32
+ // Get tooltip based on state
33
+ const getTooltipTitle = () => {
34
+ switch (state) {
35
+ case 'enabled':
36
+ return tooltipSend || i18n('tooltip-send');
37
+ case 'cancelable':
38
+ return tooltipCancel || i18n('tooltip-cancel');
39
+ case 'disabled':
40
+ case 'loading':
41
+ return undefined;
42
+ default:
43
+ return undefined;
44
+ }
45
+ };
46
+ return (_jsx(ActionButton, { view: "action", size: size, color: "brand", disabled: isDisabled, onClick: handleClick, className: b({ size, loading: isLoading, cancelable: isCancelable }, className), qa: qa, tooltipTitle: getTooltipTitle(), children: isLoading ? (_jsx("div", { className: b('loader'), children: _jsx(Spin, { className: b('spinner'), size: "xs" }) })) : (_jsx(Icon, { size: 16, data: iconData })) }));
33
47
  }
@@ -1,3 +1,4 @@
1
1
  {
2
- "tooltip-send": "Send"
2
+ "tooltip-send": "Send",
3
+ "tooltip-cancel": "Cancel"
3
4
  }
@@ -1,13 +1,13 @@
1
- export declare const i18n: ((key: "tooltip-send", params?: import("@gravity-ui/i18n").Params) => string) & {
1
+ export declare const i18n: ((key: "tooltip-send" | "tooltip-cancel", params?: import("@gravity-ui/i18n").Params) => string) & {
2
2
  Translation: import("react").ComponentType<{
3
3
  children: (props: {
4
- t: (key: "tooltip-send", params?: import("@gravity-ui/i18n").Params) => string;
4
+ t: (key: "tooltip-send" | "tooltip-cancel", params?: import("@gravity-ui/i18n").Params) => string;
5
5
  }) => React.ReactNode;
6
6
  }>;
7
7
  useTranslation: () => {
8
- t: (key: "tooltip-send", params?: import("@gravity-ui/i18n").Params) => string;
8
+ t: (key: "tooltip-send" | "tooltip-cancel", params?: import("@gravity-ui/i18n").Params) => string;
9
9
  };
10
10
  keysetData: {
11
- "g-aikit-SubmitButton": Record<"tooltip-send", import("@gravity-ui/i18n").KeyData>;
11
+ "g-aikit-SubmitButton": Record<"tooltip-send" | "tooltip-cancel", import("@gravity-ui/i18n").KeyData>;
12
12
  };
13
13
  };
@@ -1,3 +1,4 @@
1
1
  {
2
- "tooltip-send": "Отправить"
2
+ "tooltip-send": "Отправить",
3
+ "tooltip-cancel": "Отменить"
3
4
  }
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import { ButtonButtonProps } from '@gravity-ui/uikit';
2
3
  import './Suggestions.scss';
3
4
  export type SuggestionsItem = {
@@ -18,8 +19,8 @@ export type SuggestionsProps = {
18
19
  items: SuggestionsItem[];
19
20
  /** Callback function called when a suggestion is clicked */
20
21
  onClick: (content: string, id?: string) => void | Promise<void>;
21
- /** Title to display above suggestions */
22
- title?: string;
22
+ /** Title to display above suggestions - can be string or custom React element */
23
+ title?: React.ReactNode;
23
24
  /** Layout orientation: 'grid' for horizontal, 'list' for vertical */
24
25
  layout?: 'grid' | 'list';
25
26
  /** Text alignment inside buttons: 'left', 'center', or 'right' */
@@ -23,5 +23,5 @@ export function Suggestions(props) {
23
23
  'text-align': item.icon ? undefined : textAlign,
24
24
  }), children: [item.icon === 'left' && (_jsx("div", { className: b('button-icon'), children: _jsx(Icon, { data: ChevronLeft, size: 16 }) })), _jsx(Text, { as: "div", className: b(wrapText ? 'button-text-wrap' : 'button-text'), children: item.title }), item.icon === 'right' && (_jsx("div", { className: b('button-icon'), children: _jsx(Icon, { data: ChevronRight, size: 16 }) }))] }) }, item.id || index));
25
25
  };
26
- return (_jsxs("div", { className: b('container', className), "data-qa": qa, children: [title && (_jsx("div", { className: b('title'), children: _jsx(Text, { variant: "body-1", color: "primary", children: title }) })), _jsx("div", { className: b({ layout }), children: items.map((item, index) => renderButton(item, index)) })] }));
26
+ return (_jsxs("div", { className: b('container', className), "data-qa": qa, children: [title && (_jsx("div", { className: b('title'), children: typeof title === 'string' ? (_jsx(Text, { variant: "body-1", color: "primary", children: title })) : (title) })), _jsx("div", { className: b({ layout }), children: items.map((item, index) => renderButton(item, index)) })] }));
27
27
  }
@@ -14,12 +14,14 @@ export function PromptInputFull(props) {
14
14
  const { hookState, headerProps = {}, bodyProps = {}, footerProps = {}, className, qa } = props;
15
15
  const { topContent, contextItems = [], showContextIndicator = false, contextIndicatorProps, } = headerProps;
16
16
  const { placeholder = 'Plan, code, build and test anything', minRows = 1, maxRows = 15, autoFocus = false, } = bodyProps;
17
- const { bottomContent, showSettings = false, onSettingsClick, showAttachment = false, onAttachmentClick, showMicrophone = false, onMicrophoneClick, } = footerProps;
17
+ const { bottomContent, showSettings = false, onSettingsClick, showAttachment = false, onAttachmentClick, showMicrophone = false, onMicrophoneClick, submitButtonTooltipSend, submitButtonTooltipCancel, } = footerProps;
18
18
  const { value, submitButtonState, handleChange, handleKeyDown, handleSubmit } = hookState;
19
19
  const shouldShowHeader = topContent || contextItems.length > 0 || showContextIndicator;
20
20
  const shouldShowFooter = true;
21
21
  return (_jsxs("div", { className: b({ view: 'full' }, className), "data-qa": qa, children: [shouldShowHeader && (_jsx(PromptInputHeader, { contextItems: contextItems, showContextIndicator: showContextIndicator, contextIndicatorProps: contextIndicatorProps, children: topContent })), _jsx(PromptInputBody, { value: value, placeholder: placeholder, minRows: minRows, maxRows: maxRows, autoFocus: autoFocus, onChange: handleChange, onKeyDown: handleKeyDown }), shouldShowFooter && (_jsx(PromptInputFooter, { submitButton: {
22
22
  onClick: handleSubmit,
23
23
  state: submitButtonState,
24
+ tooltipSend: submitButtonTooltipSend,
25
+ tooltipCancel: submitButtonTooltipCancel,
24
26
  }, showSettings: showSettings, onSettingsClick: onSettingsClick, showAttachment: showAttachment, onAttachmentClick: onAttachmentClick, showMicrophone: showMicrophone, onMicrophoneClick: onMicrophoneClick, children: bottomContent }))] }));
25
27
  }
@@ -12,10 +12,12 @@ const b = block('prompt-input');
12
12
  export function PromptInputSimple(props) {
13
13
  const { hookState, bodyProps = {}, footerProps = {}, className, qa } = props;
14
14
  const { placeholder = 'Plan, code, build and test anything', minRows = 1, maxRows = 15, autoFocus = false, } = bodyProps;
15
- const { bottomContent, showAttachment = false, onAttachmentClick, showMicrophone = false, onMicrophoneClick, } = footerProps;
15
+ const { bottomContent, showAttachment = false, onAttachmentClick, showMicrophone = false, onMicrophoneClick, submitButtonTooltipSend, submitButtonTooltipCancel, } = footerProps;
16
16
  const { value, submitButtonState, handleChange, handleKeyDown, handleSubmit } = hookState;
17
17
  return (_jsx("div", { className: b({ view: 'simple' }, className), "data-qa": qa, children: _jsxs("div", { className: b('content'), children: [_jsx(PromptInputBody, { value: value, placeholder: placeholder, minRows: minRows, maxRows: maxRows, autoFocus: autoFocus, onChange: handleChange, onKeyDown: handleKeyDown }), _jsx(PromptInputFooter, { submitButton: {
18
18
  onClick: handleSubmit,
19
19
  state: submitButtonState,
20
+ tooltipSend: submitButtonTooltipSend,
21
+ tooltipCancel: submitButtonTooltipCancel,
20
22
  }, showAttachment: showAttachment, onAttachmentClick: onAttachmentClick, showMicrophone: showMicrophone, onMicrophoneClick: onMicrophoneClick, buttonSize: "l", children: bottomContent })] }) }));
21
23
  }
@@ -54,6 +54,10 @@ export type PromptInputFooterConfig = {
54
54
  showMicrophone?: boolean;
55
55
  /** Microphone icon click handler */
56
56
  onMicrophoneClick?: () => void;
57
+ /** Custom tooltip for submit button in enabled state */
58
+ submitButtonTooltipSend?: string;
59
+ /** Custom tooltip for submit button in cancelable state */
60
+ submitButtonTooltipCancel?: string;
57
61
  };
58
62
  /**
59
63
  * Props for the suggestions section of PromptInput
@@ -63,8 +67,8 @@ export type PromptInputSuggestionsConfig = {
63
67
  suggestions?: SuggestionsItem[];
64
68
  /** Show submit suggestions */
65
69
  showSuggestions?: boolean;
66
- /** Title for the suggestions section */
67
- suggestTitle?: string;
70
+ /** Title for the suggestions section - can be string or custom React element */
71
+ suggestTitle?: string | ReactNode;
68
72
  /** Layout orientation for suggestions: 'grid' for horizontal, 'list' for vertical */
69
73
  suggestionsLayout?: SuggestionsProps['layout'];
70
74
  /** Text alignment inside suggestion buttons */
@@ -2,7 +2,7 @@ import type { OptionsType } from '@diplodoc/transform/lib/typings';
2
2
  import type { BaseMessageProps } from '../../../types/messages';
3
3
  import './UserMessage.scss';
4
4
  export type UserMessageProps = Pick<BaseMessageProps, 'actions' | 'showActionsOnHover' | 'showTimestamp' | 'timestamp'> & {
5
- content: string | React.ReactNode;
5
+ content: React.ReactNode;
6
6
  format?: 'plain' | 'markdown';
7
7
  showAvatar?: boolean;
8
8
  avatarUrl?: string;
@@ -53,25 +53,26 @@ export function ChatContainer(props) {
53
53
  } });
54
54
  }, [welcomeConfig, i18nConfig.emptyState, emptyContainerProps, onSendMessage]);
55
55
  // Build props for MessageList
56
- const messageListProps = useMemo(() => ({
57
- messages,
58
- status,
59
- errorMessage: error ? { text: error.message } : undefined,
60
- onRetry,
56
+ const messageListProps = useMemo(() => (Object.assign(Object.assign({}, messageListConfig), { messages,
57
+ status, errorMessage: (messageListConfig === null || messageListConfig === void 0 ? void 0 : messageListConfig.errorMessage) || (error ? { text: error.message } : undefined), onRetry,
61
58
  showActionsOnHover,
62
- transformOptions,
63
- userActions: messageListConfig === null || messageListConfig === void 0 ? void 0 : messageListConfig.userActions,
64
- assistantActions: messageListConfig === null || messageListConfig === void 0 ? void 0 : messageListConfig.assistantActions,
65
- loaderStatuses: messageListConfig === null || messageListConfig === void 0 ? void 0 : messageListConfig.loaderStatuses,
66
- }), [messages, status, error, onRetry, showActionsOnHover, transformOptions, messageListConfig]);
59
+ transformOptions })), [messages, status, error, onRetry, showActionsOnHover, transformOptions, messageListConfig]);
67
60
  // Build props for PromptInput
68
61
  const finalPromptInputProps = useMemo(() => {
69
- var _a, _b;
62
+ var _a, _b, _c, _d;
70
63
  return (Object.assign(Object.assign({}, promptInputProps), { onSend: onSendMessage, onCancel,
71
64
  status, headerProps: Object.assign(Object.assign({}, promptInputProps === null || promptInputProps === void 0 ? void 0 : promptInputProps.headerProps), { contextItems }), bodyProps: Object.assign(Object.assign({}, promptInputProps === null || promptInputProps === void 0 ? void 0 : promptInputProps.bodyProps), { placeholder: ((_a = i18nConfig.promptInput) === null || _a === void 0 ? void 0 : _a.placeholder) ||
72
65
  ((_b = promptInputProps === null || promptInputProps === void 0 ? void 0 : promptInputProps.bodyProps) === null || _b === void 0 ? void 0 : _b.placeholder) ||
73
- i18n('prompt-placeholder') }) }));
74
- }, [onSendMessage, onCancel, status, contextItems, i18nConfig.promptInput, promptInputProps]);
66
+ i18n('prompt-placeholder') }), footerProps: Object.assign(Object.assign({}, promptInputProps === null || promptInputProps === void 0 ? void 0 : promptInputProps.footerProps), { submitButtonTooltipSend: (_c = i18nConfig.submitButton) === null || _c === void 0 ? void 0 : _c.sendTooltip, submitButtonTooltipCancel: (_d = i18nConfig.submitButton) === null || _d === void 0 ? void 0 : _d.cancelTooltip }) }));
67
+ }, [
68
+ onSendMessage,
69
+ onCancel,
70
+ status,
71
+ contextItems,
72
+ i18nConfig.promptInput,
73
+ i18nConfig.submitButton,
74
+ promptInputProps,
75
+ ]);
75
76
  // Build props for Disclaimer
76
77
  const disclaimerProps = useMemo(() => {
77
78
  var _a;
@@ -1,6 +1,6 @@
1
1
  import type { OptionsType } from '@diplodoc/transform/lib/typings';
2
- import type { ChatStatus, ChatType, TAssistantMessage, TChatMessage, TMessageContent, TMessageMetadata, TSubmitData, TUserMessage } from '../../../types';
3
- import type { DefaultMessageAction } from '../../../utils';
2
+ import { MessageListProps } from 'src/components/organisms/MessageList';
3
+ import type { ChatStatus, ChatType, TChatMessage, TSubmitData } from '../../../types';
4
4
  import type { ContextItemConfig } from '../../molecules/PromptInputHeader';
5
5
  import type { SuggestionsItem } from '../../molecules/Suggestions';
6
6
  import type { HeaderProps } from '../../organisms/Header';
@@ -38,9 +38,12 @@ export interface ChatContainerI18nConfig {
38
38
  promptInput?: {
39
39
  /** Placeholder text */
40
40
  placeholder?: string;
41
- /** Send button tooltip */
41
+ };
42
+ /** Submit button tooltips */
43
+ submitButton?: {
44
+ /** Send button tooltip (enabled state) */
42
45
  sendTooltip?: string;
43
- /** Cancel button tooltip */
46
+ /** Cancel button tooltip (cancelable state) */
44
47
  cancelTooltip?: string;
45
48
  };
46
49
  /** History texts */
@@ -63,11 +66,11 @@ export interface WelcomeConfig {
63
66
  /** Image or icon to display */
64
67
  image?: React.ReactNode;
65
68
  /** Title text or custom React element */
66
- title?: string | React.ReactNode;
69
+ title?: React.ReactNode;
67
70
  /** Description text or custom React element */
68
- description?: string | React.ReactNode;
69
- /** Suggestions section title */
70
- suggestionTitle?: string;
71
+ description?: React.ReactNode;
72
+ /** Suggestions section title - can be string or custom React element */
73
+ suggestionTitle?: React.ReactNode;
71
74
  /** Array of suggestions (title will be used as message content) */
72
75
  suggestions?: SuggestionsItem[];
73
76
  /** Alignment configuration for image, title, and description */
@@ -84,14 +87,7 @@ export interface WelcomeConfig {
84
87
  /**
85
88
  * MessageList configuration
86
89
  */
87
- export interface MessageListConfig {
88
- /** Default actions for user messages */
89
- userActions?: DefaultMessageAction<TUserMessage<TMessageMetadata>>[];
90
- /** Default actions for assistant messages */
91
- assistantActions?: DefaultMessageAction<TAssistantMessage<TMessageContent, TMessageMetadata>>[];
92
- /** Array of chat statuses that should display the loader */
93
- loaderStatuses?: ChatStatus[];
94
- }
90
+ export type MessageListConfig = Omit<MessageListProps, 'messages' | 'status' | 'onRetry' | 'showActionsOnHover' | 'transformOptions'>;
95
91
  /**
96
92
  * Props for ChatContainer component
97
93
  */
@@ -27,11 +27,11 @@ export interface EmptyContainerProps {
27
27
  /** Image or icon to display at the top */
28
28
  image?: React.ReactNode;
29
29
  /** Title text or custom React element for the welcome screen */
30
- title?: string | React.ReactNode;
30
+ title?: React.ReactNode;
31
31
  /** Description text or custom React element explaining the functionality */
32
- description?: string | React.ReactNode;
33
- /** Title for the suggestions section */
34
- suggestionTitle?: string;
32
+ description?: React.ReactNode;
33
+ /** Title for the suggestions section - can be string or custom React element */
34
+ suggestionTitle?: React.ReactNode;
35
35
  /** Array of suggestion items */
36
36
  suggestions?: Suggestion[];
37
37
  /** Callback when a suggestion is clicked */
@@ -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: layout, 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] }) }))] }))] })) }) }));
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: typeof suggestionTitle === 'string' ? (_jsx(Text, { variant: "subheader-3", color: "primary", children: suggestionTitle })) : (suggestionTitle) })), _jsx("div", { children: _jsx(Suggestions, { items: suggestions, onClick: onSuggestionClick, layout: layout, 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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/aikit",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Gravity UI base kit for building ai assistant chats",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",