@gravity-ui/aikit 0.3.2 → 0.4.1

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.
@@ -4,9 +4,19 @@ $block: '.#{variables.$ns}alert';
4
4
 
5
5
  #{$block} {
6
6
  display: flex;
7
- align-items: center;
7
+ flex-direction: column;
8
8
  gap: var(--g-spacing-2);
9
9
 
10
+ &__header {
11
+ display: flex;
12
+ align-items: center;
13
+ gap: var(--g-spacing-2);
14
+ }
15
+
16
+ &__text {
17
+ flex: 1;
18
+ }
19
+
10
20
  &__icon {
11
21
  flex-shrink: 0;
12
22
 
@@ -7,7 +7,9 @@ export interface AlertProps {
7
7
  content: React.ReactNode;
8
8
  onClick: () => void;
9
9
  };
10
+ content?: React.ReactNode;
11
+ initialExpanded?: boolean;
10
12
  className?: string;
11
13
  qa?: string;
12
14
  }
13
- export declare function Alert({ text, icon, button, variant, className, qa }: AlertProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function Alert({ text, icon, button, content, initialExpanded, variant, className, qa, }: AlertProps): import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
3
- import { CircleExclamationFill, CircleInfoFill, TriangleExclamationFill } from '@gravity-ui/icons';
2
+ import { useMemo, useState } from 'react';
3
+ import { ChevronDown, ChevronUp, CircleExclamationFill, CircleInfoFill, TriangleExclamationFill, } from '@gravity-ui/icons';
4
4
  import { Button, Icon, Text } from '@gravity-ui/uikit';
5
5
  import { block } from '../../../utils/cn';
6
6
  import './Alert.scss';
@@ -10,7 +10,8 @@ const statusIcons = {
10
10
  warning: TriangleExclamationFill,
11
11
  error: CircleExclamationFill,
12
12
  };
13
- export function Alert({ text, icon, button, variant = 'default', className, qa }) {
13
+ export function Alert({ text, icon, button, content, initialExpanded = false, variant = 'default', className, qa, }) {
14
+ const [isExpanded, setIsExpanded] = useState(initialExpanded);
14
15
  const statusIcon = useMemo(() => {
15
16
  if (icon) {
16
17
  return _jsx("div", { className: b('icon'), children: icon });
@@ -21,5 +22,8 @@ export function Alert({ text, icon, button, variant = 'default', className, qa }
21
22
  }
22
23
  return null;
23
24
  }, [icon, variant]);
24
- return (_jsxs("div", { className: b(null, className), "data-qa": qa, children: [statusIcon, _jsx(Text, { variant: "body-1", children: text }), button ? (_jsx(Button, { onClick: button.onClick, size: "s", view: "outlined", className: b('action'), children: button.content })) : null] }));
25
+ const toggleExpanded = () => {
26
+ setIsExpanded((prev) => !prev);
27
+ };
28
+ return (_jsxs("div", { className: b(null, className), "data-qa": qa, children: [_jsxs("div", { className: b('header'), children: [statusIcon, _jsx(Text, { variant: "body-1", className: b('text'), children: text }), content && (_jsx(Button, { onClick: toggleExpanded, size: "s", view: "flat", className: b('collapse-button'), children: _jsx(Icon, { data: isExpanded ? ChevronUp : ChevronDown, size: 16 }) })), button ? (_jsx(Button, { onClick: button.onClick, size: "s", view: "outlined", className: b('action'), children: button.content })) : null] }), content && isExpanded && _jsx("div", { className: b('content'), children: content })] }));
25
29
  }
@@ -1,19 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Text } from '@gravity-ui/uikit';
3
3
  import { block } from '../../../utils/cn';
4
- import { ActionButton, ToolIndicator } from '../../atoms';
4
+ import { ActionButton } from '../../atoms';
5
5
  import { ButtonGroup } from '../ButtonGroup';
6
+ import { ToolStatus } from '../ToolStatus';
6
7
  import './ToolHeader.scss';
7
8
  const b = block('tool-header');
8
- function getIndicatorStatus(status) {
9
- if (status === 'success' || status === 'error' || status === 'loading') {
10
- return status;
11
- }
12
- return undefined;
13
- }
14
9
  export function ToolHeader(props) {
15
10
  const { toolIcon, toolName, content, actions, status, className, qa } = props;
16
11
  const hasActions = actions && actions.length > 0;
17
- const indicatorStatus = getIndicatorStatus(status);
18
- return (_jsxs("div", { className: b('', className), "data-qa": qa, children: [_jsxs("div", { className: b('left'), children: [toolIcon, _jsx(Text, { children: toolName }), content] }), _jsxs("div", { className: b('right'), children: [hasActions && (_jsx(ButtonGroup, { children: actions.map((action, index) => (_jsx(ActionButton, Object.assign({ tooltipTitle: action.label, view: "flat-secondary", size: "s" }, action, { children: action.icon }), index))) })), indicatorStatus && _jsx(ToolIndicator, { status: indicatorStatus })] })] }));
12
+ return (_jsxs("div", { className: b('', className), "data-qa": qa, children: [_jsxs("div", { className: b('left'), children: [toolIcon, _jsx(Text, { children: toolName }), content] }), _jsxs("div", { className: b('right'), children: [hasActions && (_jsx(ButtonGroup, { children: actions.map((action, index) => (_jsx(ActionButton, Object.assign({ tooltipTitle: action.label, view: "flat-secondary", size: "s" }, action, { children: action.icon }), index))) })), _jsx(ToolStatus, { status: status })] })] }));
19
13
  }
@@ -0,0 +1,6 @@
1
+ @use '../../../styles/variables';
2
+
3
+ $block: '.#{variables.$ns}tool-status';
4
+
5
+ #{$block} {
6
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "status-cancelled": "Cancelled"
3
+ }
@@ -0,0 +1,13 @@
1
+ export declare const i18n: ((key: "status-cancelled", params?: import("@gravity-ui/i18n").Params) => string) & {
2
+ Translation: import("react").ComponentType<{
3
+ children: (props: {
4
+ t: (key: "status-cancelled", params?: import("@gravity-ui/i18n").Params) => string;
5
+ }) => React.ReactNode;
6
+ }>;
7
+ useTranslation: () => {
8
+ t: (key: "status-cancelled", params?: import("@gravity-ui/i18n").Params) => string;
9
+ };
10
+ keysetData: {
11
+ "g-aikit-ToolStatus": Record<"status-cancelled", import("@gravity-ui/i18n").KeyData>;
12
+ };
13
+ };
@@ -0,0 +1,5 @@
1
+ import { addComponentKeysets } from '@gravity-ui/uikit/i18n';
2
+ import { NAMESPACE } from '../../../../utils/cn';
3
+ import en from './en.json';
4
+ import ru from './ru.json';
5
+ export const i18n = addComponentKeysets({ en, ru }, `${NAMESPACE}ToolStatus`);
@@ -0,0 +1,3 @@
1
+ {
2
+ "status-cancelled": "Отменено"
3
+ }
@@ -0,0 +1,8 @@
1
+ import type { TToolStatus as ToolStatusType } from '../../../types/tool';
2
+ import './ToolStatus.scss';
3
+ export type ToolStatusProps = {
4
+ status?: ToolStatusType;
5
+ className?: string;
6
+ qa?: string;
7
+ };
8
+ export declare function ToolStatus(props: ToolStatusProps): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text } from '@gravity-ui/uikit';
3
+ import { block } from '../../../utils/cn';
4
+ import { ToolIndicator } from '../../atoms';
5
+ import { i18n } from './i18n';
6
+ import './ToolStatus.scss';
7
+ const b = block('tool-status');
8
+ function getIndicatorStatus(status) {
9
+ if (status === 'success' || status === 'error' || status === 'loading') {
10
+ return status;
11
+ }
12
+ return undefined;
13
+ }
14
+ export function ToolStatus(props) {
15
+ const { status, className, qa } = props;
16
+ const indicatorStatus = getIndicatorStatus(status);
17
+ if (status === 'cancelled') {
18
+ return (_jsx(Text, { color: "secondary", className: b('', className), "data-qa": qa, children: i18n('status-cancelled') }));
19
+ }
20
+ if (indicatorStatus) {
21
+ return _jsx(ToolIndicator, { status: indicatorStatus, className: className, qa: qa });
22
+ }
23
+ return null;
24
+ }
@@ -9,3 +9,4 @@ export * from './Suggestions';
9
9
  export * from './Tabs';
