@milkdown/plugin-emoji 5.3.4 → 5.3.5

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.
package/lib/index.es.js CHANGED
@@ -233,14 +233,18 @@ const filter = (utils) => {
233
233
  $active = a;
234
234
  });
235
235
  calculateNodePosition(view, dropDown, (selected, target, parent) => {
236
+ const $editor = dropDown.parentElement;
237
+ if (!$editor) {
238
+ throw new Error();
239
+ }
236
240
  const start = view.coordsAtPos(_from);
237
241
  let left = start.left - parent.left;
238
- let top = selected.bottom - parent.top + 14;
242
+ let top = selected.bottom - parent.top + 14 + $editor.scrollTop;
239
243
  if (left < 0) {
240
244
  left = 0;
241
245
  }
242
246
  if (window.innerHeight - start.bottom < target.height) {
243
- top = selected.top - parent.top - target.height - 14;
247
+ top = selected.top - parent.top - target.height - 14 + $editor.scrollTop;
244
248
  }
245
249
  return [top, left];
246
250
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/constant.ts","../src/parse.ts","../src/filter/helper.ts","../src/filter/style.ts","../src/filter/index.ts","../src/picker.ts","../src/remark-twemoji.ts","../src/node.ts","../src/index.ts"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nexport const part = /:\\+1|:-1|:[\\w-]+/;\nexport const full = /:\\+1:|:-1:|:[\\w-]+:/;\nexport const input = /(:([^:\\s]+):)$/;\nexport const keyword = ':emoji:';\n","/* Copyright 2021, Milkdown by Mirone. */\nimport twemoji from 'twemoji';\n\nexport const parse = (emoji: string) => twemoji.parse(emoji, { attributes: (text) => ({ title: text }) });\n","/* Copyright 2021, Milkdown by Mirone. */\n\nimport { EditorView } from '@milkdown/prose';\nimport { Emoji } from 'node-emoji';\n\nimport { full, part } from '../constant';\nimport { parse } from '../parse';\n\nexport const checkTrigger = (\n view: EditorView,\n from: number,\n to: number,\n text: string,\n setRange: (from: number, to: number) => void,\n setSearch: (words: string) => void,\n) => {\n if (view.composing) return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n if ($from.parent.type.spec.code) return false;\n const textBefore =\n $from.parent.textBetween(Math.max(0, $from.parentOffset - 10), $from.parentOffset, undefined, '\\ufffc') + text;\n if (full.test(textBefore)) {\n return false;\n }\n const regex = part.exec(textBefore);\n if (regex && textBefore.endsWith(regex[0])) {\n const match = regex[0];\n setRange(from - (match.length - text.length), to);\n setSearch(match);\n return true;\n }\n return false;\n};\n\nexport const renderDropdownList = (\n list: Emoji[],\n dropDown: HTMLElement,\n $active: HTMLElement | null,\n onConfirm: () => void,\n setActive: (active: HTMLElement | null) => void,\n) => {\n dropDown.innerHTML = '';\n list.forEach(({ emoji, key }, i) => {\n const container = document.createElement('div');\n container.className = 'milkdown-emoji-filter_item';\n\n const emojiSpan = document.createElement('span');\n emojiSpan.innerHTML = parse(emoji);\n\n emojiSpan.className = 'milkdown-emoji-filter_item-emoji';\n const keySpan = document.createElement('span');\n keySpan.textContent = ':' + key + ':';\n keySpan.className = 'milkdown-emoji-filter_item-key';\n\n container.appendChild(emojiSpan);\n container.appendChild(keySpan);\n dropDown.appendChild(container);\n\n if (i === 0) {\n container.classList.add('active');\n setActive(container);\n }\n\n container.addEventListener('mouseenter', (e) => {\n if ($active) {\n $active.classList.remove('active');\n }\n const { target } = e;\n if (!(target instanceof HTMLElement)) return;\n target.classList.add('active');\n setActive(target);\n });\n container.addEventListener('mouseleave', (e) => {\n const { target } = e;\n if (!(target instanceof HTMLElement)) return;\n target.classList.remove('active');\n });\n container.addEventListener('mousedown', (e) => {\n onConfirm();\n e.preventDefault();\n });\n });\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { Emotion, ThemeTool } from '@milkdown/core';\n\nexport const injectStyle = ({ size, mixin, palette, font }: ThemeTool, { css, cx }: Emotion) => {\n const border = mixin.border?.();\n const shadow = mixin.shadow?.();\n\n const style = css`\n position: absolute;\n &.hide {\n display: none;\n }\n\n border-radius: ${size.radius};\n background: ${palette('surface')};\n\n .milkdown-emoji-filter_item {\n display: flex;\n gap: 0.5rem;\n height: 2.25rem;\n padding: 0 1rem;\n align-items: center;\n justify-content: flex-start;\n cursor: pointer;\n line-height: 2;\n font-family: ${font.typography};\n font-size: 0.875rem;\n &.active {\n background: ${palette('secondary', 0.12)};\n color: ${palette('primary')};\n }\n }\n\n .emoji {\n height: 1em;\n width: 1em;\n margin: 0 0.05em 0 0.1em;\n vertical-align: -0.1em;\n }\n `;\n return cx(border, shadow, style);\n};\n","/* Copyright 2021, Milkdown by Mirone. */\n\nimport { calculateNodePosition, Plugin } from '@milkdown/prose';\nimport { Utils } from '@milkdown/utils';\nimport { search } from 'node-emoji';\n\nimport { checkTrigger, renderDropdownList } from './helper';\nimport { injectStyle } from './style';\n\nexport const filter = (utils: Utils) => {\n let trigger = false;\n let _from = 0;\n let _search = '';\n let $active: null | HTMLElement = null;\n\n const off = () => {\n trigger = false;\n _from = 0;\n _search = '';\n $active = null;\n };\n\n return new Plugin({\n props: {\n handleKeyDown(_, event) {\n if (['Delete', 'Backspace'].includes(event.key)) {\n _search = _search.slice(0, -1);\n if (_search.length <= 1) {\n off();\n }\n return false;\n }\n if (!trigger) return false;\n if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(event.key)) {\n return false;\n }\n return true;\n },\n handleTextInput(view, from, to, text) {\n trigger = checkTrigger(\n view,\n from,\n to,\n text,\n (from) => {\n _from = from;\n },\n (search) => {\n _search = search;\n },\n );\n if (!trigger) {\n off();\n }\n return false;\n },\n },\n view: (editorView) => {\n const { parentNode } = editorView.dom;\n if (!parentNode) {\n throw new Error();\n }\n\n const dropDown = document.createElement('div');\n const style = utils.getStyle(injectStyle);\n\n if (style) {\n style.split(' ').forEach((x) => dropDown.classList.add(x));\n }\n\n dropDown.classList.add('milkdown-emoji-filter', 'hide');\n\n const replace = () => {\n if (!$active) return;\n\n const { tr } = editorView.state;\n const node = editorView.state.schema.node('emoji', { html: $active.firstElementChild?.innerHTML });\n\n editorView.dispatch(tr.delete(_from, _from + _search.length).insert(_from, node));\n off();\n dropDown.classList.add('hide');\n };\n\n parentNode.appendChild(dropDown);\n parentNode.addEventListener('keydown', (e) => {\n if (!trigger || !(e instanceof KeyboardEvent)) return;\n\n const { key } = e;\n\n if (key === 'Enter') {\n replace();\n return;\n }\n\n if (['ArrowDown', 'ArrowUp'].includes(key)) {\n const next =\n key === 'ArrowDown'\n ? $active?.nextElementSibling || dropDown.firstElementChild\n : $active?.previousElementSibling || dropDown.lastElementChild;\n if ($active) {\n $active.classList.remove('active');\n }\n if (!next) return;\n next.classList.add('active');\n $active = next as HTMLElement;\n\n return;\n }\n });\n parentNode.addEventListener('mousedown', (e) => {\n if (!trigger) return;\n\n e.stopPropagation();\n off();\n dropDown.classList.add('hide');\n });\n\n return {\n update: (view) => {\n if (!trigger) {\n dropDown.classList.add('hide');\n return null;\n }\n const result = search(_search).slice(0, 5);\n const { node } = view.domAtPos(_from);\n if (result.length === 0 || !node) {\n dropDown.classList.add('hide');\n return null;\n }\n\n dropDown.classList.remove('hide');\n renderDropdownList(result, dropDown, $active, replace, (a) => {\n $active = a;\n });\n calculateNodePosition(view, dropDown, (selected, target, parent) => {\n const start = view.coordsAtPos(_from);\n let left = start.left - parent.left;\n let top = selected.bottom - parent.top + 14;\n\n if (left < 0) {\n left = 0;\n }\n\n if (window.innerHeight - start.bottom < target.height) {\n top = selected.top - parent.top - target.height - 14;\n }\n return [top, left];\n });\n\n return null;\n },\n };\n },\n });\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { EmojiButton } from '@joeattardi/emoji-button';\nimport { Decoration, DecorationSet, EditorView, Plugin } from '@milkdown/prose';\nimport { Utils } from '@milkdown/utils';\n\nimport { parse } from './parse';\n\nconst keyword = ':emoji:';\n\nconst checkTrigger = (\n view: EditorView,\n from: number,\n to: number,\n text: string,\n setRange: (from: number, to: number) => void,\n) => {\n if (view.composing) return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n if ($from.parent.type.spec.code) return false;\n const textBefore =\n $from.parent.textBetween($from.parentOffset - keyword.length + 1, $from.parentOffset, undefined, '\\ufffc') +\n text;\n if (textBefore === keyword) {\n setRange(from - keyword.length + 1, to + 1);\n return true;\n }\n return false;\n};\n\nexport const picker = (utils: Utils) => {\n let trigger = false;\n const holder = document.createElement('span');\n let _from = 0;\n let _to = 0;\n const off = () => {\n trigger = false;\n _from = 0;\n _to = 0;\n };\n\n const plugin = new Plugin({\n props: {\n handleKeyDown() {\n off();\n return false;\n },\n handleClick() {\n off();\n return false;\n },\n handleTextInput(view, from, to, text) {\n trigger = checkTrigger(view, from, to, text, (from, to) => {\n _from = from;\n _to = to;\n });\n\n if (!trigger) {\n off();\n }\n return false;\n },\n decorations(state) {\n if (!trigger) return null;\n\n return DecorationSet.create(state.doc, [Decoration.widget(state.selection.to, holder)]);\n },\n },\n view: (editorView) => {\n const { parentNode } = editorView.dom;\n if (!parentNode) {\n throw new Error();\n }\n utils.getStyle(({ palette, font }, { injectGlobal }) => {\n const css = injectGlobal;\n css`\n .emoji-picker {\n --dark-search-background-color: ${palette('surface')} !important;\n --dark-text-color: ${palette('neutral', 0.87)} !important;\n --dark-background-color: ${palette('background')} !important;\n --dark-border-color: ${palette('shadow')} !important;\n --dark-hover-color: ${palette('secondary', 0.12)} !important;\n --dark-blue-color: ${palette('primary')} !important;\n --dark-search-icon-color: ${palette('primary')} !important;\n --dark-category-button-color: ${palette('secondary', 0.4)} !important;\n --font: ${font.typography} !important;\n --font-size: 1rem !important;\n }\n `;\n });\n const emojiPicker = new EmojiButton({\n rootElement: parentNode as HTMLElement,\n autoFocusSearch: false,\n style: 'twemoji',\n theme: 'dark',\n zIndex: 99,\n });\n emojiPicker.on('emoji', (selection) => {\n const start = _from;\n const end = _to;\n off();\n const html = parse(selection.emoji);\n const node = editorView.state.schema.node('emoji', { html });\n const { tr } = editorView.state;\n\n editorView.dispatch(tr.replaceRangeWith(start, end, node));\n });\n return {\n update: () => {\n if (!trigger) {\n emojiPicker.hidePicker();\n return null;\n }\n emojiPicker.showPicker(holder);\n return null;\n },\n destroy: () => {\n emojiPicker.destroyPicker();\n },\n };\n },\n });\n\n return plugin;\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport emojiRegex from 'emoji-regex';\nimport { Literal, Node, Parent } from 'unist';\n\nimport { parse } from './parse';\n\nconst regex = emojiRegex();\n\nconst isParent = (node: Node): node is Parent => !!(node as Parent).children;\nconst isLiteral = (node: Node): node is Literal => !!(node as Literal).value;\n\nfunction flatMap(ast: Node, fn: (node: Node, index: number, parent: Node | null) => Node[]) {\n return transform(ast, 0, null)[0];\n\n function transform(node: Node, index: number, parent: Node | null) {\n if (isParent(node)) {\n const out = [];\n for (let i = 0, n = node.children.length; i < n; i++) {\n const xs = transform(node.children[i], i, node);\n if (xs) {\n for (let j = 0, m = xs.length; j < m; j++) {\n out.push(xs[j]);\n }\n }\n }\n node.children = out;\n }\n\n return fn(node, index, parent);\n }\n}\n\nexport const twemojiPlugin = () => {\n function transformer(tree: Node) {\n flatMap(tree, (node) => {\n if (!isLiteral(node)) {\n return [node];\n }\n const value = node.value as string;\n const output: Literal<string>[] = [];\n let match;\n let str = value;\n while ((match = regex.exec(str))) {\n const { index } = match;\n const emoji = match[0];\n if (index > 0) {\n output.push({ ...node, value: str.slice(0, index) });\n }\n output.push({ ...node, value: parse(emoji), type: 'emoji' });\n str = str.slice(index + emoji.length);\n }\n if (str.length) {\n output.push({ ...node, value: str });\n }\n return output;\n });\n }\n return transformer;\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { RemarkPlugin } from '@milkdown/core';\nimport { InputRule } from '@milkdown/prose';\nimport { createNode } from '@milkdown/utils';\nimport nodeEmoji from 'node-emoji';\nimport remarkEmoji from 'remark-emoji';\n\nimport { input } from './constant';\nimport { filter } from './filter';\nimport { parse } from './parse';\nimport { picker } from './picker';\nimport { twemojiPlugin } from './remark-twemoji';\n\nexport const emojiNode = createNode((utils) => {\n const style = utils.getStyle(\n (_, { css }) => css`\n display: inline-flex;\n justify-content: center;\n align-items: center;\n\n .emoji {\n height: 1em;\n width: 1em;\n margin: 0 0.05em 0 0.1em;\n vertical-align: -0.1em;\n }\n `,\n );\n return {\n id: 'emoji',\n schema: () => ({\n group: 'inline',\n inline: true,\n selectable: false,\n attrs: {\n html: {\n default: '',\n },\n },\n parseDOM: [\n {\n tag: 'span[data-type=\"emoji\"]',\n getAttrs: (dom) => {\n if (!(dom instanceof HTMLElement)) {\n throw new Error();\n }\n return { html: dom.innerHTML };\n },\n },\n ],\n toDOM: (node) => {\n const span = document.createElement('span');\n span.dataset.type = 'emoji';\n if (style) {\n span.classList.add(style);\n }\n span.classList.add('emoji-wrapper');\n span.innerHTML = node.attrs.html;\n return { dom: span };\n },\n parseMarkdown: {\n match: ({ type }) => type === 'emoji',\n runner: (state, node, type) => {\n state.addNode(type, { html: node.value as string });\n },\n },\n toMarkdown: {\n match: (node) => node.type.name === 'emoji',\n runner: (state, node) => {\n const span = document.createElement('span');\n span.innerHTML = node.attrs.html;\n const img = span.querySelector('img');\n const title = img?.title;\n span.remove();\n state.addNode('text', undefined, title);\n },\n },\n }),\n inputRules: (nodeType) => [\n new InputRule(input, (state, match, start, end) => {\n const content = match[0];\n if (!content) return null;\n const got = nodeEmoji.get(content);\n if (!got || content.includes(got)) return null;\n\n const html = parse(got);\n\n return state.tr\n .setMeta('emoji', true)\n .replaceRangeWith(start, end, nodeType.create({ html }))\n .scrollIntoView();\n }),\n ],\n remarkPlugins: () => [remarkEmoji as RemarkPlugin, twemojiPlugin],\n prosePlugins: () => [picker(utils), filter(utils)],\n };\n});\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { AtomList } from '@milkdown/utils';\n\nimport { emojiNode } from './node';\n\nexport const emoji = AtomList.create([emojiNode()]);\n\nexport { emojiNode } from './node';\n"],"names":["checkTrigger"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/constant.ts","../src/parse.ts","../src/filter/helper.ts","../src/filter/style.ts","../src/filter/index.ts","../src/picker.ts","../src/remark-twemoji.ts","../src/node.ts","../src/index.ts"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nexport const part = /:\\+1|:-1|:[\\w-]+/;\nexport const full = /:\\+1:|:-1:|:[\\w-]+:/;\nexport const input = /(:([^:\\s]+):)$/;\nexport const keyword = ':emoji:';\n","/* Copyright 2021, Milkdown by Mirone. */\nimport twemoji from 'twemoji';\n\nexport const parse = (emoji: string) => twemoji.parse(emoji, { attributes: (text) => ({ title: text }) });\n","/* Copyright 2021, Milkdown by Mirone. */\n\nimport { EditorView } from '@milkdown/prose';\nimport { Emoji } from 'node-emoji';\n\nimport { full, part } from '../constant';\nimport { parse } from '../parse';\n\nexport const checkTrigger = (\n view: EditorView,\n from: number,\n to: number,\n text: string,\n setRange: (from: number, to: number) => void,\n setSearch: (words: string) => void,\n) => {\n if (view.composing) return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n if ($from.parent.type.spec.code) return false;\n const textBefore =\n $from.parent.textBetween(Math.max(0, $from.parentOffset - 10), $from.parentOffset, undefined, '\\ufffc') + text;\n if (full.test(textBefore)) {\n return false;\n }\n const regex = part.exec(textBefore);\n if (regex && textBefore.endsWith(regex[0])) {\n const match = regex[0];\n setRange(from - (match.length - text.length), to);\n setSearch(match);\n return true;\n }\n return false;\n};\n\nexport const renderDropdownList = (\n list: Emoji[],\n dropDown: HTMLElement,\n $active: HTMLElement | null,\n onConfirm: () => void,\n setActive: (active: HTMLElement | null) => void,\n) => {\n dropDown.innerHTML = '';\n list.forEach(({ emoji, key }, i) => {\n const container = document.createElement('div');\n container.className = 'milkdown-emoji-filter_item';\n\n const emojiSpan = document.createElement('span');\n emojiSpan.innerHTML = parse(emoji);\n\n emojiSpan.className = 'milkdown-emoji-filter_item-emoji';\n const keySpan = document.createElement('span');\n keySpan.textContent = ':' + key + ':';\n keySpan.className = 'milkdown-emoji-filter_item-key';\n\n container.appendChild(emojiSpan);\n container.appendChild(keySpan);\n dropDown.appendChild(container);\n\n if (i === 0) {\n container.classList.add('active');\n setActive(container);\n }\n\n container.addEventListener('mouseenter', (e) => {\n if ($active) {\n $active.classList.remove('active');\n }\n const { target } = e;\n if (!(target instanceof HTMLElement)) return;\n target.classList.add('active');\n setActive(target);\n });\n container.addEventListener('mouseleave', (e) => {\n const { target } = e;\n if (!(target instanceof HTMLElement)) return;\n target.classList.remove('active');\n });\n container.addEventListener('mousedown', (e) => {\n onConfirm();\n e.preventDefault();\n });\n });\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { Emotion, ThemeTool } from '@milkdown/core';\n\nexport const injectStyle = ({ size, mixin, palette, font }: ThemeTool, { css, cx }: Emotion) => {\n const border = mixin.border?.();\n const shadow = mixin.shadow?.();\n\n const style = css`\n position: absolute;\n &.hide {\n display: none;\n }\n\n border-radius: ${size.radius};\n background: ${palette('surface')};\n\n .milkdown-emoji-filter_item {\n display: flex;\n gap: 0.5rem;\n height: 2.25rem;\n padding: 0 1rem;\n align-items: center;\n justify-content: flex-start;\n cursor: pointer;\n line-height: 2;\n font-family: ${font.typography};\n font-size: 0.875rem;\n &.active {\n background: ${palette('secondary', 0.12)};\n color: ${palette('primary')};\n }\n }\n\n .emoji {\n height: 1em;\n width: 1em;\n margin: 0 0.05em 0 0.1em;\n vertical-align: -0.1em;\n }\n `;\n return cx(border, shadow, style);\n};\n","/* Copyright 2021, Milkdown by Mirone. */\n\nimport { calculateNodePosition, Plugin } from '@milkdown/prose';\nimport { Utils } from '@milkdown/utils';\nimport { search } from 'node-emoji';\n\nimport { checkTrigger, renderDropdownList } from './helper';\nimport { injectStyle } from './style';\n\nexport const filter = (utils: Utils) => {\n let trigger = false;\n let _from = 0;\n let _search = '';\n let $active: null | HTMLElement = null;\n\n const off = () => {\n trigger = false;\n _from = 0;\n _search = '';\n $active = null;\n };\n\n return new Plugin({\n props: {\n handleKeyDown(_, event) {\n if (['Delete', 'Backspace'].includes(event.key)) {\n _search = _search.slice(0, -1);\n if (_search.length <= 1) {\n off();\n }\n return false;\n }\n if (!trigger) return false;\n if (!['ArrowUp', 'ArrowDown', 'Enter'].includes(event.key)) {\n return false;\n }\n return true;\n },\n handleTextInput(view, from, to, text) {\n trigger = checkTrigger(\n view,\n from,\n to,\n text,\n (from) => {\n _from = from;\n },\n (search) => {\n _search = search;\n },\n );\n if (!trigger) {\n off();\n }\n return false;\n },\n },\n view: (editorView) => {\n const { parentNode } = editorView.dom;\n if (!parentNode) {\n throw new Error();\n }\n\n const dropDown = document.createElement('div');\n const style = utils.getStyle(injectStyle);\n\n if (style) {\n style.split(' ').forEach((x) => dropDown.classList.add(x));\n }\n\n dropDown.classList.add('milkdown-emoji-filter', 'hide');\n\n const replace = () => {\n if (!$active) return;\n\n const { tr } = editorView.state;\n const node = editorView.state.schema.node('emoji', { html: $active.firstElementChild?.innerHTML });\n\n editorView.dispatch(tr.delete(_from, _from + _search.length).insert(_from, node));\n off();\n dropDown.classList.add('hide');\n };\n\n parentNode.appendChild(dropDown);\n parentNode.addEventListener('keydown', (e) => {\n if (!trigger || !(e instanceof KeyboardEvent)) return;\n\n const { key } = e;\n\n if (key === 'Enter') {\n replace();\n return;\n }\n\n if (['ArrowDown', 'ArrowUp'].includes(key)) {\n const next =\n key === 'ArrowDown'\n ? $active?.nextElementSibling || dropDown.firstElementChild\n : $active?.previousElementSibling || dropDown.lastElementChild;\n if ($active) {\n $active.classList.remove('active');\n }\n if (!next) return;\n next.classList.add('active');\n $active = next as HTMLElement;\n\n return;\n }\n });\n parentNode.addEventListener('mousedown', (e) => {\n if (!trigger) return;\n\n e.stopPropagation();\n off();\n dropDown.classList.add('hide');\n });\n\n return {\n update: (view) => {\n if (!trigger) {\n dropDown.classList.add('hide');\n return null;\n }\n const result = search(_search).slice(0, 5);\n const { node } = view.domAtPos(_from);\n if (result.length === 0 || !node) {\n dropDown.classList.add('hide');\n return null;\n }\n\n dropDown.classList.remove('hide');\n renderDropdownList(result, dropDown, $active, replace, (a) => {\n $active = a;\n });\n calculateNodePosition(view, dropDown, (selected, target, parent) => {\n const $editor = dropDown.parentElement;\n if (!$editor) {\n throw new Error();\n }\n const start = view.coordsAtPos(_from);\n let left = start.left - parent.left;\n let top = selected.bottom - parent.top + 14 + $editor.scrollTop;\n\n if (left < 0) {\n left = 0;\n }\n\n if (window.innerHeight - start.bottom < target.height) {\n top = selected.top - parent.top - target.height - 14 + $editor.scrollTop;\n }\n return [top, left];\n });\n\n return null;\n },\n };\n },\n });\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { EmojiButton } from '@joeattardi/emoji-button';\nimport { Decoration, DecorationSet, EditorView, Plugin } from '@milkdown/prose';\nimport { Utils } from '@milkdown/utils';\n\nimport { parse } from './parse';\n\nconst keyword = ':emoji:';\n\nconst checkTrigger = (\n view: EditorView,\n from: number,\n to: number,\n text: string,\n setRange: (from: number, to: number) => void,\n) => {\n if (view.composing) return false;\n const { state } = view;\n const $from = state.doc.resolve(from);\n if ($from.parent.type.spec.code) return false;\n const textBefore =\n $from.parent.textBetween($from.parentOffset - keyword.length + 1, $from.parentOffset, undefined, '\\ufffc') +\n text;\n if (textBefore === keyword) {\n setRange(from - keyword.length + 1, to + 1);\n return true;\n }\n return false;\n};\n\nexport const picker = (utils: Utils) => {\n let trigger = false;\n const holder = document.createElement('span');\n let _from = 0;\n let _to = 0;\n const off = () => {\n trigger = false;\n _from = 0;\n _to = 0;\n };\n\n const plugin = new Plugin({\n props: {\n handleKeyDown() {\n off();\n return false;\n },\n handleClick() {\n off();\n return false;\n },\n handleTextInput(view, from, to, text) {\n trigger = checkTrigger(view, from, to, text, (from, to) => {\n _from = from;\n _to = to;\n });\n\n if (!trigger) {\n off();\n }\n return false;\n },\n decorations(state) {\n if (!trigger) return null;\n\n return DecorationSet.create(state.doc, [Decoration.widget(state.selection.to, holder)]);\n },\n },\n view: (editorView) => {\n const { parentNode } = editorView.dom;\n if (!parentNode) {\n throw new Error();\n }\n utils.getStyle(({ palette, font }, { injectGlobal }) => {\n const css = injectGlobal;\n css`\n .emoji-picker {\n --dark-search-background-color: ${palette('surface')} !important;\n --dark-text-color: ${palette('neutral', 0.87)} !important;\n --dark-background-color: ${palette('background')} !important;\n --dark-border-color: ${palette('shadow')} !important;\n --dark-hover-color: ${palette('secondary', 0.12)} !important;\n --dark-blue-color: ${palette('primary')} !important;\n --dark-search-icon-color: ${palette('primary')} !important;\n --dark-category-button-color: ${palette('secondary', 0.4)} !important;\n --font: ${font.typography} !important;\n --font-size: 1rem !important;\n }\n `;\n });\n const emojiPicker = new EmojiButton({\n rootElement: parentNode as HTMLElement,\n autoFocusSearch: false,\n style: 'twemoji',\n theme: 'dark',\n zIndex: 99,\n });\n emojiPicker.on('emoji', (selection) => {\n const start = _from;\n const end = _to;\n off();\n const html = parse(selection.emoji);\n const node = editorView.state.schema.node('emoji', { html });\n const { tr } = editorView.state;\n\n editorView.dispatch(tr.replaceRangeWith(start, end, node));\n });\n return {\n update: () => {\n if (!trigger) {\n emojiPicker.hidePicker();\n return null;\n }\n emojiPicker.showPicker(holder);\n return null;\n },\n destroy: () => {\n emojiPicker.destroyPicker();\n },\n };\n },\n });\n\n return plugin;\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport emojiRegex from 'emoji-regex';\nimport { Literal, Node, Parent } from 'unist';\n\nimport { parse } from './parse';\n\nconst regex = emojiRegex();\n\nconst isParent = (node: Node): node is Parent => !!(node as Parent).children;\nconst isLiteral = (node: Node): node is Literal => !!(node as Literal).value;\n\nfunction flatMap(ast: Node, fn: (node: Node, index: number, parent: Node | null) => Node[]) {\n return transform(ast, 0, null)[0];\n\n function transform(node: Node, index: number, parent: Node | null) {\n if (isParent(node)) {\n const out = [];\n for (let i = 0, n = node.children.length; i < n; i++) {\n const xs = transform(node.children[i], i, node);\n if (xs) {\n for (let j = 0, m = xs.length; j < m; j++) {\n out.push(xs[j]);\n }\n }\n }\n node.children = out;\n }\n\n return fn(node, index, parent);\n }\n}\n\nexport const twemojiPlugin = () => {\n function transformer(tree: Node) {\n flatMap(tree, (node) => {\n if (!isLiteral(node)) {\n return [node];\n }\n const value = node.value as string;\n const output: Literal<string>[] = [];\n let match;\n let str = value;\n while ((match = regex.exec(str))) {\n const { index } = match;\n const emoji = match[0];\n if (index > 0) {\n output.push({ ...node, value: str.slice(0, index) });\n }\n output.push({ ...node, value: parse(emoji), type: 'emoji' });\n str = str.slice(index + emoji.length);\n }\n if (str.length) {\n output.push({ ...node, value: str });\n }\n return output;\n });\n }\n return transformer;\n};\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { RemarkPlugin } from '@milkdown/core';\nimport { InputRule } from '@milkdown/prose';\nimport { createNode } from '@milkdown/utils';\nimport nodeEmoji from 'node-emoji';\nimport remarkEmoji from 'remark-emoji';\n\nimport { input } from './constant';\nimport { filter } from './filter';\nimport { parse } from './parse';\nimport { picker } from './picker';\nimport { twemojiPlugin } from './remark-twemoji';\n\nexport const emojiNode = createNode((utils) => {\n const style = utils.getStyle(\n (_, { css }) => css`\n display: inline-flex;\n justify-content: center;\n align-items: center;\n\n .emoji {\n height: 1em;\n width: 1em;\n margin: 0 0.05em 0 0.1em;\n vertical-align: -0.1em;\n }\n `,\n );\n return {\n id: 'emoji',\n schema: () => ({\n group: 'inline',\n inline: true,\n selectable: false,\n attrs: {\n html: {\n default: '',\n },\n },\n parseDOM: [\n {\n tag: 'span[data-type=\"emoji\"]',\n getAttrs: (dom) => {\n if (!(dom instanceof HTMLElement)) {\n throw new Error();\n }\n return { html: dom.innerHTML };\n },\n },\n ],\n toDOM: (node) => {\n const span = document.createElement('span');\n span.dataset.type = 'emoji';\n if (style) {\n span.classList.add(style);\n }\n span.classList.add('emoji-wrapper');\n span.innerHTML = node.attrs.html;\n return { dom: span };\n },\n parseMarkdown: {\n match: ({ type }) => type === 'emoji',\n runner: (state, node, type) => {\n state.addNode(type, { html: node.value as string });\n },\n },\n toMarkdown: {\n match: (node) => node.type.name === 'emoji',\n runner: (state, node) => {\n const span = document.createElement('span');\n span.innerHTML = node.attrs.html;\n const img = span.querySelector('img');\n const title = img?.title;\n span.remove();\n state.addNode('text', undefined, title);\n },\n },\n }),\n inputRules: (nodeType) => [\n new InputRule(input, (state, match, start, end) => {\n const content = match[0];\n if (!content) return null;\n const got = nodeEmoji.get(content);\n if (!got || content.includes(got)) return null;\n\n const html = parse(got);\n\n return state.tr\n .setMeta('emoji', true)\n .replaceRangeWith(start, end, nodeType.create({ html }))\n .scrollIntoView();\n }),\n ],\n remarkPlugins: () => [remarkEmoji as RemarkPlugin, twemojiPlugin],\n prosePlugins: () => [picker(utils), filter(utils)],\n };\n});\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { AtomList } from '@milkdown/utils';\n\nimport { emojiNode } from './node';\n\nexport const emoji = AtomList.create([emojiNode()]);\n\nexport { emojiNode } from './node';\n"],"names":["checkTrigger"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;MACa,OAAO;MACP,OAAO;MACP,QAAQ;MCAR,QAAQ,CAAC,WAAkB,QAAQ,MAAM,QAAO,EAAE,YAAY,CAAC,YAAY,OAAO;MCKlFA,iBAAe,CACxB,MACA,MACA,IACA,MACA,UACA,cACC;MACG,KAAK;WAAkB;QACrB,EAAE,UAAU;QACZ,QAAQ,MAAM,IAAI,QAAQ;MAC5B,MAAM,OAAO,KAAK,KAAK;WAAa;QAClC,aACF,MAAM,OAAO,YAAY,KAAK,IAAI,GAAG,MAAM,eAAe,KAAK,MAAM,cAAc,QAAW,YAAY;MAC1G,KAAK,KAAK,aAAa;WAChB;AAAA;QAEL,SAAQ,KAAK,KAAK;MACpB,UAAS,WAAW,SAAS,OAAM,KAAK;UAClC,QAAQ,OAAM;aACX,cAAc,SAAS,KAAK,SAAS;cACpC;WACH;AAAA;SAEJ;AAAA;MAGE,qBAAqB,CAC9B,MACA,UACA,SACA,WACA,cACC;WACQ,YAAY;OAChB,QAAQ,CAAC,EAAE,eAAO,OAAO,MAAM;UAC1B,YAAY,SAAS,cAAc;cAC/B,YAAY;UAEhB,YAAY,SAAS,cAAc;cAC/B,YAAY,MAAM;cAElB,YAAY;UAChB,UAAU,SAAS,cAAc;YAC/B,cAAc,MAAM,MAAM;YAC1B,YAAY;cAEV,YAAY;cACZ,YAAY;aACb,YAAY;QAEjB,MAAM,GAAG;gBACC,UAAU,IAAI;gBACd;AAAA;cAGJ,iBAAiB,cAAc,CAAC,MAAM;UACxC,SAAS;gBACD,UAAU,OAAO;AAAA;YAEvB,EAAE,WAAW;UACf,oBAAoB;;aACjB,UAAU,IAAI;gBACX;AAAA;cAEJ,iBAAiB,cAAc,CAAC,MAAM;YACtC,EAAE,WAAW;UACf,oBAAoB;;aACjB,UAAU,OAAO;AAAA;cAElB,iBAAiB,aAAa,CAAC,MAAM;;QAEzC;AAAA;AAAA;AAAA;MC7ED,cAAc,CAAC,EAAE,MAAM,OAAO,SAAS,QAAmB,EAAE,KAAK,SAAkB;;QACtF,SAAS,YAAM,WAAN;QACT,SAAS,YAAM,WAAN;QAET,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAMO,KAAK;AAAA,sBACR,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAWH,KAAK;AAAA;AAAA;AAAA,8BAGF,QAAQ,aAAa;AAAA,yBAC1B,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;SAWtB,GAAG,QAAQ,QAAQ;AAAA;MC/BjB,SAAS,CAAC,UAAiB;MAChC,UAAU;MACV,QAAQ;MACR,UAAU;MACV,UAA8B;QAE5B,MAAM,MAAM;cACJ;YACF;cACE;cACA;AAAA;SAGP,IAAI,OAAO;AAAA,IACd,OAAO;AAAA,MACH,cAAc,GAAG,OAAO;YAChB,CAAC,UAAU,aAAa,SAAS,MAAM,MAAM;oBACnC,QAAQ,MAAM,GAAG;cACvB,QAAQ,UAAU,GAAG;;;iBAGlB;AAAA;YAEP,CAAC;iBAAgB;YACjB,CAAC,CAAC,WAAW,aAAa,SAAS,SAAS,MAAM,MAAM;iBACjD;AAAA;eAEJ;AAAA;AAAA,MAEX,gBAAgB,MAAM,MAAM,IAAI,MAAM;kBACxBA,eACN,MACA,MACA,IACA,MACA,CAAC,UAAS;kBACE;AAAA,WAEZ,CAAC,YAAW;oBACE;AAAA;YAGd,CAAC,SAAS;;;eAGP;AAAA;AAAA;AAAA,IAGf,MAAM,CAAC,eAAe;YACZ,EAAE,eAAe,WAAW;UAC9B,CAAC,YAAY;cACP,IAAI;AAAA;YAGR,WAAW,SAAS,cAAc;YAClC,QAAQ,MAAM,SAAS;UAEzB,OAAO;cACD,MAAM,KAAK,QAAQ,CAAC,MAAM,SAAS,UAAU,IAAI;AAAA;eAGlD,UAAU,IAAI,yBAAyB;YAE1C,UAAU,MAAM;;YACd,CAAC;;cAEC,EAAE,OAAO,WAAW;cACpB,OAAO,WAAW,MAAM,OAAO,KAAK,SAAS,EAAE,MAAM,cAAQ,sBAAR,mBAA2B;mBAE3E,SAAS,GAAG,OAAO,OAAO,QAAQ,QAAQ,QAAQ,OAAO,OAAO;;iBAElE,UAAU,IAAI;AAAA;iBAGhB,YAAY;iBACZ,iBAAiB,WAAW,CAAC,MAAM;YACtC,CAAC,WAAW,eAAe;;cAEzB,EAAE,QAAQ;YAEZ,QAAQ,SAAS;;;;YAKjB,CAAC,aAAa,WAAW,SAAS,MAAM;gBAClC,OACF,QAAQ,cACF,oCAAS,uBAAsB,SAAS,oBACxC,oCAAS,2BAA0B,SAAS;cAClD,SAAS;oBACD,UAAU,OAAO;AAAA;cAEzB,CAAC;;eACA,UAAU,IAAI;oBACT;;;;iBAKP,iBAAiB,aAAa,CAAC,MAAM;YACxC,CAAC;;UAEH;;iBAEO,UAAU,IAAI;AAAA;aAGpB;AAAA,QACH,QAAQ,CAAC,SAAS;cACV,CAAC,SAAS;qBACD,UAAU,IAAI;mBAChB;AAAA;gBAEL,SAAS,OAAO,SAAS,MAAM,GAAG;gBAClC,EAAE,SAAS,KAAK,SAAS;cAC3B,OAAO,WAAW,KAAK,CAAC,MAAM;qBACrB,UAAU,IAAI;mBAChB;AAAA;mBAGF,UAAU,OAAO;6BACP,QAAQ,UAAU,SAAS,SAAS,CAAC,MAAM;sBAChD;AAAA;gCAEQ,MAAM,UAAU,CAAC,UAAU,QAAQ,WAAW;kBAC1D,UAAU,SAAS;gBACrB,CAAC,SAAS;oBACJ,IAAI;AAAA;kBAER,QAAQ,KAAK,YAAY;gBAC3B,OAAO,MAAM,OAAO,OAAO;gBAC3B,MAAM,SAAS,SAAS,OAAO,MAAM,KAAK,QAAQ;gBAElD,OAAO,GAAG;qBACH;AAAA;gBAGP,OAAO,cAAc,MAAM,SAAS,OAAO,QAAQ;oBAC7C,SAAS,MAAM,OAAO,MAAM,OAAO,SAAS,KAAK,QAAQ;AAAA;mBAE5D,CAAC,KAAK;AAAA;iBAGV;AAAA;AAAA;AAAA;AAAA;AAAA;AClJ3B,MAAM,UAAU;AAEhB,MAAM,eAAe,CACjB,MACA,MACA,IACA,MACA,aACC;MACG,KAAK;WAAkB;QACrB,EAAE,UAAU;QACZ,QAAQ,MAAM,IAAI,QAAQ;MAC5B,MAAM,OAAO,KAAK,KAAK;WAAa;QAClC,aACF,MAAM,OAAO,YAAY,MAAM,eAAe,QAAQ,SAAS,GAAG,MAAM,cAAc,QAAW,YACjG;MACA,eAAe,SAAS;aACf,OAAO,QAAQ,SAAS,GAAG,KAAK;WAClC;AAAA;SAEJ;AAAA;MAGE,SAAS,CAAC,UAAiB;MAChC,UAAU;QACR,SAAS,SAAS,cAAc;MAClC,QAAQ;MACR,MAAM;QACJ,MAAM,MAAM;cACJ;YACF;UACF;AAAA;QAGJ,SAAS,IAAI,OAAO;AAAA,IACtB,OAAO;AAAA,MACH,gBAAgB;;eAEL;AAAA;AAAA,MAEX,cAAc;;eAEH;AAAA;AAAA,MAEX,gBAAgB,MAAM,MAAM,IAAI,MAAM;kBACxB,aAAa,MAAM,MAAM,IAAI,MAAM,CAAC,OAAM,QAAO;kBAC/C;gBACF;AAAA;YAGN,CAAC,SAAS;;;eAGP;AAAA;AAAA,MAEX,YAAY,OAAO;YACX,CAAC;iBAAgB;eAEd,cAAc,OAAO,MAAM,KAAK,CAAC,WAAW,OAAO,MAAM,UAAU,IAAI;AAAA;AAAA;AAAA,IAGtF,MAAM,CAAC,eAAe;YACZ,EAAE,eAAe,WAAW;UAC9B,CAAC,YAAY;cACP,IAAI;AAAA;YAER,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,mBAAmB;cAC9C,MAAM;;;0DAG8B,QAAQ;AAAA,6CACrB,QAAQ,WAAW;AAAA,mDACb,QAAQ;AAAA,+CACZ,QAAQ;AAAA,8CACT,QAAQ,aAAa;AAAA,6CACtB,QAAQ;AAAA,oDACD,QAAQ;AAAA,wDACJ,QAAQ,aAAa;AAAA,kCAC3C,KAAK;AAAA;AAAA;AAAA;AAAA;YAKrB,cAAc,IAAI,YAAY;AAAA,QAChC,aAAa;AAAA,QACb,iBAAiB;AAAA,QACjB,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA;kBAEA,GAAG,SAAS,CAAC,cAAc;cAC7B,QAAQ;cACR,MAAM;;cAEN,OAAO,MAAM,UAAU;cACvB,OAAO,WAAW,MAAM,OAAO,KAAK,SAAS,EAAE;cAC/C,EAAE,OAAO,WAAW;mBAEf,SAAS,GAAG,iBAAiB,OAAO,KAAK;AAAA;aAEjD;AAAA,QACH,QAAQ,MAAM;cACN,CAAC,SAAS;wBACE;mBACL;AAAA;sBAEC,WAAW;iBAChB;AAAA;AAAA,QAEX,SAAS,MAAM;sBACC;AAAA;AAAA;AAAA;AAAA;SAMrB;AAAA;ACrHX,MAAM,QAAQ;AAEd,MAAM,WAAW,CAAC,SAA+B,CAAC,CAAE,KAAgB;AACpE,MAAM,YAAY,CAAC,SAAgC,CAAC,CAAE,KAAiB;AAEvE,iBAAiB,KAAW,IAAgE;SACjF,UAAU,KAAK,GAAG,MAAM;qBAEZ,MAAY,OAAe,QAAqB;QAC3D,SAAS,OAAO;YACV,MAAM;eACH,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,IAAI,GAAG,KAAK;cAC5C,KAAK,UAAU,KAAK,SAAS,IAAI,GAAG;YACtC,IAAI;mBACK,IAAI,GAAG,IAAI,GAAG,QAAQ,IAAI,GAAG,KAAK;gBACnC,KAAK,GAAG;AAAA;AAAA;AAAA;WAInB,WAAW;AAAA;WAGb,GAAG,MAAM,OAAO;AAAA;AAAA;MAIlB,gBAAgB,MAAM;uBACV,MAAY;YACrB,MAAM,CAAC,SAAS;UAChB,CAAC,UAAU,OAAO;eACX,CAAC;AAAA;YAEN,QAAQ,KAAK;YACb,SAA4B;UAC9B;UACA,MAAM;aACF,QAAQ,MAAM,KAAK,MAAO;cACxB,EAAE,UAAU;cACZ,SAAQ,MAAM;YAChB,QAAQ,GAAG;iBACJ,KAAK,iCAAK,OAAL,EAAW,OAAO,IAAI,MAAM,GAAG;AAAA;eAExC,KAAK,iCAAK,OAAL,EAAW,OAAO,MAAM,SAAQ,MAAM;cAC5C,IAAI,MAAM,QAAQ,OAAM;AAAA;UAE9B,IAAI,QAAQ;eACL,KAAK,iCAAK,OAAL,EAAW,OAAO;AAAA;aAE3B;AAAA;AAAA;SAGR;AAAA;MC5CE,YAAY,WAAW,CAAC,UAAU;QACrC,QAAQ,MAAM,SAChB,CAAC,GAAG,EAAE,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;SAab;AAAA,IACH,IAAI;AAAA,IACJ,QAAQ;MACJ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,OAAO;AAAA,QACH,MAAM;AAAA,UACF,SAAS;AAAA;AAAA;AAAA,MAGjB,UAAU;AAAA,QACN;AAAA,UACI,KAAK;AAAA,UACL,UAAU,CAAC,QAAQ;gBACX,iBAAiB,cAAc;oBACzB,IAAI;AAAA;mBAEP,EAAE,MAAM,IAAI;AAAA;AAAA;AAAA;AAAA,MAI/B,OAAO,CAAC,SAAS;cACP,OAAO,SAAS,cAAc;aAC/B,QAAQ,OAAO;YAChB,OAAO;eACF,UAAU,IAAI;AAAA;aAElB,UAAU,IAAI;aACd,YAAY,KAAK,MAAM;eACrB,EAAE,KAAK;AAAA;AAAA,MAElB,eAAe;AAAA,QACX,OAAO,CAAC,EAAE,WAAW,SAAS;AAAA,QAC9B,QAAQ,CAAC,OAAO,MAAM,SAAS;gBACrB,QAAQ,MAAM,EAAE,MAAM,KAAK;AAAA;AAAA;AAAA,MAGzC,YAAY;AAAA,QACR,OAAO,CAAC,SAAS,KAAK,KAAK,SAAS;AAAA,QACpC,QAAQ,CAAC,OAAO,SAAS;gBACf,OAAO,SAAS,cAAc;eAC/B,YAAY,KAAK,MAAM;gBACtB,MAAM,KAAK,cAAc;gBACzB,QAAQ,2BAAK;eACd;gBACC,QAAQ,QAAQ,QAAW;AAAA;AAAA;AAAA;AAAA,IAI7C,YAAY,CAAC,aAAa;AAAA,MACtB,IAAI,UAAU,OAAO,CAAC,OAAO,OAAO,OAAO,QAAQ;cACzC,UAAU,MAAM;YAClB,CAAC;iBAAgB;cACf,MAAM,UAAU,IAAI;YACtB,CAAC,OAAO,QAAQ,SAAS;iBAAa;cAEpC,OAAO,MAAM;eAEZ,MAAM,GACR,QAAQ,SAAS,MACjB,iBAAiB,OAAO,KAAK,SAAS,OAAO,EAAE,SAC/C;AAAA;AAAA;AAAA,IAGb,eAAe,MAAM,CAAC,aAA6B;AAAA,IACnD,cAAc,MAAM,CAAC,OAAO,QAAQ,OAAO;AAAA;AAAA;MCzFtC,QAAQ,SAAS,OAAO,CAAC;;"}
@@ -1 +1 @@
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,qBAiJlC,CAAC"}
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,qBAqJlC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milkdown/plugin-emoji",
3
- "version": "5.3.4",
3
+ "version": "5.3.5",
4
4
  "type": "module",
5
5
  "main": "./lib/index.es.js",
6
6
  "types": "./lib/index.d.ts",
@@ -16,9 +16,9 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "@joeattardi/emoji-button": "^4.6.0",
19
- "@milkdown/core": "5.3.4",
20
- "@milkdown/prose": "5.3.4",
21
- "@milkdown/utils": "5.3.4",
19
+ "@milkdown/core": "5.3.5",
20
+ "@milkdown/prose": "5.3.5",
21
+ "@milkdown/utils": "5.3.5",
22
22
  "@types/node-emoji": "^1.8.1",
23
23
  "@types/twemoji": "^12.1.2",
24
24
  "emoji-regex": "^10.0.0",
@@ -133,16 +133,20 @@ export const filter = (utils: Utils) => {
133
133
  $active = a;
134
134
  });
135
135
  calculateNodePosition(view, dropDown, (selected, target, parent) => {
136
+ const $editor = dropDown.parentElement;
137
+ if (!$editor) {
138
+ throw new Error();
139
+ }
136
140
  const start = view.coordsAtPos(_from);
137
141
  let left = start.left - parent.left;
138
- let top = selected.bottom - parent.top + 14;
142
+ let top = selected.bottom - parent.top + 14 + $editor.scrollTop;
139
143
 
140
144
  if (left < 0) {
141
145
  left = 0;
142
146
  }
143
147
 
144
148
  if (window.innerHeight - start.bottom < target.height) {
145
- top = selected.top - parent.top - target.height - 14;
149
+ top = selected.top - parent.top - target.height - 14 + $editor.scrollTop;
146
150
  }
147
151
  return [top, left];
148
152
  });