Skip to content

Commit 0040e2a

Browse files
authored
feat(toolbar, bundle): add ToolbarButtonPopup type and use it for link, image and file actions in murkup mode (#228)
1 parent bd82b46 commit 0040e2a

17 files changed

+491
-462
lines changed
Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import React from 'react';
2+
13
import {i18n} from '../../i18n/menubar';
24
import {
35
isBoldActive,
@@ -10,6 +12,7 @@ import {
1012
isItalicActive,
1113
} from '../../markup/active';
1214
import {
15+
insertLink,
1316
insertTable,
1417
liftListItem,
1518
sinkListItem,
@@ -45,19 +48,21 @@ import {ToolbarData} from '../../toolbar/Toolbar';
4548
import {ToolbarGroupData} from '../../toolbar/ToolbarGroup';
4649
import {ToolbarListButtonData} from '../../toolbar/ToolbarListButton';
4750
import {
51+
ToolbarButtonPopupData,
4852
ToolbarDataType,
4953
ToolbarListItemData,
5054
ToolbarReactComponentData,
5155
ToolbarSingleItemData,
5256
} from '../../toolbar/types';
57+
import {ToolbarLinkPopup} from '../toolbar/custom/ToolbarLinkPopup';
5358
import {MToolbarColors} from '../toolbar/markup/MToolbarColors';
54-
import {MToolbarFile} from '../toolbar/markup/MToolbarFile';
55-
import {MToolbarImage} from '../toolbar/markup/MToolbarImage';
56-
import {MToolbarLink} from '../toolbar/markup/MToolbarLink';
59+
import {MToolbarFilePopup} from '../toolbar/markup/MToolbarFilePopup';
60+
import {MToolbarImagePopup} from '../toolbar/markup/MToolbarImagePopup';
5761

5862
import {ActionName} from './action-names';
5963
import {icons} from './icons';
6064

65+
const noop = () => {};
6166
const isActiveFn = () => false;
6267
const isEnableFn = () => true;
6368

@@ -278,11 +283,29 @@ export const mListMoveListConfig: MToolbarListButtonData = {
278283
],
279284
};
280285

281-
export const mLinkButton: MToolbarReactComponentData = {
286+
export const mLinkButton: ToolbarButtonPopupData<CodeEditor> = {
282287
id: ActionName.link,
283-
type: ToolbarDataType.ReactComponent,
284-
component: MToolbarLink,
285-
width: 28,
288+
type: ToolbarDataType.ButtonPopup,
289+
icon: icons.link,
290+
title: i18n('link'),
291+
exec: noop,
292+
isActive: isActiveFn,
293+
isEnable: isEnableFn,
294+
renderPopup: (props) => {
295+
const {editor} = props;
296+
const selection = editor.cm.getSelection();
297+
298+
return (
299+
<ToolbarLinkPopup
300+
{...props}
301+
formInitialText={selection}
302+
formReadOnlyText={Boolean(selection)}
303+
onSubmit={(url, text) => {
304+
insertLink({url, text})(editor.cm);
305+
}}
306+
/>
307+
);
308+
},
286309
};
287310

288311
export const mNoteButton: MToolbarSingleItemData = {
@@ -427,15 +450,23 @@ export const mToolbarConfig: MToolbarData = [
427450
[
428451
{
429452
id: 'image',
430-
type: ToolbarDataType.ReactComponent,
431-
component: MToolbarImage,
432-
width: 28,
453+
type: ToolbarDataType.ButtonPopup,
454+
icon: icons.image,
455+
title: i18n('image'),
456+
exec: noop,
457+
isActive: isActiveFn,
458+
isEnable: isEnableFn,
459+
renderPopup: (props) => <MToolbarImagePopup {...props} />,
433460
},
434461
{
435462
id: 'file',
436-
type: ToolbarDataType.ReactComponent,
437-
component: MToolbarFile,
438-
width: 28,
463+
type: ToolbarDataType.ButtonPopup,
464+
icon: icons.file,
465+
title: i18n('file'),
466+
exec: noop,
467+
isActive: isActiveFn,
468+
isEnable: isEnableFn,
469+
renderPopup: (props) => <MToolbarFilePopup {...props} />,
439470
},
440471
mTableButton,
441472
mCheckboxButton,

src/bundle/toolbar/custom/ToolbarFile.tsx

Lines changed: 0 additions & 103 deletions
This file was deleted.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import React, {RefObject, useCallback} from 'react';
2+
3+
import {Popup, PopupPlacement} from '@gravity-ui/uikit';
4+
5+
import {FileForm, FileFormProps} from '../../../forms/FileForm';
6+
import {i18n} from '../../../i18n/forms';
7+
import {useBooleanState} from '../../../react-utils/hooks';
8+
import {useToaster} from '../../../react-utils/toaster';
9+
import type {ToolbarBaseProps} from '../../../toolbar';
10+
import {BatchUploadResult, FileUploadHandler, batchUploadFiles} from '../../../utils/upload';
11+
12+
const placement: PopupPlacement = ['bottom-start', 'top-start', 'bottom-end', 'top-end'];
13+
14+
export type ToolbarFilePopupProps = Omit<ToolbarBaseProps<never>, 'editor'> & {
15+
hide: () => void;
16+
anchorRef: RefObject<HTMLElement>;
17+
18+
uploadHandler?: FileUploadHandler;
19+
onSuccessUpload?: (result: BatchUploadResult) => void;
20+
} & Pick<FileFormProps, 'onSubmit'>;
21+
22+
export const ToolbarFilePopup: React.FC<ToolbarFilePopupProps> = ({
23+
className,
24+
hide,
25+
anchorRef,
26+
27+
onSubmit,
28+
focus,
29+
onClick,
30+
uploadHandler,
31+
onSuccessUpload,
32+
}) => {
33+
const toaster = useToaster();
34+
const [loading, showLoading, hideLoading] = useBooleanState(false);
35+
36+
const handleCancel = useCallback(() => {
37+
hide();
38+
focus();
39+
}, [focus, hide]);
40+
41+
return (
42+
<Popup
43+
open
44+
onClose={handleCancel}
45+
anchorRef={anchorRef}
46+
placement={placement}
47+
className={className}
48+
>
49+
<FileForm
50+
autoFocus
51+
onAttach={
52+
uploadHandler &&
53+
((files) => {
54+
showLoading();
55+
batchUploadFiles(files, uploadHandler).then(
56+
(res) => {
57+
hideLoading();
58+
hide();
59+
onSuccessUpload?.(res);
60+
},
61+
(error) => {
62+
hideLoading();
63+
toaster.add({
64+
theme: 'danger',
65+
name: 'toolbar_file_upload',
66+
title: i18n('file_upload_failed'),
67+
content: String(error),
68+
});
69+
},
70+
);
71+
})
72+
}
73+
onCancel={handleCancel}
74+
onSubmit={(data) => {
75+
hide();
76+
focus();
77+
onSubmit(data);
78+
onClick?.('addFile');
79+
}}
80+
loading={loading}
81+
/>
82+
</Popup>
83+
);
84+
};

src/bundle/toolbar/custom/ToolbarImage.tsx

Lines changed: 0 additions & 103 deletions
This file was deleted.

0 commit comments

Comments
 (0)