@cloud-ru/uikit-product-claudia 1.8.4 → 1.9.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.
- package/CHANGELOG.md +20 -0
- package/README.md +21 -0
- package/dist/cjs/components/RateForm/RateForm.d.ts +45 -0
- package/dist/cjs/components/RateForm/RateForm.js +27 -0
- package/dist/cjs/components/RateForm/components/FieldSubmitButton.d.ts +15 -0
- package/dist/cjs/components/RateForm/components/FieldSubmitButton.js +13 -0
- package/dist/cjs/components/RateForm/components/TextFieldWithAccordionMessage/TextFieldWithAccordionMessage.d.ts +19 -0
- package/dist/cjs/components/RateForm/components/TextFieldWithAccordionMessage/TextFieldWithAccordionMessage.js +56 -0
- package/dist/cjs/components/RateForm/components/TextFieldWithAccordionMessage/index.d.ts +1 -0
- package/dist/cjs/components/RateForm/components/TextFieldWithAccordionMessage/index.js +17 -0
- package/dist/cjs/components/RateForm/components/TextFieldWithAccordionMessage/styles.module.css +62 -0
- package/dist/cjs/components/RateForm/constants.d.ts +2 -0
- package/dist/cjs/components/RateForm/constants.js +5 -0
- package/dist/cjs/components/RateForm/index.d.ts +3 -0
- package/dist/cjs/components/RateForm/index.js +21 -0
- package/dist/cjs/components/RateForm/styles.module.css +127 -0
- package/dist/cjs/components/RateForm/types.d.ts +8 -0
- package/dist/cjs/components/RateForm/types.js +2 -0
- package/dist/cjs/components/SshField/SshField.d.ts +1 -1
- package/dist/cjs/components/SshField/components/MobileFieldAi/MobileFieldAi.d.ts +1 -1
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/index.js +1 -0
- package/dist/esm/components/RateForm/RateForm.d.ts +45 -0
- package/dist/esm/components/RateForm/RateForm.js +21 -0
- package/dist/esm/components/RateForm/components/FieldSubmitButton.d.ts +15 -0
- package/dist/esm/components/RateForm/components/FieldSubmitButton.js +10 -0
- package/dist/esm/components/RateForm/components/TextFieldWithAccordionMessage/TextFieldWithAccordionMessage.d.ts +19 -0
- package/dist/esm/components/RateForm/components/TextFieldWithAccordionMessage/TextFieldWithAccordionMessage.js +50 -0
- package/dist/esm/components/RateForm/components/TextFieldWithAccordionMessage/index.d.ts +1 -0
- package/dist/esm/components/RateForm/components/TextFieldWithAccordionMessage/index.js +1 -0
- package/dist/esm/components/RateForm/components/TextFieldWithAccordionMessage/styles.module.css +62 -0
- package/dist/esm/components/RateForm/constants.d.ts +2 -0
- package/dist/esm/components/RateForm/constants.js +2 -0
- package/dist/esm/components/RateForm/index.d.ts +3 -0
- package/dist/esm/components/RateForm/index.js +2 -0
- package/dist/esm/components/RateForm/styles.module.css +127 -0
- package/dist/esm/components/RateForm/types.d.ts +8 -0
- package/dist/esm/components/RateForm/types.js +1 -0
- package/dist/esm/components/SshField/SshField.d.ts +1 -1
- package/dist/esm/components/SshField/components/MobileFieldAi/MobileFieldAi.d.ts +1 -1
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/index.js +1 -0
- package/package.json +6 -3
- package/src/components/RateForm/RateForm.tsx +136 -0
- package/src/components/RateForm/components/FieldSubmitButton.tsx +45 -0
- package/src/components/RateForm/components/TextFieldWithAccordionMessage/TextFieldWithAccordionMessage.tsx +147 -0
- package/src/components/RateForm/components/TextFieldWithAccordionMessage/index.ts +1 -0
- package/src/components/RateForm/components/TextFieldWithAccordionMessage/styles.module.scss +68 -0
- package/src/components/RateForm/constants.ts +3 -0
- package/src/components/RateForm/index.ts +3 -0
- package/src/components/RateForm/styles.module.scss +143 -0
- package/src/components/RateForm/types.ts +8 -0
- package/src/components/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 1.9.1 (2025-12-03)
|
|
7
|
+
|
|
8
|
+
### Only dependencies have been changed
|
|
9
|
+
* [@cloud-ru/uikit-product-mobile-fields@0.12.0](https://gitverse.ru/cloud-ru-tech/uikit-product/-/blob/master/packages/mobile-fields/CHANGELOG.md)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# 1.9.0 (2025-12-01)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **AINFR-4454:** new component rate block for claudia ([234e89a](https://gitverse.ru/cloud-ru-tech/uikit-product/commits/234e89accd3018b17979ccd3bab1944ccb30806e))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
6
26
|
## 1.8.4 (2025-11-28)
|
|
7
27
|
|
|
8
28
|
### Only dependencies have been changed
|
package/README.md
CHANGED
|
@@ -107,6 +107,27 @@
|
|
|
107
107
|
| contentClassName | `string` | - | |
|
|
108
108
|
| onActionClick | `() => void` | - | |
|
|
109
109
|
| className | `string` | - | CSS-класс |
|
|
110
|
+
## RateForm
|
|
111
|
+
### Props
|
|
112
|
+
| name | type | default value | description |
|
|
113
|
+
|------|------|---------------|-------------|
|
|
114
|
+
| grades* | `Grade[]` | - | Массив доступных оценок |
|
|
115
|
+
| selectedGrade | `Grade` | - | Текущая выбранная оценка |
|
|
116
|
+
| title | `string` | - | Заголовок формы (показывается когда оценка не выбрана) |
|
|
117
|
+
| ratedLabel | `string` | - | Текст "Вы поставили" |
|
|
118
|
+
| ratedSubtitle | `string` | - | Подзаголовок после выбора оценки |
|
|
119
|
+
| comment | `string` | - | Комментарий пользователя |
|
|
120
|
+
| isLoading | `boolean` | - | Состояние загрузки |
|
|
121
|
+
| onGradeClick | `(grade: Grade) => void` | - | Callback при клике на оценку |
|
|
122
|
+
| onClose | `() => void` | - | Callback при закрытии формы |
|
|
123
|
+
| onCommentChange | `(comment: string) => void` | - | Callback при изменении комментария |
|
|
124
|
+
| onCommentSubmit | `(comment: string) => void` | - | Callback при отправке комментария |
|
|
125
|
+
| commentPlaceholder | `string` | - | Плейсхолдер для поля комментария |
|
|
126
|
+
| showCloseButton | `boolean` | true | Показывать ли кнопку закрытия |
|
|
127
|
+
| className | `string` | - | Дополнительный className |
|
|
128
|
+
| isTouchDevice | `boolean` | - | Является ли устройство тач-девайсом |
|
|
129
|
+
| submitTooltipText | `string` | - | Текст тултипа для кнопки отправки |
|
|
130
|
+
| renderTextField | `(props: { comment?: string; grade: Grade; placeholder?: string; onChange?: (value: string) => void; onSubmit?: (value: string) => void; }) => ReactNode` | - | Render prop для кастомного отображения текстового поля |
|
|
110
131
|
## IconGiga
|
|
111
132
|
### Props
|
|
112
133
|
| name | type | default value | description |
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Grade } from './types';
|
|
3
|
+
export type RateFormProps = {
|
|
4
|
+
/** Массив доступных оценок */
|
|
5
|
+
grades: Grade[];
|
|
6
|
+
/** Текущая выбранная оценка */
|
|
7
|
+
selectedGrade?: Grade | null;
|
|
8
|
+
/** Заголовок формы (показывается когда оценка не выбрана) */
|
|
9
|
+
title?: string;
|
|
10
|
+
/** Текст "Вы поставили" */
|
|
11
|
+
ratedLabel?: string;
|
|
12
|
+
/** Подзаголовок после выбора оценки */
|
|
13
|
+
ratedSubtitle?: string;
|
|
14
|
+
/** Комментарий пользователя */
|
|
15
|
+
comment?: string;
|
|
16
|
+
/** Состояние загрузки */
|
|
17
|
+
isLoading?: boolean;
|
|
18
|
+
/** Callback при клике на оценку */
|
|
19
|
+
onGradeClick?: (grade: Grade) => void;
|
|
20
|
+
/** Callback при закрытии формы */
|
|
21
|
+
onClose?: () => void;
|
|
22
|
+
/** Callback при изменении комментария */
|
|
23
|
+
onCommentChange?: (comment: string) => void;
|
|
24
|
+
/** Callback при отправке комментария */
|
|
25
|
+
onCommentSubmit?: (comment: string) => void;
|
|
26
|
+
/** Плейсхолдер для поля комментария */
|
|
27
|
+
commentPlaceholder?: string;
|
|
28
|
+
/** Показывать ли кнопку закрытия */
|
|
29
|
+
showCloseButton?: boolean;
|
|
30
|
+
/** Дополнительный className */
|
|
31
|
+
className?: string;
|
|
32
|
+
/** Является ли устройство тач-девайсом */
|
|
33
|
+
isTouchDevice?: boolean;
|
|
34
|
+
/** Текст тултипа для кнопки отправки */
|
|
35
|
+
submitTooltipText?: string;
|
|
36
|
+
/** Render prop для кастомного отображения текстового поля */
|
|
37
|
+
renderTextField?: (props: {
|
|
38
|
+
comment?: string;
|
|
39
|
+
grade: Grade;
|
|
40
|
+
placeholder?: string;
|
|
41
|
+
onChange?: (value: string) => void;
|
|
42
|
+
onSubmit?: (value: string) => void;
|
|
43
|
+
}) => ReactNode;
|
|
44
|
+
};
|
|
45
|
+
export declare function RateForm({ grades, selectedGrade, title, ratedLabel, ratedSubtitle, comment, isLoading, onGradeClick, onClose, onCommentChange, onCommentSubmit, commentPlaceholder, showCloseButton, className, isTouchDevice, submitTooltipText, renderTextField, }: RateFormProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RateForm = RateForm;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
9
|
+
const figma_tokens_cloud_platform_1 = require("@sbercloud/figma-tokens-cloud-platform");
|
|
10
|
+
const icons_1 = require("@snack-uikit/icons");
|
|
11
|
+
const loaders_1 = require("@snack-uikit/loaders");
|
|
12
|
+
const typography_1 = require("@snack-uikit/typography");
|
|
13
|
+
const TextFieldWithAccordionMessage_1 = require("./components/TextFieldWithAccordionMessage");
|
|
14
|
+
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
15
|
+
function RateForm({ grades, selectedGrade, title, ratedLabel, ratedSubtitle, comment, isLoading = false, onGradeClick, onClose, onCommentChange, onCommentSubmit, commentPlaceholder, showCloseButton = true, className, isTouchDevice = false, submitTooltipText, renderTextField, }) {
|
|
16
|
+
if (isLoading) {
|
|
17
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.feedbackFormLoading, className), "data-loading": true, children: (0, jsx_runtime_1.jsx)(loaders_1.Spinner, { size: 's' }) }));
|
|
18
|
+
}
|
|
19
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.feedbackForm, className), "data-touch": isTouchDevice || undefined, children: [selectedGrade ? ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.ratingContainer, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.ratingTitle, children: [ratedLabel && (0, jsx_runtime_1.jsx)(typography_1.Typography.SansLabelL, { children: ratedLabel }), (0, jsx_runtime_1.jsx)(typography_1.Typography.SansTitleL, { className: styles_module_scss_1.default.ratingIcon, children: selectedGrade.icon })] }), ratedSubtitle && ((0, jsx_runtime_1.jsx)(typography_1.Typography.SansBodyM, { className: styles_module_scss_1.default.ratingSubtitle, children: ratedSubtitle }))] })) : (title && (0, jsx_runtime_1.jsx)(typography_1.Typography.SansLabelL, { className: styles_module_scss_1.default.feedbackFormTitle, children: title })), !selectedGrade && ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.gradeBlock, children: grades.map(grade => ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.grade, onClick: () => onGradeClick === null || onGradeClick === void 0 ? void 0 : onGradeClick(grade), role: 'presentation', children: [(0, jsx_runtime_1.jsx)(typography_1.Typography.SansHeadlineL, { className: styles_module_scss_1.default.gradeIcon, children: grade.icon }), (0, jsx_runtime_1.jsx)(typography_1.Typography.LightLabelS, { className: styles_module_scss_1.default.description, children: grade.description })] }, grade.id))) })), selectedGrade &&
|
|
20
|
+
(renderTextField ? (renderTextField({
|
|
21
|
+
comment,
|
|
22
|
+
grade: selectedGrade,
|
|
23
|
+
placeholder: commentPlaceholder,
|
|
24
|
+
onChange: onCommentChange,
|
|
25
|
+
onSubmit: onCommentSubmit,
|
|
26
|
+
})) : ((0, jsx_runtime_1.jsx)(TextFieldWithAccordionMessage_1.TextFieldWithAccordionMessage, { comment: comment, placeholder: commentPlaceholder, onChange: onCommentChange, onSubmit: onCommentSubmit, isTouchDevice: isTouchDevice, submitTooltipText: submitTooltipText }))), showCloseButton && selectedGrade && ((0, jsx_runtime_1.jsx)(icons_1.CrossSVG, { className: styles_module_scss_1.default.closeIcon, size: 24, color: figma_tokens_cloud_platform_1.themeVars.sys.neutral.textSupport, onClick: onClose }))] }));
|
|
27
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type FieldSubmitButtonProps = {
|
|
2
|
+
/** Активна ли кнопка */
|
|
3
|
+
active: boolean;
|
|
4
|
+
/** Callback при клике */
|
|
5
|
+
onClick: () => void;
|
|
6
|
+
/** Размер кнопки */
|
|
7
|
+
size?: 'xs' | 's';
|
|
8
|
+
/** Дополнительный className */
|
|
9
|
+
className?: string;
|
|
10
|
+
/** Кнопка на всю ширину */
|
|
11
|
+
fullWidth?: boolean;
|
|
12
|
+
/** Текст тултипа */
|
|
13
|
+
tooltipText?: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function FieldSubmitButton({ active, onClick, size, className, fullWidth, tooltipText, }: FieldSubmitButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FieldSubmitButton = FieldSubmitButton;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const uikit_product_icons_1 = require("@cloud-ru/uikit-product-icons");
|
|
6
|
+
const button_1 = require("@snack-uikit/button");
|
|
7
|
+
const tooltip_1 = require("@snack-uikit/tooltip");
|
|
8
|
+
function FieldSubmitButton({ active, onClick, size = 'xs', className, fullWidth, tooltipText, }) {
|
|
9
|
+
if (active) {
|
|
10
|
+
return ((0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { tip: tooltipText, hoverDelayOpen: 600, open: tooltipText ? undefined : false, children: (0, jsx_runtime_1.jsx)(button_1.ButtonTonal, { fullWidth: fullWidth, icon: (0, jsx_runtime_1.jsx)(uikit_product_icons_1.ArrowUpSVG, {}), size: size, appearance: 'primary', type: 'button', onClick: onClick, className: className }) }));
|
|
11
|
+
}
|
|
12
|
+
return (0, jsx_runtime_1.jsx)(button_1.ButtonTonal, { icon: (0, jsx_runtime_1.jsx)(uikit_product_icons_1.ArrowUpSVG, {}), size: size, disabled: true, className: className, fullWidth: fullWidth });
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type TextFieldWithAccordionMessageProps = {
|
|
2
|
+
/** Существующий комментарий */
|
|
3
|
+
comment?: string;
|
|
4
|
+
/** Плейсхолдер для поля ввода */
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
/** Callback при изменении текста */
|
|
7
|
+
onChange?: (value: string) => void;
|
|
8
|
+
/** Callback при отправке */
|
|
9
|
+
onSubmit?: (value: string) => void;
|
|
10
|
+
/** Максимальная длина сообщения */
|
|
11
|
+
maxLength?: number;
|
|
12
|
+
/** Является ли устройство тач-девайсом */
|
|
13
|
+
isTouchDevice?: boolean;
|
|
14
|
+
/** Показывать ли тултип на кнопке отправки */
|
|
15
|
+
showSubmitTooltip?: boolean;
|
|
16
|
+
/** Текст тултипа для кнопки отправки */
|
|
17
|
+
submitTooltipText?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function TextFieldWithAccordionMessage({ comment, placeholder, onChange, onSubmit, maxLength, isTouchDevice, showSubmitTooltip, submitTooltipText, }: TextFieldWithAccordionMessageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TextFieldWithAccordionMessage = TextFieldWithAccordionMessage;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const figma_tokens_cloud_platform_1 = require("@sbercloud/figma-tokens-cloud-platform");
|
|
10
|
+
const uikit_product_icons_1 = require("@cloud-ru/uikit-product-icons");
|
|
11
|
+
const divider_1 = require("@snack-uikit/divider");
|
|
12
|
+
const fields_1 = require("@snack-uikit/fields");
|
|
13
|
+
const typography_1 = require("@snack-uikit/typography");
|
|
14
|
+
const utils_1 = require("@snack-uikit/utils");
|
|
15
|
+
const constants_1 = require("../../constants");
|
|
16
|
+
const FieldSubmitButton_1 = require("../FieldSubmitButton");
|
|
17
|
+
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
18
|
+
function TextFieldWithAccordionMessage({ comment, placeholder, onChange, onSubmit, maxLength = constants_1.MESSAGE_MAX_LENGTH, isTouchDevice = false, showSubmitTooltip = true, submitTooltipText, }) {
|
|
19
|
+
const textRef = (0, react_1.useRef)(null);
|
|
20
|
+
const [isMultiLine, setIsMultiLine] = (0, react_1.useState)(false);
|
|
21
|
+
const [isExpanded, setIsExpanded] = (0, react_1.useState)(false);
|
|
22
|
+
const [message, setMessage] = (0, react_1.useState)(comment || '');
|
|
23
|
+
const isValid = typeof message === 'string' && message.trim().length > 0;
|
|
24
|
+
(0, utils_1.useLayoutEffect)(() => {
|
|
25
|
+
if (!comment)
|
|
26
|
+
return;
|
|
27
|
+
setMessage(comment);
|
|
28
|
+
const timeout = setTimeout(() => {
|
|
29
|
+
if (textRef.current) {
|
|
30
|
+
const textHeight = textRef.current.scrollHeight;
|
|
31
|
+
setIsMultiLine(textHeight > constants_1.STATIC_LINE_HEIGHT * 2 + 5);
|
|
32
|
+
}
|
|
33
|
+
}, 0);
|
|
34
|
+
return () => clearTimeout(timeout);
|
|
35
|
+
}, [comment]);
|
|
36
|
+
const handleClickMessage = () => {
|
|
37
|
+
setIsExpanded(!isExpanded);
|
|
38
|
+
};
|
|
39
|
+
const handleChangeMessage = (value) => {
|
|
40
|
+
const truncatedValue = value.slice(0, maxLength);
|
|
41
|
+
setMessage(truncatedValue);
|
|
42
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(truncatedValue);
|
|
43
|
+
};
|
|
44
|
+
const handleSubmit = () => {
|
|
45
|
+
if (isValid) {
|
|
46
|
+
onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(message);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const handleKeyDown = event => {
|
|
50
|
+
if (event.key === 'Enter' && !event.shiftKey && !isTouchDevice) {
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
handleSubmit();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [comment && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.comment, children: [(0, jsx_runtime_1.jsx)(divider_1.Divider, {}), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.container, "data-clickable": isMultiLine || undefined, onClick: isMultiLine ? handleClickMessage : undefined, role: isMultiLine ? 'button' : undefined, children: [(0, jsx_runtime_1.jsx)("div", { ref: textRef, className: styles_module_scss_1.default.textContainer, "data-collapsed": (isMultiLine && !isExpanded) || undefined, children: (0, jsx_runtime_1.jsx)(typography_1.Typography.LightBodyS, { className: styles_module_scss_1.default.text, children: message }) }), isMultiLine && ((0, jsx_runtime_1.jsx)(uikit_product_icons_1.ChevronUpInterfaceSVG, { color: figma_tokens_cloud_platform_1.themeVars.sys.neutral.textLight, className: styles_module_scss_1.default.textIcon, "data-rotated": !isExpanded || undefined, size: 20 }))] })] })), !comment && ((0, jsx_runtime_1.jsx)(fields_1.FieldTextArea, { value: message, size: 'm', minRows: 1, maxRows: 4, placeholder: placeholder, onChange: handleChangeMessage, onKeyDown: handleKeyDown, spellCheck: true, footer: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.actionsFooter, children: (0, jsx_runtime_1.jsx)(FieldSubmitButton_1.FieldSubmitButton, { tooltipText: showSubmitTooltip && !isTouchDevice ? submitTooltipText : undefined, className: styles_module_scss_1.default.buttonRight, "data-mobile": isTouchDevice || undefined, active: isValid, onClick: handleSubmit, size: isTouchDevice ? 's' : 'xs' }) }), showClearButton: false }))] }));
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TextFieldWithAccordionMessage';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./TextFieldWithAccordionMessage"), exports);
|
package/dist/cjs/components/RateForm/components/TextFieldWithAccordionMessage/styles.module.css
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
.actionsFooter{
|
|
2
|
+
display:flex;
|
|
3
|
+
flex-direction:row;
|
|
4
|
+
justify-content:flex-end;
|
|
5
|
+
align-items:center;
|
|
6
|
+
width:100%;
|
|
7
|
+
padding:0 10px 9px 0;
|
|
8
|
+
cursor:text;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.textIcon{
|
|
12
|
+
min-width:20px;
|
|
13
|
+
min-height:20px;
|
|
14
|
+
transition:transform 0.2s ease;
|
|
15
|
+
}
|
|
16
|
+
.textIcon[data-rotated]{
|
|
17
|
+
transform:rotate(180deg);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.textContainer{
|
|
21
|
+
flex:1;
|
|
22
|
+
min-width:0;
|
|
23
|
+
line-height:16px;
|
|
24
|
+
}
|
|
25
|
+
.textContainer[data-collapsed]{
|
|
26
|
+
display:-webkit-box;
|
|
27
|
+
-webkit-box-orient:vertical;
|
|
28
|
+
-webkit-line-clamp:2;
|
|
29
|
+
line-clamp:2;
|
|
30
|
+
overflow:hidden;
|
|
31
|
+
text-overflow:ellipsis;
|
|
32
|
+
line-height:16px;
|
|
33
|
+
max-height:32px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.comment{
|
|
37
|
+
width:100%;
|
|
38
|
+
display:flex;
|
|
39
|
+
flex-direction:column;
|
|
40
|
+
justify-content:center;
|
|
41
|
+
align-items:flex-start;
|
|
42
|
+
gap:16px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.text{
|
|
46
|
+
color:var(--sys-neutral-text-light, #8b8e9b);
|
|
47
|
+
line-height:16px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.container{
|
|
51
|
+
display:flex;
|
|
52
|
+
flex-direction:row;
|
|
53
|
+
align-items:flex-end;
|
|
54
|
+
gap:4px;
|
|
55
|
+
width:100%;
|
|
56
|
+
}
|
|
57
|
+
.container svg path{
|
|
58
|
+
fill:var(--sys-neutral-text-light, #8b8e9b);
|
|
59
|
+
}
|
|
60
|
+
.container[data-clickable]{
|
|
61
|
+
cursor:pointer;
|
|
62
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.STATIC_LINE_HEIGHT = exports.MESSAGE_MAX_LENGTH = void 0;
|
|
18
|
+
__exportStar(require("./RateForm"), exports);
|
|
19
|
+
var constants_1 = require("./constants");
|
|
20
|
+
Object.defineProperty(exports, "MESSAGE_MAX_LENGTH", { enumerable: true, get: function () { return constants_1.MESSAGE_MAX_LENGTH; } });
|
|
21
|
+
Object.defineProperty(exports, "STATIC_LINE_HEIGHT", { enumerable: true, get: function () { return constants_1.STATIC_LINE_HEIGHT; } });
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
.closeIcon{
|
|
2
|
+
cursor:pointer;
|
|
3
|
+
position:absolute;
|
|
4
|
+
top:8px;
|
|
5
|
+
right:8px;
|
|
6
|
+
opacity:0;
|
|
7
|
+
transition:opacity 0.2s ease;
|
|
8
|
+
will-change:opacity;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.feedbackForm{
|
|
12
|
+
position:relative;
|
|
13
|
+
display:flex;
|
|
14
|
+
flex-direction:column;
|
|
15
|
+
align-items:center;
|
|
16
|
+
justify-content:center;
|
|
17
|
+
width:296px;
|
|
18
|
+
background-color:var(--sys-neutral-background2-level, #ffffff);
|
|
19
|
+
border:1px solid var(--sys-neutral-decor-default, #dde0ea);
|
|
20
|
+
border-radius:8px;
|
|
21
|
+
padding:24px;
|
|
22
|
+
gap:16px;
|
|
23
|
+
}
|
|
24
|
+
.feedbackForm:hover .closeIcon{
|
|
25
|
+
opacity:1;
|
|
26
|
+
}
|
|
27
|
+
.feedbackForm[data-touch] .closeIcon{
|
|
28
|
+
opacity:1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.feedbackFormTitle{
|
|
32
|
+
color:var(--sys-neutral-text-main, #41424e);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.feedbackFormLoading{
|
|
36
|
+
display:flex;
|
|
37
|
+
flex-direction:column;
|
|
38
|
+
align-items:center;
|
|
39
|
+
justify-content:center;
|
|
40
|
+
width:296px;
|
|
41
|
+
height:141px;
|
|
42
|
+
background-color:var(--sys-neutral-background2-level, #ffffff);
|
|
43
|
+
border:1px solid var(--sys-neutral-decor-default, #dde0ea);
|
|
44
|
+
border-radius:8px;
|
|
45
|
+
padding:24px;
|
|
46
|
+
}
|
|
47
|
+
.feedbackFormLoading[data-loading]{
|
|
48
|
+
cursor:wait;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.gradeBlock{
|
|
52
|
+
display:flex;
|
|
53
|
+
flex-direction:row;
|
|
54
|
+
align-items:center;
|
|
55
|
+
justify-content:center;
|
|
56
|
+
gap:14px;
|
|
57
|
+
position:relative;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.description{
|
|
61
|
+
color:var(--sys-neutral-text-light, #8b8e9b);
|
|
62
|
+
position:absolute;
|
|
63
|
+
bottom:-12px;
|
|
64
|
+
opacity:0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.grade{
|
|
68
|
+
cursor:pointer;
|
|
69
|
+
display:flex;
|
|
70
|
+
flex-direction:column;
|
|
71
|
+
justify-content:center;
|
|
72
|
+
align-items:center;
|
|
73
|
+
transition:all 0.2s ease;
|
|
74
|
+
height:40px;
|
|
75
|
+
width:36px;
|
|
76
|
+
}
|
|
77
|
+
.grade:hover > .description{
|
|
78
|
+
opacity:1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.gradeIcon{
|
|
82
|
+
transition:all 0.2s ease;
|
|
83
|
+
font-size:32px;
|
|
84
|
+
}
|
|
85
|
+
.gradeIcon:hover{
|
|
86
|
+
font-size:36px !important;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.ratingContainer{
|
|
90
|
+
display:flex;
|
|
91
|
+
flex-direction:column;
|
|
92
|
+
justify-content:center;
|
|
93
|
+
align-items:center;
|
|
94
|
+
gap:4px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.ratingTitle{
|
|
98
|
+
display:flex;
|
|
99
|
+
flex-direction:row;
|
|
100
|
+
justify-content:center;
|
|
101
|
+
align-items:center;
|
|
102
|
+
gap:4px;
|
|
103
|
+
color:var(--sys-neutral-text-main, #41424e);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.ratingSubtitle{
|
|
107
|
+
color:var(--sys-neutral-text-main, #41424e);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.ratingIcon{
|
|
111
|
+
line-height:20px !important;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.mobileSubmitButton{
|
|
115
|
+
position:relative !important;
|
|
116
|
+
flex-shrink:0 !important;
|
|
117
|
+
}
|
|
118
|
+
.mobileSubmitButton:after{
|
|
119
|
+
content:"";
|
|
120
|
+
display:flex;
|
|
121
|
+
width:48px;
|
|
122
|
+
height:48px;
|
|
123
|
+
position:absolute;
|
|
124
|
+
top:50%;
|
|
125
|
+
left:50%;
|
|
126
|
+
transform:translate(-50%, -50%);
|
|
127
|
+
}
|
|
@@ -6,7 +6,7 @@ export type SshFieldProps = WithLayoutType<Omit<FieldTextAreaProps, 'placeholder
|
|
|
6
6
|
/** Колбек отмены действия */
|
|
7
7
|
onCancel(): void;
|
|
8
8
|
}>;
|
|
9
|
-
export declare const SshField: import("react").ForwardRefExoticComponent<Omit<FieldTextAreaProps, "label" | "size" | "placeholder" | "
|
|
9
|
+
export declare const SshField: import("react").ForwardRefExoticComponent<Omit<FieldTextAreaProps, "label" | "size" | "placeholder" | "spellCheck" | "labelTooltip" | "required" | "footer"> & {
|
|
10
10
|
/** Колбек действия при отправке */
|
|
11
11
|
onSubmit(value: string): void;
|
|
12
12
|
/** Колбек отмены действия */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FieldTextAreaProps } from '@cloud-ru/uikit-product-mobile-fields';
|
|
2
|
-
export declare const MobileFieldAi: import("react").ForwardRefExoticComponent<Omit<FieldTextAreaProps, "label" | "size" | "placeholder" | "
|
|
2
|
+
export declare const MobileFieldAi: import("react").ForwardRefExoticComponent<Omit<FieldTextAreaProps, "label" | "size" | "placeholder" | "spellCheck" | "labelTooltip" | "required" | "footer"> & {
|
|
3
3
|
onSubmit(): void;
|
|
4
4
|
submitEnabled: boolean;
|
|
5
5
|
} & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./ButtonClaudia"), exports);
|
|
18
18
|
__exportStar(require("./ButtonGiga"), exports);
|
|
19
19
|
__exportStar(require("./ChatStatusAnnouncement"), exports);
|
|
20
|
+
__exportStar(require("./RateForm"), exports);
|
|
20
21
|
__exportStar(require("./IconGiga"), exports);
|
|
21
22
|
__exportStar(require("./RecommendPannel"), exports);
|
|
22
23
|
__exportStar(require("./SshField"), exports);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Grade } from './types';
|
|
3
|
+
export type RateFormProps = {
|
|
4
|
+
/** Массив доступных оценок */
|
|
5
|
+
grades: Grade[];
|
|
6
|
+
/** Текущая выбранная оценка */
|
|
7
|
+
selectedGrade?: Grade | null;
|
|
8
|
+
/** Заголовок формы (показывается когда оценка не выбрана) */
|
|
9
|
+
title?: string;
|
|
10
|
+
/** Текст "Вы поставили" */
|
|
11
|
+
ratedLabel?: string;
|
|
12
|
+
/** Подзаголовок после выбора оценки */
|
|
13
|
+
ratedSubtitle?: string;
|
|
14
|
+
/** Комментарий пользователя */
|
|
15
|
+
comment?: string;
|
|
16
|
+
/** Состояние загрузки */
|
|
17
|
+
isLoading?: boolean;
|
|
18
|
+
/** Callback при клике на оценку */
|
|
19
|
+
onGradeClick?: (grade: Grade) => void;
|
|
20
|
+
/** Callback при закрытии формы */
|
|
21
|
+
onClose?: () => void;
|
|
22
|
+
/** Callback при изменении комментария */
|
|
23
|
+
onCommentChange?: (comment: string) => void;
|
|
24
|
+
/** Callback при отправке комментария */
|
|
25
|
+
onCommentSubmit?: (comment: string) => void;
|
|
26
|
+
/** Плейсхолдер для поля комментария */
|
|
27
|
+
commentPlaceholder?: string;
|
|
28
|
+
/** Показывать ли кнопку закрытия */
|
|
29
|
+
showCloseButton?: boolean;
|
|
30
|
+
/** Дополнительный className */
|
|
31
|
+
className?: string;
|
|
32
|
+
/** Является ли устройство тач-девайсом */
|
|
33
|
+
isTouchDevice?: boolean;
|
|
34
|
+
/** Текст тултипа для кнопки отправки */
|
|
35
|
+
submitTooltipText?: string;
|
|
36
|
+
/** Render prop для кастомного отображения текстового поля */
|
|
37
|
+
renderTextField?: (props: {
|
|
38
|
+
comment?: string;
|
|
39
|
+
grade: Grade;
|
|
40
|
+
placeholder?: string;
|
|
41
|
+
onChange?: (value: string) => void;
|
|
42
|
+
onSubmit?: (value: string) => void;
|
|
43
|
+
}) => ReactNode;
|
|
44
|
+
};
|
|
45
|
+
export declare function RateForm({ grades, selectedGrade, title, ratedLabel, ratedSubtitle, comment, isLoading, onGradeClick, onClose, onCommentChange, onCommentSubmit, commentPlaceholder, showCloseButton, className, isTouchDevice, submitTooltipText, renderTextField, }: RateFormProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
import { themeVars } from '@sbercloud/figma-tokens-cloud-platform';
|
|
4
|
+
import { CrossSVG } from '@snack-uikit/icons';
|
|
5
|
+
import { Spinner } from '@snack-uikit/loaders';
|
|
6
|
+
import { Typography } from '@snack-uikit/typography';
|
|
7
|
+
import { TextFieldWithAccordionMessage } from './components/TextFieldWithAccordionMessage';
|
|
8
|
+
import styles from './styles.module.css';
|
|
9
|
+
export function RateForm({ grades, selectedGrade, title, ratedLabel, ratedSubtitle, comment, isLoading = false, onGradeClick, onClose, onCommentChange, onCommentSubmit, commentPlaceholder, showCloseButton = true, className, isTouchDevice = false, submitTooltipText, renderTextField, }) {
|
|
10
|
+
if (isLoading) {
|
|
11
|
+
return (_jsx("div", { className: cn(styles.feedbackFormLoading, className), "data-loading": true, children: _jsx(Spinner, { size: 's' }) }));
|
|
12
|
+
}
|
|
13
|
+
return (_jsxs("div", { className: cn(styles.feedbackForm, className), "data-touch": isTouchDevice || undefined, children: [selectedGrade ? (_jsxs("div", { className: styles.ratingContainer, children: [_jsxs("div", { className: styles.ratingTitle, children: [ratedLabel && _jsx(Typography.SansLabelL, { children: ratedLabel }), _jsx(Typography.SansTitleL, { className: styles.ratingIcon, children: selectedGrade.icon })] }), ratedSubtitle && (_jsx(Typography.SansBodyM, { className: styles.ratingSubtitle, children: ratedSubtitle }))] })) : (title && _jsx(Typography.SansLabelL, { className: styles.feedbackFormTitle, children: title })), !selectedGrade && (_jsx("div", { className: styles.gradeBlock, children: grades.map(grade => (_jsxs("div", { className: styles.grade, onClick: () => onGradeClick === null || onGradeClick === void 0 ? void 0 : onGradeClick(grade), role: 'presentation', children: [_jsx(Typography.SansHeadlineL, { className: styles.gradeIcon, children: grade.icon }), _jsx(Typography.LightLabelS, { className: styles.description, children: grade.description })] }, grade.id))) })), selectedGrade &&
|
|
14
|
+
(renderTextField ? (renderTextField({
|
|
15
|
+
comment,
|
|
16
|
+
grade: selectedGrade,
|
|
17
|
+
placeholder: commentPlaceholder,
|
|
18
|
+
onChange: onCommentChange,
|
|
19
|
+
onSubmit: onCommentSubmit,
|
|
20
|
+
})) : (_jsx(TextFieldWithAccordionMessage, { comment: comment, placeholder: commentPlaceholder, onChange: onCommentChange, onSubmit: onCommentSubmit, isTouchDevice: isTouchDevice, submitTooltipText: submitTooltipText }))), showCloseButton && selectedGrade && (_jsx(CrossSVG, { className: styles.closeIcon, size: 24, color: themeVars.sys.neutral.textSupport, onClick: onClose }))] }));
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type FieldSubmitButtonProps = {
|
|
2
|
+
/** Активна ли кнопка */
|
|
3
|
+
active: boolean;
|
|
4
|
+
/** Callback при клике */
|
|
5
|
+
onClick: () => void;
|
|
6
|
+
/** Размер кнопки */
|
|
7
|
+
size?: 'xs' | 's';
|
|
8
|
+
/** Дополнительный className */
|
|
9
|
+
className?: string;
|
|
10
|
+
/** Кнопка на всю ширину */
|
|
11
|
+
fullWidth?: boolean;
|
|
12
|
+
/** Текст тултипа */
|
|
13
|
+
tooltipText?: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function FieldSubmitButton({ active, onClick, size, className, fullWidth, tooltipText, }: FieldSubmitButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowUpSVG } from '@cloud-ru/uikit-product-icons';
|
|
3
|
+
import { ButtonTonal } from '@snack-uikit/button';
|
|
4
|
+
import { Tooltip } from '@snack-uikit/tooltip';
|
|
5
|
+
export function FieldSubmitButton({ active, onClick, size = 'xs', className, fullWidth, tooltipText, }) {
|
|
6
|
+
if (active) {
|
|
7
|
+
return (_jsx(Tooltip, { tip: tooltipText, hoverDelayOpen: 600, open: tooltipText ? undefined : false, children: _jsx(ButtonTonal, { fullWidth: fullWidth, icon: _jsx(ArrowUpSVG, {}), size: size, appearance: 'primary', type: 'button', onClick: onClick, className: className }) }));
|
|
8
|
+
}
|
|
9
|
+
return _jsx(ButtonTonal, { icon: _jsx(ArrowUpSVG, {}), size: size, disabled: true, className: className, fullWidth: fullWidth });
|
|
10
|
+
}
|