@milkdown/plugin-emoji 5.4.1 → 6.0.0-next.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.
Files changed (42) hide show
  1. package/lib/{src/constant.d.ts → constant.d.ts} +0 -1
  2. package/lib/constant.d.ts.map +1 -0
  3. package/lib/{src/filter → filter}/helper.d.ts +0 -0
  4. package/lib/filter/helper.d.ts.map +1 -0
  5. package/lib/filter/index.d.ts +5 -0
  6. package/lib/filter/index.d.ts.map +1 -0
  7. package/lib/filter/style.d.ts +3 -0
  8. package/lib/filter/style.d.ts.map +1 -0
  9. package/lib/index.d.ts +2 -1
  10. package/lib/index.d.ts.map +1 -0
  11. package/lib/index.es.js +102 -176
  12. package/lib/index.es.js.map +1 -1
  13. package/lib/node.d.ts +9 -0
  14. package/lib/node.d.ts.map +1 -0
  15. package/lib/{src/parse.d.ts → parse.d.ts} +0 -0
  16. package/lib/parse.d.ts.map +1 -0
  17. package/lib/{src/remark-twemoji.d.ts → remark-twemoji.d.ts} +0 -0
  18. package/lib/remark-twemoji.d.ts.map +1 -0
  19. package/package.json +33 -11
  20. package/src/constant.ts +0 -1
  21. package/src/filter/helper.ts +17 -9
  22. package/src/filter/index.ts +24 -11
  23. package/src/filter/style.ts +22 -10
  24. package/src/index.ts +1 -7
  25. package/src/node.ts +30 -23
  26. package/src/parse.ts +4 -1
  27. package/src/remark-twemoji.ts +16 -8
  28. package/lib/src/constant.d.ts.map +0 -1
  29. package/lib/src/filter/helper.d.ts.map +0 -1
  30. package/lib/src/filter/index.d.ts +0 -4
  31. package/lib/src/filter/index.d.ts.map +0 -1
  32. package/lib/src/filter/style.d.ts +0 -3
  33. package/lib/src/filter/style.d.ts.map +0 -1
  34. package/lib/src/index.d.ts +0 -4
  35. package/lib/src/index.d.ts.map +0 -1
  36. package/lib/src/node.d.ts +0 -6
  37. package/lib/src/node.d.ts.map +0 -1
  38. package/lib/src/parse.d.ts.map +0 -1
  39. package/lib/src/picker.d.ts +0 -4
  40. package/lib/src/picker.d.ts.map +0 -1
  41. package/lib/src/remark-twemoji.d.ts.map +0 -1
  42. package/src/picker.ts +0 -125
File without changes
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,KAAK,UAAW,MAAM,KAAG,MACyD,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remark-twemoji.d.ts","sourceRoot":"","sources":["../src/remark-twemoji.ts"],"names":[],"mappings":"AAEA,OAAO,EAAW,IAAI,EAAU,MAAM,OAAO,CAAC;AAoC9C,eAAO,MAAM,aAAa,eACK,IAAI,SA2BlC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milkdown/plugin-emoji",
3
- "version": "5.4.1",
3
+ "version": "6.0.0-next.1",
4
4
  "type": "module",
5
5
  "main": "./lib/index.es.js",
6
6
  "types": "./lib/index.d.ts",
@@ -15,30 +15,52 @@
15
15
  "milkdown plugin"
16
16
  ],
17
17
  "devDependencies": {
18
- "@milkdown/core": "5.4.1",
19
- "@milkdown/prose": "5.4.1"
18
+ "@milkdown/core": "6.0.0-next.1",
19
+ "@milkdown/prose": "6.0.0-next.1"
20
20
  },
21
21
  "peerDependencies": {
22
- "@milkdown/core": "^5.4.0",
23
- "@milkdown/prose": "^5.4.0"
22
+ "@milkdown/core": "^6.0.0-next.0",
23
+ "@milkdown/prose": "^6.0.0-next.0"
24
24
  },
