@yuntijs/ui 1.2.0-beta.2 → 1.2.0-beta.4

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.
@@ -26,6 +26,13 @@ export interface MentionsProps extends MentionPickerPluginProps {
26
26
  onPressEnter?: (value: string, { event }: {
27
27
  event: KeyboardEvent | null;
28
28
  }) => void;
29
+ /**
30
+ * 用户输入 trigger 后的回调
31
+ */
32
+ /**
33
+ * 按下键盘的回调
34
+ */
35
+ onKeyDown?: (event: KeyboardEvent | null) => void;
29
36
  /**
30
37
  * 用户输入 trigger 后的回调
31
38
  */
@@ -11,7 +11,7 @@ import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
11
11
  import { ConfigProvider } from 'antd';
12
12
  // @Todo: 升级 0.25.0 后,ops-console 使用的时候出现了只输入 / 无法触发的问题
13
13
  import { $getRoot, TextNode } from 'lexical';
14
- import React, { forwardRef, useMemo } from 'react';
14
+ import React, { forwardRef, useCallback, useMemo } from 'react';
15
15
  import { isBrowser } from "../utils/tools";
16
16
  import { CustomTextNode } from "./plugins/custom-text/node";
17
17
  import { EditablePlugin } from "./plugins/editable";
@@ -19,6 +19,7 @@ import { EditorRefPlugin } from "./plugins/editor-ref";
19
19
  import { MentionNode, MentionNodePlugin, MentionNodePluginReplacement } from "./plugins/mention-node";
20
20
  import { MentionPickerPlugin } from "./plugins/mention-picker";
21
21
  import { OnBlurBlockPlugin } from "./plugins/on-blur-block";
22
+ import { OnKeyDownPlugin } from "./plugins/on-key-down";
22
23
  import { ShiftEnterKeyPlugin } from "./plugins/shift-enter-key";
23
24
  import { MentionsConfigProvider } from "./provider";
24
25
  import { useStyles } from "./style";
@@ -56,6 +57,7 @@ export var Mentions = /*#__PURE__*/forwardRef(function (_ref, ref) {
56
57
  code = _ref$code === void 0 ? false : _ref$code,
57
58
  getPopContainer = _ref.getPopContainer,
58
59
  onPressEnter = _ref.onPressEnter,
60
+ onKeyDown = _ref.onKeyDown,
59
61
  onTrigger = _ref.onTrigger;
60
62
  var _ConfigProvider$useCo = ConfigProvider.useConfig(),
61
63
  componentDisabled = _ConfigProvider$useCo.componentDisabled;
@@ -127,6 +129,11 @@ export var Mentions = /*#__PURE__*/forwardRef(function (_ref, ref) {
127
129
  return document.fullscreenElement;
128
130
  }
129
131
  }, [getPopContainer]);
132
+ var onMentionPickerOpen = useCallback(function (resolution) {
133
+ var _resolution$match$rep, _resolution$match;
134
+ var _trigger = (_resolution$match$rep = (_resolution$match = resolution.match) === null || _resolution$match === void 0 ? void 0 : _resolution$match.replaceableString) !== null && _resolution$match$rep !== void 0 ? _resolution$match$rep : triggers[0];
135
+ onTrigger === null || onTrigger === void 0 || onTrigger(_trigger);
136
+ }, [onTrigger, triggers]);
130
137
  return /*#__PURE__*/_jsx(LexicalComposer, {
131
138
  initialConfig: _objectSpread(_objectSpread({}, initialConfig), {}, {
132
139
  editable: editable
@@ -149,10 +156,7 @@ export var Mentions = /*#__PURE__*/forwardRef(function (_ref, ref) {
149
156
  })
150
157
  }), editable && /*#__PURE__*/_jsx(MentionPickerPlugin, {
151
158
  allowSpaces: allowSpaces,
152
- onOpen: function onOpen(resolution) {
153
- var _resolution$match$rep, _resolution$match;
154
- return onTrigger === null || onTrigger === void 0 ? void 0 : onTrigger((_resolution$match$rep = (_resolution$match = resolution.match) === null || _resolution$match === void 0 ? void 0 : _resolution$match.replaceableString) !== null && _resolution$match$rep !== void 0 ? _resolution$match$rep : triggers[0]);
155
- },
159
+ onOpen: onMentionPickerOpen,
156
160
  onSelect: onSelect,
157
161
  options: options,
158
162
  overlayClassName: classNames === null || classNames === void 0 ? void 0 : classNames.menuOverlay,
@@ -171,6 +175,8 @@ export var Mentions = /*#__PURE__*/forwardRef(function (_ref, ref) {
171
175
  editorRef: ref
172
176
  }), /*#__PURE__*/_jsx(ClearEditorPlugin, {}), onPressEnter && /*#__PURE__*/_jsx(ShiftEnterKeyPlugin, {
173
177
  onPressEnter: onPressEnter
178
+ }), onKeyDown && /*#__PURE__*/_jsx(OnKeyDownPlugin, {
179
+ onKeyDown: onKeyDown
174
180
  })]
175
181
  })
176
182
  })
@@ -7,4 +7,5 @@ export var CLEAR_HIDE_MENU_TIMEOUT = createCommand('CLEAR_HIDE_MENU_TIMEOUT');
7
7
  // export const MENTION_REGEX = /{{(.+?)}}/g;
8
8
  // {{plugin-m67m66l8-794.json."id"}}
9
9
  // {{plugin-m67m66l8-794.json."tags"[0]."id"}}
10
- export var MENTION_REGEX = /{{([\w-]{1,50}(\."?[_a-z][\w"[\]]*){1,10})}}/gi;
10
+ // export const MENTION_REGEX = /{{([\w-]{1,50}(\."?[_a-z][\w"[\]]*){1,10})}}/gi;
11
+ export var MENTION_REGEX = /{{[^.}]+\.(.+)}}/gi;
@@ -1,5 +1,5 @@
1
1
  import type { MentionOption } from '../../types';
