@blocklet/editor 1.6.195 → 1.6.197

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.
@@ -4,7 +4,10 @@ import { usePopper } from 'react-popper';
4
4
  import { useState } from 'react';
5
5
  const CreatePopperElement = ({ portalElement, parentElement, }) => {
6
6
  const [popperElement, setPopperElement] = useState(null);
7
- const { styles, attributes } = usePopper(parentElement, popperElement, { placement: 'bottom-start' });
7
+ const { styles, attributes } = usePopper(parentElement, popperElement, {
8
+ placement: 'bottom-start',
9
+ strategy: 'fixed',
10
+ });
8
11
  return (_jsx("div", { ref: setPopperElement, style: { ...styles.popper, zIndex: 1 }, ...attributes.popper, children: portalElement }));
9
12
  };
10
13
  const createPortal = (portalElement, parentElement) => {
@@ -9,7 +9,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
9
9
  import { $getSelection, $isRangeSelection, $createTextNode, COMMAND_PRIORITY_EDITOR, KEY_DOWN_COMMAND, } from 'lexical';
10
10
  import { AutoEmbedOption, URL_MATCHER, LexicalAutoEmbedPlugin, } from '@lexical/react/LexicalAutoEmbedPlugin';
11
11
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
12
- import { useMemo, useState, useEffect } from 'react';
12
+ import { useMemo, useState, useEffect, useRef } from 'react';
13
13
  import { $getNearestNodeOfType } from '@lexical/utils';
14
14
  import { LinkNode, $createLinkNode } from '@lexical/link';
15
15
  import compact from 'lodash/compact';
@@ -24,11 +24,11 @@ import { createBookmarkOption } from '../../../ext/BookmarkPlugin';
24
24
  import { get as getFromUrlParseCache, wrap } from './urlParseCache';
25
25
  import { BilibiliEmbedConfig } from '../../../ext/BilibiliPlugin/config';
26
26
  import { createPostLinkAutoEmbedOption } from '../../../ext/PostLinkEmbedPlugin';
27
- import createPortal from '../../../components/createPortal';
28
27
  import { $createGithubNode } from '../../../ext/nodes/GithubNode';
29
28
  import { $createEmojiNode } from '../../nodes/EmojiNode';
30
29
  import { useEditorConfig } from '../../../config';
31
30
  import { fetchOpenGraphInfo } from '../../../ext/utils';
31
+ import createPortal from '../../../components/createPortal';
32
32
  export const YoutubeEmbedConfig = {
33
33
  contentName: 'Youtube Video',
34
34
  exampleUrl: 'https://www.youtube.com/watch?v=jNQXAC9IVRw',
@@ -206,10 +206,19 @@ export default function AutoEmbedPlugin() {
206
206
  const [editor] = useLexicalComposerContext();
207
207
  const [modal, showModal] = useModal();
208
208
  const editorConfig = useEditorConfig();
209
+ const dismissFnRef = useRef(null);
209
210
  const openEmbedModal = (embedConfig) => {
210
211
  showModal(`Embed ${embedConfig.contentName}`, (onClose) => (_jsx(AutoEmbedDialog, { embedConfig: embedConfig, onClose: onClose })));
211
212
  };
213
+ // Dismiss the menu when moving the cursor
214
+ // (https://community.arcblock.io/discussions/29f1b7a4-2af6-407f-8653-1267067d8899)
215
+ useEffect(() => {
216
+ return editor.registerUpdateListener(() => {
217
+ dismissFnRef.current?.();
218
+ });
219
+ }, [editor]);
212
220
  const getMenuOptions = (activeEmbedConfig, embedFn, dismissFn) => {
221
+ dismissFnRef.current = dismissFn;
213
222
  return compact([
214
223
  new AutoEmbedOption('Dismiss', {
215
224
  onSelect: dismissFn,
@@ -314,15 +323,17 @@ export default function AutoEmbedPlugin() {
314
323
  return false;
315
324
  }, COMMAND_PRIORITY_EDITOR);
316
325
  }, [editor]);
317
- return (_jsxs(_Fragment, { children: [modal, _jsx(LexicalAutoEmbedPlugin, { embedConfigs: EmbedConfigs, onOpenEmbedModalForConfig: openEmbedModal, getMenuOptions: getMenuOptions, menuRenderFn: (anchorElementRef, { selectedIndex, options, selectOptionAndCleanUp, setHighlightedIndex }) => anchorElementRef.current
318
- ? createPortal(_jsx("div", { className: "typeahead-popover auto-embed-menu", style: {
319
- marginLeft: anchorElementRef.current.style.width,
320
- width: 200,
321
- }, children: _jsx(AutoEmbedMenu, { options: options, selectedItemIndex: selectedIndex, onOptionClick: (option, index) => {
322
- setHighlightedIndex(index);
323
- selectOptionAndCleanUp(option);
324
- }, onOptionMouseEnter: (index) => {
325
- setHighlightedIndex(index);
326
- } }) }), anchorElementRef.current)
327
- : null })] }));
326
+ return (_jsxs(_Fragment, { children: [modal, _jsx(LexicalAutoEmbedPlugin, { embedConfigs: EmbedConfigs, onOpenEmbedModalForConfig: openEmbedModal, getMenuOptions: getMenuOptions, menuRenderFn: (anchorElementRef, { selectedIndex, options, selectOptionAndCleanUp, setHighlightedIndex }) => {
327
+ return anchorElementRef.current
328
+ ? createPortal(_jsx("div", { className: "typeahead-popover auto-embed-menu", style: {
329
+ marginLeft: `${Math.max(parseFloat(anchorElementRef.current.style.width) - 200, 0)}px`,
330
+ width: 200,
331
+ }, children: _jsx(AutoEmbedMenu, { options: options, selectedItemIndex: selectedIndex, onOptionClick: (option, index) => {
332
+ setHighlightedIndex(index);
333
+ selectOptionAndCleanUp(option);
334
+ }, onOptionMouseEnter: (index) => {
335
+ setHighlightedIndex(index);
336
+ } }) }), anchorElementRef.current)
337
+ : null;
338
+ } })] }));
328
339
  }
@@ -8,22 +8,21 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
8
8
  *
9
9
  */
10
10
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
11
- import { $createTextNode, $getSelection } from 'lexical';
11
+ import { LexicalTypeaheadMenuPlugin, useBasicTypeaheadTriggerMatch, } from '@lexical/react/LexicalTypeaheadMenuPlugin';
12
12
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
13
13
  import debounce from 'lodash/debounce';
14
- import { LexicalTypeaheadMenuPlugin, TypeaheadOption, useBasicTypeaheadTriggerMatch, } from '../LexicalTypeaheadMenuPlugin';
15
14
  import { $createMentionNode } from '../../nodes/MentionNode';
16
15
  import { useEditorConfig } from '../../../config';
17
16
  import HighlightStyle from './HighlightStyle';
18
- import createPortal from '../../../components/createPortal';
19
17
  import sortArrayByKey from '../../../libs/sort-array-by-key';
18
+ import { TypeaheadOption } from '../LexicalTypeaheadMenuPlugin';
19
+ import createPortal from '../../../components/createPortal';
20
20
  const PUNCTUATION = '\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%\'"~=<>_:;';
21
21
  const NAME = `\\b[A-Z][^\\s${PUNCTUATION}]`;
22
22
  const DocumentMentionsRegex = {
23
23
  NAME,
24
24
  PUNCTUATION,
25
25
  };
26
- const CapitalizedNameMentionsRegex = new RegExp(`(^|[^#])((?:${DocumentMentionsRegex.NAME}{${1},})$)`);
27
26
  const PUNC = DocumentMentionsRegex.PUNCTUATION;
28
27
  const TRIGGERS = ['@'].join('');
29
28
  // Chars we expect to see in a mention (non-space, non-punctuation).
@@ -75,23 +74,6 @@ function useMentionLookupService(mentionString) {
75
74
  }, [mentionString]);
76
75
  return results;
77
76
  }
78
- function checkForCapitalizedNameMentions(text, minMatchLength) {
79
- const match = CapitalizedNameMentionsRegex.exec(text);
80
- if (match !== null) {
81
- // The strategy ignores leading whitespace but we need to know it's
82
- // length to add it to the leadOffset
83
- const maybeLeadingWhitespace = match[1];
84
- const matchingString = match[2];
85
- if (matchingString != null && matchingString.length >= minMatchLength) {
86
- return {
87
- leadOffset: match.index + maybeLeadingWhitespace.length,
88
- matchingString,
89
- replaceableString: matchingString,
90
- };
91
- }
92
- }
93
- return null;
94
- }
95
77
  function checkForAtSignMentions(text, minMatchLength) {
96
78
  // 输入 @ 符号立即显示用户列表 (#383)
97
79
  if (/([\s]|^)@$/.test(text)) {
@@ -121,10 +103,7 @@ function checkForAtSignMentions(text, minMatchLength) {
121
103
  return null;
122
104
  }
123
105
  function getPossibleQueryMatch(text) {
124
- const match = checkForAtSignMentions(text, 1);
125
- // 禁用 "连续输入 (4 个?) 大写字母触发 mention"
126
- // return match === null ? checkForCapitalizedNameMentions(text, 3) : match;
127
- return match;
106
+ return checkForAtSignMentions(text, 1);
128
107
  }
129
108
  class MentionTypeaheadOption extends TypeaheadOption {
130
109
  user;
@@ -155,27 +134,28 @@ export default function NewMentionsPlugin() {
155
134
  nodeToReplace.replace(mentionNode);
156
135
  }
157
136
  mentionNode.select();
158
- const textNode = $createTextNode(' ');
159
- const selection = $getSelection();
160
- selection?.insertNodes([textNode]);
161
137
  closeMenu();
162
138
  });
163
139
  }, [editor]);
164
140
  const checkForMentionMatch = useCallback((text) => {
165
- const mentionMatch = getPossibleQueryMatch(text);
166
141
  const slashMatch = checkForSlashTriggerMatch(text, editor);
167
- return !slashMatch && mentionMatch ? mentionMatch : null;
142
+ if (slashMatch !== null) {
143
+ return null;
144
+ }
145
+ return getPossibleQueryMatch(text);
168
146
  }, [checkForSlashTriggerMatch, editor]);
169
- return (_jsxs(_Fragment, { children: [_jsx(LexicalTypeaheadMenuPlugin, { onQueryChange: setQueryString, onSelectOption: onSelectOption, triggerFn: checkForMentionMatch, options: options, menuRenderFn: (anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => anchorElementRef.current && results.length
170
- ? createPortal(_jsx("div", { className: "typeahead-popover mentions-menu", children: _jsx("ul", { children: options.map((option, i) => (_jsx(MentionsTypeaheadMenuItem, { index: i, isSelected: selectedIndex === i, onClick: () => {
171
- setHighlightedIndex(i);
172
- selectOptionAndCleanUp(option);
173
- }, onMouseEnter: () => {
174
- setHighlightedIndex(i);
175
- // hover option 时显示用户 did
176
- if (option?.ref?.current) {
177
- option.ref.current.title = option.user.did;
178
- }
179
- }, option: option }, option.key))) }) }), anchorElementRef.current)
180
- : null }), _jsx(HighlightStyle, {})] }));
147
+ return (_jsxs(_Fragment, { children: [_jsx(LexicalTypeaheadMenuPlugin, { onQueryChange: setQueryString, onSelectOption: onSelectOption, triggerFn: checkForMentionMatch, options: options, menuRenderFn: (anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => {
148
+ return anchorElementRef.current && results.length
149
+ ? createPortal(_jsx("div", { className: "typeahead-popover mentions-menu", children: _jsx("ul", { children: options.map((option, i) => (_jsx(MentionsTypeaheadMenuItem, { index: i, isSelected: selectedIndex === i, onClick: () => {
150
+ setHighlightedIndex(i);
151
+ selectOptionAndCleanUp(option);
152
+ }, onMouseEnter: () => {
153
+ setHighlightedIndex(i);
154
+ // hover option 时显示用户 did
155
+ if (option?.ref?.current) {
156
+ option.ref.current.title = option.user.did;
157
+ }
158
+ }, option: option }, option.key))) }) }), anchorElementRef.current)
159
+ : null;
160
+ } }), _jsx(HighlightStyle, {})] }));
181
161
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/editor",
3
- "version": "1.6.195",
3
+ "version": "1.6.197",
4
4
  "main": "lib/index.js",
5
5
  "scripts": {
6
6
  "dev": "npm run storybook",
@@ -37,9 +37,9 @@
37
37
  ]
38
38
  },
39
39
  "dependencies": {
40
- "@arcblock/ux": "^2.9.58",
40
+ "@arcblock/ux": "^2.9.63",
41
41
  "@blocklet/embed": "^0.1.11",
42
- "@blocklet/pdf": "1.6.195",
42
+ "@blocklet/pdf": "1.6.197",
43
43
  "@excalidraw/excalidraw": "^0.14.2",
44
44
  "@iconify/iconify": "^3.0.1",
45
45
  "@lexical/clipboard": "0.13.1",
@@ -108,5 +108,5 @@
108
108
  "react": "*",
109
109
  "react-dom": "*"
110
110
  },
111
- "gitHead": "5c9deace228af5f06acbb41ac675780e46368027"
111
+ "gitHead": "0dfec64ec8d8047b70efdffe51b2ded92fbe796f"
112
112
  }