25
25
  "dependencies": {
26
- "@joeattardi/emoji-button": "^4.6.0",
27
- "@milkdown/utils": "5.4.1",
26
+ "@milkdown/utils": "6.0.0-next.1",
28
27
  "@types/node-emoji": "^1.8.1",
29
- "@types/twemoji": "^12.1.2",
30
28
  "emoji-regex": "^10.0.0",
31
29
  "node-emoji": "^1.10.0",
32
30
  "remark-emoji": "^3.0.1",
33
31
  "tslib": "^2.3.1",
34
- "twemoji": "^13.1.0",
32
+ "twemoji": "^14.0.1",
35
33
  "unist-util-visit": "^4.0.0"
36
34
  },
35
+ "nx": {
36
+ "targets": {
37
+ "build": {
38
+ "outputs": [
39
+ "packages/plugin-emoji/lib"
40
+ ],
41
+ "dependsOn": [
42
+ {
43
+ "target": "build",
44
+ "projects": "dependencies"
45
+ }
46
+ ]
47
+ },
48
+ "tsc": {
49
+ "outputs": [],
50
+ "dependsOn": [
51
+ {
52
+ "target": "build",
53
+ "projects": "dependencies"
54
+ }
55
+ ]
56
+ }
57
+ }
58
+ },
37
59
  "scripts": {
38
- "start": "vite build --watch",
60
+ "start": "concurrently -n es,dts \"vite build --watch\" \"tsc --emitDeclarationOnly --watch\"",
39
61
  "test": "vitest",
40
62
  "tsc": "tsc --noEmit",
41
- "build": "vite build"
63
+ "build": "vite build && tsc --emitDeclarationOnly"
42
64
  },
43
65
  "readme": "# @milkdown/plugin-emoji\n\nEmoji plugin for [milkdown](https://saul-mirone.github.io/milkdown/).\nAdd support for emoji through [shortcuts](https://www.webfx.com/tools/emoji-cheat-sheet/).\nRendered by [twemoji](https://github.com/twitter/twemoji).\n\n# Example Usage\n\n```typescript\nimport { Editor } from '@milkdown/core';\nimport { commonmark } from '@milkdown/preset-commonmark';\nimport { nord } from '@milkdown/theme-nord';\n\nimport { emoji } from '@milkdown/plugin-emoji';\n\nEditor.make().use(nord).use(commonmark).use(emoji).create();\n```\n\n# License\n\nMilkdown is open sourced software licensed under [MIT license](https://github.com/Saul-Mirone/milkdown/blob/main/LICENSE).\n"
44
66
  }
package/src/constant.ts CHANGED
@@ -2,4 +2,3 @@
2
2
  export const part = /:\+1|:-1|:[\w-]+/;
3
3
  export const full = /:\+1:|:-1:|:[\w-]+:/;
4
4
  export const input = /(:([^:\s]+):)$/;
5
- export const keyword = ':emoji:';
@@ -25,7 +25,7 @@ export const checkTrigger = (
25
25
  return false;
26
26
  }
27
27
  const regex = part.exec(textBefore);