10
10
  export * from './ToolFooter';
11
11
  export * from './ToolHeader';
12
+ export * from './ToolStatus';
@@ -10,3 +10,4 @@ export * from './Suggestions';
10
10
  export * from './Tabs';
11
11
  export * from './ToolFooter';
12
12
  export * from './ToolHeader';
13
+ export * from './ToolStatus';
@@ -23,5 +23,6 @@ export function PromptInputFull(props) {
23
23
  state: submitButtonState,
24
24
  tooltipSend: submitButtonTooltipSend,
25
25
  tooltipCancel: submitButtonTooltipCancel,
26
+ qa: 'submit-button-full',
26
27
  }, showSettings: showSettings, onSettingsClick: onSettingsClick, showAttachment: showAttachment, onAttachmentClick: onAttachmentClick, showMicrophone: showMicrophone, onMicrophoneClick: onMicrophoneClick, children: bottomContent }))] }));
27
28
  }
@@ -19,5 +19,6 @@ export function PromptInputSimple(props) {
19
19
  state: submitButtonState,
20
20
  tooltipSend: submitButtonTooltipSend,
21
21
  tooltipCancel: submitButtonTooltipCancel,
22
+ qa: 'submit-button-simple',
22
23
  }, showAttachment: showAttachment, onAttachmentClick: onAttachmentClick, showMicrophone: showMicrophone, onMicrophoneClick: onMicrophoneClick, buttonSize: "l", children: bottomContent })] }) }));
