@skbkontur/markdown 2.5.8-alpha.0 → 2.5.8-alpha.10

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.
Files changed (25) hide show
  1. package/index.d.ts +1 -1
  2. package/package.json +1 -1
  3. package/src/Markdown/Markdown.d.ts +0 -2
  4. package/src/Markdown/Markdown.js +32 -25
  5. package/src/Markdown/Markdown.styled.d.ts +0 -1
  6. package/src/Markdown/Markdown.styled.js +10 -11
  7. package/src/Markdown/MarkdownActions/AIActionsDropdown/AIActionsDropdown.d.ts +10 -0
  8. package/src/Markdown/MarkdownActions/AIActionsDropdown/AIActionsDropdown.js +140 -0
  9. package/src/Markdown/MarkdownActions/AIActionsDropdown/AIActionsDropdown.styled.d.ts +3 -0
  10. package/src/Markdown/MarkdownActions/AIActionsDropdown/AIActionsDropdown.styled.js +9 -0
  11. package/src/Markdown/MarkdownActions/AIActionsDropdown/constants.d.ts +2 -0
  12. package/src/Markdown/MarkdownActions/AIActionsDropdown/constants.js +2 -0
  13. package/src/Markdown/{MarkdownActions.d.ts → MarkdownActions/MarkdownActions.d.ts} +4 -4
  14. package/src/Markdown/{MarkdownActions.js → MarkdownActions/MarkdownActions.js} +22 -24
  15. package/src/Markdown/MarkdownActions/MarkdownDropdown/MarkdownDropdown.d.ts +11 -0
  16. package/src/Markdown/MarkdownActions/MarkdownDropdown/MarkdownDropdown.js +14 -0
  17. package/src/Markdown/MarkdownActions/MarkdownDropdown/MarkdownDropdown.styled.d.ts +1 -0
  18. package/src/Markdown/MarkdownActions/MarkdownDropdown/MarkdownDropdown.styled.js +7 -0
  19. package/src/Markdown/types.d.ts +13 -3
  20. package/src/MarkdownIcons/Copy.d.ts +2 -0
  21. package/src/MarkdownIcons/Copy.js +6 -0
  22. package/src/MarkdownIcons/NatureFxSparkleA2.d.ts +2 -0
  23. package/src/MarkdownIcons/NatureFxSparkleA2.js +6 -0
  24. package/src/Markdown/AIActionsButton/AIActionsDropdown.d.ts +0 -13
  25. package/src/Markdown/AIActionsButton/AIActionsDropdown.js +0 -113
package/index.d.ts CHANGED
@@ -2,6 +2,6 @@ export { Markdown, MarkdownProps } from './src/Markdown/Markdown';
2
2
  export { MarkdownCombination } from './src/MarkdownCombination/MarkdownCombination';
3
3
  export { markdownHelpItems, markdownHelpFiles, markdownHelpLists, markdownHelpOther, } from './src/Markdown/MarkdownHelpItems';
4
4
  export { MarkdownViewer } from './src/MarkdownViewer/MarkdownViewer';
5
- export { MarkdownApi, RefItem, User, Token, HorizontalPaddings, ViewMode, HideActionsOptions, } from '././src/Markdown/types';
5
+ export { MarkdownApi, RefItem, User, Token, HorizontalPaddings, ViewMode, HideActionsOptions, AIMethod, AIApi, } from '././src/Markdown/types';
6
6
  export { ThemeMode, ColorScheme } from './src/styles/types';
7
7
  export { MarkdownTheme, MarkdownThemeProvider, MarkdownThemeConsumer, MarkdownThemeContext } from './src/styles/theme';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skbkontur/markdown",