28
- if (regex && textBefore.endsWith(regex[0])) {
28
+ if (regex && regex[0] && textBefore.endsWith(regex[0])) {
29
29
  const match = regex[0];
30
30
  setRange(from - (match.length - text.length), to);
31
31
  setSearch(match);
@@ -41,7 +41,9 @@ export const renderDropdownList = (
41
41
  onConfirm: () => void,
42
42
  setActive: (active: HTMLElement | null) => void,
43
43
  ) => {
44
- dropDown.innerHTML = '';
44
+ while (dropDown.firstChild) {
45
+ dropDown.firstChild.remove();
46
+ }
45
47
  list.forEach(({ emoji, key }, i) => {
46
48
  const container = document.createElement('div');
47
49
  container.className = 'milkdown-emoji-filter_item';
@@ -63,7 +65,7 @@ export const renderDropdownList = (
63
65
  setActive(container);
64
66
  }
65
67
 
66
- container.addEventListener('mouseenter', (e) => {
68
+ const onEnter = (e: MouseEvent) => {
67
69
  if ($active) {
68
70
  $active.classList.remove('active');
69
71
  }
@@ -71,15 +73,21 @@ export const renderDropdownList = (
71
73
  if (!(target instanceof HTMLElement)) return;
72
74
  target.classList.add('active');
73
75
  setActive(target);
74
- });
75
- container.addEventListener('mouseleave', (e) => {
76
+ };
77
+
78
+ const onLeave = (e: MouseEvent) => {
76
79
  const { target } = e;
77
80
  if (!(target instanceof HTMLElement)) return;
78
81
  target.classList.remove('active');
79
- });
80
- container.addEventListener('mousedown', (e) => {
81
- onConfirm();
82
+ };
83
+
84
+ const onClick = (e: MouseEvent) => {
82
85
  e.preventDefault();
83
- });
86
+ onConfirm();
87
+ };
88
+
89
+ container.addEventListener('mouseenter', onEnter);
90
+ container.addEventListener('mouseleave', onLeave);
91
+ container.addEventListener('mousedown', onClick);
84
92
  });
85
93
  };
@@ -1,13 +1,15 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
2
 
3
- import { calculateNodePosition, Plugin } from '@milkdown/prose';
3
+ import { calculateNodePosition, Plugin, PluginKey } from '@milkdown/prose';
4
4
  import { Utils } from '@milkdown/utils';
5
5
  import { search } from 'node-emoji';
6
6
 
7
7
  import { checkTrigger, renderDropdownList } from './helper';
8
8
  import { injectStyle } from './style';
9
9
 
10
- export const filter = (utils: Utils) => {
10
+ export const key = new PluginKey('MILKDOWN_PLUGIN_EMOJI_FILTER');
11
+
12
+ export const filter = (utils: Utils, maxListSize: number) => {
11
13
  let trigger = false;
12
14
  let _from = 0;
13
15
  let _search = '';
@@ -21,6 +23,7 @@ export const filter = (utils: Utils) => {
21
23
  };
22
24
 
23
25
  return new Plugin({
26
+ key,
24
27
  props: {
25
28
  handleKeyDown(_, event) {
26
29
  if (['Delete', 'Backspace'].includes(event.key)) {
@@ -62,11 +65,13 @@ export const filter = (utils: Utils) => {
62
65
  }
63
66
 
64
67
  const dropDown = document.createElement('div');
65
- const style = utils.getStyle(injectStyle);
66
68
 
67
- if (style) {
68
- style.split(' ').forEach((x) => dropDown.classList.add(x));
69
- }
69
+ utils.themeManager.onFlush(() => {
70
+ const style = utils.getStyle(injectStyle);
71
+ if (style) {
72
+ style.split(' ').forEach((x) => dropDown.classList.add(x));
73
+ }
74
+ });
70
75
 
71
76
  dropDown.classList.add('milkdown-emoji-filter', 'hide');
72
77
 
@@ -82,7 +87,7 @@ export const filter = (utils: Utils) => {
82
87
  };
83
88
 
84
89
  parentNode.appendChild(dropDown);
85
- parentNode.addEventListener('keydown', (e) => {
90
+ const onKeydown = (e: Event) => {
86
91
  if (!trigger || !(e instanceof KeyboardEvent)) return;
87
92
 
88
93
  const { key } = e;
@@ -106,14 +111,16 @@ export const filter = (utils: Utils) => {
106
111
 
107
112
  return;
108
113
  }
109
- });
110
- parentNode.addEventListener('mousedown', (e) => {
114
+ };
115
+ const onClick = (e: Event) => {
111
116
  if (!trigger) return;
112
117
 
113
118
  e.stopPropagation();
114
119
  off();
115
120
  dropDown.classList.add('hide');
116
- });
121
+ };
122
+ parentNode.addEventListener('keydown', onKeydown);
123
+ parentNode.addEventListener('mousedown', onClick);
117
124
 
118
125
  return {
119
126
  update: (view) => {
@@ -124,7 +131,7 @@ export const filter = (utils: Utils) => {
124
131
  dropDown.classList.add('hide');
125
132
  return null;
126
133
  }
127
- const result = search(_search).slice(0, 5);
134
+ const result = search(_search).slice(0, maxListSize);
128
135
  const { node } = view.domAtPos(_from);
129
136
  if (result.length === 0 || !node) {
130
137
  dropDown.classList.add('hide');
@@ -156,6 +163,12 @@ export const filter = (utils: Utils) => {
156
163
 
157
164
  return null;
158
165
  },
166
+
167
+ destroy: () => {
168
+ parentNode.removeEventListener('keydown', onKeydown);
169
+ parentNode.removeEventListener('mousedown', onClick);
170
+ dropDown.remove();
171
+ },
159
172
  };
160
173
  },
161
174
  });
@@ -1,9 +1,21 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import type { Emotion, ThemeTool } from '@milkdown/core';
2
+ import {
3
+ Color,
4
+ Emotion,
5
+ ThemeBorder,
6
+ ThemeColor,
7
+ ThemeFont,
8
+ ThemeManager,
9
+ ThemeShadow,
10
+ ThemeSize,
11
+ } from '@milkdown/core';
3
12
 
4
- export const injectStyle = ({ size, mixin, palette, font }: ThemeTool, { css, cx }: Emotion) => {
5
- const border = mixin.border?.();
6
- const shadow = mixin.shadow?.();
13
+ export const injectStyle = (themeManager: ThemeManager, { css, cx }: Emotion) => {
14
+ const border = themeManager.get(ThemeBorder, undefined);
15
+ const shadow = themeManager.get(ThemeShadow, undefined);
16
+ const radius = themeManager.get(ThemeSize, 'radius');
17
+ const typography = themeManager.get(ThemeFont, 'typography');
18
+ const palette = (color: Color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity]);
7
19
 
8
20
  const style = css`
9
21
  position: absolute;
@@ -11,20 +23,20 @@ export const injectStyle = ({ size, mixin, palette, font }: ThemeTool, { css, cx
11
23
  display: none;
12
24
  }
13
25
 
14
- border-radius: ${size.radius};
26
+ border-radius: ${radius};
15
27
  background: ${palette('surface')};
16
28
 
17
29
  .milkdown-emoji-filter_item {
18
30
  display: flex;
19
- gap: 0.5rem;
20
- height: 2.25rem;
21
- padding: 0 1rem;
31
+ gap: 0.5em;
32
+ height: 2.57143em;
33
+ padding: 0 1em;
22
34
  align-items: center;
23
35
  justify-content: flex-start;
24
36
  cursor: pointer;
25
37
  line-height: 2;
26
- font-family: ${font.typography};
27
- font-size: 0.875rem;
38
+ font-family: ${typography};
39
+ font-size: 0.875em;
28
40
  &.active {
29
41
  background: ${palette('secondary', 0.12)};
30
42
  color: ${palette('primary')};
package/src/index.ts CHANGED
@@ -1,8 +1,2 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { AtomList } from '@milkdown/utils';
3
-
4
- import { emojiNode } from './node';
5
-
6
- export const emoji = AtomList.create([emojiNode()]);
7
-
8
- export { emojiNode } from './node';
2
+ export * from './node';
package/src/node.ts CHANGED
@@ -8,24 +8,28 @@ import remarkEmoji from 'remark-emoji';
8
8
  import { input } from './constant';
9
9
  import { filter } from './filter';
10
10
  import { parse } from './parse';
11
- import { picker } from './picker';
12
11
  import { twemojiPlugin } from './remark-twemoji';
13
12
 
14
- export const emojiNode = createNode((utils) => {
15
- const style = utils.getStyle(
16
- (_, { css }) => css`
17
- display: inline-flex;
18
- justify-content: center;
19
- align-items: center;
13
+ export type EmojiOptions = {
14
+ maxListSize: number;
15
+ };
20
16
 
21
- .emoji {
22
- height: 1em;
23
- width: 1em;
24
- margin: 0 0.05em 0 0.1em;
25
- vertical-align: -0.1em;
26
- }
27
- `,
28
- );
17
+ export const emoji = createNode<string, EmojiOptions>((utils, options) => {
18
+ const getStyle = () =>
19
+ utils.getStyle(
20
+ (_, { css }) => css`
21
+ display: inline-flex;
22
+ justify-content: center;
23
+ align-items: center;
24
+
25
+ .emoji {
26
+ height: 1em;
27
+ width: 1em;
28
+ margin: 0 0.05em 0 0.1em;
29
+ vertical-align: -0.1em;
30
+ }
31
+ `,
32
+ );
29
33
  return {
30
34
  id: 'emoji',
31
35
  schema: () => ({
@@ -50,25 +54,28 @@ export const emojiNode = createNode((utils) => {
50
54
  ],
51
55
  toDOM: (node) => {
52
56
  const span = document.createElement('span');
53
- span.dataset.type = 'emoji';
54
- if (style) {
55
- span.classList.add(style);
56
- }
57
+ span.dataset['type'] = 'emoji';
58
+ utils.themeManager.onFlush(() => {
59
+ const style = getStyle();
60
+ if (style) {
61
+ span.classList.add(style);
62
+ }
63
+ });
57
64
  span.classList.add('emoji-wrapper');
58
- span.innerHTML = node.attrs.html;
65
+ span.innerHTML = node.attrs['html'];
59
66
  return { dom: span };
60
67
  },
61
68
  parseMarkdown: {
62
69
  match: ({ type }) => type === 'emoji',
63
70
  runner: (state, node, type) => {
64
- state.addNode(type, { html: node.value as string });
71
+ state.addNode(type, { html: node['value'] as string });
65
72
  },
66
73
  },
67
74
  toMarkdown: {
68
75
  match: (node) => node.type.name === 'emoji',
69
76
  runner: (state, node) => {
70
77
  const span = document.createElement('span');
71
- span.innerHTML = node.attrs.html;
78
+ span.innerHTML = node.attrs['html'];
72
79
  const img = span.querySelector('img');
73
80
  const title = img?.title;
74
81
  span.remove();
@@ -92,6 +99,6 @@ export const emojiNode = createNode((utils) => {
92
99
  }),
93
100
  ],
94
101
  remarkPlugins: () => [remarkEmoji as RemarkPlugin, twemojiPlugin],
95
- prosePlugins: () => [picker(utils), filter(utils)],
102
+ prosePlugins: () => [filter(utils, options?.maxListSize ?? 6)],
96
103
  };
97
104
  });
package/src/parse.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
2
  import twemoji from 'twemoji';
3
3
 
4
- export const parse = (emoji: string) => twemoji.parse(emoji, { attributes: (text) => ({ title: text }) });
4
+ const setAttr = (text: string) => ({ title: text });
5
+
6
+ export const parse = (emoji: string): string =>
7
+ twemoji.parse(emoji, { attributes: setAttr as unknown as () => void }) as unknown as string;
@@ -16,10 +16,16 @@ function flatMap(ast: Node, fn: (node: Node, index: number, parent: Node | null)
16
16
  if (isParent(node)) {
17
17
  const out = [];
18
18
  for (let i = 0, n = node.children.length; i < n; i++) {
19
- const xs = transform(node.children[i], i, node);
20
- if (xs) {
21
- for (let j = 0, m = xs.length; j < m; j++) {
22
- out.push(xs[j]);
19
+ const nthChild = node.children[i];
20
+ if (nthChild) {
21
+ const xs = transform(nthChild, i, node);
22
+ if (xs) {
23
+ for (let j = 0, m = xs.length; j < m; j++) {
24
+ const item = xs[j];
25
+ if (item) {
26
+ out.push(item);
27
+ }
28
+ }
23
29
  }
24
30
  }
25
31
  }
@@ -43,11 +49,13 @@ export const twemojiPlugin = () => {
43
49
  while ((match = regex.exec(str))) {
44
50
  const { index } = match;
45
51
  const emoji = match[0];
46
- if (index > 0) {
47
- output.push({ ...node, value: str.slice(0, index) });
52
+ if (emoji) {
53
+ if (index > 0) {
54
+ output.push({ ...node, value: str.slice(0, index) });
55
+ }
56
+ output.push({ ...node, value: parse(emoji), type: 'emoji' });
57
+ str = str.slice(index + emoji.length);
48
58
  }
49
- output.push({ ...node, value: parse(emoji), type: 'emoji' });
50
- str = str.slice(index + emoji.length);
51
59
  }
52
60
  if (str.length) {
53
61
  output.push({ ...node, value: str });
@@ -1 +0,0 @@
1
- {"version":3,"file":"constant.d.ts","sourceRoot":"","sources":["constant.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,IAAI,QAAqB,CAAC;AACvC,eAAO,MAAM,IAAI,QAAwB,CAAC;AAC1C,eAAO,MAAM,KAAK,QAAmB,CAAC;AACtC,eAAO,MAAM,OAAO,YAAY,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["helper.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAKnC,eAAO,MAAM,YAAY,SACf,UAAU,QACV,MAAM,MACR,MAAM,QACJ,MAAM,mBACK,MAAM,MAAM,MAAM,KAAK,IAAI,qBACzB,MAAM,KAAK,IAAI,YAoBrC,CAAC;AAEF,eAAO,MAAM,kBAAkB,SACrB,KAAK,EAAE,YACH,WAAW,WACZ,WAAW,GAAG,IAAI,aAChB,MAAM,IAAI,sBACD,WAAW,GAAG,IAAI,KAAK,IAAI,SA2ClD,CAAC"}
@@ -1,4 +0,0 @@
1
- import { Plugin } from '@milkdown/prose';
2
- import { Utils } from '@milkdown/utils';
3
- export declare const filter: (utils: Utils) => Plugin<any, any>;
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyB,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAMxC,eAAO,MAAM,MAAM,UAAW,KAAK,qBAwJlC,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { Emotion, ThemeTool } from '@milkdown/core';
2
- export declare const injectStyle: ({ size, mixin, palette, font }: ThemeTool, { css, cx }: Emotion) => string;
3
- //# sourceMappingURL=style.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["style.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEzD,eAAO,MAAM,WAAW,mCAAoC,SAAS,eAAe,OAAO,WAsC1F,CAAC"}
@@ -1,4 +0,0 @@
1
- import { AtomList } from '@milkdown/utils';
2
- export declare const emoji: AtomList<import("@milkdown/utils/lib/src/types").Metadata<import("@milkdown/utils/lib/src/types").GetPlugin<string, import("@milkdown/utils").UnknownRecord>> & import("@milkdown/core").MilkdownPlugin>;
3
- export { emojiNode } from './node';
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAI3C,eAAO,MAAM,KAAK,0MAAiC,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC"}
package/lib/src/node.d.ts DELETED
@@ -1,6 +0,0 @@
1
- export declare const emojiNode: import("@milkdown/utils/lib/src/types").WithExtend<string, import("@milkdown/utils").UnknownRecord, import("prosemirror-model").NodeType<any>, {
2
- id: string;
3
- schema: (ctx: import("@milkdown/core").Ctx) => import("@milkdown/core").NodeSchema;
4
- view?: ((ctx: import("@milkdown/core").Ctx) => import("@milkdown/prose").NodeViewFactory) | undefined;
5
- }>;
6
- //# sourceMappingURL=node.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["node.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,SAAS;;;;EAmFpB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["parse.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,KAAK,UAAW,MAAM,WAAsE,CAAC"}
@@ -1,4 +0,0 @@
1
- import { Plugin } from '@milkdown/prose';
2
- import { Utils } from '@milkdown/utils';
3
- export declare const picker: (utils: Utils) => Plugin<any, any>;
4
- //# sourceMappingURL=picker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"picker.d.ts","sourceRoot":"","sources":["picker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyC,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AA2BxC,eAAO,MAAM,MAAM,UAAW,KAAK,qBA8FlC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"remark-twemoji.d.ts","sourceRoot":"","sources":["remark-twemoji.ts"],"names":[],"mappings":"AAEA,OAAO,EAAW,IAAI,EAAU,MAAM,OAAO,CAAC;AA8B9C,eAAO,MAAM,aAAa,eACK,IAAI,SAyBlC,CAAC"}
package/src/picker.ts DELETED
@@ -1,125 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import { EmojiButton } from '@joeattardi/emoji-button';
3
- import { Decoration, DecorationSet, EditorView, Plugin } from '@milkdown/prose';
4
- import { Utils } from '@milkdown/utils';
5
-
6
- import { parse } from './parse';
7
-
8
- const keyword = ':emoji:';
9
-
10
- const checkTrigger = (
11
- view: EditorView,
12
- from: number,
13
- to: number,
14
- text: string,
15
- setRange: (from: number, to: number) => void,
16
- ) => {
17
- if (view.composing) return false;
18
- const { state } = view;
19
- const $from = state.doc.resolve(from);
20
- if ($from.parent.type.spec.code) return false;
21
- const textBefore =
22
- $from.parent.textBetween($from.parentOffset - keyword.length + 1, $from.parentOffset, undefined, '\ufffc') +
23
- text;
24
- if (textBefore === keyword) {
25
- setRange(from - keyword.length + 1, to + 1);
26
- return true;
27
- }
28
- return false;
29
- };
30
-
31
- export const picker = (utils: Utils) => {
32
- let trigger = false;
33
- const holder = document.createElement('span');
34
- let _from = 0;
35
- let _to = 0;
36
- const off = () => {
37
- trigger = false;
38
- _from = 0;
39
- _to = 0;
40
- };
41
-
42
- const plugin = new Plugin({
43
- props: {
44
- handleKeyDown() {
45
- off();
46
- return false;
47
- },
48
- handleClick() {
49
- off();
50
- return false;
51
- },
52
- handleTextInput(view, from, to, text) {
53
- trigger = checkTrigger(view, from, to, text, (from, to) => {
54
- _from = from;
55
- _to = to;
56
- });
57
-
58
- if (!trigger) {
59
- off();
60
- }
61
- return false;
62
- },
63
- decorations(state) {
64
- if (!trigger) return null;
65
-
66
- return DecorationSet.create(state.doc, [Decoration.widget(state.selection.to, holder)]);
67
- },
68
- },
69
- view: (editorView) => {
70
- const { parentNode } = editorView.dom;
71
- if (!parentNode) {
72
- throw new Error();
73
- }
74
- utils.getStyle(({ palette, font }, { injectGlobal }) => {
75
- const css = injectGlobal;
76
- css`
77
- .emoji-picker {
78
- --dark-search-background-color: ${palette('surface')} !important;
79
- --dark-text-color: ${palette('neutral', 0.87)} !important;
80
- --dark-background-color: ${palette('background')} !important;
81
- --dark-border-color: ${palette('shadow')} !important;
82
- --dark-hover-color: ${palette('secondary', 0.12)} !important;
83
- --dark-blue-color: ${palette('primary')} !important;
84
- --dark-search-icon-color: ${palette('primary')} !important;
85
- --dark-category-button-color: ${palette('secondary', 0.4)} !important;
86
- --font: ${font.typography} !important;
87
- --font-size: 1rem !important;
88
- }
89
- `;
90
- });
91
- const emojiPicker = new EmojiButton({
92
- rootElement: parentNode as HTMLElement,
93
- autoFocusSearch: false,
94
- style: 'twemoji',
95
- theme: 'dark',
96
- zIndex: 99,
97
- });
98
- emojiPicker.on('emoji', (selection) => {
99
- const start = _from;
100
- const end = _to;
101
- off();
102
- const html = parse(selection.emoji);
103
- const node = editorView.state.schema.node('emoji', { html });
104
- const { tr } = editorView.state;
105
-
106
- editorView.dispatch(tr.replaceRangeWith(start, end, node));
107
- });
108
- return {
109
- update: () => {
110
- if (!trigger) {
111
- emojiPicker.hidePicker();
112
- return null;
113
- }
114
- emojiPicker.showPicker(holder);
115
- return null;
116
- },
117
- destroy: () => {
118
- emojiPicker.destroyPicker();
119
- },
120
- };
121
- },
122
- });
123
-
124
- return plugin;
125
- };