@gravity-ui/aikit 2.28.0 → 2.28.1-beta.330ff88818384aa9f99cd1bb9695be70fe7b0977.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/README.md +4 -0
- package/build/cjs/components/atoms/ChatDate/ChatDate.js +3 -2
- package/build/cjs/components/atoms/ChatDate/ChatDate.js.map +1 -1
- package/build/cjs/components/atoms/InlineCitation/InlineCitation.js +5 -4
- package/build/cjs/components/atoms/InlineCitation/InlineCitation.js.map +1 -1
- package/build/cjs/components/atoms/Loader/Loader.js +1 -1
- package/build/cjs/components/atoms/Loader/Loader.js.map +1 -1
- package/build/cjs/components/atoms/SubmitButton/SubmitButton.js +3 -2
- package/build/cjs/components/atoms/SubmitButton/SubmitButton.js.map +1 -1
- package/build/cjs/components/molecules/ActionPopup/ActionPopup.js +2 -1
- package/build/cjs/components/molecules/ActionPopup/ActionPopup.js.map +1 -1
- package/build/cjs/components/molecules/BaseMessage/index.js +2 -1
- package/build/cjs/components/molecules/BaseMessage/index.js.map +1 -1
- package/build/cjs/components/molecules/FeedbackForm/FeedbackForm.js +3 -2
- package/build/cjs/components/molecules/FeedbackForm/FeedbackForm.js.map +1 -1
- package/build/cjs/components/molecules/FileDropZone/FileDropZone.js +2 -1
- package/build/cjs/components/molecules/FileDropZone/FileDropZone.js.map +1 -1
- package/build/cjs/components/molecules/FileItem/FileItem.js +2 -1
- package/build/cjs/components/molecules/FileItem/FileItem.js.map +1 -1
- package/build/cjs/components/molecules/InputContext/InputContextProvider.js +3 -2
- package/build/cjs/components/molecules/InputContext/InputContextProvider.js.map +1 -1
- package/build/cjs/components/molecules/PromptInputFooter/PromptInputFooter.js +3 -2
- package/build/cjs/components/molecules/PromptInputFooter/PromptInputFooter.js.map +1 -1
- package/build/cjs/components/molecules/StarRating/StarRating.js +3 -2
- package/build/cjs/components/molecules/StarRating/StarRating.js.map +1 -1
- package/build/cjs/components/molecules/ToolStatus/index.js +2 -1
- package/build/cjs/components/molecules/ToolStatus/index.js.map +1 -1
- package/build/cjs/components/organisms/AttachmentPicker/AttachmentPicker.d.ts +1 -1
- package/build/cjs/components/organisms/AttachmentPicker/AttachmentPicker.js +5 -11
- package/build/cjs/components/organisms/AttachmentPicker/AttachmentPicker.js.map +1 -1
- package/build/cjs/components/organisms/FileUploadDialog/FileUploadDialog.d.ts +1 -1
- package/build/cjs/components/organisms/FileUploadDialog/FileUploadDialog.js +10 -2
- package/build/cjs/components/organisms/FileUploadDialog/FileUploadDialog.js.map +1 -1
- package/build/cjs/components/organisms/Header/Header.js +8 -8
- package/build/cjs/components/organisms/Header/Header.js.map +1 -1
- package/build/cjs/components/organisms/MessageList/ErrorAlert.js +3 -2
- package/build/cjs/components/organisms/MessageList/ErrorAlert.js.map +1 -1
- package/build/cjs/components/organisms/MessageList/MessageList.virtualized.js +3 -3
- package/build/cjs/components/organisms/MessageList/MessageList.virtualized.js.map +1 -1
- package/build/cjs/components/organisms/PromptInput/PromptInput.js +2 -1
- package/build/cjs/components/organisms/PromptInput/PromptInput.js.map +1 -1
- package/build/cjs/components/organisms/PromptInput/PromptInputCommands.js +7 -2
- package/build/cjs/components/organisms/PromptInput/PromptInputCommands.js.map +1 -1
- package/build/cjs/components/organisms/ThinkingMessage/useThinkingMessage.js +3 -2
- package/build/cjs/components/organisms/ThinkingMessage/useThinkingMessage.js.map +1 -1
- package/build/cjs/components/organisms/ThinkingMessageGroup/CompactHeading.js +2 -1
- package/build/cjs/components/organisms/ThinkingMessageGroup/CompactHeading.js.map +1 -1
- package/build/cjs/components/organisms/ThinkingMessageGroup/ThinkingMessageGroup.js +6 -5
- package/build/cjs/components/organisms/ThinkingMessageGroup/ThinkingMessageGroup.js.map +1 -1
- package/build/cjs/components/pages/AIStudioChat/McpToolRenderer.js +2 -1
- package/build/cjs/components/pages/AIStudioChat/McpToolRenderer.js.map +1 -1
- package/build/cjs/components/pages/ChatContainer/ChatContainer.js +14 -9
- package/build/cjs/components/pages/ChatContainer/ChatContainer.js.map +1 -1
- package/build/cjs/components/templates/EmptyContainer/EmptyContainer.js +2 -1
- package/build/cjs/components/templates/EmptyContainer/EmptyContainer.js.map +1 -1
- package/build/cjs/components/templates/History/ChatItem.d.ts +3 -1
- package/build/cjs/components/templates/History/ChatItem.js +3 -2
- package/build/cjs/components/templates/History/ChatItem.js.map +1 -1
- package/build/cjs/components/templates/History/History.css +10 -1
- package/build/cjs/components/templates/History/History.js +4 -3
- package/build/cjs/components/templates/History/History.js.map +1 -1
- package/build/cjs/components/templates/History/HistoryList.js +31 -25
- package/build/cjs/components/templates/History/HistoryList.js.map +1 -1
- package/build/cjs/hooks/useMermaid.js +1 -3
- package/build/cjs/hooks/useMermaid.js.map +1 -1
- package/build/cjs/hooks/useMobileControlSize.d.ts +1 -1
- package/build/cjs/hooks/useMobileControlSize.js.map +1 -1
- package/build/cjs/hooks/useToolMessage.js +13 -12
- package/build/cjs/hooks/useToolMessage.js.map +1 -1
- package/build/cjs/hooks/useVirtualStickToBottom.d.ts +1 -1
- package/build/cjs/hooks/useVirtualStickToBottom.js +2 -2
- package/build/cjs/hooks/useVirtualStickToBottom.js.map +1 -1
- package/build/cjs/package.json +1 -1
- package/build/cjs/utils/chatUtils.d.ts +2 -3
- package/build/cjs/utils/chatUtils.js.map +1 -1
- package/build/cjs/utils/toolset/index.js +3 -2
- package/build/cjs/utils/toolset/index.js.map +1 -1
- package/build/docs/INDEX.md +8 -1
- package/build/docs/components/templates/History.md +2 -2
- package/build/docs/guides/AI_AGENTS.md +2 -2
- package/build/docs/guides/ARCHITECTURE.md +4 -4
- package/build/docs/guides/GETTING_STARTED.md +5 -3
- package/build/docs/guides/I18N.md +22 -15
- package/build/docs/guides/README.md +5 -0
- package/build/docs/guides/THEMER.md +6 -4
- package/build/docs/guides/THEMING.md +6 -4
- package/build/docs/guides/TROUBLESHOOTING.md +6 -6
- package/build/docs/guides/changelog-v3.md +61 -0
- package/build/docs/guides/migration-to-v3-ru.md +148 -0
- package/build/docs/guides/migration-to-v3.md +146 -0
- package/build/esm/components/atoms/ChatDate/ChatDate.js +3 -2
- package/build/esm/components/atoms/ChatDate/ChatDate.js.map +1 -1
- package/build/esm/components/atoms/InlineCitation/InlineCitation.js +5 -4
- package/build/esm/components/atoms/InlineCitation/InlineCitation.js.map +1 -1
- package/build/esm/components/atoms/Loader/Loader.js +1 -1
- package/build/esm/components/atoms/Loader/Loader.js.map +1 -1
- package/build/esm/components/atoms/SubmitButton/SubmitButton.js +3 -2
- package/build/esm/components/atoms/SubmitButton/SubmitButton.js.map +1 -1
- package/build/esm/components/molecules/ActionPopup/ActionPopup.js +2 -1
- package/build/esm/components/molecules/ActionPopup/ActionPopup.js.map +1 -1
- package/build/esm/components/molecules/BaseMessage/index.js +2 -1
- package/build/esm/components/molecules/BaseMessage/index.js.map +1 -1
- package/build/esm/components/molecules/FeedbackForm/FeedbackForm.js +3 -2
- package/build/esm/components/molecules/FeedbackForm/FeedbackForm.js.map +1 -1
- package/build/esm/components/molecules/FileDropZone/FileDropZone.js +2 -1
- package/build/esm/components/molecules/FileDropZone/FileDropZone.js.map +1 -1
- package/build/esm/components/molecules/FileItem/FileItem.js +2 -1
- package/build/esm/components/molecules/FileItem/FileItem.js.map +1 -1
- package/build/esm/components/molecules/InputContext/InputContextProvider.js +3 -2
- package/build/esm/components/molecules/InputContext/InputContextProvider.js.map +1 -1
- package/build/esm/components/molecules/PromptInputFooter/PromptInputFooter.js +3 -2
- package/build/esm/components/molecules/PromptInputFooter/PromptInputFooter.js.map +1 -1
- package/build/esm/components/molecules/StarRating/StarRating.js +3 -2
- package/build/esm/components/molecules/StarRating/StarRating.js.map +1 -1
- package/build/esm/components/molecules/ToolStatus/index.js +2 -1
- package/build/esm/components/molecules/ToolStatus/index.js.map +1 -1
- package/build/esm/components/organisms/AttachmentPicker/AttachmentPicker.d.ts +1 -1
- package/build/esm/components/organisms/AttachmentPicker/AttachmentPicker.js +6 -12
- package/build/esm/components/organisms/AttachmentPicker/AttachmentPicker.js.map +1 -1
- package/build/esm/components/organisms/FileUploadDialog/FileUploadDialog.d.ts +1 -1
- package/build/esm/components/organisms/FileUploadDialog/FileUploadDialog.js +10 -2
- package/build/esm/components/organisms/FileUploadDialog/FileUploadDialog.js.map +1 -1
- package/build/esm/components/organisms/Header/Header.js +9 -9
- package/build/esm/components/organisms/Header/Header.js.map +1 -1
- package/build/esm/components/organisms/MessageList/ErrorAlert.js +3 -2
- package/build/esm/components/organisms/MessageList/ErrorAlert.js.map +1 -1
- package/build/esm/components/organisms/MessageList/MessageList.virtualized.js +1 -1
- package/build/esm/components/organisms/MessageList/MessageList.virtualized.js.map +1 -1
- package/build/esm/components/organisms/PromptInput/PromptInput.js +2 -1
- package/build/esm/components/organisms/PromptInput/PromptInput.js.map +1 -1
- package/build/esm/components/organisms/PromptInput/PromptInputCommands.js +7 -2
- package/build/esm/components/organisms/PromptInput/PromptInputCommands.js.map +1 -1
- package/build/esm/components/organisms/ThinkingMessage/useThinkingMessage.js +3 -2
- package/build/esm/components/organisms/ThinkingMessage/useThinkingMessage.js.map +1 -1
- package/build/esm/components/organisms/ThinkingMessageGroup/CompactHeading.js +2 -1
- package/build/esm/components/organisms/ThinkingMessageGroup/CompactHeading.js.map +1 -1
- package/build/esm/components/organisms/ThinkingMessageGroup/ThinkingMessageGroup.js +6 -5
- package/build/esm/components/organisms/ThinkingMessageGroup/ThinkingMessageGroup.js.map +1 -1
- package/build/esm/components/pages/AIStudioChat/McpToolRenderer.js +2 -1
- package/build/esm/components/pages/AIStudioChat/McpToolRenderer.js.map +1 -1
- package/build/esm/components/pages/ChatContainer/ChatContainer.js +14 -9
- package/build/esm/components/pages/ChatContainer/ChatContainer.js.map +1 -1
- package/build/esm/components/templates/EmptyContainer/EmptyContainer.js +2 -1
- package/build/esm/components/templates/EmptyContainer/EmptyContainer.js.map +1 -1
- package/build/esm/components/templates/History/ChatItem.d.ts +3 -1
- package/build/esm/components/templates/History/ChatItem.js +3 -2
- package/build/esm/components/templates/History/ChatItem.js.map +1 -1
- package/build/esm/components/templates/History/History.css +10 -1
- package/build/esm/components/templates/History/History.js +4 -3
- package/build/esm/components/templates/History/History.js.map +1 -1
- package/build/esm/components/templates/History/HistoryList.js +33 -26
- package/build/esm/components/templates/History/HistoryList.js.map +1 -1
- package/build/esm/hooks/useMermaid.js +3 -5
- package/build/esm/hooks/useMermaid.js.map +1 -1
- package/build/esm/hooks/useMobileControlSize.d.ts +1 -1
- package/build/esm/hooks/useMobileControlSize.js.map +1 -1
- package/build/esm/hooks/useToolMessage.js +13 -12
- package/build/esm/hooks/useToolMessage.js.map +1 -1
- package/build/esm/hooks/useVirtualStickToBottom.d.ts +1 -1
- package/build/esm/hooks/useVirtualStickToBottom.js +1 -1
- package/build/esm/hooks/useVirtualStickToBottom.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/utils/chatUtils.d.ts +2 -3
- package/build/esm/utils/chatUtils.js.map +1 -1
- package/build/esm/utils/toolset/index.js +3 -2
- package/build/esm/utils/toolset/index.js.map +1 -1
- package/docs/AI_AGENTS.md +2 -2
- package/docs/ARCHITECTURE.md +4 -4
- package/docs/GETTING_STARTED.md +5 -3
- package/docs/I18N.md +22 -15
- package/docs/README.md +5 -0
- package/docs/THEMER.md +6 -4
- package/docs/THEMING.md +6 -4
- package/docs/TROUBLESHOOTING.md +6 -6
- package/docs/changelog-v3.md +61 -0
- package/docs/migration-to-v3-ru.md +148 -0
- package/docs/migration-to-v3.md +146 -0
- package/llms-full.txt +270 -38
- package/llms.txt +7 -2
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -53,6 +53,10 @@ src/
|
|
|
53
53
|
npm install @gravity-ui/aikit
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
AIKit 3 requires `@gravity-ui/uikit@^8.0.0`, React/React DOM 18 or 19, and Node.js 20+. Wrap the application in UIKit's `Provider` as shown in [Getting started](./docs/GETTING_STARTED.md).
|
|
57
|
+
|
|
58
|
+
Upgrading from v2? Read the [migration guide](./docs/migration-to-v3.md) ([Русский](./docs/migration-to-v3-ru.md)) and [v3 release notes](./docs/changelog-v3.md).
|
|
59
|
+
|
|
56
60
|
## Quick Start
|
|
57
61
|
|
|
58
62
|
```typescript
|
|
@@ -16,6 +16,7 @@ const b = (0, cn_1.block)('chat-date');
|
|
|
16
16
|
* @returns React component
|
|
17
17
|
*/
|
|
18
18
|
function ChatDate(props) {
|
|
19
|
+
const { t } = i18n_1.i18n.useTranslation();
|
|
19
20
|
const { date, showTime = false, format, locale, localeConfig, className, qa, relative = false, style, } = props;
|
|
20
21
|
const isMobile = (0, uikit_1.useMobile)();
|
|
21
22
|
const { formattedDate, formattedTime, fullDate, dateObject, isValid, diffDays } = (0, hooks_1.useDateFormatter)({
|
|
@@ -25,8 +26,8 @@ function ChatDate(props) {
|
|
|
25
26
|
localeConfig,
|
|
26
27
|
});
|
|
27
28
|
if (!isValid || !dateObject) {
|
|
28
|
-
return (
|
|
29
|
+
return t('invalid-date');
|
|
29
30
|
}
|
|
30
|
-
return ((0, jsx_runtime_1.jsx)("time", { className: b({ mobile: isMobile }, className), dateTime: dateObject.toISOString(), title: fullDate, "data-qa": qa, style: style, children: relative && typeof diffDays === 'number' ? ((0, jsx_runtime_1.jsx)("span", { children: (
|
|
31
|
+
return ((0, jsx_runtime_1.jsx)("time", { className: b({ mobile: isMobile }, className), dateTime: dateObject.toISOString(), title: fullDate, "data-qa": qa, style: style, children: relative && typeof diffDays === 'number' ? ((0, jsx_runtime_1.jsx)("span", { children: t('ago', { count: diffDays }) })) : ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { children: formattedDate }), (0, jsx_runtime_1.jsx)("span", { children: showTime && formattedTime && ` ${formattedTime}` })] })) }));
|
|
31
32
|
}
|
|
32
33
|
//# sourceMappingURL=ChatDate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatDate.js","sourceRoot":"../../../../../src","sources":["components/atoms/ChatDate/ChatDate.tsx"],"names":[],"mappings":";;AAmCA,
|
|
1
|
+
{"version":3,"file":"ChatDate.js","sourceRoot":"../../../../../src","sources":["components/atoms/ChatDate/ChatDate.tsx"],"names":[],"mappings":";;AAmCA,4BA8CC;;AAjFD,iCAA+B;AAE/B,6CAA+D;AAE/D,mDAAkE;AAClE,6CAAwC;AAExC,0CAA4B;AAE5B,0BAAyB;AAEzB,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,WAAW,CAAC,CAAC;AAkB7B;;;;;GAKG;AACH,SAAgB,QAAQ,CAAC,KAAoB;IACzC,MAAM,EAAC,CAAC,EAAC,GAAG,WAAI,CAAC,cAAc,EAAE,CAAC;IAClC,MAAM,EACF,IAAI,EACJ,QAAQ,GAAG,KAAK,EAChB,MAAM,EACN,MAAM,EACN,YAAY,EACZ,SAAS,EACT,EAAE,EACF,QAAQ,GAAG,KAAK,EAChB,KAAK,GACR,GAAG,KAAK,CAAC;IAEV,MAAM,QAAQ,GAAG,IAAA,iBAAS,GAAE,CAAC;IAE7B,MAAM,EAAC,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAC,GACzE,IAAA,wBAAgB,EAAC;QACb,IAAI;QACJ,MAAM;QACN,MAAM;QACN,YAAY;KACf,CAAC,CAAC;IAEP,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;QAC1B,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,CACH,iCACI,SAAS,EAAE,CAAC,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAC,EAAE,SAAS,CAAC,EAC3C,QAAQ,EAAE,UAAU,CAAC,WAAW,EAAE,EAClC,KAAK,EAAE,QAAQ,aACN,EAAE,EACX,KAAK,EAAE,KAAK,YAEX,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CACxC,2CAAO,CAAC,CAAC,KAAK,EAAE,EAAC,KAAK,EAAE,QAAQ,EAAC,CAAC,GAAQ,CAC7C,CAAC,CAAC,CAAC,CACA,wBAAC,gBAAQ,eACL,2CAAO,aAAa,GAAQ,EAC5B,2CAAO,QAAQ,IAAI,aAAa,IAAI,IAAI,aAAa,EAAE,GAAQ,IACxD,CACd,GACE,CACV,CAAC;AACN,CAAC","sourcesContent":["import {Fragment} from 'react';\n\nimport {DOMProps, QAProps, useMobile} from '@gravity-ui/uikit';\n\nimport {DateLocaleConfig, useDateFormatter} from '../../../hooks';\nimport {block} from '../../../utils/cn';\n\nimport {i18n} from './i18n';\n\nimport './ChatDate.scss';\n\nconst b = block('chat-date');\n\nexport type ChatDateProps = QAProps &\n DOMProps & {\n /** Date value in string, Date, or number (timestamp) format */\n date: string | Date | number;\n /** Show time along with date */\n showTime?: boolean;\n /** Custom format string (dayjs format) */\n format?: string;\n /** Locale for date formatting */\n locale?: string;\n /** Dayjs locale configuration for the provided locale */\n localeConfig?: DateLocaleConfig;\n /** Display relative dates (today, yesterday, two days ago, etc.) */\n relative?: boolean;\n };\n\n/**\n * ChatDate component displays formatted dates with optional time\n *\n * @param props - Component props\n * @returns React component\n */\nexport function ChatDate(props: ChatDateProps) {\n const {t} = i18n.useTranslation();\n const {\n date,\n showTime = false,\n format,\n locale,\n localeConfig,\n className,\n qa,\n relative = false,\n style,\n } = props;\n\n const isMobile = useMobile();\n\n const {formattedDate, formattedTime, fullDate, dateObject, isValid, diffDays} =\n useDateFormatter({\n date,\n format,\n locale,\n localeConfig,\n });\n\n if (!isValid || !dateObject) {\n return t('invalid-date');\n }\n\n return (\n <time\n className={b({mobile: isMobile}, className)}\n dateTime={dateObject.toISOString()}\n title={fullDate}\n data-qa={qa}\n style={style}\n >\n {relative && typeof diffDays === 'number' ? (\n <span>{t('ago', {count: diffDays})}</span>\n ) : (\n <Fragment>\n <span>{formattedDate}</span>\n <span>{showTime && formattedTime && ` ${formattedTime}`}</span>\n </Fragment>\n )}\n </time>\n );\n}\n"]}
|
|
@@ -20,6 +20,7 @@ function getSourceUrl(url) {
|
|
|
20
20
|
}
|
|
21
21
|
function InlineCitation({ sources, label, open, defaultOpen = false, onOpenChange, onSourceClick, className, qa, }) {
|
|
22
22
|
var _a, _b, _c, _d;
|
|
23
|
+
const { t } = i18n_1.i18n.useTranslation();
|
|
23
24
|
const [internalOpen, setInternalOpen] = (0, react_1.useState)(defaultOpen);
|
|
24
25
|
const [interactive, setInteractive] = (0, react_1.useState)(defaultOpen);
|
|
25
26
|
const [triggerElement, setTriggerElement] = (0, react_1.useState)(null);
|
|
@@ -118,10 +119,10 @@ function InlineCitation({ sources, label, open, defaultOpen = false, onOpenChang
|
|
|
118
119
|
return null;
|
|
119
120
|
}
|
|
120
121
|
const hostname = (_a = getSourceUrl(sources[0].url)) === null || _a === void 0 ? void 0 : _a.hostname;
|
|
121
|
-
const triggerLabel = (_c = (_b = label !== null && label !== void 0 ? label : hostname) !== null && _b !== void 0 ? _b : sources[0].title) !== null && _c !== void 0 ? _c : (
|
|
122
|
+
const triggerLabel = (_c = (_b = label !== null && label !== void 0 ? label : hostname) !== null && _b !== void 0 ? _b : sources[0].title) !== null && _c !== void 0 ? _c : t('source');
|
|
122
123
|
const sourceUrl = getSourceUrl(source.url);
|
|
123
|
-
const title = source.title || (sourceUrl === null || sourceUrl === void 0 ? void 0 : sourceUrl.hostname) || (
|
|
124
|
-
return ((0, jsx_runtime_1.jsxs)("span", { className: b(null, className), "data-qa": qa, children: [(0, jsx_runtime_1.jsxs)("button", { ref: setTriggerRef, type: "button", className: b('trigger'), "aria-label": (
|
|
124
|
+
const title = source.title || (sourceUrl === null || sourceUrl === void 0 ? void 0 : sourceUrl.hostname) || t('source');
|
|
125
|
+
return ((0, jsx_runtime_1.jsxs)("span", { className: b(null, className), "data-qa": qa, children: [(0, jsx_runtime_1.jsxs)("button", { ref: setTriggerRef, type: "button", className: b('trigger'), "aria-label": t('show-sources', { count: sources.length }), "aria-haspopup": "dialog", "aria-expanded": isOpen, "aria-controls": isOpen ? cardId : undefined, onPointerEnter: handlePointerEnter, onPointerLeave: scheduleClose, onFocus: () => {
|
|
125
126
|
if (suppressFocusRef.current) {
|
|
126
127
|
suppressFocusRef.current = false;
|
|
127
128
|
}
|
|
@@ -140,6 +141,6 @@ function InlineCitation({ sources, label, open, defaultOpen = false, onOpenChang
|
|
|
140
141
|
}, children: [(0, jsx_runtime_1.jsx)("span", { className: b('label'), children: triggerLabel }), sources.length > 1 && (0, jsx_runtime_1.jsxs)("span", { className: b('count'), children: ["+", sources.length - 1] })] }), (0, jsx_runtime_1.jsx)(uikit_1.Popup, { open: isOpen, anchorElement: triggerElement, placement: cardLayout.above ? 'top-start' : 'bottom-start', onOpenChange: changeOpen, className: b('popup', className), initialFocus: interactive ? 0 : -1, returnFocus: interactive, qa: qa ? `${qa}-popup` : undefined, children: (0, jsx_runtime_1.jsxs)("div", { ref: cardRef, role: "dialog", tabIndex: -1, id: cardId, "aria-labelledby": titleId, className: b('card'), style: { maxHeight: `min(480px, ${cardLayout.availableHeight}px)` }, onPointerEnter: clearTimer, onPointerLeave: scheduleClose, onFocus: () => {
|
|
141
142
|
clearTimer();
|
|
142
143
|
setInteractive(true);
|
|
143
|
-
}, onBlur: scheduleClose, children: [(0, jsx_runtime_1.jsxs)("div", { className: b('header'), children: [sources.length > 1 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(uikit_1.Button, { view: "flat-secondary", size: "s", disabled: selectedIndex === 0, "aria-label": (
|
|
144
|
+
}, onBlur: scheduleClose, children: [(0, jsx_runtime_1.jsxs)("div", { className: b('header'), children: [sources.length > 1 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(uikit_1.Button, { view: "flat-secondary", size: "s", disabled: selectedIndex === 0, "aria-label": t('previous'), onClick: (event) => navigateSource(selectedIndex - 1, event), children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.ChevronLeft, size: 16 }) }), (0, jsx_runtime_1.jsxs)("span", { className: b('index'), "aria-live": "polite", "aria-atomic": "true", children: [selectedIndex + 1, " / ", sources.length] }), (0, jsx_runtime_1.jsx)(uikit_1.Button, { view: "flat-secondary", size: "s", disabled: selectedIndex === sources.length - 1, "aria-label": t('next'), onClick: (event) => navigateSource(selectedIndex + 1, event), children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.ChevronRight, size: 16 }) })] })), (0, jsx_runtime_1.jsx)(uikit_1.Button, { view: "flat-secondary", size: "s", className: b('close'), "aria-label": t('close'), onClick: () => changeOpen(false), children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Xmark, size: 16 }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: b('source'), children: [(0, jsx_runtime_1.jsx)("div", { id: titleId, className: b('title'), children: sourceUrl ? ((0, jsx_runtime_1.jsx)(uikit_1.Link, { href: source.url, target: "_blank", rel: "noopener noreferrer", onClick: (event) => onSourceClick === null || onSourceClick === void 0 ? void 0 : onSourceClick(source, event), children: title })) : (title) }), (0, jsx_runtime_1.jsx)("div", { className: b('url'), children: (_d = sourceUrl === null || sourceUrl === void 0 ? void 0 : sourceUrl.hostname) !== null && _d !== void 0 ? _d : source.url }), source.description && ((0, jsx_runtime_1.jsx)("div", { className: b('description'), children: source.description })), source.quote && ((0, jsx_runtime_1.jsx)("blockquote", { className: b('quote'), children: source.quote }))] }, source.id)] }) })] }));
|
|
144
145
|
}
|
|
145
146
|
//# sourceMappingURL=InlineCitation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InlineCitation.js","sourceRoot":"../../../../../src","sources":["components/atoms/InlineCitation/InlineCitation.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {useCallback, useEffect, useId, useRef, useState} from 'react';\n\nimport {ChevronLeft, ChevronRight, Xmark} from '@gravity-ui/icons';\nimport {Button, Icon, Link, Popup} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\n\nimport {i18n} from './i18n';\n\nimport './InlineCitation.scss';\n\nconst b = block('inline-citation');\n\nexport interface InlineCitationSource {\n /** Stable identifier, unique within this citation. */\n id: string;\n /** Absolute HTTP or HTTPS URL. Other URLs are displayed without a link. */\n url: string;\n title?: string;\n description?: string;\n quote?: string;\n}\n\nexport interface InlineCitationProps {\n sources: readonly InlineCitationSource[];\n /** Overrides the first source's hostname in the trigger. */\n label?: string;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Call event.preventDefault() to override navigation. */\n onSourceClick?: (\n source: InlineCitationSource,\n event: React.MouseEvent<HTMLAnchorElement>,\n ) => void;\n className?: string;\n qa?: string;\n}\n\nfunction getSourceUrl(url: string) {\n try {\n const parsed = new URL(url);\n return ['http:', 'https:'].includes(parsed.protocol) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function InlineCitation({\n sources,\n label,\n open,\n defaultOpen = false,\n onOpenChange,\n onSourceClick,\n className,\n qa,\n}: InlineCitationProps) {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const [interactive, setInteractive] = useState(defaultOpen);\n const [triggerElement, setTriggerElement] = useState<HTMLButtonElement | null>(null);\n const [selectedId, setSelectedId] = useState<string>();\n const [cardLayout, setCardLayout] = useState({above: false, availableHeight: 480});\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const cardRef = useRef<HTMLDivElement>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout>>();\n const pinnedRef = useRef(defaultOpen);\n const suppressFocusRef = useRef(false);\n const cardId = useId();\n const titleId = useId();\n const setTriggerRef = useCallback((element: HTMLButtonElement | null) => {\n triggerRef.current = element;\n setTriggerElement(element);\n }, []);\n const isOpen = (open ?? internalOpen) && sources.length > 0;\n const selectedIndex = Math.max(\n 0,\n sources.findIndex((source) => source.id === selectedId),\n );\n const source = sources[selectedIndex];\n\n const clearTimer = useCallback(() => {\n clearTimeout(timerRef.current);\n timerRef.current = undefined;\n }, []);\n\n useEffect(() => clearTimer, [clearTimer]);\n\n useEffect(() => {\n if (!isOpen || !triggerElement) {\n return undefined;\n }\n const updateLayout = () => {\n const rect = triggerElement.getBoundingClientRect();\n const above = rect.top;\n const below = window.innerHeight - rect.bottom;\n setCardLayout({\n above: above > below,\n availableHeight: Math.max(0, Math.max(above, below) - 16),\n });\n };\n updateLayout();\n window.addEventListener('resize', updateLayout);\n window.addEventListener('scroll', updateLayout, true);\n return () => {\n window.removeEventListener('resize', updateLayout);\n window.removeEventListener('scroll', updateLayout, true);\n };\n }, [isOpen, triggerElement]);\n\n useEffect(() => {\n if (!isOpen) {\n clearTimer();\n pinnedRef.current = false;\n setInteractive(false);\n }\n }, [isOpen, clearTimer]);\n\n const changeOpen = (nextOpen: boolean) => {\n clearTimer();\n if (!nextOpen) {\n pinnedRef.current = false;\n suppressFocusRef.current = Boolean(cardRef.current?.contains(document.activeElement));\n }\n if (open === undefined) {\n setInternalOpen(nextOpen);\n }\n if (nextOpen !== isOpen) {\n onOpenChange?.(nextOpen);\n }\n };\n\n const scheduleClose = () => {\n clearTimer();\n if (pinnedRef.current) {\n return;\n }\n timerRef.current = setTimeout(() => {\n const activeElement = document.activeElement;\n if (activeElement !== triggerRef.current && !cardRef.current?.contains(activeElement)) {\n changeOpen(false);\n }\n }, 200);\n };\n\n const handlePointerEnter = (event: React.PointerEvent) => {\n clearTimer();\n if (event.pointerType === 'mouse' && !isOpen) {\n timerRef.current = setTimeout(() => changeOpen(true), 150);\n }\n };\n\n const navigateSource = (nextIndex: number, event: React.MouseEvent<HTMLButtonElement>) => {\n if (\n (nextIndex === 0 || nextIndex === sources.length - 1) &&\n document.activeElement === event.currentTarget\n ) {\n // Keep focus in the preview before the active navigation button becomes disabled.\n cardRef.current?.focus();\n }\n setSelectedId(sources[nextIndex].id);\n };\n\n if (!source) {\n return null;\n }\n\n const hostname = getSourceUrl(sources[0].url)?.hostname;\n const triggerLabel = label ?? hostname ?? sources[0].title ?? i18n('source');\n const sourceUrl = getSourceUrl(source.url);\n const title = source.title || sourceUrl?.hostname || i18n('source');\n\n return (\n <span className={b(null, className)} data-qa={qa}>\n <button\n ref={setTriggerRef}\n type=\"button\"\n className={b('trigger')}\n aria-label={i18n('show-sources', {count: sources.length})}\n aria-haspopup=\"dialog\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? cardId : undefined}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={scheduleClose}\n onFocus={() => {\n if (suppressFocusRef.current) {\n suppressFocusRef.current = false;\n } else {\n changeOpen(true);\n }\n }}\n onBlur={scheduleClose}\n onClick={() => {\n if (isOpen && pinnedRef.current) {\n changeOpen(false);\n } else {\n pinnedRef.current = true;\n setInteractive(true);\n changeOpen(true);\n }\n }}\n >\n <span className={b('label')}>{triggerLabel}</span>\n {sources.length > 1 && <span className={b('count')}>+{sources.length - 1}</span>}\n </button>\n <Popup\n open={isOpen}\n anchorElement={triggerElement}\n placement={cardLayout.above ? 'top-start' : 'bottom-start'}\n onOpenChange={changeOpen}\n className={b('popup', className)}\n initialFocus={interactive ? 0 : -1}\n returnFocus={interactive}\n qa={qa ? `${qa}-popup` : undefined}\n >\n <div\n ref={cardRef}\n role=\"dialog\"\n tabIndex={-1}\n id={cardId}\n aria-labelledby={titleId}\n className={b('card')}\n style={{maxHeight: `min(480px, ${cardLayout.availableHeight}px)`}}\n onPointerEnter={clearTimer}\n onPointerLeave={scheduleClose}\n onFocus={() => {\n clearTimer();\n setInteractive(true);\n }}\n onBlur={scheduleClose}\n >\n <div className={b('header')}>\n {sources.length > 1 && (\n <>\n <Button\n view=\"flat-secondary\"\n size=\"s\"\n disabled={selectedIndex === 0}\n aria-label={i18n('previous')}\n onClick={(event) => navigateSource(selectedIndex - 1, event)}\n >\n <Icon data={ChevronLeft} size={16} />\n </Button>\n <span className={b('index')} aria-live=\"polite\" aria-atomic=\"true\">\n {selectedIndex + 1} / {sources.length}\n </span>\n <Button\n view=\"flat-secondary\"\n size=\"s\"\n disabled={selectedIndex === sources.length - 1}\n aria-label={i18n('next')}\n onClick={(event) => navigateSource(selectedIndex + 1, event)}\n >\n <Icon data={ChevronRight} size={16} />\n </Button>\n </>\n )}\n <Button\n view=\"flat-secondary\"\n size=\"s\"\n className={b('close')}\n aria-label={i18n('close')}\n onClick={() => changeOpen(false)}\n >\n <Icon data={Xmark} size={16} />\n </Button>\n </div>\n <div className={b('source')} key={source.id}>\n <div id={titleId} className={b('title')}>\n {sourceUrl ? (\n <Link\n href={source.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={(event) => onSourceClick?.(source, event)}\n >\n {title}\n </Link>\n ) : (\n title\n )}\n </div>\n <div className={b('url')}>{sourceUrl?.hostname ?? source.url}</div>\n {source.description && (\n <div className={b('description')}>{source.description}</div>\n )}\n {source.quote && (\n <blockquote className={b('quote')}>{source.quote}</blockquote>\n )}\n </div>\n </div>\n </Popup>\n </span>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"InlineCitation.js","sourceRoot":"../../../../../src","sources":["components/atoms/InlineCitation/InlineCitation.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {useCallback, useEffect, useId, useRef, useState} from 'react';\n\nimport {ChevronLeft, ChevronRight, Xmark} from '@gravity-ui/icons';\nimport {Button, Icon, Link, Popup} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\n\nimport {i18n} from './i18n';\n\nimport './InlineCitation.scss';\n\nconst b = block('inline-citation');\n\nexport interface InlineCitationSource {\n /** Stable identifier, unique within this citation. */\n id: string;\n /** Absolute HTTP or HTTPS URL. Other URLs are displayed without a link. */\n url: string;\n title?: string;\n description?: string;\n quote?: string;\n}\n\nexport interface InlineCitationProps {\n sources: readonly InlineCitationSource[];\n /** Overrides the first source's hostname in the trigger. */\n label?: string;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Call event.preventDefault() to override navigation. */\n onSourceClick?: (\n source: InlineCitationSource,\n event: React.MouseEvent<HTMLAnchorElement>,\n ) => void;\n className?: string;\n qa?: string;\n}\n\nfunction getSourceUrl(url: string) {\n try {\n const parsed = new URL(url);\n return ['http:', 'https:'].includes(parsed.protocol) ? parsed : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function InlineCitation({\n sources,\n label,\n open,\n defaultOpen = false,\n onOpenChange,\n onSourceClick,\n className,\n qa,\n}: InlineCitationProps) {\n const {t} = i18n.useTranslation();\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const [interactive, setInteractive] = useState(defaultOpen);\n const [triggerElement, setTriggerElement] = useState<HTMLButtonElement | null>(null);\n const [selectedId, setSelectedId] = useState<string>();\n const [cardLayout, setCardLayout] = useState({above: false, availableHeight: 480});\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const cardRef = useRef<HTMLDivElement>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout>>();\n const pinnedRef = useRef(defaultOpen);\n const suppressFocusRef = useRef(false);\n const cardId = useId();\n const titleId = useId();\n const setTriggerRef = useCallback((element: HTMLButtonElement | null) => {\n triggerRef.current = element;\n setTriggerElement(element);\n }, []);\n const isOpen = (open ?? internalOpen) && sources.length > 0;\n const selectedIndex = Math.max(\n 0,\n sources.findIndex((source) => source.id === selectedId),\n );\n const source = sources[selectedIndex];\n\n const clearTimer = useCallback(() => {\n clearTimeout(timerRef.current);\n timerRef.current = undefined;\n }, []);\n\n useEffect(() => clearTimer, [clearTimer]);\n\n useEffect(() => {\n if (!isOpen || !triggerElement) {\n return undefined;\n }\n const updateLayout = () => {\n const rect = triggerElement.getBoundingClientRect();\n const above = rect.top;\n const below = window.innerHeight - rect.bottom;\n setCardLayout({\n above: above > below,\n availableHeight: Math.max(0, Math.max(above, below) - 16),\n });\n };\n updateLayout();\n window.addEventListener('resize', updateLayout);\n window.addEventListener('scroll', updateLayout, true);\n return () => {\n window.removeEventListener('resize', updateLayout);\n window.removeEventListener('scroll', updateLayout, true);\n };\n }, [isOpen, triggerElement]);\n\n useEffect(() => {\n if (!isOpen) {\n clearTimer();\n pinnedRef.current = false;\n setInteractive(false);\n }\n }, [isOpen, clearTimer]);\n\n const changeOpen = (nextOpen: boolean) => {\n clearTimer();\n if (!nextOpen) {\n pinnedRef.current = false;\n suppressFocusRef.current = Boolean(cardRef.current?.contains(document.activeElement));\n }\n if (open === undefined) {\n setInternalOpen(nextOpen);\n }\n if (nextOpen !== isOpen) {\n onOpenChange?.(nextOpen);\n }\n };\n\n const scheduleClose = () => {\n clearTimer();\n if (pinnedRef.current) {\n return;\n }\n timerRef.current = setTimeout(() => {\n const activeElement = document.activeElement;\n if (activeElement !== triggerRef.current && !cardRef.current?.contains(activeElement)) {\n changeOpen(false);\n }\n }, 200);\n };\n\n const handlePointerEnter = (event: React.PointerEvent) => {\n clearTimer();\n if (event.pointerType === 'mouse' && !isOpen) {\n timerRef.current = setTimeout(() => changeOpen(true), 150);\n }\n };\n\n const navigateSource = (nextIndex: number, event: React.MouseEvent<HTMLButtonElement>) => {\n if (\n (nextIndex === 0 || nextIndex === sources.length - 1) &&\n document.activeElement === event.currentTarget\n ) {\n // Keep focus in the preview before the active navigation button becomes disabled.\n cardRef.current?.focus();\n }\n setSelectedId(sources[nextIndex].id);\n };\n\n if (!source) {\n return null;\n }\n\n const hostname = getSourceUrl(sources[0].url)?.hostname;\n const triggerLabel = label ?? hostname ?? sources[0].title ?? t('source');\n const sourceUrl = getSourceUrl(source.url);\n const title = source.title || sourceUrl?.hostname || t('source');\n\n return (\n <span className={b(null, className)} data-qa={qa}>\n <button\n ref={setTriggerRef}\n type=\"button\"\n className={b('trigger')}\n aria-label={t('show-sources', {count: sources.length})}\n aria-haspopup=\"dialog\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? cardId : undefined}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={scheduleClose}\n onFocus={() => {\n if (suppressFocusRef.current) {\n suppressFocusRef.current = false;\n } else {\n changeOpen(true);\n }\n }}\n onBlur={scheduleClose}\n onClick={() => {\n if (isOpen && pinnedRef.current) {\n changeOpen(false);\n } else {\n pinnedRef.current = true;\n setInteractive(true);\n changeOpen(true);\n }\n }}\n >\n <span className={b('label')}>{triggerLabel}</span>\n {sources.length > 1 && <span className={b('count')}>+{sources.length - 1}</span>}\n </button>\n <Popup\n open={isOpen}\n anchorElement={triggerElement}\n placement={cardLayout.above ? 'top-start' : 'bottom-start'}\n onOpenChange={changeOpen}\n className={b('popup', className)}\n initialFocus={interactive ? 0 : -1}\n returnFocus={interactive}\n qa={qa ? `${qa}-popup` : undefined}\n >\n <div\n ref={cardRef}\n role=\"dialog\"\n tabIndex={-1}\n id={cardId}\n aria-labelledby={titleId}\n className={b('card')}\n style={{maxHeight: `min(480px, ${cardLayout.availableHeight}px)`}}\n onPointerEnter={clearTimer}\n onPointerLeave={scheduleClose}\n onFocus={() => {\n clearTimer();\n setInteractive(true);\n }}\n onBlur={scheduleClose}\n >\n <div className={b('header')}>\n {sources.length > 1 && (\n <>\n <Button\n view=\"flat-secondary\"\n size=\"s\"\n disabled={selectedIndex === 0}\n aria-label={t('previous')}\n onClick={(event) => navigateSource(selectedIndex - 1, event)}\n >\n <Icon data={ChevronLeft} size={16} />\n </Button>\n <span className={b('index')} aria-live=\"polite\" aria-atomic=\"true\">\n {selectedIndex + 1} / {sources.length}\n </span>\n <Button\n view=\"flat-secondary\"\n size=\"s\"\n disabled={selectedIndex === sources.length - 1}\n aria-label={t('next')}\n onClick={(event) => navigateSource(selectedIndex + 1, event)}\n >\n <Icon data={ChevronRight} size={16} />\n </Button>\n </>\n )}\n <Button\n view=\"flat-secondary\"\n size=\"s\"\n className={b('close')}\n aria-label={t('close')}\n onClick={() => changeOpen(false)}\n >\n <Icon data={Xmark} size={16} />\n </Button>\n </div>\n <div className={b('source')} key={source.id}>\n <div id={titleId} className={b('title')}>\n {sourceUrl ? (\n <Link\n href={source.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={(event) => onSourceClick?.(source, event)}\n >\n {title}\n </Link>\n ) : (\n title\n )}\n </div>\n <div className={b('url')}>{sourceUrl?.hostname ?? source.url}</div>\n {source.description && (\n <div className={b('description')}>{source.description}</div>\n )}\n {source.quote && (\n <blockquote className={b('quote')}>{source.quote}</blockquote>\n )}\n </div>\n </div>\n </Popup>\n </span>\n );\n}\n"]}
|
|
@@ -14,6 +14,6 @@ function Loader({ view = 'streaming', size = 's', message, className, withMessag
|
|
|
14
14
|
return loader;
|
|
15
15
|
}
|
|
16
16
|
const messageContent = ((0, jsx_runtime_1.jsx)(uikit_1.Text, { variant: isMobile ? 'body-2' : 'body-1', color: "secondary", children: message }));
|
|
17
|
-
return ((0, jsx_runtime_1.jsxs)(uikit_1.Flex, { gap: 2, className: b(null, className), children: [loader, withMessageShimmer ? (0, jsx_runtime_1.jsx)(Shimmer_1.Shimmer, { children: messageContent }) : messageContent] }));
|
|
17
|
+
return ((0, jsx_runtime_1.jsxs)(uikit_1.Flex, { gap: "spacing-2", className: b(null, className), children: [loader, withMessageShimmer ? (0, jsx_runtime_1.jsx)(Shimmer_1.Shimmer, { children: messageContent }) : messageContent] }));
|
|
18
18
|
}
|
|
19
19
|
//# sourceMappingURL=Loader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Loader.js","sourceRoot":"../../../../../src","sources":["components/atoms/Loader/Loader.tsx"],"names":[],"mappings":";;AAoBA,wBAoCC;;AAxDD,6CAA8D;AAE9D,6CAAwC;AACxC,iDAAmC;AAEnC,wBAAuB;AAEvB,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,QAAQ,CAAC,CAAC;AAa1B,SAAgB,MAAM,CAAC,EACnB,IAAI,GAAG,WAAW,EAClB,IAAI,GAAG,GAAG,EACV,OAAO,EACP,SAAS,EACT,kBAAkB,EAClB,EAAE,GACQ;IACV,MAAM,QAAQ,GAAG,IAAA,iBAAS,GAAE,CAAC;IAC7B,MAAM,MAAM,GACR,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CACnB,iCAAK,SAAS,EAAE,CAAC,CAAC,EAAC,IAAI,EAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAW,EAAE,aAC5D,gCAAK,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,GAAI,EAC7B,gCAAK,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAI,EAC/B,gCAAK,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,GAAI,IAC5B,CACT,CAAC,CAAC,CAAC,CACA,uBAAC,YAAI,IAAC,IAAI,EAAE,IAAI,aAAW,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAC,IAAI,EAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAI,CACpF,CAAC;IAEN,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,MAAM,cAAc,GAAG,CACnB,uBAAC,YAAI,IAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAC,WAAW,YAC3D,OAAO,GACL,CACV,CAAC;IAEF,OAAO,CACH,wBAAC,YAAI,IAAC,GAAG,
|
|
1
|
+
{"version":3,"file":"Loader.js","sourceRoot":"../../../../../src","sources":["components/atoms/Loader/Loader.tsx"],"names":[],"mappings":";;AAoBA,wBAoCC;;AAxDD,6CAA8D;AAE9D,6CAAwC;AACxC,iDAAmC;AAEnC,wBAAuB;AAEvB,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,QAAQ,CAAC,CAAC;AAa1B,SAAgB,MAAM,CAAC,EACnB,IAAI,GAAG,WAAW,EAClB,IAAI,GAAG,GAAG,EACV,OAAO,EACP,SAAS,EACT,kBAAkB,EAClB,EAAE,GACQ;IACV,MAAM,QAAQ,GAAG,IAAA,iBAAS,GAAE,CAAC;IAC7B,MAAM,MAAM,GACR,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CACnB,iCAAK,SAAS,EAAE,CAAC,CAAC,EAAC,IAAI,EAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAW,EAAE,aAC5D,gCAAK,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,GAAI,EAC7B,gCAAK,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAI,EAC/B,gCAAK,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,GAAI,IAC5B,CACT,CAAC,CAAC,CAAC,CACA,uBAAC,YAAI,IAAC,IAAI,EAAE,IAAI,aAAW,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAC,IAAI,EAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAI,CACpF,CAAC;IAEN,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,MAAM,cAAc,GAAG,CACnB,uBAAC,YAAI,IAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAC,WAAW,YAC3D,OAAO,GACL,CACV,CAAC;IAEF,OAAO,CACH,wBAAC,YAAI,IAAC,GAAG,EAAC,WAAW,EAAC,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,aAC9C,MAAM,EACN,kBAAkB,CAAC,CAAC,CAAC,uBAAC,iBAAO,cAAE,cAAc,GAAW,CAAC,CAAC,CAAC,cAAc,IACvE,CACV,CAAC;AACN,CAAC","sourcesContent":["import {Flex, Spin, Text, useMobile} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\nimport {Shimmer} from '../Shimmer';\n\nimport './Loader.scss';\n\nconst b = block('loader');\n\nexport type LoaderSize = 'xs' | 's' | 'm';\n\nexport interface LoaderProps {\n view?: 'streaming' | 'loading';\n size?: LoaderSize;\n message?: string;\n className?: string;\n qa?: string;\n withMessageShimmer?: boolean;\n}\n\nexport function Loader({\n view = 'streaming',\n size = 's',\n message,\n className,\n withMessageShimmer,\n qa,\n}: LoaderProps) {\n const isMobile = useMobile();\n const loader =\n view === 'streaming' ? (\n <div className={b({size}, message ? '' : className)} data-qa={qa}>\n <div className={b('left')} />\n <div className={b('center')} />\n <div className={b('right')} />\n </div>\n ) : (\n <Spin size={size} data-qa={qa} className={b({view}, message ? '' : className)} />\n );\n\n if (!message) {\n return loader;\n }\n\n const messageContent = (\n <Text variant={isMobile ? 'body-2' : 'body-1'} color=\"secondary\">\n {message}\n </Text>\n );\n\n return (\n <Flex gap=\"spacing-2\" className={b(null, className)}>\n {loader}\n {withMessageShimmer ? <Shimmer>{messageContent}</Shimmer> : messageContent}\n </Flex>\n );\n}\n"]}
|
|
@@ -23,6 +23,7 @@ const b = (0, cn_1.block)('submit-button');
|
|
|
23
23
|
* @returns Submit button component
|
|
24
24
|
*/
|
|
25
25
|
function SubmitButton({ onClick, state, className, size: sizeProp, disabled = false, tooltipSend, tooltipCancel, cancelableText, qa, }) {
|
|
26
|
+
const { t } = i18n_1.i18n.useTranslation();
|
|
26
27
|
const size = (0, useMobileControlSize_1.useMobileControlSize)(sizeProp, 'm', 'xl');
|
|
27
28
|
const iconSize = (0, useMobileControlSize_1.getControlIconSize)(size);
|
|
28
29
|
const isCancelable = state === 'cancelable';
|
|
@@ -41,9 +42,9 @@ function SubmitButton({ onClick, state, className, size: sizeProp, disabled = fa
|
|
|
41
42
|
}
|
|
42
43
|
switch (state) {
|
|
43
44
|
case 'enabled':
|
|
44
|
-
return tooltipSend || (
|
|
45
|
+
return tooltipSend || t('tooltip-send');
|
|
45
46
|
case 'cancelable':
|
|
46
|
-
return tooltipCancel || (
|
|
47
|
+
return tooltipCancel || t('tooltip-cancel');
|
|
47
48
|
case 'disabled':
|
|
48
49
|
case 'loading':
|
|
49
50
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubmitButton.js","sourceRoot":"../../../../../src","sources":["components/atoms/SubmitButton/SubmitButton.tsx"],"names":[],"mappings":";;AAmEA,
|
|
1
|
+
{"version":3,"file":"SubmitButton.js","sourceRoot":"../../../../../src","sources":["components/atoms/SubmitButton/SubmitButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useCallback} from 'react';\n\nimport {ArrowUp, CircleStop} from '@gravity-ui/icons';\nimport {ButtonButtonProps, Icon, Spin} from '@gravity-ui/uikit';\n\nimport {getControlIconSize, useMobileControlSize} from '../../../hooks/useMobileControlSize';\nimport {block} from '../../../utils/cn';\nimport {ActionButton} from '../ActionButton';\n\nimport {i18n} from './i18n';\n\nimport './SubmitButton.scss';\n\nconst b = block('submit-button');\n\nexport type SubmitButtonState = 'enabled' | 'disabled' | 'loading' | 'cancelable';\n\nexport interface SubmitButtonProps {\n /**\n * Click handler\n */\n onClick: () => Promise<void>;\n /**\n * Button state\n */\n state: SubmitButtonState;\n /**\n * Additional CSS class\n */\n className?: string;\n /**\n * Button size. Defaults to `m`, or `xl` in mobile mode\n */\n size?: ButtonButtonProps['size'];\n /**\n * Force the button into a disabled state\n */\n disabled?: ButtonButtonProps['disabled'];\n /**\n * Custom tooltip for enabled state\n */\n tooltipSend?: string;\n /**\n * Custom tooltip for cancelable state\n */\n tooltipCancel?: string;\n /**\n * Custom cancelable text (if provided, will be shown in cancelable state)\n */\n cancelableText?: string;\n /**\n * QA/test identifier\n */\n qa?: string;\n}\n\n/**\n * Submit button component with state management through props\n *\n * States:\n * - disabled: disabled button state\n * - enabled: enabled button state\n * - loading: loading state\n * - cancelable: cancellation state (during loading)\n *\n * @returns Submit button component\n */\nexport function SubmitButton({\n onClick,\n state,\n className,\n size: sizeProp,\n disabled = false,\n tooltipSend,\n tooltipCancel,\n cancelableText,\n qa,\n}: SubmitButtonProps) {\n const {t} = i18n.useTranslation();\n const size = useMobileControlSize(sizeProp, 'm', 'xl');\n const iconSize = getControlIconSize(size);\n const isCancelable = state === 'cancelable';\n const isLoading = state === 'loading';\n const isDisabled = disabled || state === 'disabled';\n const handleClick = useCallback(async () => {\n if (!disabled && ['enabled', 'cancelable'].includes(state)) {\n return onClick();\n }\n\n return Promise.resolve();\n }, [disabled, state, onClick]);\n\n // Get tooltip based on state\n const getTooltipTitle = (): string | undefined => {\n if (disabled) {\n return undefined;\n }\n\n switch (state) {\n case 'enabled':\n return tooltipSend || t('tooltip-send');\n case 'cancelable':\n return tooltipCancel || t('tooltip-cancel');\n case 'disabled':\n case 'loading':\n return undefined;\n default:\n return undefined;\n }\n };\n\n const renderContent = () => {\n if (isLoading) {\n return (\n <div className={b('loader')}>\n <Spin className={b('spinner')} size=\"xs\" />\n </div>\n );\n }\n\n if (isCancelable) {\n return cancelableText ? (\n [<Icon key=\"icon\" size={iconSize} data={CircleStop} />, cancelableText]\n ) : (\n <Icon size={iconSize} data={CircleStop} />\n );\n }\n\n return <Icon size={iconSize} data={ArrowUp} />;\n };\n\n return (\n <ActionButton\n view=\"action\"\n size={size}\n color=\"brand\"\n disabled={isDisabled}\n onClick={handleClick}\n className={b({size, loading: isLoading, cancelable: isCancelable}, className)}\n qa={qa}\n tooltipTitle={getTooltipTitle()}\n data-state={state}\n >\n {renderContent()}\n </ActionButton>\n );\n}\n"]}
|
|
@@ -18,10 +18,11 @@ const b = (0, cn_1.block)('action-popup');
|
|
|
18
18
|
* @returns React element with anchored popup
|
|
19
19
|
*/
|
|
20
20
|
function ActionPopup({ open, onOpenChange, anchorElement, title, subtitle, children, placement = 'bottom-start', className, qa, }) {
|
|
21
|
+
const { t } = i18n_1.i18n.useTranslation();
|
|
21
22
|
const hasHeader = title || subtitle;
|
|
22
23
|
const handleClose = () => {
|
|
23
24
|
onOpenChange(false);
|
|
24
25
|
};
|
|
25
|
-
return ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { open: open, onOpenChange: onOpenChange, anchorElement: anchorElement, placement: placement, hasArrow: true, className: b(null, className), qa: qa, children: (0, jsx_runtime_1.jsxs)("div", { className: b('container'), children: [hasHeader && ((0, jsx_runtime_1.jsxs)("div", { className: b('header'), children: [(0, jsx_runtime_1.jsxs)("div", { className: b('header-content'), children: [title && (0, jsx_runtime_1.jsx)(uikit_1.Text, { variant: "subheader-2", children: title }), subtitle && ((0, jsx_runtime_1.jsx)(uikit_1.Text, { variant: "body-1", color: "secondary", children: subtitle }))] }), (0, jsx_runtime_1.jsx)(uikit_1.Button, { view: "flat-secondary", size: "s", onClick: handleClose, className: b('close-button'), qa: qa ? `${qa}-close` : undefined, "aria-label": (
|
|
26
|
+
return ((0, jsx_runtime_1.jsx)(uikit_1.Popup, { open: open, onOpenChange: onOpenChange, anchorElement: anchorElement, placement: placement, hasArrow: true, className: b(null, className), qa: qa, children: (0, jsx_runtime_1.jsxs)("div", { className: b('container'), children: [hasHeader && ((0, jsx_runtime_1.jsxs)("div", { className: b('header'), children: [(0, jsx_runtime_1.jsxs)("div", { className: b('header-content'), children: [title && (0, jsx_runtime_1.jsx)(uikit_1.Text, { variant: "subheader-2", children: title }), subtitle && ((0, jsx_runtime_1.jsx)(uikit_1.Text, { variant: "body-1", color: "secondary", children: subtitle }))] }), (0, jsx_runtime_1.jsx)(uikit_1.Button, { view: "flat-secondary", size: "s", onClick: handleClose, className: b('close-button'), qa: qa ? `${qa}-close` : undefined, "aria-label": t('close'), children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Xmark, size: 16 }) })] })), children] }) }));
|
|
26
27
|
}
|
|
27
28
|
//# sourceMappingURL=ActionPopup.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionPopup.js","sourceRoot":"../../../../../src","sources":["components/molecules/ActionPopup/ActionPopup.tsx"],"names":[],"mappings":";;AA8CA,
|
|
1
|
+
{"version":3,"file":"ActionPopup.js","sourceRoot":"../../../../../src","sources":["components/molecules/ActionPopup/ActionPopup.tsx"],"names":[],"mappings":";;AA8CA,kCAuDC;;AAnGD,6CAAwC;AACxC,6CAAiF;AAGjF,6CAAwC;AAExC,0CAA4B;AAE5B,6BAA4B;AAE5B,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,cAAc,CAAC,CAAC;AAyBhC;;;;;;;;GAQG;AACH,SAAgB,WAAW,CAAC,EACxB,IAAI,EACJ,YAAY,EACZ,aAAa,EACb,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,SAAS,GAAG,cAAc,EAC1B,SAAS,EACT,EAAE,GACa;IACf,MAAM,EAAC,CAAC,EAAC,GAAG,WAAI,CAAC,cAAc,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,KAAK,IAAI,QAAQ,CAAC;IAEpC,MAAM,WAAW,GAAG,GAAG,EAAE;QACrB,YAAY,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC,CAAC;IAEF,OAAO,CACH,uBAAC,aAAK,IACF,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,YAAY,EAC1B,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,SAAS,EACpB,QAAQ,QACR,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,EAC7B,EAAE,EAAE,EAAE,YAEN,iCAAK,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC,aACzB,SAAS,IAAI,CACV,iCAAK,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,aACvB,iCAAK,SAAS,EAAE,CAAC,CAAC,gBAAgB,CAAC,aAC9B,KAAK,IAAI,uBAAC,YAAI,IAAC,OAAO,EAAC,aAAa,YAAE,KAAK,GAAQ,EACnD,QAAQ,IAAI,CACT,uBAAC,YAAI,IAAC,OAAO,EAAC,QAAQ,EAAC,KAAK,EAAC,WAAW,YACnC,QAAQ,GACN,CACV,IACC,EACN,uBAAC,cAAM,IACH,IAAI,EAAC,gBAAgB,EACrB,IAAI,EAAC,GAAG,EACR,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,CAAC,CAAC,cAAc,CAAC,EAC5B,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,gBACtB,CAAC,CAAC,OAAO,CAAC,YAEtB,uBAAC,YAAI,IAAC,IAAI,EAAE,aAAK,EAAE,IAAI,EAAE,EAAE,GAAI,GAC1B,IACP,CACT,EACA,QAAQ,IACP,GACF,CACX,CAAC;AACN,CAAC","sourcesContent":["import React from 'react';\n\nimport {Xmark} from '@gravity-ui/icons';\nimport {Button, Icon, Popup, type PopupPlacement, Text} from '@gravity-ui/uikit';\n\nimport type {ActionPopupConfig, ActionPopupContext} from '../../../types/messages';\nimport {block} from '../../../utils/cn';\n\nimport {i18n} from './i18n';\n\nimport './ActionPopup.scss';\n\nconst b = block('action-popup');\n\nexport type {ActionPopupConfig, ActionPopupContext};\n\nexport interface ActionPopupProps {\n /** Control popup open state */\n open: boolean;\n /** Callback when popup open state changes */\n onOpenChange: (open: boolean) => void;\n /** Anchor element for the popup */\n anchorElement: HTMLElement | null;\n /** Optional title text */\n title?: string;\n /** Optional subtitle text */\n subtitle?: string;\n /** Content to display in popup */\n children: React.ReactNode;\n /** Popup placement relative to anchor (default: 'bottom-start') */\n placement?: PopupPlacement;\n /** Additional CSS class */\n className?: string;\n /** QA/test identifier */\n qa?: string;\n}\n\n/**\n * ActionPopup - Universal anchored popup container for displaying content near action buttons\n *\n * This component provides a flexible popup container that can be anchored to any element\n * (typically action buttons). It supports optional title and subtitle, and can contain\n * any React content as children.\n *\n * @returns React element with anchored popup\n */\nexport function ActionPopup({\n open,\n onOpenChange,\n anchorElement,\n title,\n subtitle,\n children,\n placement = 'bottom-start',\n className,\n qa,\n}: ActionPopupProps) {\n const {t} = i18n.useTranslation();\n const hasHeader = title || subtitle;\n\n const handleClose = () => {\n onOpenChange(false);\n };\n\n return (\n <Popup\n open={open}\n onOpenChange={onOpenChange}\n anchorElement={anchorElement}\n placement={placement}\n hasArrow\n className={b(null, className)}\n qa={qa}\n >\n <div className={b('container')}>\n {hasHeader && (\n <div className={b('header')}>\n <div className={b('header-content')}>\n {title && <Text variant=\"subheader-2\">{title}</Text>}\n {subtitle && (\n <Text variant=\"body-1\" color=\"secondary\">\n {subtitle}\n </Text>\n )}\n </div>\n <Button\n view=\"flat-secondary\"\n size=\"s\"\n onClick={handleClose}\n className={b('close-button')}\n qa={qa ? `${qa}-close` : undefined}\n aria-label={t('close')}\n >\n <Icon data={Xmark} size={16} />\n </Button>\n </div>\n )}\n {children}\n </div>\n </Popup>\n );\n}\n"]}
|
|
@@ -16,6 +16,7 @@ const i18n_1 = require("./i18n/index.js");
|
|
|
16
16
|
require("./BaseMessage.css");
|
|
17
17
|
const b = (0, cn_1.block)('base-message');
|
|
18
18
|
const BaseMessageComponent = (props) => {
|
|
19
|
+
const { t } = i18n_1.i18n.useTranslation();
|
|
19
20
|
const { className, qa, showActionsOnHover, actions, extraInfo, children, role: variant, showTimestamp, timestamp = '', userRating, onActionPopup, } = props;
|
|
20
21
|
// Get tooltip text for action
|
|
21
22
|
const getTooltipText = (actionType) => {
|
|
@@ -24,7 +25,7 @@ const BaseMessageComponent = (props) => {
|
|
|
24
25
|
return '';
|
|
25
26
|
}
|
|
26
27
|
try {
|
|
27
|
-
return (
|
|
28
|
+
return t(`action-tooltip-${actionType}`);
|
|
28
29
|
}
|
|
29
30
|
catch (_a) {
|
|
30
31
|
return '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["components/molecules/BaseMessage/index.tsx"],"names":[],"mappings":";;;;;AAAA,uDAAkC;AAElC,6CAS2B;AAC3B,6CAAuC;AAGvC,yDAA8D;AAC9D,+DAA0D;AAC1D,6CAAwC;AACxC,oEAAsD;AACtD,4DAA8C;AAC9C,yDAA2C;AAE3C,0CAA4B;AAE5B,6BAA4B;AAE5B,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,cAAc,CAAC,CAAC;AAEhC,MAAM,oBAAoB,GAAG,CAAC,KAAuB,EAAE,EAAE;IACrD,MAAM,EACF,SAAS,EACT,EAAE,EACF,kBAAkB,EAClB,OAAO,EACP,SAAS,EACT,QAAQ,EACR,IAAI,EAAE,OAAO,EACb,aAAa,EACb,SAAS,GAAG,EAAE,EACd,UAAU,EACV,aAAa,GAChB,GAAG,KAAK,CAAC;IAEV,8BAA8B;IAC9B,MAAM,cAAc,GAAG,CAAC,UAAmB,EAAU,EAAE;QACnD,MAAM,UAAU,GAAa,MAAM,CAAC,MAAM,CAAC,gCAAqB,CAAC,CAAC;QAClE,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAClD,OAAO,EAAE,CAAC;QACd,CAAC;QACD,IAAI,CAAC;YACD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"../../../../../src","sources":["components/molecules/BaseMessage/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {memo} from 'react';\n\nimport {\n ArrowRotateLeft,\n Copy as CopyIcon,\n Pencil,\n ThumbsDown,\n ThumbsDownFill,\n ThumbsUp,\n ThumbsUpFill,\n TrashBin,\n} from '@gravity-ui/icons';\nimport {Icon} from '@gravity-ui/uikit';\n\nimport type {BaseMessageProps, UserRating} from '../../../types/messages';\nimport {BaseMessageActionType} from '../../../types/messages';\nimport {isActionConfig} from '../../../utils/actionUtils';\nimport {block} from '../../../utils/cn';\nimport {ActionButton} from '../../atoms/ActionButton';\nimport {ChatDate} from '../../atoms/ChatDate';\nimport {ButtonGroup} from '../ButtonGroup';\n\nimport {i18n} from './i18n';\n\nimport './BaseMessage.scss';\n\nconst b = block('base-message');\n\nconst BaseMessageComponent = (props: BaseMessageProps) => {\n const {t} = i18n.useTranslation();\n const {\n className,\n qa,\n showActionsOnHover,\n actions,\n extraInfo,\n children,\n role: variant,\n showTimestamp,\n timestamp = '',\n userRating,\n onActionPopup,\n } = props;\n\n // Get tooltip text for action\n const getTooltipText = (actionType?: string): string => {\n const knownTypes: string[] = Object.values(BaseMessageActionType);\n if (!actionType || !knownTypes.includes(actionType)) {\n return '';\n }\n try {\n return t(`action-tooltip-${actionType}` as Parameters<typeof i18n>[0]);\n } catch {\n return '';\n }\n };\n const hasActions = actions && actions.length > 0;\n const showFooter = hasActions || Boolean(extraInfo);\n\n return (\n <div className={b({variant, 'btn-hover': showActionsOnHover}, className)} data-qa={qa}>\n {children}\n {showFooter && (\n <div className={b('actions', {reverse: variant !== 'user'})}>\n {showTimestamp ? <ChatDate date={timestamp} format=\"HH:mm\" showTime /> : null}\n {hasActions && (\n <ButtonGroup>\n {actions?.map((action, index) => {\n if (!isActionConfig(action)) {\n return <React.Fragment key={index}>{action}</React.Fragment>;\n }\n\n const tooltipText = getTooltipText(action.actionType);\n\n const defaultIcon = getDefaultIcon(action.actionType, userRating);\n\n // Determine tooltip title\n let tooltipTitle: string | undefined;\n if (action.label) {\n tooltipTitle = action.label;\n } else if (tooltipText && action.actionType !== 'custom') {\n tooltipTitle = tooltipText;\n }\n\n // Exclude custom props that shouldn't be passed to DOM\n const {\n actionType: _actionType,\n popup: _popup,\n icon: _icon,\n label: _label,\n children: actionChildren,\n onClick: actionOnClick,\n ...buttonProps\n } = action;\n\n // Determine button content; children takes precedence over icon\n let buttonContent: React.ReactNode;\n if (actionChildren) {\n buttonContent = actionChildren;\n } else if (action.icon) {\n buttonContent = action.icon;\n } else if (defaultIcon) {\n buttonContent = <Icon size={16} data={defaultIcon} />;\n } else if (action.label) {\n buttonContent = action.label;\n } else {\n buttonContent = action.actionType;\n }\n\n return (\n <ActionButton\n key={action.actionType || index}\n {...buttonProps}\n tooltipTitle={tooltipTitle}\n view={action.view || 'flat-secondary'}\n onClick={(e) => {\n onActionPopup?.(action, e.currentTarget);\n actionOnClick?.(e);\n }}\n >\n {buttonContent}\n </ActionButton>\n );\n })}\n </ButtonGroup>\n )}\n {extraInfo}\n </div>\n )}\n </div>\n );\n};\n\nexport const BaseMessage = memo(BaseMessageComponent);\nBaseMessage.displayName = 'BaseMessage';\n\nfunction getDefaultIcon(actionType?: string, userRating?: UserRating) {\n switch (actionType) {\n case BaseMessageActionType.Copy:\n return CopyIcon;\n case BaseMessageActionType.Edit:\n return Pencil;\n case BaseMessageActionType.Retry:\n return ArrowRotateLeft;\n case BaseMessageActionType.Delete:\n return TrashBin;\n case BaseMessageActionType.Like:\n return userRating === 'like' ? ThumbsUpFill : ThumbsUp;\n case BaseMessageActionType.Dislike:\n return userRating === 'dislike' ? ThumbsDownFill : ThumbsDown;\n default:\n return undefined;\n }\n}\n"]}
|
|
@@ -18,6 +18,7 @@ const b = (0, cn_1.block)('feedback-form');
|
|
|
18
18
|
* @returns React element with feedback form
|
|
19
19
|
*/
|
|
20
20
|
function FeedbackForm({ options, onSubmit, reasonsLabel, commentLabel, commentPlaceholder, showComment = true, submitLabel, disabled = false, className, qa, }) {
|
|
21
|
+
const { t } = i18n_1.i18n.useTranslation();
|
|
21
22
|
const [selectedReasons, setSelectedReasons] = (0, react_1.useState)([]);
|
|
22
23
|
const [comment, setComment] = (0, react_1.useState)('');
|
|
23
24
|
const handleReasonToggle = (reasonId) => {
|
|
@@ -31,8 +32,8 @@ function FeedbackForm({ options, onSubmit, reasonsLabel, commentLabel, commentPl
|
|
|
31
32
|
const isReasonSelected = (reasonId) => selectedReasons.includes(reasonId);
|
|
32
33
|
// Submit button is disabled if no reason selected AND no comment provided (when comment is shown)
|
|
33
34
|
const isSubmitDisabled = disabled || (selectedReasons.length === 0 && (!showComment || comment.trim() === ''));
|
|
34
|
-
const displayCommentPlaceholder = commentPlaceholder || (
|
|
35
|
-
const displaySubmitLabel = submitLabel || (
|
|
35
|
+
const displayCommentPlaceholder = commentPlaceholder || t('comment-placeholder');
|
|
36
|
+
const displaySubmitLabel = submitLabel || t('submit');
|
|
36
37
|
return ((0, jsx_runtime_1.jsxs)("div", { className: b(null, className), "data-qa": qa, children: [reasonsLabel && ((0, jsx_runtime_1.jsx)(uikit_1.Text, { variant: "subheader-2", "data-qa": qa ? `${qa}-reasons-label` : undefined, children: reasonsLabel })), (0, jsx_runtime_1.jsx)("div", { className: b('reasons'), "data-qa": qa ? `${qa}-reasons` : undefined, children: options.map((option) => {
|
|
37
38
|
const selected = isReasonSelected(option.id);
|
|
38
39
|
return ((0, jsx_runtime_1.jsx)(uikit_1.Button, { view: "normal", size: "m", selected: selected, onClick: () => handleReasonToggle(option.id), className: b('reason-chip', { selected }), "data-qa": qa ? `${qa}-reason-${option.id}` : undefined, disabled: disabled, children: option.label }, option.id));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FeedbackForm.js","sourceRoot":"../../../../../src","sources":["components/molecules/FeedbackForm/FeedbackForm.tsx"],"names":[],"mappings":";;AAmDA,
|
|
1
|
+
{"version":3,"file":"FeedbackForm.js","sourceRoot":"../../../../../src","sources":["components/molecules/FeedbackForm/FeedbackForm.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useState} from 'react';\n\nimport {Button, Text, TextArea} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\n\nimport {i18n} from './i18n';\n\nimport './FeedbackForm.scss';\n\nconst b = block('feedback-form');\n\nexport interface FeedbackOption {\n /** Unique identifier for the option */\n id: string;\n /** Display label for the option */\n label: string;\n}\n\nexport interface FeedbackFormProps {\n /** Array of reason options to display as selectable chips */\n options: FeedbackOption[];\n /** Callback when form is submitted with selected reasons and comment */\n onSubmit: (reasons: string[], comment: string) => void;\n /** Label text for reasons section */\n reasonsLabel?: string;\n /** Label text for comment field */\n commentLabel?: string;\n /** Placeholder text for comment field */\n commentPlaceholder?: string;\n /** Whether to show the comment textarea (default: true) */\n showComment?: boolean;\n /** Text for submit button */\n submitLabel?: string;\n /** Disable form interaction */\n disabled?: boolean;\n /** Additional CSS class */\n className?: string;\n /** QA/test identifier */\n qa?: string;\n}\n\n/**\n * FeedbackForm - Reusable feedback form with reason selection and comment field\n *\n * This component provides a user-friendly way to collect feedback with multiple\n * selectable reasons (rendered as chips) and an optional comment field.\n * Can be used standalone or inside ActionPopup.\n *\n * @returns React element with feedback form\n */\nexport function FeedbackForm({\n options,\n onSubmit,\n reasonsLabel,\n commentLabel,\n commentPlaceholder,\n showComment = true,\n submitLabel,\n disabled = false,\n className,\n qa,\n}: FeedbackFormProps) {\n const {t} = i18n.useTranslation();\n const [selectedReasons, setSelectedReasons] = useState<string[]>([]);\n const [comment, setComment] = useState('');\n\n const handleReasonToggle = (reasonId: string) => {\n setSelectedReasons((prev) =>\n prev.includes(reasonId) ? prev.filter((id) => id !== reasonId) : [...prev, reasonId],\n );\n };\n\n const handleSubmit = () => {\n onSubmit(selectedReasons, comment);\n setSelectedReasons([]);\n setComment('');\n };\n\n const isReasonSelected = (reasonId: string) => selectedReasons.includes(reasonId);\n\n // Submit button is disabled if no reason selected AND no comment provided (when comment is shown)\n const isSubmitDisabled =\n disabled || (selectedReasons.length === 0 && (!showComment || comment.trim() === ''));\n\n const displayCommentPlaceholder = commentPlaceholder || t('comment-placeholder');\n const displaySubmitLabel = submitLabel || t('submit');\n\n return (\n <div className={b(null, className)} data-qa={qa}>\n {reasonsLabel && (\n <Text variant=\"subheader-2\" data-qa={qa ? `${qa}-reasons-label` : undefined}>\n {reasonsLabel}\n </Text>\n )}\n <div className={b('reasons')} data-qa={qa ? `${qa}-reasons` : undefined}>\n {options.map((option) => {\n const selected = isReasonSelected(option.id);\n return (\n <Button\n key={option.id}\n view=\"normal\"\n size=\"m\"\n selected={selected}\n onClick={() => handleReasonToggle(option.id)}\n className={b('reason-chip', {selected})}\n data-qa={qa ? `${qa}-reason-${option.id}` : undefined}\n disabled={disabled}\n >\n {option.label}\n </Button>\n );\n })}\n </div>\n\n {showComment && (\n <>\n {commentLabel && (\n <Text\n variant=\"subheader-2\"\n data-qa={qa ? `${qa}-comment-label` : undefined}\n >\n {commentLabel}\n </Text>\n )}\n <TextArea\n value={comment}\n onUpdate={setComment}\n placeholder={displayCommentPlaceholder}\n minRows={2}\n maxRows={6}\n className={b('comment')}\n disabled={disabled}\n qa={qa ? `${qa}-comment` : undefined}\n />\n </>\n )}\n\n <Button\n view=\"action\"\n size=\"l\"\n onClick={handleSubmit}\n disabled={isSubmitDisabled}\n className={b('submit')}\n qa={qa ? `${qa}-submit` : undefined}\n >\n {displaySubmitLabel}\n </Button>\n </div>\n );\n}\n"]}
|
|
@@ -14,6 +14,7 @@ const b = (0, cn_1.block)('file-drop-zone');
|
|
|
14
14
|
* Uses native HTML5 DnD — no external dependencies.
|
|
15
15
|
*/
|
|
16
16
|
const FileDropZone = ({ accept, multiple = true, disabled = false, onAdd, label, hint, className, }) => {
|
|
17
|
+
const { t } = i18n_1.i18n.useTranslation();
|
|
17
18
|
const [isDragging, setIsDragging] = (0, react_1.useState)(false);
|
|
18
19
|
const inputRef = (0, react_1.useRef)(null);
|
|
19
20
|
const handleFiles = (0, react_1.useCallback)((fileList) => {
|
|
@@ -55,7 +56,7 @@ const FileDropZone = ({ accept, multiple = true, disabled = false, onAdd, label,
|
|
|
55
56
|
handleClick();
|
|
56
57
|
}
|
|
57
58
|
}, [handleClick]);
|
|
58
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: b({ dragging: isDragging, disabled }, className), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: handleClick, onKeyDown: handleKeyDown, role: "button", tabIndex: disabled ? -1 : 0, "aria-disabled": disabled, children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, type: "file", accept: accept, multiple: multiple, onChange: handleInputChange, className: b('input'), tabIndex: -1, "aria-hidden": true }), (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.ArrowUpToLine, size: 24, className: b('icon') }), (0, jsx_runtime_1.jsx)(uikit_1.Text, { variant: "body-2", className: b('label'), children: label !== null && label !== void 0 ? label : (
|
|
59
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: b({ dragging: isDragging, disabled }, className), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: handleClick, onKeyDown: handleKeyDown, role: "button", tabIndex: disabled ? -1 : 0, "aria-disabled": disabled, children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, type: "file", accept: accept, multiple: multiple, onChange: handleInputChange, className: b('input'), tabIndex: -1, "aria-hidden": true }), (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.ArrowUpToLine, size: 24, className: b('icon') }), (0, jsx_runtime_1.jsx)(uikit_1.Text, { variant: "body-2", className: b('label'), children: label !== null && label !== void 0 ? label : t('label') }), hint && ((0, jsx_runtime_1.jsx)(uikit_1.Text, { variant: "body-1", className: b('hint'), children: hint }))] }));
|
|
59
60
|
};
|
|
60
61
|
exports.FileDropZone = FileDropZone;
|
|
61
62
|
//# sourceMappingURL=FileDropZone.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileDropZone.js","sourceRoot":"../../../../../src","sources":["components/molecules/FileDropZone/FileDropZone.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"FileDropZone.js","sourceRoot":"../../../../../src","sources":["components/molecules/FileDropZone/FileDropZone.tsx"],"names":[],"mappings":";;;;AAAA,iCAA2D;AAE3D,6CAAgD;AAChD,6CAA6C;AAE7C,6CAAwC;AAExC,0CAA4B;AAE5B,8BAA6B;AAE7B,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,gBAAgB,CAAC,CAAC;AAYlC;;;GAGG;AACI,MAAM,YAAY,GAAG,CAAC,EACzB,MAAM,EACN,QAAQ,GAAG,IAAI,EACf,QAAQ,GAAG,KAAK,EAChB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,SAAS,GACO,EAAE,EAAE;IACpB,MAAM,EAAC,CAAC,EAAC,GAAG,WAAI,CAAC,cAAc,EAAE,CAAC;IAClC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAA,cAAM,EAAmB,IAAI,CAAC,CAAC;IAEhD,MAAM,WAAW,GAAG,IAAA,mBAAW,EAC3B,CAAC,QAAyB,EAAE,EAAE;QAC1B,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,KAAK,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC,EACD,CAAC,KAAK,CAAC,CACV,CAAC;IAEF,MAAM,cAAc,GAAG,IAAA,mBAAW,EAC9B,CAAC,CAAkB,EAAE,EAAE;QACnB,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,IAAI,CAAC,QAAQ;YAAE,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC,EACD,CAAC,QAAQ,CAAC,CACb,CAAC;IAEF,MAAM,eAAe,GAAG,IAAA,mBAAW,EAAC,CAAC,CAAkB,EAAE,EAAE;QACvD,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,aAAa,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,UAAU,GAAG,IAAA,mBAAW,EAC1B,CAAC,CAAkB,EAAE,EAAE;QACnB,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,QAAQ;YAAE,OAAO;QACrB,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC,EACD,CAAC,QAAQ,EAAE,WAAW,CAAC,CAC1B,CAAC;IAEF,MAAM,iBAAiB,GAAG,IAAA,mBAAW,EACjC,CAAC,CAAsC,EAAE,EAAE;QACvC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,mDAAmD;QACnD,6CAA6C;QAC7C,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC;IACxB,CAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;IAEF,MAAM,WAAW,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE;;QACjC,IAAI,CAAC,QAAQ;YAAE,MAAA,QAAQ,CAAC,OAAO,0CAAE,KAAK,EAAE,CAAC;IAC7C,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,MAAM,aAAa,GAAG,IAAA,mBAAW,EAC7B,CAAC,CAAsB,EAAE,EAAE;QACvB,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;YACrC,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,WAAW,EAAE,CAAC;QAClB,CAAC;IACL,CAAC,EACD,CAAC,WAAW,CAAC,CAChB,CAAC;IAEF,OAAO,CACH,iCACI,SAAS,EAAE,CAAC,CAAC,EAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAC,EAAE,SAAS,CAAC,EACzD,UAAU,EAAE,cAAc,EAC1B,WAAW,EAAE,eAAe,EAC5B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mBACZ,QAAQ,aAEvB,kCACI,GAAG,EAAE,QAAQ,EACb,IAAI,EAAC,MAAM,EACX,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,EACrB,QAAQ,EAAE,CAAC,CAAC,wBAEd,EACF,uBAAC,YAAI,IAAC,IAAI,EAAE,qBAAa,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,GAAI,EAC7D,uBAAC,YAAI,IAAC,OAAO,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,YACvC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,CAAC,CAAC,OAAO,CAAC,GACjB,EACN,IAAI,IAAI,CACL,uBAAC,YAAI,IAAC,OAAO,EAAC,QAAQ,EAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,YACtC,IAAI,GACF,CACV,IACC,CACT,CAAC;AACN,CAAC,CAAC;AAtGW,QAAA,YAAY,gBAsGvB","sourcesContent":["import React, {useCallback, useRef, useState} from 'react';\n\nimport {ArrowUpToLine} from '@gravity-ui/icons';\nimport {Icon, Text} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\n\nimport {i18n} from './i18n';\n\nimport './FileDropZone.scss';\n\nconst b = block('file-drop-zone');\n\nexport type FileDropZoneProps = {\n accept?: string;\n multiple?: boolean;\n disabled?: boolean;\n onAdd: (files: File[]) => void;\n label?: string;\n hint?: string;\n className?: string;\n};\n\n/**\n * FileDropZone provides a drag-and-drop area plus a hidden file input for picking files.\n * Uses native HTML5 DnD — no external dependencies.\n */\nexport const FileDropZone = ({\n accept,\n multiple = true,\n disabled = false,\n onAdd,\n label,\n hint,\n className,\n}: FileDropZoneProps) => {\n const {t} = i18n.useTranslation();\n const [isDragging, setIsDragging] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleFiles = useCallback(\n (fileList: FileList | null) => {\n if (!fileList || fileList.length === 0) return;\n const files = Array.from(fileList);\n onAdd(files);\n },\n [onAdd],\n );\n\n const handleDragOver = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n if (!disabled) setIsDragging(true);\n },\n [disabled],\n );\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n if (disabled) return;\n handleFiles(e.dataTransfer.files);\n },\n [disabled, handleFiles],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n handleFiles(e.target.files);\n // Reset input so the same file can be picked again\n // eslint-disable-next-line no-param-reassign\n e.target.value = '';\n },\n [handleFiles],\n );\n\n const handleClick = useCallback(() => {\n if (!disabled) inputRef.current?.click();\n }, [disabled]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleClick();\n }\n },\n [handleClick],\n );\n\n return (\n <div\n className={b({dragging: isDragging, disabled}, className)}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled}\n >\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n onChange={handleInputChange}\n className={b('input')}\n tabIndex={-1}\n aria-hidden\n />\n <Icon data={ArrowUpToLine} size={24} className={b('icon')} />\n <Text variant=\"body-2\" className={b('label')}>\n {label ?? t('label')}\n </Text>\n {hint && (\n <Text variant=\"body-1\" className={b('hint')}>\n {hint}\n </Text>\n )}\n </div>\n );\n};\n"]}
|
|
@@ -20,7 +20,8 @@ function formatSize(bytes) {
|
|
|
20
20
|
* FileItem displays a single file row with icon, name, optional size, status indicator, and remove button.
|
|
21
21
|
*/
|
|
22
22
|
const FileItem = ({ name, size, status, mimeType, previewUrl, disabled, onRemove, className, }) => {
|
|
23
|
-
|
|
23
|
+
const { t } = i18n_1.i18n.useTranslation();
|
|
24
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: b({ status, disabled }, className), children: [(0, jsx_runtime_1.jsx)("div", { className: b('icon'), children: previewUrl ? ((0, jsx_runtime_1.jsx)("img", { src: previewUrl, alt: name, className: b('preview') })) : ((0, jsx_runtime_1.jsx)(FileIcon_1.FileIcon, { mimeType: mimeType, fileName: name, size: "m" })) }), (0, jsx_runtime_1.jsxs)("div", { className: b('info'), children: [(0, jsx_runtime_1.jsx)("span", { className: b('name'), title: name, children: name }), size !== undefined && (0, jsx_runtime_1.jsx)("span", { className: b('size'), children: formatSize(size) })] }), (0, jsx_runtime_1.jsxs)("div", { className: b('status'), children: [status === 'loading' && (0, jsx_runtime_1.jsx)(uikit_1.Spin, { size: "xs" }), status === 'success' && ((0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.CircleCheck, size: 16, className: b('status-icon', { success: true }) })), status === 'error' && ((0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.CircleXmark, size: 16, className: b('status-icon', { error: true }) }))] }), onRemove && ((0, jsx_runtime_1.jsx)("button", { type: "button", className: b('remove'), onClick: onRemove, disabled: disabled, "aria-label": t('remove-button-label'), children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Xmark, size: 12 }) }))] }));
|
|
24
25
|
};
|
|
25
26
|
exports.FileItem = FileItem;
|
|
26
27
|
//# sourceMappingURL=FileItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileItem.js","sourceRoot":"../../../../../src","sources":["components/molecules/FileItem/FileItem.tsx"],"names":[],"mappings":";;;;AAAA,6CAAkE;AAClE,6CAA6C;AAE7C,6CAAwC;AACxC,4DAA8C;AAE9C,0CAA4B;AAE5B,0BAAyB;AAEzB,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,WAAW,CAAC,CAAC;AAgB7B,SAAS,UAAU,CAAC,KAAa;IAC7B,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,CAAC;IACtC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AACtD,CAAC;AAED;;GAEG;AACI,MAAM,QAAQ,GAAG,CAAC,EACrB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,SAAS,GACG,EAAE,EAAE;IAChB,OAAO,CACH,iCAAK,SAAS,EAAE,CAAC,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAC,EAAE,SAAS,CAAC,aAC5C,gCAAK,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,YACpB,UAAU,CAAC,CAAC,CAAC,CACV,gCAAK,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,GAAI,CAC/D,CAAC,CAAC,CAAC,CACA,uBAAC,mBAAQ,IAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAC,GAAG,GAAG,CAC5D,GACC,EACN,iCAAK,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,aACrB,iCAAM,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,YAClC,IAAI,GACF,EACN,IAAI,KAAK,SAAS,IAAI,iCAAM,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,YAAG,UAAU,CAAC,IAAI,CAAC,GAAQ,IAC1E,EACN,iCAAK,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,aACtB,MAAM,KAAK,SAAS,IAAI,uBAAC,YAAI,IAAC,IAAI,EAAC,IAAI,GAAG,EAC1C,MAAM,KAAK,SAAS,IAAI,CACrB,uBAAC,YAAI,IACD,IAAI,EAAE,mBAAW,EACjB,IAAI,EAAE,EAAE,EACR,SAAS,EAAE,CAAC,CAAC,aAAa,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,GAC9C,CACL,EACA,MAAM,KAAK,OAAO,IAAI,CACnB,uBAAC,YAAI,IACD,IAAI,EAAE,mBAAW,EACjB,IAAI,EAAE,EAAE,EACR,SAAS,EAAE,CAAC,CAAC,aAAa,EAAE,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC,GAC5C,CACL,IACC,EACL,QAAQ,IAAI,CACT,mCACI,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,EACtB,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,QAAQ,gBACN,
|
|
1
|
+
{"version":3,"file":"FileItem.js","sourceRoot":"../../../../../src","sources":["components/molecules/FileItem/FileItem.tsx"],"names":[],"mappings":";;;;AAAA,6CAAkE;AAClE,6CAA6C;AAE7C,6CAAwC;AACxC,4DAA8C;AAE9C,0CAA4B;AAE5B,0BAAyB;AAEzB,MAAM,CAAC,GAAG,IAAA,UAAK,EAAC,WAAW,CAAC,CAAC;AAgB7B,SAAS,UAAU,CAAC,KAAa;IAC7B,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,IAAI,CAAC;IACtC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AACtD,CAAC;AAED;;GAEG;AACI,MAAM,QAAQ,GAAG,CAAC,EACrB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,SAAS,GACG,EAAE,EAAE;IAChB,MAAM,EAAC,CAAC,EAAC,GAAG,WAAI,CAAC,cAAc,EAAE,CAAC;IAClC,OAAO,CACH,iCAAK,SAAS,EAAE,CAAC,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAC,EAAE,SAAS,CAAC,aAC5C,gCAAK,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,YACpB,UAAU,CAAC,CAAC,CAAC,CACV,gCAAK,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,GAAI,CAC/D,CAAC,CAAC,CAAC,CACA,uBAAC,mBAAQ,IAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAC,GAAG,GAAG,CAC5D,GACC,EACN,iCAAK,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,aACrB,iCAAM,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,YAClC,IAAI,GACF,EACN,IAAI,KAAK,SAAS,IAAI,iCAAM,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,YAAG,UAAU,CAAC,IAAI,CAAC,GAAQ,IAC1E,EACN,iCAAK,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,aACtB,MAAM,KAAK,SAAS,IAAI,uBAAC,YAAI,IAAC,IAAI,EAAC,IAAI,GAAG,EAC1C,MAAM,KAAK,SAAS,IAAI,CACrB,uBAAC,YAAI,IACD,IAAI,EAAE,mBAAW,EACjB,IAAI,EAAE,EAAE,EACR,SAAS,EAAE,CAAC,CAAC,aAAa,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,GAC9C,CACL,EACA,MAAM,KAAK,OAAO,IAAI,CACnB,uBAAC,YAAI,IACD,IAAI,EAAE,mBAAW,EACjB,IAAI,EAAE,EAAE,EACR,SAAS,EAAE,CAAC,CAAC,aAAa,EAAE,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC,GAC5C,CACL,IACC,EACL,QAAQ,IAAI,CACT,mCACI,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,EACtB,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,QAAQ,gBACN,CAAC,CAAC,qBAAqB,CAAC,YAEpC,uBAAC,YAAI,IAAC,IAAI,EAAE,aAAK,EAAE,IAAI,EAAE,EAAE,GAAI,GAC1B,CACZ,IACC,CACT,CAAC;AACN,CAAC,CAAC;AAxDW,QAAA,QAAQ,YAwDnB","sourcesContent":["import {CircleCheck, CircleXmark, Xmark} from '@gravity-ui/icons';\nimport {Icon, Spin} from '@gravity-ui/uikit';\n\nimport {block} from '../../../utils/cn';\nimport {FileIcon} from '../../atoms/FileIcon';\n\nimport {i18n} from './i18n';\n\nimport './FileItem.scss';\n\nconst b = block('file-item');\n\nexport type FileItemStatus = 'loading' | 'success' | 'error';\n\nexport type FileItemProps = {\n name: string;\n size?: number;\n status?: FileItemStatus;\n mimeType?: string;\n /** Image preview URL (blob URL or data URL). Shown instead of file icon when provided. */\n previewUrl?: string;\n disabled?: boolean;\n onRemove?: () => void;\n className?: string;\n};\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/**\n * FileItem displays a single file row with icon, name, optional size, status indicator, and remove button.\n */\nexport const FileItem = ({\n name,\n size,\n status,\n mimeType,\n previewUrl,\n disabled,\n onRemove,\n className,\n}: FileItemProps) => {\n const {t} = i18n.useTranslation();\n return (\n <div className={b({status, disabled}, className)}>\n <div className={b('icon')}>\n {previewUrl ? (\n <img src={previewUrl} alt={name} className={b('preview')} />\n ) : (\n <FileIcon mimeType={mimeType} fileName={name} size=\"m\" />\n )}\n </div>\n <div className={b('info')}>\n <span className={b('name')} title={name}>\n {name}\n </span>\n {size !== undefined && <span className={b('size')}>{formatSize(size)}</span>}\n </div>\n <div className={b('status')}>\n {status === 'loading' && <Spin size=\"xs\" />}\n {status === 'success' && (\n <Icon\n data={CircleCheck}\n size={16}\n className={b('status-icon', {success: true})}\n />\n )}\n {status === 'error' && (\n <Icon\n data={CircleXmark}\n size={16}\n className={b('status-icon', {error: true})}\n />\n )}\n </div>\n {onRemove && (\n <button\n type=\"button\"\n className={b('remove')}\n onClick={onRemove}\n disabled={disabled}\n aria-label={t('remove-button-label')}\n >\n <Icon data={Xmark} size={12} />\n </button>\n )}\n </div>\n );\n};\n"]}
|