23
24
  }
@@ -47,7 +47,7 @@ export function useChatContainer(props) {
47
47
  // Build baseActions for Header
48
48
  const baseActions = useMemo(() => {
49
49
  const actions = [];
50
- if (showNewChat) {
50
+ if (showNewChat && chatContentView !== 'empty') {
51
51
  actions.push(HeaderAction.NewChat);
52
52
  }
53
53
  if (showHistory) {
@@ -57,7 +57,7 @@ export function useChatContainer(props) {
57
57
  actions.push(HeaderAction.Close);
58
58
  }
59
59
  return actions;
60
- }, [showNewChat, showHistory, showClose]);
60
+ }, [showNewChat, showHistory, showClose, chatContentView]);
61
61
  return {
62
62
  // State
63
63
  chatContentView,
@@ -15,5 +15,5 @@ export function ChatContent(props) {
15
15
  const isEmptyView = view === 'empty';
16
16
  return (_jsx("div", { className: b(null, className), "data-qa": qa, children: isEmptyView
17
17
  ? emptyContainerProps && _jsx(EmptyContainer, Object.assign({}, emptyContainerProps))
18
- : messageListProps && (_jsx("div", { className: b('message-list-container'), children: _jsx(MessageList, Object.assign({}, messageListProps, { className: b('message-list', messageListProps.className) })) })) }));
18
+ : messageListProps && (_jsx("div", { className: b('message-list-container'), children: _jsx(MessageList, Object.assign({}, messageListProps, { className: b('message-list', messageListProps.className), qa: `message-list${qa ? `-${qa}` : ''}` })) })) }));
19
19
  }
@@ -2,3 +2,5 @@ export * from './useDateFormatter';
2
2
  export * from './useToolMessage';
3
3
  export * from './useSmartScroll';
4
4
  export * from './useScrollPreservation';
5
+ export * from './useAutoCollapseOnSuccess';
6
+ export * from './useAutoCollapseOnCancelled';
@@ -2,3 +2,5 @@ export * from './useDateFormatter';
2
2
  export * from './useToolMessage';
3
3
  export * from './useSmartScroll';
4
4
  export * from './useScrollPreservation';
