Skip to content

Commit 5d083cd

Browse files
committed
refactor: emoiji extension
1 parent ee24bda commit 5d083cd

File tree

15 files changed

+154
-169
lines changed

15 files changed

+154
-169
lines changed

docs/extensions/Emoji/index.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,21 @@ const extensions = [
5050

5151
...
5252
// Import Extensions Here
53-
Emoji// [!code ++]
53+
Emoji.configure({
54+
suggestion: {
55+
char: ':',
56+
items: async ({ query, }: any) => {
57+
const lowerCaseQuery = query?.toLowerCase();
58+
59+
return EMOJI_LIST.filter(({ name }) =>
60+
name.toLowerCase().includes(lowerCaseQuery)
61+
);
62+
},
63+
},
64+
}),
5465
];
5566

67+
5668
const RichTextToolbar = () => {
5769
return (
5870
<RichTextEmoji /> {/* [!code ++] */}
@@ -78,3 +90,6 @@ const App = () => {
7890
);
7991
};
8092
```
93+
94+
95+
- Copy Emoji List here: https://github.com/hunghg255/reactjs-tiptap-editor-demo/blob/master/src/components/Editor/emojis.ts

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@
528528
"default": "./lib/Video.js"
529529
}
530530
},
531-
"./callout": {
531+
"./callout": {
532532
"require": {
533533
"types": "./lib/extensions/Callout/index.d.ts",
534534
"default": "./lib/Callout.cjs"
@@ -792,11 +792,11 @@
792792
"react-colorful": "^5.6.1",
793793
"react-image-crop": "^11.0.10",
794794
"react-tweet": "^3.3.0",
795+
"reactjs-signal": "^2.0.4",
795796
"scroll-into-view-if-needed": "^3.1.0",
796797
"svg64": "^2.0.0",
797798
"y-protocols": "^1.0.7",
798-
"yjs": "^13.6.28",
799-
"zustand": "^5.0.9"
799+
"yjs": "^13.6.28"
800800
},
801801
"devDependencies": {
802802
"@hunghg255/eslint-config": "^1.0.1",

playground/src/App.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ import 'katex/contrib/mhchem'
9999
// import { HocuspocusProvider } from '@hocuspocus/provider'
100100
// import * as Y from 'yjs'
101101
import { EditorContent, useEditor } from '@tiptap/react';
102+
import { EMOJI_LIST } from '@/emojis'
102103

103104
// const ydoc = new Y.Doc()
104105

@@ -204,7 +205,17 @@ const extensions = [
204205
TextUnderline,
205206
Strike,
206207
MoreMark,
207-
Emoji,
208+
Emoji.configure({
209+
suggestion: {
210+
items: async ({ query, }: any) => {
211+
const lowerCaseQuery = query?.toLowerCase();
212+
213+
return EMOJI_LIST.filter(({ name }) =>
214+
name.toLowerCase().includes(lowerCaseQuery)
215+
);
216+
},
217+
},
218+
}),
208219
Color,
209220
Highlight,
210221
BulletList,
@@ -334,7 +345,7 @@ Callout
334345
// }),
335346
]
336347

337-
const DEFAULT = `<div class="callout" dir="auto" type="note" title="1" body="1"></div><div class="callout" dir="auto" type="tip" title="2" body="2"></div><div class="callout" dir="auto" type="important" title="3" body="3"></div><div class="callout" dir="auto" type="warning" title="4" body="4"></div><div class="callout" dir="auto" type="caution" title="5" body="5"></div><p dir="auto"></p>`
348+
const DEFAULT = `<div class="callout" dir="auto" type="note" title="1" body="1"></div><div class="callout" dir="auto" type="tip" title="2" body="2"></div><div class="callout" dir="auto" type="important" title="3" body="3"></div><div class="callout" dir="auto" type="warning" title="4" body="4"></div><div class="callout" dir="auto" type="caution" title="5" body="5"></div><p dir="auto"><span dir="auto" data-name="smiley" data-type="emoji">😃</span> </p>`
338349

339350
function debounce(func: any, wait: number) {
340351
let timeout: NodeJS.Timeout
@@ -351,6 +362,8 @@ const Header = ({ editor, theme, setTheme }) => {
351362
const currentTheme = useTheme();
352363

353364
useEffect(() => {
365+
localeActions.setLang('vi')
366+
themeActions.setColor('red')
354367
setEditorEditable(editor?.isEditable ?? true);
355368
}, []);
356369

src/extensions/Emoji/components/EmojiList/emojis.ts renamed to playground/src/emojis.ts

File renamed without changes.

pnpm-lock.yaml

Lines changed: 17 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/extensions/Callout/Callout.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ export interface CalloutOptions extends GeneralOptions<CalloutOptions> {
2020

2121
function getDatasetAttribute(attribute: string) {
2222
return (element: any) => {
23-
console.log({
24-
element
25-
});
26-
2723
return element.getAttribute(attribute);
2824
};
2925
}
@@ -65,10 +61,6 @@ export const Callout = /* @__PURE__ */ Node.create<CalloutOptions>({
6561
},
6662

6763
renderHTML({ HTMLAttributes }) {
68-
console.log({
69-
HTMLAttributes
70-
});
71-
7264
return ['div', mergeAttributes((this.options && this.options.HTMLAttributes) || {}, HTMLAttributes)];
7365
},
7466

src/extensions/Emoji/Emoji.ts

Lines changed: 19 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
/* eslint-disable @typescript-eslint/ban-ts-comment */
2-
import TiptapEmoji from '@tiptap/extension-emoji';
3-
import { ReactRenderer } from '@tiptap/react';
2+
import TiptapEmoji, { type EmojiOptions } from '@tiptap/extension-emoji';
3+
import { Extension } from '@tiptap/react';
44

5-
import { updatePosition } from '@/utils/updatePosition';
5+
import { renderNodeViewClosure } from '@/utils/renderNodeView';
66

77
import EmojiNodeView from './components/EmojiList/EmojiNodeView';
88

99
export * from '@/extensions/Emoji/components/RichTextEmoji';
1010

1111
export const EXTENSION_PRIORITY_HIGHEST = 200;
1212

13-
export const Emoji = /* @__PURE__ */ TiptapEmoji.extend({
13+
export const Emoji = /* @__PURE__ */ Extension.create<EmojiOptions>({
14+
name: 'richTextEmojiWrapper',
1415
priority: EXTENSION_PRIORITY_HIGHEST,
1516
// emojis: gitHubEmojis,
1617
enableEmoticons: true,
@@ -38,60 +39,20 @@ export const Emoji = /* @__PURE__ */ TiptapEmoji.extend({
3839
};
3940
},
4041

41-
}).configure({
42-
suggestion: {
43-
// items: ({ query }: any) => {
44-
// return emojiSearch(query);
45-
// },
46-
47-
allowSpaces: false,
48-
49-
render: () => {
50-
let reactRenderer: any;
51-
52-
return {
53-
onStart: (props: any) => {
54-
if (!props.clientRect) {
55-
return;
56-
}
57-
58-
reactRenderer = new ReactRenderer(EmojiNodeView, {
59-
props,
60-
editor: props.editor,
61-
});
62-
63-
reactRenderer.element.style.position = 'absolute';
64-
65-
document.body.appendChild(reactRenderer.element);
66-
67-
updatePosition(props.editor, reactRenderer.element);
68-
},
69-
70-
onUpdate(props) {
71-
reactRenderer.updateProps(props);
72-
73-
if (!props.clientRect) {
74-
return;
75-
}
76-
updatePosition(props.editor, reactRenderer.element);
77-
},
78-
79-
onKeyDown(props) {
80-
if (props.event.key === 'Escape') {
81-
reactRenderer.destroy();
82-
reactRenderer.element.remove();
83-
84-
return true;
85-
}
86-
87-
return reactRenderer.ref?.onKeyDown(props);
88-
},
42+
addExtensions() {
43+
const config: any = {
44+
...this.options
45+
};
8946

90-
onExit() {
91-
reactRenderer.destroy();
92-
reactRenderer.element.remove();
93-
},
47+
if (this.options?.suggestion) {
48+
config['suggestion'] = {
49+
render: renderNodeViewClosure(EmojiNodeView),
50+
...this.options.suggestion,
9451
};
95-
},
96-
}
52+
}
53+
54+
return [TiptapEmoji.configure({
55+
...config,
56+
})];
57+
},
9758
});

src/extensions/Emoji/components/EmojiList/EmojiNodeView.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
11
/* eslint-disable @typescript-eslint/no-unused-expressions */
22
/* eslint-disable @typescript-eslint/no-unsafe-argument */
3-
import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
3+
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
44

55
import clsx from 'clsx';
66
import scrollIntoView from 'scroll-into-view-if-needed';
77

8-
import { EMOJI_LIST } from '@/extensions/Emoji/components/EmojiList/emojis';
98
import { useLocale } from '@/locales';
109

11-
function EmojiNodeView (props: any, ref: any) {
10+
interface IPropsEmojiNodeVIew {
11+
items: Array<{
12+
name: string
13+
emoji: string
14+
}>
15+
16+
query: string
17+
command: any
18+
}
19+
20+
function EmojiNodeView(props: IPropsEmojiNodeVIew, ref: any) {
1221
const $container: any = useRef<HTMLDivElement>(null);
1322
const [selectedIndex, setSelectedIndex] = useState(0);
1423
const { t } = useLocale();
1524

16-
const filteredEmojis = useMemo(() => {
17-
const lowerCaseQuery = props?.query?.toLowerCase();
18-
19-
return EMOJI_LIST.filter(({ name }) =>
20-
name.toLowerCase().includes(lowerCaseQuery)
21-
);
22-
}, [props?.query]);
25+
const filteredEmojis = props?.items ?? [];
2326

2427
const selectItem = (index: any) => {
2528
const item = filteredEmojis[index];
@@ -89,9 +92,9 @@ function EmojiNodeView (props: any, ref: any) {
8992
})}
9093
>
9194
{emoji}
92-
:
93-
{name}
94-
:
95+
:
96+
{name}
97+
:
9598
</span>
9699
);
97100
})

src/extensions/Emoji/components/RichTextEmoji.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ export function RichTextEmoji() {
7474

7575
return (
7676
<EmojiPickerWrap
77-
disabled={disabled}
78-
onSelectEmoji={onAction}
77+
disabled={disabled}
78+
onSelectEmoji={onAction}
7979
>
8080
<ActionButton
8181
icon={icon}

src/extensions/ImportWord/ImportWord.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { Extension } from '@tiptap/core';
22
import type { default as Mammoth } from 'mammoth';
33

4-
export * from '@/extensions/ImportWord/components/RichTextImportWord';
54
import type { GeneralOptions } from '@/types';
65

6+
export * from '@/extensions/ImportWord/components/RichTextImportWord';
7+
78
interface ImportWordOptions extends GeneralOptions<ImportWordOptions> {
89
/** Function for converting Word files to HTML */
910
convert?: (file: File) => Promise<string>

0 commit comments

Comments
 (0)