Skip to content

Commit ad320a7

Browse files
authored
fix: fixed style, exports and typings after adding more functionality (#213)
1 parent c9c6fb5 commit ad320a7

File tree

15 files changed

+387
-43
lines changed

15 files changed

+387
-43
lines changed

package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@
5050
"require": "./build/cjs/view/*",
5151
"import": "./build/esm/view/*"
5252
},
53+
"./bundle/*": {
54+
"types": "./build/esm/bundle/*",
55+
"require": "./build/cjs/bundle/*",
56+
"import": "./build/esm/bundle/*"
57+
},
5358
"./pm/*": {
5459
"types": "./build/esm/pm/*",
5560
"require": "./build/cjs/pm/*",
@@ -89,6 +94,15 @@
8994
],
9095
"_/*": [
9196
"./build/esm/*"
97+
],
98+
"./extensions": [
99+
"./build/esm/extensions/index.js"
100+
],
101+
"./view/*": [
102+
"./build/esm/view/*"
103+
],
104+
"./bundle/*": [
105+
"./build/esm/bundle/*"
92106
]
93107
}
94108
},

src/bundle/YfmEditor.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export type YfmEditorRef = Editor & {
2727
* The `YfmEditor` component will be removed soon.
2828
* Use `useYfmEditor` hook and `YfmEditorView` component instead.
2929
*/
30-
export type YfmEditorProps = ClassNameProps &
30+
export type YfmEditorProps<T extends object = {}> = ClassNameProps &
3131
Pick<
3232
YfmEditorViewProps,
3333
'settingsVisible' | 'toaster' | 'wysiwygHiddenActionsConfig' | 'markupHiddenActionsConfig'
@@ -107,7 +107,7 @@ export type YfmEditorProps = ClassNameProps &
107107
onCancel?(editor: YfmEditorRef): boolean;
108108

109109
onFileUpload?: UseYfmEditorProps['fileUploadHandler'];
110-
extensionOptions?: UseYfmEditorProps['extensionOptions'];
110+
extensionOptions?: UseYfmEditorProps<T>['extensionOptions'];
111111

112112
/**
113113
* If we need to set dimensions for uploaded images
@@ -122,7 +122,7 @@ export type YfmEditorProps = ClassNameProps &
122122
* The `YfmEditor` component will be removed soon.
123123
* Use `useYfmEditor` hook and `YfmEditorView` component instead.
124124
*/
125-
export const YfmEditor = React.forwardRef<YfmEditorRef, YfmEditorProps>(function YfmEditor(
125+
export const YfmEditor = React.forwardRef(function YfmEditor<T extends object>(
126126
{
127127
className,
128128
splitMode,
@@ -156,8 +156,8 @@ export const YfmEditor = React.forwardRef<YfmEditorRef, YfmEditorProps>(function
156156
wysiwygHiddenActionsConfig,
157157
markupHiddenActionsConfig,
158158
stickyToolbar = true,
159-
},
160-
ref,
159+
}: YfmEditorProps<T>,
160+
ref: React.Ref<YfmEditorRef>,
161161
) {
162162
const editor = useYfmEditor({
163163
splitMode,
@@ -279,4 +279,6 @@ export const YfmEditor = React.forwardRef<YfmEditorRef, YfmEditorProps>(function
279279
stickyToolbar={stickyToolbar}
280280
/>
281281
);
282-
});
282+
}) as <T extends object = {}>(
283+
props: YfmEditorProps<T> & {ref?: React.Ref<YfmEditorRef>},
284+
) => JSX.Element;

src/bundle/useYfmEditor.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,21 @@ import {logger} from '../logger';
77
import {Editor, EditorImpl, EditorInt, EditorOptions, EditorType} from './Editor';
88
import {BundlePreset, ExtensionsOptions} from './wysiwyg-preset';
99

10-
export type UseYfmEditorProps = Omit<EditorOptions, 'extensions' | 'renderStorage'> & {
10+
export type UseYfmEditorProps<T extends object = {}> = Omit<
11+
EditorOptions,
12+
'extensions' | 'renderStorage'
13+
> & {
1114
breaks?: boolean;
1215
/** Used only first value. Сhanging the value will not lead to anything */
13-
extensionOptions?: Omit<ExtensionsOptions, 'reactRenderer'>;
16+
extensionOptions?: Omit<ExtensionsOptions, 'reactRenderer'> & T;
1417
/** Used only first value. Сhanging the value will not lead to anything */
1518
extraExtensions?: Extension;
1619
};
1720

18-
export function useYfmEditor(props: UseYfmEditorProps, deps: React.DependencyList = []): Editor {
21+
export function useYfmEditor<T extends object = {}>(
22+
props: UseYfmEditorProps<T>,
23+
deps: React.DependencyList = [],
24+
): Editor {
1925
const editor = useMemo<EditorInt>(
2026
() => {
2127
const renderStorage = new ReactRenderStorage();
@@ -37,7 +43,7 @@ export function useYfmEditor(props: UseYfmEditorProps, deps: React.DependencyLis
3743
props.needToSetDimensionsForUploadedImages,
3844
});
3945
if (props.extraExtensions) {
40-
builder.use(props.extraExtensions);
46+
builder.use(props.extraExtensions, props.extensionOptions);
4147
}
4248
};
4349
return new EditorImpl({...props, extensions, renderStorage});

src/extensions/yfm/Mermaid/MermaidNodeView/Mermaid.scss

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.Mermaid {
1+
.ye-Mermaid {
22
display: flex;
33
justify-content: space-between;
44

@@ -12,32 +12,32 @@
1212
display: flex;
1313
}
1414

15-
&-Preview {
15+
&__Preview {
1616
flex: 1;
1717
}
1818

19-
&-Error {
19+
&__Error {
2020
flex: 1;
2121

2222
font-family: var(--g-font-family-monospace);
2323

2424
color: var(--g-color-text-danger);
2525
}
2626

27-
&-Editor {
27+
&__Editor {
2828
flex: 1;
2929

3030
white-space: nowrap;
3131
caret-color: auto;
3232
}
3333

34-
&-EditorPopover {
34+
&__EditorPopover {
3535
z-index: 1;
3636

3737
float: right;
3838
}
3939

40-
&-Controls {
40+
&__Controls {
4141
display: flex;
4242
justify-content: end;
4343

src/extensions/yfm/YfmTabs/index.scss

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,8 @@
44
.yfm-tabs {
55
@include mixins.block-border-hover();
66
}
7-
8-
.yfm-tab {
9-
position: relative;
10-
11-
display: flex;
12-
align-items: center;
13-
14-
margin-right: 3px;
15-
padding-bottom: 0;
16-
17-
border-bottom: none;
18-
19-
.ye-placeholder {
20-
color: var(--g-color-text-hint);
21-
}
22-
23-
&-wrapper {
7+
.ye-yfm-tab {
8+
&__wrapper {
249
position: relative;
2510

2611
display: flex;
@@ -33,13 +18,7 @@
3318
background-clip: padding-box;
3419
}
3520

36-
&[data-diplodoc-is-active='true'] {
37-
.yfm-tab-wrapper {
38-
border-bottom-color: #027bf3;
39-
}
40-
}
41-
42-
&-remove-button {
21+
&__remove-button {
4322
display: flex;
4423

4524
width: 15px;
@@ -54,7 +33,7 @@
5433
}
5534
}
5635

57-
&-create-button {
36+
&__create-button {
5837
display: flex;
5938
justify-content: center;
6039
align-items: center;
@@ -73,10 +52,31 @@
7352
background: var(--g-color-base-generic-hover);
7453
}
7554
}
55+
}
56+
.yfm-tab {
57+
position: relative;
58+
59+
display: flex;
60+
align-items: center;
61+
62+
margin-right: 3px;
63+
padding-bottom: 0;
64+
65+
border-bottom: none;
66+
67+
.ye-placeholder {
68+
color: var(--g-color-text-hint);
69+
}
70+
71+
&[data-diplodoc-is-active='true'] {
72+
.ye-yfm-tab__wrapper {
73+
border-bottom-color: #027bf3;
74+
}
75+
}
7676

7777
&:hover,
7878
&:last-child {
79-
.yfm-tab-create-button {
79+
.ye-yfm-tab__create-button {
8080
opacity: 1;
8181
}
8282
}

src/forms/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './base';
2+
export * from './components';

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ export * from './react-utils';
66
export * from './classname';
77
export * from './logger';
88
export * from './extensions';
9+
export * from './plugins';
910
export * from './extensions/specs';
11+
export * from './forms';
1012

1113
export {Lang, configure} from './configure';
1214

src/plugins/BaseTooltip/index.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
min-height: 100%;
2020
}
2121

22-
&-content {
22+
&__content {
2323
&__row {
2424
display: flex;
2525
justify-content: space-between;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React, {ReactNode, useLayoutEffect, useRef, useState} from 'react';
2+
3+
import {Ellipsis} from '@gravity-ui/icons';
4+
import {Button, Icon, Popup, PopupPlacement, PopupProps} from '@gravity-ui/uikit';
5+
6+
import {useBooleanState} from '../../react-utils';
7+
8+
type TooltipButtonProps = Pick<PopupProps, 'onOutsideClick'> & {
9+
domRef: HTMLElement | null;
10+
children?: React.ReactNode;
11+
};
12+
13+
export const TooltipButton: React.FC<TooltipButtonProps> = ({domRef, onOutsideClick, children}) => {
14+
const [width, setWidth] = useState(0);
15+
const [open, , hide, toggleOpen] = useBooleanState(false);
16+
const placement: PopupPlacement = ['bottom-end', 'bottom-start'];
17+
const ref = useRef<HTMLDivElement>(null);
18+
const childrenRef = useRef<ReactNode>(children);
19+
20+
useLayoutEffect(() => {
21+
if (ref.current?.clientWidth) {
22+
setWidth(ref.current?.clientWidth);
23+
}
24+
}, [ref.current?.clientWidth]);
25+
26+
return (
27+
<Popup
28+
open
29+
keepMounted={false}
30+
hasArrow={false}
31+
anchorRef={{current: domRef}}
32+
placement={'right-start'}
33+
offset={[3, -(width + 3)]}
34+
onOutsideClick={onOutsideClick}
35+
modifiers={[
36+
{
37+
name: 'preventOverflow',
38+
enabled: false,
39+
},
40+
]}
41+
>
42+
<Button onClick={toggleOpen} ref={ref} size="s" view={open ? 'normal' : 'raised'}>
43+
<Icon data={Ellipsis} />
44+
</Button>
45+
<Popup open={open} anchorRef={ref} onClose={hide} placement={placement}>
46+
{childrenRef.current}
47+
</Popup>
48+
</Popup>
49+
);
50+
};
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React from 'react';
2+
3+
import {NodeType} from 'prosemirror-model';
4+
import {EditorView} from 'prosemirror-view';
5+
6+
import {
7+
BaseTooltipNode,
8+
BaseTooltipPluginOptions,
9+
BaseTooltipPluginView,
10+
TooltipOnChangeCallback,
11+
} from '../BaseTooltip';
12+
13+
import {TooltipButton} from './TooltipButton';
14+
15+
type ButtonContent = (
16+
view: EditorView,
17+
node: BaseTooltipNode,
18+
toggleEdit: () => void,
19+
) => React.ReactElement;
20+
21+
type FormContent = (
22+
view: EditorView,
23+
node: BaseTooltipNode,
24+
onChange?: TooltipOnChangeCallback,
25+
) => React.ReactElement;
26+
27+
interface TooltipMenuOptions extends BaseTooltipPluginOptions {
28+
disableHideOnBlur?: boolean;
29+
buttonContent: ButtonContent;
30+
formContent: FormContent;
31+
}
32+
33+
export class TooltipButtonPluginView extends BaseTooltipPluginView {
34+
private enableHideOnBlur?: boolean;
35+
private forceEdit = false;
36+
private buttonContent: ButtonContent;
37+
private formContent: FormContent;
38+
39+
constructor(view: EditorView, options: TooltipMenuOptions) {
40+
super(view, options);
41+
42+
this.enableHideOnBlur = options.disableHideOnBlur !== true;
43+
this.buttonContent = options.buttonContent;
44+
this.formContent = options.formContent;
45+
if (this.enableHideOnBlur) {
46+
(this.view.dom as HTMLElement).addEventListener('focus', this.onViewFocus);
47+
}
48+
}
49+
50+
toggleEdit = () => {
51+
this.forceEdit = !this.forceEdit;
52+
this.render();
53+
};
54+
55+
destroy(): void {
56+
super.destroy();
57+
(this.view.dom as HTMLElement).removeEventListener('focus', this.onViewFocus);
58+
}
59+
60+
protected renderContent(currentNode: BaseTooltipNode): React.ReactNode {
61+
return (
62+
<>
63+
{this.forceEdit && this.formContent ? (
64+
<div>{this.formContent(this.view, currentNode, this.changeAttrsCb)}</div>
65+
) : (
66+
<TooltipButton domRef={currentNode.dom} onOutsideClick={this.onOutsideClick}>
67+
{this.buttonContent(this.view, currentNode, this.toggleEdit)}
68+
</TooltipButton>
69+
)}
70+
</>
71+
);
72+
}
73+
74+
protected setCurrentNode(node: NodeType) {
75+
super.setCurrentNode(node);
76+
this.currentNode?.dom?.addEventListener('dblclick', this.toggleEdit);
77+
}
78+
79+
protected updateTooltipView() {
80+
this.currentNode?.dom?.removeEventListener('dblclick', this.toggleEdit);
81+
super.updateTooltipView();
82+
}
83+
84+
private onViewFocus = () => {
85+
this.forceEdit = false;
86+
this.manualHidden = false;
87+
this.render();
88+
};
89+
}

0 commit comments

Comments
 (0)