2
2
  import { MentionMenuOption } from './utils';
3
- export declare const useOptions: (allOptions: MentionOption[], queryString: string | null) => {
3
+ export declare const useOptions: (allOptions: MentionOption[], queryString: string | null, trigger: string | null) => {
4
4
  options: MentionMenuOption[];
5
5
  };
@@ -18,17 +18,20 @@ var filterOptionWithChildren = function filterOptionWithChildren(option, filterO
18
18
  });
19
19
  return option;
20
20
  };
21
- export var useOptions = function useOptions(allOptions, queryString) {
21
+ export var useOptions = function useOptions(allOptions, queryString, trigger) {
22
22
  var _useLexicalComposerCo = useLexicalComposerContext(),
23
23
  _useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
24
24
  editor = _useLexicalComposerCo2[0];
25
25
  var filterOption = useCallback(function (option) {
26
26
  var _option$keywords;
27
+ if (option.triggers && trigger && !option.triggers.includes(trigger)) {
28
+ return false;
29
+ }
27
30
  var regex = new RegExp(escapeRegExp(queryString), 'i');
28
31
  return regex.test(option.label) || ((_option$keywords = option.keywords) === null || _option$keywords === void 0 ? void 0 : _option$keywords.some(function (keyword) {
29
32
  return regex.test(keyword);
30
33
  })) || false;
31
- }, [queryString]);
34
+ }, [queryString, trigger]);
32
35
  var options = useMemo(function () {
33
36
  var _addOnselect = function _addOnselect(option) {
34
37
  var menuOption = _objectSpread(_objectSpread({}, option), {}, {
@@ -48,9 +51,9 @@ export var useOptions = function useOptions(allOptions, queryString) {
48
51
  var menuOptions = allOptions.map(function (o) {
49
52
  return new MentionMenuOption(_addOnselect(o));
50
53
  });
51
- if (!queryString) {
52
- return menuOptions;
53
- }
54
+ // if (!queryString) {
55
+ // return menuOptions;
56
+ // }
54
57
  return menuOptions.map(function (o) {
55
58
  if (!o.children) {
56
59
  return o;
@@ -59,7 +62,7 @@ export var useOptions = function useOptions(allOptions, queryString) {
59
62
  }).filter(function (o) {
60
63
  return filterOption(o) || (o.children || []).length > 0;
61
64
  });
62
- }, [allOptions, queryString, editor, filterOption]);
65
+ }, [allOptions, editor, filterOption]);
63
66
  return {
64
67
  options: options
65
68
  };
@@ -46,7 +46,7 @@ export var MentionPickerPlugin = /*#__PURE__*/memo(function (_ref) {
46
46
  _useState2 = _slicedToArray(_useState, 2),
47
47
  queryString = _useState2[0],
48
48
  setQueryString = _useState2[1];
49
- var _useOptions = useOptions(allOptions, queryString),
49
+ var _useOptions = useOptions(allOptions, queryString, trigger),
50
50
  options = _useOptions.options;
51
51
  var flatOptions = useMemo(function () {
52
52
  var _flattenTree = function _flattenTree(nodes) {
@@ -10,6 +10,8 @@ export interface MentionMenuOptionInitParams {
10
10
  keywords?: Array<string>;
11
11
  keyboardShortcut?: string;
12
12
  disabled?: boolean;
13
+ /** 指定触发这个选项的 triggers,指定后会根据指定的 triggers 进行筛选 */
14
+ triggers?: string[];
13
15
  onSelect: (queryString: string) => void;
14
16
  isChild?: boolean;
15
17
  children?: MentionMenuOptionInitParams[];
@@ -26,8 +28,9 @@ export declare class MentionMenuOption extends MenuOption {
26
28
  keyboardShortcut?: string;
27
29
  onSelect: (queryString: string) => void;
28
30
  disabled?: boolean;
31
+ triggers?: string[];
29
32
  data?: any;
30
33
  children?: MentionMenuOption[];
31
34
  isChild?: boolean;
32
- constructor({ label, value, title, data, icon, extraElement, keywords, keyboardShortcut, disabled, onSelect, children, isChild, }: MentionMenuOptionInitParams);
35
+ constructor({ label, value, title, data, icon, extraElement, keywords, keyboardShortcut, disabled, triggers, onSelect, children, isChild, }: MentionMenuOptionInitParams);
33
36
  }
@@ -24,6 +24,7 @@ export var MentionMenuOption = /*#__PURE__*/function (_MenuOption) {
24
24
  keywords = _ref.keywords,
25
25
  keyboardShortcut = _ref.keyboardShortcut,
26
26
  disabled = _ref.disabled,
27
+ triggers = _ref.triggers,
27
28
  onSelect = _ref.onSelect,
28
29
  children = _ref.children,
29
30
  isChild = _ref.isChild;
@@ -42,6 +43,7 @@ export var MentionMenuOption = /*#__PURE__*/function (_MenuOption) {
42
43
  _defineProperty(_assertThisInitialized(_this), "keyboardShortcut", void 0);
43
44
  _defineProperty(_assertThisInitialized(_this), "onSelect", void 0);
44
45
  _defineProperty(_assertThisInitialized(_this), "disabled", void 0);
46
+ _defineProperty(_assertThisInitialized(_this), "triggers", void 0);
45
47
  _defineProperty(_assertThisInitialized(_this), "data", void 0);
46
48
  _defineProperty(_assertThisInitialized(_this), "children", void 0);
47
49
  _defineProperty(_assertThisInitialized(_this), "isChild", void 0);
@@ -56,6 +58,7 @@ export var MentionMenuOption = /*#__PURE__*/function (_MenuOption) {
56
58
  _this.keyboardShortcut = keyboardShortcut;
57
59
  _this.onSelect = onSelect.bind(_assertThisInitialized(_this));
58
60
  _this.disabled = disabled;
61
+ _this.triggers = triggers;
59
62
  _this.data = data;
60
63
  _this.isChild = isChild !== null && isChild !== void 0 ? isChild : false;
61
64
  _this.children = children === null || children === void 0 ? void 0 : children.map(function (m) {
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import type { MentionsProps } from '..';
3
+ export interface OnKeyDownPluginProps {
4
+ onKeyDown: Required<MentionsProps>['onKeyDown'];
5
+ }
6
+ export declare const OnKeyDownPlugin: React.FC<OnKeyDownPluginProps>;
@@ -0,0 +1,31 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
3
+ import { COMMAND_PRIORITY_LOW, KEY_DOWN_COMMAND } from 'lexical';
4
+ import { useEffect, useRef } from 'react';
5
+ export var OnKeyDownPlugin = function OnKeyDownPlugin(_ref) {
6
+ var onKeyDown = _ref.onKeyDown;
7
+ var _useLexicalComposerCo = useLexicalComposerContext(),
8
+ _useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1),
9
+ editor = _useLexicalComposerCo2[0];
10
+ var onKeyDownRef = useRef(onKeyDown);
11
+ useEffect(function () {
12
+ onKeyDownRef.current = onKeyDown;
13
+ }, [onKeyDown]);
14
+ useEffect(function () {
15
+ // https://github.com/facebook/lexical/discussions/4464#discussioncomment-5833227
16
+ editor.registerCommand(KEY_DOWN_COMMAND, function (event) {
17
+ // 这里把 onKeyDown 放在下一次事件循环中触发,是为了避免跟 Lexical 还未结束的输入等事务发生冲突
18
+ if (window.queueMicrotask === undefined) {
19
+ setTimeout(function () {
20
+ onKeyDownRef.current(event);
21
+ }, 0);
22
+ } else {
23
+ queueMicrotask(function () {
24
+ onKeyDownRef.current(event);
25
+ });
26
+ }
27
+ return false;
28
+ }, COMMAND_PRIORITY_LOW);
29
+ }, [editor]);
30
+ return null;
31
+ };
@@ -1,4 +1,4 @@
1
- import { MentionMenuOptionInitParams } from './plugins/mention-picker/utils';
1
+ import type { MentionMenuOptionInitParams } from './plugins/mention-picker/utils';
2
2
  export interface MentionOption extends Omit<MentionMenuOptionInitParams, 'onSelect' | 'children'> {
3
3
  /** 选中后展示的 label 名称,不指定则直接使用 label */
4
4
  selectedLabel?: string;
@@ -6,4 +6,9 @@ export declare const DELETE_MENTION_COMMAND: import("lexical").LexicalCommand<un
6
6
  export declare const CLEAR_HIDE_MENU_TIMEOUT: import("lexical").LexicalCommand<unknown>;
7
7
  export declare const UPDATE_MENTIONS_OPTIONS: import("lexical").LexicalCommand<unknown>;
8
8
  export declare const decoratorTransform: (node: CustomTextNode, getMatch: (text: string) => null | EntityMatch, createNode: (textNode: TextNode) => LexicalNode) => void;
9
- export declare function textToEditorState(initialValue: string, triggers: string[]): () => void;
9
+ export interface TextToEditorStateOptions {
10
+ /** 光标位置,默认为 end */
11
+ cursor?: 'start' | 'end' | 'all';
12
+ punctuation?: string;
13
+ }
14
+ export declare function textToEditorState(initialValue: string, triggers: string[], options?: TextToEditorStateOptions): () => void;
@@ -1,6 +1,6 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
2
2
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3
- import { $createParagraphNode, $getRoot, $isTextNode, createCommand } from 'lexical';
3
+ import { $createParagraphNode, $getRoot, $isTextNode, $selectAll, createCommand } from 'lexical';
4
4
  import { $convertToMentionNodes } from "./plugins/mention-converter";
5
5
  export var INSERT_MENTION_COMMAND = createCommand('INSERT_MENTION_COMMAND');
6
6
  export var DELETE_MENTION_COMMAND = createCommand('DELETE_MENTION_COMMAND');
@@ -65,12 +65,27 @@ export var decoratorTransform = function decoratorTransform(node, getMatch, crea
65
65
  }
66
66
  }
67
67
  };
68
- export function textToEditorState(initialValue, triggers) {
68
+ export function textToEditorState(initialValue, triggers, options) {
69
69
  return function () {
70
+ var _ref = options || {
71
+ cursor: 'end'
72
+ },
73
+ punctuation = _ref.punctuation,
74
+ cursor = _ref.cursor;
70
75
  var root = $getRoot();
71
76
  root.clear();
72
77
  var paragraph = $createParagraphNode();
73
- paragraph.append.apply(paragraph, _toConsumableArray($convertToMentionNodes(initialValue, triggers)));
78
+ paragraph.append.apply(paragraph, _toConsumableArray($convertToMentionNodes(initialValue, triggers, punctuation)));
74
79
  root.append(paragraph);
80
+ if (!cursor || cursor === 'end') {
81
+ // 👇 把光标移动到文本末尾
82
+ var lastNode = paragraph.getLastDescendant();
83
+ if ($isTextNode(lastNode)) {
84
+ lastNode.select(); // 选中并聚焦尾部
85
+ }
86
+ }
87
+ if (cursor === 'all') {
88
+ $selectAll();
89
+ }
75
90
  };
76
91
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuntijs/ui",
3
- "version": "1.2.0-beta.2",
3
+ "version": "1.2.0-beta.4",
4
4
  "description": "☁️ Yunti UI - an open-source UI component library for building Cloud Native web apps",
5
5
  "keywords": [
6
6
  "yuntijs",