5
+ export * from './useAutoCollapseOnSuccess';
6
+ export * from './useAutoCollapseOnCancelled';
@@ -0,0 +1,6 @@
1
+ import type { TToolStatus } from '../types/tool';
2
+ export declare function useAutoCollapseOnCancelled(options: {
3
+ enabled: boolean;
4
+ status: TToolStatus | undefined;
5
+ setIsExpanded: (expanded: boolean) => void;
6
+ }): void;
@@ -0,0 +1,10 @@
1
+ import { useEffect } from 'react';
2
+ export function useAutoCollapseOnCancelled(options) {
3
+ const { enabled, status, setIsExpanded } = options;
4
+ const isCancelled = status === 'cancelled';
5
+ useEffect(() => {
6
+ if (enabled && isCancelled) {
7
+ setIsExpanded(false);
8
+ }
9
+ }, [enabled, isCancelled, setIsExpanded]);
10
+ }
@@ -0,0 +1,6 @@
1
+ import type { TToolStatus } from '../types/tool';
2
+ export declare function useAutoCollapseOnSuccess(options: {
3
+ enabled: boolean;
4
+ status: TToolStatus | undefined;
5
+ setIsExpanded: (expanded: boolean) => void;
6
+ }): void;
@@ -0,0 +1,10 @@
1
+ import { useEffect } from 'react';
2
+ export function useAutoCollapseOnSuccess(options) {
3
+ const { enabled, status, setIsExpanded } = options;
4
+ const isSuccess = status === 'success';
5
+ useEffect(() => {
6
+ if (enabled && isSuccess) {
7
+ setIsExpanded(false);
8
+ }
9
+ }, [enabled, isSuccess, setIsExpanded]);
10
+ }
@@ -3,6 +3,8 @@ import { useCallback, useMemo, useState } from 'react';
3
3
  import { ChevronDown, ChevronUp } from '@gravity-ui/icons';
4
4
  import { Icon } from '@gravity-ui/uikit';
5
5
  import { i18n } from '../components/organisms/ToolMessage/i18n';
6
+ import { useAutoCollapseOnCancelled } from './useAutoCollapseOnCancelled';
7
+ import { useAutoCollapseOnSuccess } from './useAutoCollapseOnSuccess';
6
8
  function getDefaultFooterActions(status, footerActions, onAccept, onReject) {
7
9
  if (footerActions !== undefined) {
8
10
  return footerActions;
@@ -60,8 +62,10 @@ function getDefaultInitialExpanded(status, initialExpanded) {
60
62
  }
61
63
  const defaultHeaderActions = [];
62
64
  export function useToolMessage(options) {
63
- const { footerActions, headerActions = defaultHeaderActions, bodyContent, status, footerContent, expandable = Boolean(bodyContent), initialExpanded, onAccept, onReject, } = options;
65
+ const { footerActions, headerActions = defaultHeaderActions, bodyContent, status, footerContent, expandable = Boolean(bodyContent), initialExpanded, autoCollapseOnSuccess, autoCollapseOnCancelled, onAccept, onReject, } = options;
64
66
  const [isExpanded, setIsExpanded] = useState(getDefaultInitialExpanded(status, initialExpanded));
67
+ useAutoCollapseOnSuccess({ enabled: Boolean(autoCollapseOnSuccess), status, setIsExpanded });
68
+ useAutoCollapseOnCancelled({ enabled: Boolean(autoCollapseOnCancelled), status, setIsExpanded });
65
69
  const toggleExpanded = useCallback(() => {
66
70
  setIsExpanded((prev) => !prev);
67
71
  }, []);
@@ -1,11 +1,11 @@
1
1
  import { Action } from './common';
2
- export type ToolStatus = 'success' | 'error' | 'loading' | 'waitingConfirmation' | 'waitingSubmission';
2
+ export type TToolStatus = 'success' | 'error' | 'loading' | 'waitingConfirmation' | 'waitingSubmission' | 'cancelled';
3
3
  export type ToolHeaderProps = {
4
4
  toolIcon?: React.ReactNode;
5
5
  toolName: string;
6
6
  content?: React.ReactNode;
7
7
  actions?: Action[];
8
- status?: ToolStatus;
8
+ status?: TToolStatus;
9
9
  className?: string;
10
10
  qa?: string;
11
11
  };
@@ -24,9 +24,11 @@ export type ToolMessageProps = {
24
24
  bodyContent?: React.ReactNode;
25
25
  headerContent?: React.ReactNode;
26
26
  footerContent?: React.ReactNode;
27
- status?: ToolStatus;
27
+ status?: TToolStatus;
28
28
  expandable?: boolean;
29
29
  initialExpanded?: boolean;
30
+ autoCollapseOnSuccess?: boolean;
31
+ autoCollapseOnCancelled?: boolean;
30
32
  onAccept?: () => void;
31
33
  onReject?: () => void;
32
34
  className?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/aikit",
3
- "version": "0.3.2",
3
+ "version": "0.4.1",
4
4
  "description": "Gravity UI base kit for building ai assistant chats",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",