3
- "version": "2.5.8-alpha.0",
3
+ "version": "2.5.8-alpha.10",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -4,8 +4,6 @@ import { HideActionsOptions, HorizontalPaddings, MarkdownApi, ViewMode } from '.
4
4
  export interface MarkdownProps extends MarkdownEditorProps {
5
5
  /** Методы апи для загрузки/скачивания файлов, меншена, ИИ */
6
6
  api?: MarkdownApi;
7
- /** Доступные методы ИИ апи */
8
- availableAIMethods?: string[];
9
7
  /** Режим прозрачной рамки у Textarea */
10
8
  borderless?: boolean;
11
9
  /** Url апи для файлов */
@@ -28,7 +28,7 @@ import { MENTION_WRAPPER_ID_POSTFIX, SPLIT_VIEW_THRESHOLD } from './constants';
28
28
  import { useEmojiLogic } from './Emoji/Emoji.logic';
29
29
  import { useFileLogic } from './Files/Files.logic';
30
30
  import { DroppablePlaceholder, FlexCenter, getMarkdownReactUiTheme, MarkdownEditorBlock, MarkdownPreview, MentionWrapper, SplitViewContainer, SplitViewEditContainer, SplitViewMaxWidth, SplitViewPreviewContainer, Wrapper, } from './Markdown.styled';
31
- import { MarkdownActions } from './MarkdownActions';
31
+ import { MarkdownActions } from './MarkdownActions/MarkdownActions';
32
32
  import { MarkdownEditor } from './MarkdownEditor';
33
33
  import { EmptyPreview } from './MarkdownHelpers/EmptyPreview';
34
34
  import { usePasteFromClipboard } from './MarkdownHelpers/markdownHelpers';
@@ -43,8 +43,7 @@ import { ThemeProvider } from '../styles/styled-components';
43
43
  import { DEFAULT_MARKDOWN_THEME, MarkdownThemeConsumer } from '../styles/theme';
44
44
  export var Markdown = function (props) {
45
45
  var _a;
46
- var availableAIMethods = props.availableAIMethods, panelHorizontalPadding = props.panelHorizontalPadding, onClick = props.onClick, onChange = props.onChange, onSelect = props.onSelect, markdownViewer = props.markdownViewer, renderFilesValidation = props.renderFilesValidation, fileApiUrl = props.fileApiUrl, profileUrl = props.profileUrl, api = props.api, borderless = props.borderless, showActionHints = props.showActionHints, showShortKeys = props.showShortKeys, _b = props.showShotKeys, showShotKeys = _b === void 0 ? true : _b, hideActionsOptions = props.hideActionsOptions, onChangeViewMode = props.onChangeViewMode, textareaProps = __rest(props, ["availableAIMethods", "panelHorizontalPadding", "onClick", "onChange", "onSelect", "markdownViewer", "renderFilesValidation", "fileApiUrl", "profileUrl", "api", "borderless", "showActionHints", "showShortKeys", "showShotKeys", "hideActionsOptions", "onChangeViewMode"]);
47
- var textareaRef = useRef(null);
46
+ var panelHorizontalPadding = props.panelHorizontalPadding, onClick = props.onClick, onChange = props.onChange, onSelect = props.onSelect, markdownViewer = props.markdownViewer, renderFilesValidation = props.renderFilesValidation, fileApiUrl = props.fileApiUrl, profileUrl = props.profileUrl, api = props.api, borderless = props.borderless, showActionHints = props.showActionHints, showShortKeys = props.showShortKeys, _b = props.showShotKeys, showShotKeys = _b === void 0 ? true : _b, hideActionsOptions = props.hideActionsOptions, onChangeViewMode = props.onChangeViewMode, textareaProps = __rest(props, ["panelHorizontalPadding", "onClick", "onChange", "onSelect", "markdownViewer", "renderFilesValidation", "fileApiUrl", "profileUrl", "api", "borderless", "showActionHints", "showShortKeys", "showShotKeys", "hideActionsOptions", "onChangeViewMode"]);
48
47
  var _c = useState(), mention = _c[0], setMention = _c[1];
49
48
  var _d = useState(ViewMode.Edit), viewMode = _d[0], setViewMode = _d[1];
50
49
  var _e = useState(false), fullscreen = _e[0], setFullScreen = _e[1];
@@ -52,6 +51,8 @@ export var Markdown = function (props) {
52
51
  var _g = useState(), selectionStart = _g[0], setSelectionStart = _g[1];
53
52
  var _h = useState(), selectionEnd = _h[0], setSelectionEnd = _h[1];
54
53
  var guid = useRef(new Guid().generate()).current;
54
+ var textareaRef = useRef(null);
55
+ var textareaNode = getTextareaNode();
55
56
  var isEditMode = viewMode !== ViewMode.Preview;
56
57
  var width = fullscreen || !textareaProps.width ? '100%' : textareaProps.width;
57
58
  var _j = useResponsiveLayout({
@@ -65,9 +66,9 @@ export var Markdown = function (props) {
65
66
  useListenTextareaScroll(resetMention, textareaRef.current);
66
67
  var fullscreenTextareaPadding = useFullscreenHorizontalPadding(fullscreen, viewMode, initialWidth);
67
68
  useLayoutEffect(function () {
68
- var _a;
69
- var textareaNode = (_a = textareaRef.current) === null || _a === void 0 ? void 0 : _a.node;
70
- setInitialWidth(textareaNode.clientWidth);
69
+ var textareaNode = getTextareaNode();
70
+ if (textareaNode)
71
+ setInitialWidth(textareaNode.clientWidth);
71
72
  }, []);
72
73
  useEffect(function () {
73
74
  if (fullscreen && isSplitViewAvailable)
@@ -80,23 +81,31 @@ export var Markdown = function (props) {
80
81
  setFullScreen(false);
81
82
  }, [isMobile]);
82
83
  useEffect(function () {
83
- var _a;
84
84
  if (fullscreen && isEditMode && textareaRef) {
85
- var textareaNode = (_a = textareaRef.current) === null || _a === void 0 ? void 0 : _a.node;
86
- if (textareaNode) {
87
- textareaNode.focus();
88
- textareaNode.selectionStart = selectionStart !== null && selectionStart !== void 0 ? selectionStart : 0;
89
- textareaNode.selectionEnd = selectionEnd !== null && selectionEnd !== void 0 ? selectionEnd : 0;
85
+ var textareaNode_1 = getTextareaNode();
86
+ if (textareaNode_1) {
87
+ textareaNode_1.focus();
88
+ textareaNode_1.selectionStart = selectionStart !== null && selectionStart !== void 0 ? selectionStart : 0;
89
+ textareaNode_1.selectionEnd = selectionEnd !== null && selectionEnd !== void 0 ? selectionEnd : 0;
90
90
  }
91
91
  }
92
92
  }, [fullscreen, isEditMode, selectionEnd, selectionStart, textareaRef]);
93
+ useEffect(function () {
94
+ var handleSelectionChange = function () {
95
+ var textareaNode = getTextareaNode();
96
+ setSelectionStart(textareaNode === null || textareaNode === void 0 ? void 0 : textareaNode.selectionStart);
97
+ setSelectionEnd(textareaNode === null || textareaNode === void 0 ? void 0 : textareaNode.selectionEnd);
98
+ };
99
+ document.addEventListener('selectionchange', handleSelectionChange);
100
+ return function () { return document.removeEventListener('selectionchange', handleSelectionChange); };
101
+ }, []);
93
102
  var horizontalPaddings = {
94
103
  panelPadding: panelHorizontalPadding,
95
104
  fullscreenPadding: fullscreenTextareaPadding,
96
105
  };
97
106
  var content = (React.createElement(Foco, { component: "div", onClickOutside: resetStates },
98
107
  React.createElement(Wrapper, __assign({}, getRootProps()),
99
- !(hideActionsOptions === null || hideActionsOptions === void 0 ? void 0 : hideActionsOptions.allActions) && (React.createElement(MarkdownActions, { showActionHints: showActionHints !== undefined ? showActionHints : showShotKeys, showShortKeys: showShortKeys !== undefined ? showShortKeys : showShotKeys, textAreaRef: textareaRef, width: width, viewMode: viewMode, loadingFile: requestStatus === RequestStatus.isFetching, fullscreen: fullscreen, selectionStart: selectionStart, selectionEnd: selectionEnd, horizontalPaddings: horizontalPaddings, hideOptions: hideActionsOptions, hasFilesApi: !!(api === null || api === void 0 ? void 0 : api.fileDownloadApi) && !!(api === null || api === void 0 ? void 0 : api.fileUploadApi), isSplitViewAvailable: isSplitViewAvailable, disableFullscreen: isMobile, availableAIMethods: availableAIMethods, AIApi: api === null || api === void 0 ? void 0 : api.AIApi, onOpenFileDialog: open, onChangeViewMode: handleChangeViewMode, onClickFullscreen: handleClickFullscreen, onSelectEmoji: onSelectEmoji })),
108
+ !(hideActionsOptions === null || hideActionsOptions === void 0 ? void 0 : hideActionsOptions.allActions) && (React.createElement(MarkdownActions, { showActionHints: showActionHints !== undefined ? showActionHints : showShotKeys, showShortKeys: showShortKeys !== undefined ? showShortKeys : showShotKeys, textAreaRef: textareaRef, width: width, viewMode: viewMode, loadingFile: requestStatus === RequestStatus.isFetching, fullscreen: fullscreen, selectionStart: selectionStart, selectionEnd: selectionEnd, horizontalPaddings: horizontalPaddings, hideOptions: hideActionsOptions, hasFilesApi: !!(api === null || api === void 0 ? void 0 : api.fileDownloadApi) && !!(api === null || api === void 0 ? void 0 : api.fileUploadApi), isSplitViewAvailable: isSplitViewAvailable, disableFullscreen: isMobile, AIApi: api === null || api === void 0 ? void 0 : api.AIApi, onOpenFileDialog: open, onChangeViewMode: handleChangeViewMode, onClickFullscreen: handleClickFullscreen, onSelectEmoji: onSelectEmoji })),
100
109
  isEditMode && error && (api === null || api === void 0 ? void 0 : api.getUsersApi) && (renderFilesValidation === null || renderFilesValidation === void 0 ? void 0 : renderFilesValidation(horizontalPaddings, onResetError)),
101
110
  fullscreen && viewMode === ViewMode.Split && !fullscreenTextareaPadding && (React.createElement(SplitViewContainer, null,
102
111
  React.createElement(SplitViewEditContainer, null, renderEditContainer()),
@@ -122,7 +131,7 @@ export var Markdown = function (props) {
122
131
  return (React.createElement(MarkdownEditorBlock, null,
123
132
  React.createElement(MentionWrapper, { id: "".concat(guid).concat(MENTION_WRAPPER_ID_POSTFIX) }),
124
133
  showMention && renderMentions(),
125
- React.createElement(MarkdownEditor, __assign({}, textareaProps, { maxRows: fullscreen ? undefined : textareaProps.maxRows, width: width, textareaRef: textareaRef, onChange: listenChange, onSelect: listenSelection, onClick: listenClick }))));
134
+ React.createElement(MarkdownEditor, __assign({}, textareaProps, { maxRows: fullscreen ? undefined : textareaProps.maxRows, width: width, textareaRef: textareaRef, onChange: listenChange, onSelect: listenSelect, onClick: listenClick }))));
126
135
  }
127
136
  function renderPreview() {
128
137
  var _a;
@@ -131,9 +140,7 @@ export var Markdown = function (props) {
131
140
  return (React.createElement(MarkdownPreview, __assign({}, horizontalPaddings, { viewMode: viewMode, width: width }), (markdownViewer === null || markdownViewer === void 0 ? void 0 : markdownViewer(props.value)) || (React.createElement(MarkdownViewer, { source: (_a = props.value) !== null && _a !== void 0 ? _a : '', downloadFileApi: api === null || api === void 0 ? void 0 : api.fileDownloadApi, fileApiUrl: fileApiUrl, profileUrl: profileUrl }))));
132
141
  }
133
142
  function renderMentions() {
134
- var _a;
135
- if (textareaRef.current && mention && (api === null || api === void 0 ? void 0 : api.getUsersApi)) {
136
- var textareaNode = (_a = textareaRef.current) === null || _a === void 0 ? void 0 : _a.node;
143
+ if (textareaNode && mention && (api === null || api === void 0 ? void 0 : api.getUsersApi)) {
137
144
  var position = getCursorCoordinates(textareaNode, guid);
138
145
  return (React.createElement(MarkdownMention, { value: getMentionValue(mention), getUsersApi: api.getUsersApi, y: position.y, x: position.x, onSelectUser: handleSelectUser }));
139
146
  }
@@ -143,18 +150,13 @@ export var Markdown = function (props) {
143
150
  onChangeViewMode === null || onChangeViewMode === void 0 ? void 0 : onChangeViewMode(mode);
144
151
  }
145
152
  function handleSelectUser(login, name) {
146
- if (textareaRef.current && mention) {
147
- var htmlTextArea = textareaRef.current;
148
- htmlTextArea.setSelectionRange(mention.positions[0] ? mention.positions[0] - 1 : 0, mention.positions[1]);
153
+ if (textareaNode && mention) {
154
+ textareaNode.setSelectionRange(mention.positions[0] ? mention.positions[0] - 1 : 0, mention.positions[1]);
149
155
  document.execCommand('insertText', false, "[".concat(name, "](@").concat(login, ")"));
150
156
  resetMention();
151
157
  }
152
158
  }
153
- function listenSelection(event) {
154
- var _a = event.currentTarget, textSelectionStart = _a.selectionStart, textSelectionEnd = _a.selectionEnd;
155
- console.log('textSelectionStart', textSelectionStart);
156
- setSelectionStart(textSelectionStart);
157
- setSelectionEnd(textSelectionEnd);
159
+ function listenSelect(event) {
158
160
  onSelect && onSelect(event);
159
161
  checkMention(event);
160
162
  }
@@ -174,6 +176,7 @@ export var Markdown = function (props) {
174
176
  resetMention();
175
177
  setSelectionStart(undefined);
176
178
  setSelectionEnd(undefined);
179
+ textareaNode === null || textareaNode === void 0 ? void 0 : textareaNode.setSelectionRange(0, 0);
177
180
  }
178
181
  function resetMention() {
179
182
  setMention(undefined);
@@ -182,4 +185,8 @@ export var Markdown = function (props) {
182
185
  setViewMode(function (prevState) { return (prevState !== ViewMode.Split && isSplitViewAvailable ? ViewMode.Split : ViewMode.Edit); });
183
186
  setFullScreen(!fullscreen);
184
187
  }
188
+ function getTextareaNode() {
189
+ var _a;
190
+ return (_a = textareaRef === null || textareaRef === void 0 ? void 0 : textareaRef.current) === null || _a === void 0 ? void 0 : _a.node;
191
+ }
185
192
  };
@@ -33,7 +33,6 @@ export declare const ActionsRightWrapper: import("styled-components").StyledComp
33
33
  export declare const ActionsLeftWrapper: import("styled-components").StyledComponent<"div", MarkdownTheme, {}, never>;
34
34
  export declare const MarkdownButtonWrapper: import("styled-components").StyledComponent<typeof Button, MarkdownTheme, {}, never>;
35
35
  export declare const MarkdownButtonIcon: import("styled-components").StyledComponent<"div", MarkdownTheme, {}, never>;
36
- export declare const MarkdownDropdown: import("styled-components").StyledComponent<"div", MarkdownTheme, {}, never>;
37
36
  export declare const MarkdownSymbolWrapper: import("styled-components").StyledComponent<"span", MarkdownTheme, {}, never>;
38
37
  export declare const MarkdownMenuItem: import("styled-components").StyledComponent<typeof MenuItem, MarkdownTheme, {}, never>;
39
38
  export declare const MarkdownEditorBlock: import("styled-components").StyledComponent<"div", MarkdownTheme, {}, never>;
@@ -55,21 +55,20 @@ export var ActionsRightWrapper = styled.div(templateObject_16 || (templateObject
55
55
  export var ActionsLeftWrapper = styled(ActionsRightWrapper)(templateObject_17 || (templateObject_17 = __makeTemplateObject(["\n flex-wrap: wrap;\n"], ["\n flex-wrap: wrap;\n"])));
56
56
  export var MarkdownButtonWrapper = styled(Button)(templateObject_18 || (templateObject_18 = __makeTemplateObject(["\n button {\n padding: 4px;\n border: none;\n box-sizing: border-box;\n }\n"], ["\n button {\n padding: 4px;\n border: none;\n box-sizing: border-box;\n }\n"])));
57
57
  export var MarkdownButtonIcon = styled.div(templateObject_19 || (templateObject_19 = __makeTemplateObject(["\n height: 24px;\n display: flex;\n width: 100%;\n align-items: center;\n justify-content: center;\n"], ["\n height: 24px;\n display: flex;\n width: 100%;\n align-items: center;\n justify-content: center;\n"])));
58
- export var MarkdownDropdown = styled.div(templateObject_20 || (templateObject_20 = __makeTemplateObject(["\n display: flex;\n align-items: end;\n padding-bottom: 1px;\n\n button {\n font-size: ", ";\n }\n"], ["\n display: flex;\n align-items: end;\n padding-bottom: 1px;\n\n button {\n font-size: ", ";\n }\n"])), function (p) { return p.theme.elementsFontSize; });
59
- export var MarkdownSymbolWrapper = styled.span(templateObject_21 || (templateObject_21 = __makeTemplateObject(["\n color: ", ";\n font-weight: 700;\n"], ["\n color: ", ";\n font-weight: 700;\n"])), function (p) { return p.theme.colors.brand; });
60
- export var MarkdownMenuItem = styled(MenuItem)(templateObject_22 || (templateObject_22 = __makeTemplateObject(["\n padding-left: 8px;\n padding-right: 8px;\n color: ", ";\n"], ["\n padding-left: 8px;\n padding-right: 8px;\n color: ", ";\n"])), function (p) { return p.theme.colors.grayDefault; });
61
- export var MarkdownEditorBlock = styled.div(templateObject_23 || (templateObject_23 = __makeTemplateObject(["\n position: relative;\n"], ["\n position: relative;\n"])));
58
+ export var MarkdownSymbolWrapper = styled.span(templateObject_20 || (templateObject_20 = __makeTemplateObject(["\n color: ", ";\n font-weight: 700;\n"], ["\n color: ", ";\n font-weight: 700;\n"])), function (p) { return p.theme.colors.brand; });
59
+ export var MarkdownMenuItem = styled(MenuItem)(templateObject_21 || (templateObject_21 = __makeTemplateObject(["\n padding-left: 8px;\n padding-right: 8px;\n color: ", ";\n"], ["\n padding-left: 8px;\n padding-right: 8px;\n color: ", ";\n"])), function (p) { return p.theme.colors.text; });
60
+ export var MarkdownEditorBlock = styled.div(templateObject_22 || (templateObject_22 = __makeTemplateObject(["\n position: relative;\n"], ["\n position: relative;\n"])));
62
61
  export var getMarkdownMentionStyle = function (x, y) { return ({
63
62
  position: 'absolute',
64
63
  top: y,
65
64
  left: x,
66
65
  }); };
67
- export var UserDescriptions = styled.div(templateObject_24 || (templateObject_24 = __makeTemplateObject(["\n white-space: pre-line;\n overflow-wrap: break-word;\n word-wrap: break-word;\n word-break: break-word;\n overflow: hidden;\n margin-top: 4px;\n"], ["\n white-space: pre-line;\n overflow-wrap: break-word;\n word-wrap: break-word;\n word-break: break-word;\n overflow: hidden;\n margin-top: 4px;\n"])));
68
- export var MentionMenuItem = styled(MenuItem)(templateObject_25 || (templateObject_25 = __makeTemplateObject(["\n padding: 4px 28px;\n"], ["\n padding: 4px 28px;\n"])));
69
- export var VisuallyHidden = styled.span(templateObject_26 || (templateObject_26 = __makeTemplateObject(["\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n"], ["\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n"])));
70
- export var EmptyPreviewContainer = styled.div(templateObject_27 || (templateObject_27 = __makeTemplateObject(["\n display: flex;\n width: 407px;\n flex-direction: column;\n"], ["\n display: flex;\n width: 407px;\n flex-direction: column;\n"])));
71
- export var EmptyPreviewText = styled.span(templateObject_28 || (templateObject_28 = __makeTemplateObject(["\n font-weight: 700;\n font-size: 40px;\n line-height: 48px;\n color: #d6d6d6;\n"], ["\n font-weight: 700;\n font-size: 40px;\n line-height: 48px;\n color: #d6d6d6;\n"])));
72
- export var EmptyPreviewIconWrapper = styled.div(templateObject_29 || (templateObject_29 = __makeTemplateObject(["\n margin-top: 16px;\n margin-bottom: 32px;\n"], ["\n margin-top: 16px;\n margin-bottom: 32px;\n"])));
66
+ export var UserDescriptions = styled.div(templateObject_23 || (templateObject_23 = __makeTemplateObject(["\n white-space: pre-line;\n overflow-wrap: break-word;\n word-wrap: break-word;\n word-break: break-word;\n overflow: hidden;\n margin-top: 4px;\n"], ["\n white-space: pre-line;\n overflow-wrap: break-word;\n word-wrap: break-word;\n word-break: break-word;\n overflow: hidden;\n margin-top: 4px;\n"])));
67
+ export var MentionMenuItem = styled(MenuItem)(templateObject_24 || (templateObject_24 = __makeTemplateObject(["\n padding: 4px 28px;\n"], ["\n padding: 4px 28px;\n"])));
68
+ export var VisuallyHidden = styled.span(templateObject_25 || (templateObject_25 = __makeTemplateObject(["\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n"], ["\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n"])));
69
+ export var EmptyPreviewContainer = styled.div(templateObject_26 || (templateObject_26 = __makeTemplateObject(["\n display: flex;\n width: 407px;\n flex-direction: column;\n"], ["\n display: flex;\n width: 407px;\n flex-direction: column;\n"])));
70
+ export var EmptyPreviewText = styled.span(templateObject_27 || (templateObject_27 = __makeTemplateObject(["\n font-weight: 700;\n font-size: 40px;\n line-height: 48px;\n color: #d6d6d6;\n"], ["\n font-weight: 700;\n font-size: 40px;\n line-height: 48px;\n color: #d6d6d6;\n"])));
71
+ export var EmptyPreviewIconWrapper = styled.div(templateObject_28 || (templateObject_28 = __makeTemplateObject(["\n margin-top: 16px;\n margin-bottom: 32px;\n"], ["\n margin-top: 16px;\n margin-bottom: 32px;\n"])));
73
72
  var extendThemeConfigWithSized = function (config) {
74
73
  var finalConfig = {};
75
74
  var configKeys = Object.keys(config);
@@ -114,4 +113,4 @@ export var getMarkdownReactUiTheme = function (theme, viewMode, reactUiTheme, pa
114
113
  textareaPaddingY: '0',
115
114
  })))))), reactUiTheme);
116
115
  };
117
- var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22, templateObject_23, templateObject_24, templateObject_25, templateObject_26, templateObject_27, templateObject_28, templateObject_29;
116
+ var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22, templateObject_23, templateObject_24, templateObject_25, templateObject_26, templateObject_27, templateObject_28;
@@ -0,0 +1,10 @@
1
+ import { Textarea } from '@skbkontur/react-ui';
2
+ import { FC, RefObject } from 'react';
3
+ import { AIApi } from '../../types';
4
+ interface Props {
5
+ api: AIApi;
6
+ textareaRef: RefObject<Textarea>;
7
+ isPreviewMode?: boolean;
8
+ }
9
+ export declare const AIActionsDropdown: FC<Props>;
10
+ export {};
@@ -0,0 +1,140 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ import { Button, Hint, Spinner, Toast, Tooltip } from '@skbkontur/react-ui';
38
+ import React, { useEffect, useRef, useState } from 'react';
39
+ import { DropdownCaptionWrapper, TooltipButtonsWrapper, TooltipWrapper } from './AIActionsDropdown.styled';
40
+ import { COPY_BUTTON_TEXT, ERRORS_NOT_FOUND_TEXT } from './constants';
41
+ import { Copy } from '../../../MarkdownIcons/Copy';
42
+ import { NatureFxSparkleA2 } from '../../../MarkdownIcons/NatureFxSparkleA2';
43
+ import { MarkdownMenuItem } from '../../Markdown.styled';
44
+ import { Guid } from '../../utils/guid';
45
+ import { RequestStatus } from '../../utils/requestStatus';
46
+ import { MarkdownDropdown } from '../MarkdownDropdown/MarkdownDropdown';
47
+ export var AIActionsDropdown = function (_a) {
48
+ var _b;
49
+ var textareaRef = _a.textareaRef, isPreviewMode = _a.isPreviewMode, api = _a.api;
50
+ var _c = useState(), processedText = _c[0], setProcessedText = _c[1];
51
+ var _d = useState(RequestStatus.Default), requestStatus = _d[0], setRequestStatus = _d[1];
52
+ var tooltipRef = useRef(null);
53
+ var taskIdRef = useRef(new Guid());
54
+ var availableMethods = api.availableMethods, onSendMessage = api.onSendMessage;
55
+ var htmlTextArea = (_b = textareaRef.current) === null || _b === void 0 ? void 0 : _b.node;
56
+ var selectionStart = htmlTextArea === null || htmlTextArea === void 0 ? void 0 : htmlTextArea.selectionStart;
57
+ var selectionEnd = htmlTextArea === null || htmlTextArea === void 0 ? void 0 : htmlTextArea.selectionEnd;
58
+ useEffect(function () {
59
+ handleCloseTooltip();
60
+ }, [selectionStart, selectionEnd]);
61
+ if (!(textareaRef === null || textareaRef === void 0 ? void 0 : textareaRef.current))
62
+ return null;
63
+ var value = htmlTextArea.value.substring(Number(selectionStart), selectionEnd !== null && selectionEnd !== void 0 ? selectionEnd : undefined);
64
+ var isEmptySelected = selectionEnd === selectionStart;
65
+ return (React.createElement(Tooltip, { ref: tooltipRef, pos: "top right", allowedPositions: ['top right', 'right middle', 'bottom right'], trigger: "manual", render: renderTooltipContent, onClose: handleCloseTooltip },
66
+ React.createElement(MarkdownDropdown, { hintText: isEmptySelected ? 'Выдели текст' : 'ИИ-помощник', caption: React.createElement(DropdownCaptionWrapper, null,
67
+ React.createElement(NatureFxSparkleA2, null),
68
+ " \u0418\u0418"), menuWidth: 180, disabled: isPreviewMode || isEmptySelected, onOpen: handleCloseTooltip }, availableMethods.map(function (_a) {
69
+ var method = _a.method, caption = _a.caption;
70
+ return (React.createElement(MarkdownMenuItem, { key: method, onClick: function () { return handleProcessText(method); } }, caption));
71
+ }))));
72
+ function renderTooltipContent() {
73
+ if (requestStatus === RequestStatus.isFetching)
74
+ return React.createElement(Spinner, { caption: "\u041E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u0435\u043C", type: "mini" });
75
+ return (React.createElement(TooltipWrapper, null,
76
+ React.createElement("div", null, processedText),
77
+ processedText !== ERRORS_NOT_FOUND_TEXT && (React.createElement(TooltipButtonsWrapper, null,
78
+ React.createElement(Button, { onClick: handleSetText }, "\u0417\u0430\u043C\u0435\u043D\u0438\u0442\u044C \u0442\u0435\u043A\u0441\u0442"),
79
+ React.createElement(Hint, { text: COPY_BUTTON_TEXT },
80
+ React.createElement(Button, { "aria-label": COPY_BUTTON_TEXT, icon: React.createElement(Copy, null), onClick: handleCopyText }))))));
81
+ }
82
+ function handleProcessText(method) {
83
+ var _a;
84
+ return __awaiter(this, void 0, void 0, function () {
85
+ var taskId, response, e_1;
86
+ return __generator(this, function (_b) {
87
+ switch (_b.label) {
88
+ case 0:
89
+ _b.trys.push([0, 2, , 3]);
90
+ (_a = tooltipRef === null || tooltipRef === void 0 ? void 0 : tooltipRef.current) === null || _a === void 0 ? void 0 : _a.show();
91
+ taskId = taskIdRef.current.generate();
92
+ setRequestStatus(RequestStatus.isFetching);
93
+ return [4 /*yield*/, onSendMessage(value, method)];
94
+ case 1:
95
+ response = _b.sent();
96
+ if (response && taskId === taskIdRef.current.generated) {
97
+ setRequestStatus(RequestStatus.isLoaded);
98
+ setProcessedText(value === response ? ERRORS_NOT_FOUND_TEXT : response);
99
+ }
100
+ return [3 /*break*/, 3];
101
+ case 2:
102
+ e_1 = _b.sent();
103
+ handleCloseTooltip();
104
+ Toast.push('Ошибка обработки текста');
105
+ return [3 /*break*/, 3];
106
+ case 3: return [2 /*return*/];
107
+ }
108
+ });
109
+ });
110
+ }
111
+ function handleCopyText() {
112
+ return __awaiter(this, void 0, void 0, function () {
113
+ return __generator(this, function (_a) {
114
+ switch (_a.label) {
115
+ case 0: return [4 /*yield*/, navigator.clipboard.writeText(processedText || '')];
116
+ case 1:
117
+ _a.sent();
118
+ handleCloseTooltip();
119
+ return [2 /*return*/];
120
+ }
121
+ });
122
+ });
123
+ }
124
+ function handleSetText() {
125
+ if (!(textareaRef === null || textareaRef === void 0 ? void 0 : textareaRef.current))
126
+ return null;
127
+ textareaRef.current.focus();
128
+ var valueLength = value.length;
129
+ var spaceInStartCount = valueLength - value.trimStart().length;
130
+ var spaceInEndCount = valueLength - value.trimEnd().length;
131
+ htmlTextArea.setSelectionRange(selectionStart + spaceInStartCount, selectionEnd - spaceInEndCount);
132
+ document.execCommand('insertText', false, processedText);
133
+ handleCloseTooltip();
134
+ }
135
+ function handleCloseTooltip() {
136
+ var _a;
137
+ setProcessedText(undefined);
138
+ (_a = tooltipRef === null || tooltipRef === void 0 ? void 0 : tooltipRef.current) === null || _a === void 0 ? void 0 : _a.hide();
139
+ }
140
+ };
@@ -0,0 +1,3 @@
1
+ export declare const TooltipWrapper: import("styled-components").StyledComponent<"div", import("../../../..").MarkdownTheme, {}, never>;
2
+ export declare const TooltipButtonsWrapper: import("styled-components").StyledComponent<"div", import("../../../..").MarkdownTheme, {}, never>;
3
+ export declare const DropdownCaptionWrapper: import("styled-components").StyledComponent<"div", import("../../../..").MarkdownTheme, {}, never>;
@@ -0,0 +1,9 @@
1
+ var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
2
+ if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
3
+ return cooked;
4
+ };
5
+ import styled from '../../../styles/styled-components';
6
+ export var TooltipWrapper = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-width: 300px;\n"], ["\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-width: 300px;\n"])));
7
+ export var TooltipButtonsWrapper = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: 8px;\n"], ["\n display: flex;\n align-items: center;\n gap: 8px;\n"])));
8
+ export var DropdownCaptionWrapper = styled.div(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n gap: 4px;\n"], ["\n display: flex;\n align-items: center;\n gap: 4px;\n"])));
9
+ var templateObject_1, templateObject_2, templateObject_3;
@@ -0,0 +1,2 @@
1
+ export declare const ERRORS_NOT_FOUND_TEXT = "\u041E\u0448\u0438\u0431\u043E\u043A \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E";
2
+ export declare const COPY_BUTTON_TEXT = "\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C";
@@ -0,0 +1,2 @@
1
+ export var ERRORS_NOT_FOUND_TEXT = 'Ошибок не найдено';
2
+ export var COPY_BUTTON_TEXT = 'Скопировать';
@@ -1,7 +1,7 @@
1
1
  import { Textarea } from '@skbkontur/react-ui';
2
2
  import { FC, RefObject } from 'react';
3
- import { EmojiData } from './Emoji/Emoji.logic';
4
- import { HideActionsOptions, HorizontalPaddings, Nullable, ViewMode } from './types';
3
+ import { EmojiData } from '../Emoji/Emoji.logic';
4
+ import { AIApi, HideActionsOptions, HorizontalPaddings, Nullable, ViewMode } from '../types';
5
5
  interface Props {
6
6
  horizontalPaddings: HorizontalPaddings;
7
7
  onChangeViewMode: (viewMode: ViewMode) => void;
@@ -12,12 +12,12 @@ interface Props {
12
12
  showShortKeys: boolean;
13
13
  textAreaRef: RefObject<Textarea>;
14
14
  viewMode: ViewMode;
15
- AIApi?: (query: string, method: string) => Promise<string>;
16
- availableAIMethods?: string[];
15
+ AIApi?: AIApi;
17
16
  disableFullscreen?: boolean;
18
17
  fullscreen?: boolean;
19
18
  hasFilesApi?: boolean;
20
19
  hideOptions?: HideActionsOptions;
20
+ isFocused?: boolean;
21
21
  isSplitViewAvailable?: boolean;
22
22
  loadingFile?: boolean;
23
23
  selectionEnd?: Nullable<number>;
@@ -9,34 +9,32 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
- import { Dropdown, Hint } from '@skbkontur/react-ui';
13
12
  import React from 'react';
14
- import { AIActionsDropdown } from './AIActionsButton/AIActionsDropdown';
15
- import { COMMONMARK_HELP_URL } from './constants';
16
- import { EmojiDropdown } from './Emoji/EmojiDropdown';
17
- import { ActionsLeftWrapper, ActionsRightWrapper, ButtonsWrapper, MarkdownActionsWrapper, MarkdownDropdown, MarkdownMenuItem, } from './Markdown.styled';
18
- import { MarkdownFormatButton } from './MarkdownHelpers/MarkdownFormatButton';
19
- import { setMarkdown } from './MarkdownHelpers/markdownHelpers';
20
- import { markdownHelpHeaders, markdownHelpLists, markdownHelpOther, markdownHelpText } from './MarkdownHelpItems';
21
- import { ViewMode } from './types';
22
- import { MarkdownCombination } from '../MarkdownCombination/MarkdownCombination';
23
- import { AttachPaperclip } from '../MarkdownIcons/AttachPaperclip';
24
- import { Collapse } from '../MarkdownIcons/Collapse';
25
- import { DocIcon } from '../MarkdownIcons/DocIcon';
26
- import { Expand } from '../MarkdownIcons/Expand';
27
- import { EyeOpen } from '../MarkdownIcons/EyeOpen';
28
- import { SplitView } from '../MarkdownIcons/SplitView';
29
- import { ToolPencil } from '../MarkdownIcons/ToolPencil';
13
+ import { AIActionsDropdown } from './AIActionsDropdown/AIActionsDropdown';
14
+ import { MarkdownDropdown } from './MarkdownDropdown/MarkdownDropdown';
15
+ import { MarkdownCombination } from '../../MarkdownCombination/MarkdownCombination';
16
+ import { AttachPaperclip } from '../../MarkdownIcons/AttachPaperclip';
17
+ import { Collapse } from '../../MarkdownIcons/Collapse';
18
+ import { DocIcon } from '../../MarkdownIcons/DocIcon';
19
+ import { Expand } from '../../MarkdownIcons/Expand';
20
+ import { EyeOpen } from '../../MarkdownIcons/EyeOpen';
21
+ import { SplitView } from '../../MarkdownIcons/SplitView';
22
+ import { ToolPencil } from '../../MarkdownIcons/ToolPencil';
23
+ import { COMMONMARK_HELP_URL } from '../constants';
24
+ import { EmojiDropdown } from '../Emoji/EmojiDropdown';
25
+ import { ActionsLeftWrapper, ActionsRightWrapper, ButtonsWrapper, MarkdownActionsWrapper, MarkdownMenuItem, } from '../Markdown.styled';
26
+ import { MarkdownFormatButton } from '../MarkdownHelpers/MarkdownFormatButton';
27
+ import { setMarkdown } from '../MarkdownHelpers/markdownHelpers';
28
+ import { markdownHelpHeaders, markdownHelpLists, markdownHelpOther, markdownHelpText } from '../MarkdownHelpItems';
29
+ import { ViewMode } from '../types';
30
30
  export var MarkdownActions = function (_a) {
31
- var textAreaRef = _a.textAreaRef, selectionStart = _a.selectionStart, selectionEnd = _a.selectionEnd, loadingFile = _a.loadingFile, onOpenFileDialog = _a.onOpenFileDialog, onClickFullscreen = _a.onClickFullscreen, fullscreen = _a.fullscreen, viewMode = _a.viewMode, onChangeViewMode = _a.onChangeViewMode, horizontalPaddings = _a.horizontalPaddings, hasFilesApi = _a.hasFilesApi, width = _a.width, showActionHints = _a.showActionHints, showShortKeys = _a.showShortKeys, hideOptions = _a.hideOptions, onSelectEmoji = _a.onSelectEmoji, isSplitViewAvailable = _a.isSplitViewAvailable, disableFullscreen = _a.disableFullscreen, availableAIMethods = _a.availableAIMethods, AIApi = _a.AIApi;
31
+ var textAreaRef = _a.textAreaRef, selectionStart = _a.selectionStart, selectionEnd = _a.selectionEnd, loadingFile = _a.loadingFile, onOpenFileDialog = _a.onOpenFileDialog, onClickFullscreen = _a.onClickFullscreen, fullscreen = _a.fullscreen, viewMode = _a.viewMode, onChangeViewMode = _a.onChangeViewMode, horizontalPaddings = _a.horizontalPaddings, hasFilesApi = _a.hasFilesApi, width = _a.width, showActionHints = _a.showActionHints, showShortKeys = _a.showShortKeys, hideOptions = _a.hideOptions, onSelectEmoji = _a.onSelectEmoji, isSplitViewAvailable = _a.isSplitViewAvailable, disableFullscreen = _a.disableFullscreen, AIApi = _a.AIApi;
32
32
  var isPreviewMode = viewMode === ViewMode.Preview;
33
33
  return (React.createElement(MarkdownActionsWrapper, __assign({}, horizontalPaddings, { width: width, fullscreen: fullscreen }),
34
34
  React.createElement(ButtonsWrapper, { fullscreen: fullscreen },
35
35
  React.createElement(ActionsLeftWrapper, null,
36
- !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.heading) && (React.createElement(MarkdownDropdown, null,
37
- React.createElement(Hint, { text: "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A", pos: "top left" },
38
- React.createElement(Dropdown, { disablePortal: true, disabled: isPreviewMode, menuWidth: 300, caption: "H" }, markdownHelpHeaders.map(function (helper, idx) { return (React.createElement(MarkdownMenuItem, { key: idx, onClick: function (event) { return handleMarkdownItemClick(event, helper.format); } },
39
- React.createElement(MarkdownCombination, { showShortKey: showShortKeys, format: helper.format, text: helper.node }))); }))))),
36
+ !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.heading) && (React.createElement(MarkdownDropdown, { caption: "H", hintText: "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A", disabled: isPreviewMode }, markdownHelpHeaders.map(function (helper, idx) { return (React.createElement(MarkdownMenuItem, { key: idx, onClick: function (event) { return handleMarkdownItemClick(event, helper.format); } },
37
+ React.createElement(MarkdownCombination, { showShortKey: showShortKeys, format: helper.format, text: helper.node }))); }))),
40
38
  markdownHelpText.map(function (helper, idx) {
41
39
  if (isHiddenOptions(helper.format))
42
40
  return null;
@@ -54,9 +52,9 @@ export var MarkdownActions = function (_a) {
54
52
  }),
55
53
  hasFilesApi && !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.file) && (React.createElement(MarkdownFormatButton, { hintText: "\u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B", showActionHint: showActionHints, showShortKey: showShortKeys, disabled: isPreviewMode, isLoading: loadingFile, icon: React.createElement(AttachPaperclip, null), text: "\u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B", onClick: onOpenFileDialog })),
56
54
  !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.emoji) && (React.createElement(EmojiDropdown, { showShortKey: showShortKeys, isPreviewMode: isPreviewMode, onSelect: onSelectEmoji })),
57
- !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.help) && (React.createElement(MarkdownFormatButton, { hintText: "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F Markdown", icon: React.createElement(DocIcon, null), text: "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F Markdown", href: COMMONMARK_HELP_URL })),
58
- !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.heading) && !!(availableAIMethods === null || availableAIMethods === void 0 ? void 0 : availableAIMethods.length) && !!AIApi && (React.createElement(AIActionsDropdown, { textAreaRef: textAreaRef, isPreviewMode: isPreviewMode, selectionStart: selectionStart, selectionEnd: selectionEnd, availableAIMethods: availableAIMethods, AIApi: AIApi }))),
55
+ !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.AI) && !!AIApi && (React.createElement(AIActionsDropdown, { textareaRef: textAreaRef, isPreviewMode: isPreviewMode, api: AIApi }))),
59
56
  React.createElement(ActionsRightWrapper, null,
57
+ !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.help) && (React.createElement(MarkdownFormatButton, { hintText: "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F Markdown", icon: React.createElement(DocIcon, null), text: "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F Markdown", href: COMMONMARK_HELP_URL })),
60
58
  !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.viewMode) && renderViewModeButton(),
61
59
  !(hideOptions === null || hideOptions === void 0 ? void 0 : hideOptions.screenMode) && !disableFullscreen && (React.createElement(MarkdownFormatButton, { hintText: fullscreen ? 'Свернуть' : 'Развернуть', icon: fullscreen ? React.createElement(Collapse, null) : React.createElement(Expand, null), text: fullscreen ? 'Свернуть' : ' Развернуть', onClick: onClickFullscreen }))))));
62
60
  function renderViewModeButton() {
@@ -0,0 +1,11 @@
1
+ import { FC, PropsWithChildren, ReactElement, ReactNode } from 'react';
2
+ interface Props {
3
+ caption: ReactNode;
4
+ disabled?: boolean;
5
+ hintText?: string;
6
+ icon?: ReactElement;
7
+ menuWidth?: number;
8
+ onOpen?: () => void;
9
+ }
10
+ export declare const MarkdownDropdown: FC<PropsWithChildren<Props>>;
11
+ export {};
@@ -0,0 +1,14 @@
1
+ import { Dropdown, Hint } from '@skbkontur/react-ui';
2
+ import React, { useState } from 'react';
3
+ import { Wrapper } from './MarkdownDropdown.styled';
4
+ export var MarkdownDropdown = function (_a) {
5
+ var icon = _a.icon, disabled = _a.disabled, children = _a.children, caption = _a.caption, onOpen = _a.onOpen, menuWidth = _a.menuWidth, hintText = _a.hintText;
6
+ var _b = useState(false), isOpened = _b[0], setIsOpened = _b[1];
7
+ return (React.createElement(Wrapper, { onMouseDown: function (e) { return e.preventDefault(); } },
8
+ React.createElement(Hint, { text: hintText, pos: "top left", manual: isOpened, opened: !isOpened },
9
+ React.createElement(Dropdown, { disablePortal: true, disabled: disabled, menuWidth: menuWidth !== null && menuWidth !== void 0 ? menuWidth : 300, caption: caption, icon: icon, onOpen: handleOpen, onClose: function () { return setIsOpened(false); } }, children))));
10
+ function handleOpen() {
11
+ onOpen === null || onOpen === void 0 ? void 0 : onOpen();
12
+ setIsOpened(true);
13
+ }
14
+ };
@@ -0,0 +1 @@
1
+ export declare const Wrapper: import("styled-components").StyledComponent<"div", import("../../../..").MarkdownTheme, {}, never>;
@@ -0,0 +1,7 @@
1
+ var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
2
+ if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
3
+ return cooked;
4
+ };
5
+ import styled from '../../../styles/styled-components';
6
+ export var Wrapper = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n align-items: end;\n padding-bottom: 1px;\n\n button {\n font-size: ", ";\n }\n"], ["\n display: flex;\n align-items: end;\n padding-bottom: 1px;\n\n button {\n font-size: ", ";\n }\n"])), function (p) { return p.theme.elementsFontSize; });
7
+ var templateObject_1;
@@ -25,9 +25,19 @@ export interface User {
25
25
  teams: RefItem[];
26
26
  sid?: string;
27
27
  }
28
- export interface MarkdownApi {
28
+ export interface AIMethod {
29
+ caption: string;
30
+ method: string;
31
+ }
32
+ export interface AIApi {
33
+ /** Доступные методы ИИ апи */
34
+ availableMethods: AIMethod[];
29
35
  /** Метод для обработки текста с помощью ИИ */
30
- AIApi?: (query: string, method: string) => Promise<string>;
36
+ onSendMessage: (query: string, method: string) => Promise<Nullable<string>>;
37
+ }
38
+ export interface MarkdownApi {
39
+ /** Апи для взаимодействия с ИИ */
40
+ AIApi?: AIApi;
31
41
  /** Метод для загрузки файла */
32
42
  fileDownloadApi?: (id: string) => Promise<File>;
33
43
  /** Метод для скачивания файла */
@@ -41,4 +51,4 @@ export interface TestCase<V, E> {
41
51
  values: V;
42
52
  }
43
53
  export type ReactUIThemeType = Partial<typeof THEME_2022>;
44
- export type HideActionsOptions = Partial<Record<MarkdownFormat | 'heading' | 'emoji' | 'viewMode' | 'screenMode' | 'help' | 'allActions', boolean>>;
54
+ export type HideActionsOptions = Partial<Record<MarkdownFormat | 'heading' | 'emoji' | 'viewMode' | 'screenMode' | 'help' | 'allActions' | 'AI', boolean>>;
@@ -0,0 +1,2 @@
1
+ import { FC } from 'react';
2
+ export declare const Copy: FC;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export var Copy = function () {
3
+ return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 20 20", fill: "none" },
4
+ React.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M7 2C5.34315 2 4 3.34315 4 5V15C4 16.6569 5.34315 18 7 18H13C14.6569 18 16 16.6569 16 15V5C16 3.34315 14.6569 2 13 2H7ZM5 5C5 3.89543 5.89543 3 7 3H13C14.1046 3 15 3.89543 15 5V15C15 16.1046 14.1046 17 13 17H7C5.89543 17 5 16.1046 5 15V5Z", fill: "currentColor" }),
5
+ React.createElement("path", { d: "M18 8.5C18 8.22386 17.7761 8 17.5 8C17.2239 8 17 8.22386 17 8.5V15.5C17 17.433 15.433 19 13.5 19H8.5C8.22386 19 8 19.2239 8 19.5C8 19.7761 8.22386 20 8.5 20H13.5C15.9853 20 18 17.9853 18 15.5V8.5Z", fill: "currentColor" })));
6
+ };
@@ -0,0 +1,2 @@
1
+ import { FC } from 'react';
2
+ export declare const NatureFxSparkleA2: FC;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export var NatureFxSparkleA2 = function () {
3
+ return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 20 20", fill: "none" },
4
+ React.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M15.0413 1.49763C14.9148 0.934973 14.0776 0.935061 13.9512 1.49773C13.8878 1.77985 13.7684 2.24714 13.5864 2.72017C13.3999 3.20461 13.1678 3.64088 12.9029 3.90557C12.6384 4.16985 12.2027 4.40143 11.719 4.5875C11.2466 4.7692 10.7799 4.88837 10.4978 4.9517C9.93495 5.07806 9.93504 5.91564 10.4979 6.0419C10.7802 6.1052 11.2472 6.22439 11.7199 6.40617C12.204 6.59234 12.6399 6.82409 12.9044 7.08863C13.1689 7.35316 13.4007 7.78906 13.5869 8.27315C13.7686 8.74585 13.8878 9.21288 13.9511 9.49509C14.0774 10.058 14.915 10.0581 15.0413 9.4952C15.1047 9.21313 15.2238 8.74645 15.4055 8.27407C15.5916 7.79031 15.8232 7.35465 16.0875 7.09015C16.3521 6.82526 16.7884 6.59315 17.2729 6.40668C17.7459 6.2246 18.2132 6.10521 18.4953 6.04183C19.058 5.91544 19.0581 5.07826 18.4954 4.95176C18.2134 4.88837 17.7465 4.76899 17.2738 4.587C16.7897 4.40062 16.3536 4.16869 16.089 3.90404C15.8243 3.6394 15.5924 3.20335 15.406 2.71926C15.224 2.24654 15.1047 1.77959 15.0413 1.49763ZM14.4964 3.139C14.9555 4.30255 15.6905 5.03751 16.854 5.49666C15.6907 5.95548 14.9553 6.68969 14.4964 7.85299C14.0378 6.68993 13.3031 5.95528 12.14 5.49666C13.3033 5.03771 14.0376 4.30231 14.4964 3.139Z", fill: "currentColor" }),
5
+ React.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M7.55535 5.97566C7.42933 5.39847 6.56967 5.39855 6.44376 5.97577C6.3559 6.37855 6.17724 7.10496 5.89522 7.85362C5.60854 8.61465 5.23608 9.34063 4.78623 9.79012C4.33703 10.239 3.61201 10.6106 2.85198 10.8967C2.10429 11.1781 1.37878 11.3565 0.976004 11.4443C0.398567 11.5701 0.398646 12.4302 0.976106 12.556C1.37908 12.6438 2.10513 12.8221 2.85332 13.1037C3.61387 13.3899 4.33931 13.7618 4.78859 14.2111C5.23788 14.6604 5.60979 15.3858 5.89601 16.1464C6.17759 16.8946 6.35592 17.6206 6.44369 18.0236C6.56945 18.601 7.42955 18.6011 7.55542 18.0237C7.64322 17.6209 7.82156 16.8954 8.10299 16.1477C8.38907 15.3877 8.76071 14.6627 9.20956 14.2134C9.65905 13.7636 10.385 13.3911 11.1461 13.1045C11.8947 12.8224 12.6211 12.6438 13.0239 12.5559C13.6011 12.43 13.6012 11.5703 13.024 11.4443C12.6214 11.3564 11.8956 11.1778 11.1474 10.8959C10.3869 10.6094 9.66133 10.2372 9.21192 9.78776C8.76251 9.33836 8.39031 8.61279 8.10378 7.85228C7.8219 7.10412 7.64324 6.37824 7.55535 5.97566ZM6.99971 7.72905C7.32853 8.71941 7.75702 9.74708 8.50481 10.4949C9.25261 11.2427 10.2803 11.6712 11.2706 12C10.2793 12.329 9.25042 12.7578 8.50217 13.5066C7.75568 14.2537 7.32793 15.2799 6.99971 16.269C6.67134 15.2789 6.24323 14.2515 5.4957 13.504C4.74817 12.7564 3.72074 12.3283 2.73064 12C3.71974 11.6718 4.74597 11.244 5.49306 10.4975C6.2419 9.74927 6.67074 8.72041 6.99971 7.72905Z", fill: "currentColor" })));
6
+ };
@@ -1,13 +0,0 @@
1
- import { Textarea } from '@skbkontur/react-ui';
2
- import { FC, RefObject } from 'react';
3
- import { Nullable } from '../types';
4
- interface Props {
5
- AIApi: (query: string, type: string) => Promise<string>;
6
- availableAIMethods: string[];
7
- textAreaRef: RefObject<Textarea>;
8
- isPreviewMode?: boolean;
9
- selectionEnd?: Nullable<number>;
10
- selectionStart?: Nullable<number>;
11
- }
12
- export declare const AIActionsDropdown: FC<Props>;
13
- export {};
@@ -1,113 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var __generator = (this && this.__generator) || function (thisArg, body) {
11
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
- function verb(n) { return function (v) { return step([n, v]); }; }
14
- function step(op) {
15
- if (f) throw new TypeError("Generator is already executing.");
16
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
- if (y = 0, t) op = [op[0] & 2, t.value];
19
- switch (op[0]) {
20
- case 0: case 1: t = op; break;
21
- case 4: _.label++; return { value: op[1], done: false };
22
- case 5: _.label++; y = op[1]; op = [0]; continue;
23
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
- default:
25
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
- if (t[2]) _.ops.pop();
30
- _.trys.pop(); continue;
31
- }
32
- op = body.call(thisArg, _);
33
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
- }
36
- };
37
- import { Button, Dropdown, Hint, Spinner, Toast, Tooltip } from '@skbkontur/react-ui';
38
- import React, { useEffect, useRef, useState } from 'react';
39
- import { MarkdownDropdown, MarkdownMenuItem } from '../Markdown.styled';
40
- import { Guid } from '../utils/guid';
41
- import { RequestStatus } from '../utils/requestStatus';
42
- export var AIActionsDropdown = function (_a) {
43
- var selectionStart = _a.selectionStart, selectionEnd = _a.selectionEnd, textAreaRef = _a.textAreaRef, isPreviewMode = _a.isPreviewMode, availableAIMethods = _a.availableAIMethods, AIApi = _a.AIApi;
44
- var _b = useState(), processedText = _b[0], setProcessedText = _b[1];
45
- var _c = useState(RequestStatus.Default), requestStatus = _c[0], setRequestStatus = _c[1];
46
- var tooltipRef = useRef(null);
47
- var taskIdRef = useRef(new Guid());
48
- useEffect(function () {
49
- handleCloseTooltip();
50
- }, [selectionStart, selectionEnd, AIApi]);
51
- if (!(textAreaRef === null || textAreaRef === void 0 ? void 0 : textAreaRef.current))
52
- return null;
53
- var htmlTextArea = textAreaRef.current.node;
54
- var content = (React.createElement(MarkdownDropdown, { onMouseDown: function (e) { return e.preventDefault(); } },
55
- React.createElement(Hint, { text: "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A", pos: "top left" },
56
- React.createElement(Dropdown, { disablePortal: true, disabled: isPreviewMode, menuWidth: 180, caption: "AI", onOpen: handleCloseTooltip }, availableAIMethods.map(function (method) { return (React.createElement(MarkdownMenuItem, { key: method, onClick: function () {
57
- var _a;
58
- (_a = tooltipRef === null || tooltipRef === void 0 ? void 0 : tooltipRef.current) === null || _a === void 0 ? void 0 : _a.show();
59
- handleProcessText(method);
60
- } }, method)); })))));
61
- return (React.createElement(Tooltip, { ref: tooltipRef, trigger: "manual", render: renderTooltipContent, onClose: handleCloseTooltip }, content));
62
- function renderTooltipContent() {
63
- if (requestStatus === RequestStatus.isFetching)
64
- return React.createElement(Spinner, { caption: "\u041E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u0435\u043C", type: "mini" });
65
- return (React.createElement("div", { style: { maxWidth: 300, display: 'flex', gap: 16, flexDirection: 'column' } },
66
- React.createElement("div", null, processedText),
67
- React.createElement(Button, { onClick: handleSetText }, "\u0417\u0430\u043C\u0435\u043D\u0438\u0442\u044C \u0442\u0435\u043A\u0441\u0442")));
68
- }
69
- function handleProcessText(method) {
70
- return __awaiter(this, void 0, void 0, function () {
71
- var taskId, value, response, e_1;
72
- return __generator(this, function (_a) {
73
- switch (_a.label) {
74
- case 0:
75
- _a.trys.push([0, 2, , 3]);
76
- taskIdRef.current.generate();
77
- taskId = taskIdRef.current.generated;
78
- setRequestStatus(RequestStatus.isFetching);
79
- value = htmlTextArea.value.substring(Number(selectionStart), selectionEnd !== null && selectionEnd !== void 0 ? selectionEnd : undefined);
80
- return [4 /*yield*/, AIApi(value, method)];
81
- case 1:
82
- response = _a.sent();
83
- if (response && taskId === taskIdRef.current.generated) {
84
- setRequestStatus(RequestStatus.isLoaded);
85
- setProcessedText(response);
86
- }
87
- return [3 /*break*/, 3];
88
- case 2:
89
- e_1 = _a.sent();
90
- Toast.push('Ошибка обработки текста');
91
- return [3 /*break*/, 3];
92
- case 3: return [2 /*return*/];
93
- }
94
- });
95
- });
96
- }
97
- function handleSetText() {
98
- if (isNaN(Number(selectionStart)) || isNaN(Number(selectionEnd)))
99
- return null;
100
- if (textAreaRef === null || textAreaRef === void 0 ? void 0 : textAreaRef.current) {
101
- textAreaRef.current.focus();
102
- htmlTextArea.selectionStart = Number(selectionStart);
103
- htmlTextArea.selectionEnd = Number(selectionEnd);
104
- document.execCommand('insertText', false, processedText);
105
- handleCloseTooltip();
106
- }
107
- }
108
- function handleCloseTooltip() {
109
- var _a;
110
- setProcessedText(undefined);
111
- (_a = tooltipRef === null || tooltipRef === void 0 ? void 0 : tooltipRef.current) === null || _a === void 0 ? void 0 : _a.hide();
112
- }
113
- };