@haklex/rich-plugin-slash-menu 0.0.64 → 0.0.66

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/README.md CHANGED
@@ -1,44 +1,83 @@
1
1
  # @haklex/rich-plugin-slash-menu
2
2
 
3
- 斜杠命令菜单插件。
3
+ Slash command menu plugin for inserting blocks via `/` trigger.
4
4
 
5
- ## 安装
5
+ ## Installation
6
6
 
7
7
  ```bash
8
- pnpm add @haklex/rich-plugin-slash-menu @haklex/rich-editor
8
+ pnpm add @haklex/rich-plugin-slash-menu
9
9
  ```
10
10
 
11
- ## 导出
11
+ ## Peer Dependencies
12
12
 
13
- ```ts
14
- export { SlashMenuPlugin } from './SlashMenuPlugin'
15
- export type { SlashMenuPluginProps } from './SlashMenuPlugin'
16
- export { SlashMenuItem } from './SlashMenuItem'
17
- export { SlashMenuList } from './SlashMenuList'
18
- export { getBuiltinItems } from './builtinItems'
19
- ```
13
+ | Package | Version |
14
+ | --- | --- |
15
+ | `@lexical/list` | `^0.41.0` |
16
+ | `@lexical/react` | `^0.41.0` |
17
+ | `@lexical/rich-text` | `^0.41.0` |
18
+ | `@lexical/selection` | `^0.41.0` |
19
+ | `@lexical/table` | `^0.41.0` |
20
+ | `lexical` | `^0.41.0` |
21
+ | `lucide-react` | `^0.574.0` |
22
+ | `react` | `>= 19` |
23
+ | `react-dom` | `>= 19` |
20
24
 
21
- ## 使用
25
+ ## Usage
22
26
 
23
27
  ```tsx
24
28
  import { SlashMenuPlugin } from '@haklex/rich-plugin-slash-menu'
25
- import { RichEditor } from '@haklex/rich-editor'
29
+ import '@haklex/rich-plugin-slash-menu/style.css'
26
30
 
27
- <RichEditor>
28
- <SlashMenuPlugin />
29
- </RichEditor>
31
+ function Editor() {
32
+ return (
33
+ <RichEditor>
34
+ <SlashMenuPlugin />
35
+ </RichEditor>
36
+ )
37
+ }
30
38
  ```
31
39
 
32
- ## Props
40
+ Typing `/` at the start of a block opens a command menu with filterable block insertion options (headings, lists, code blocks, tables, etc.). The menu supports keyboard navigation and fuzzy matching.
33
41
 
34
- ```ts
35
- interface SlashMenuPluginProps {
36
- items?: SlashMenuItem[] // 自定义项目
37
- extraItems?: SlashMenuItem[] // 额外项目
38
- triggerChar?: string // 触发字符,默认 '/'
39
- }
42
+ ```tsx
43
+ import {
44
+ SlashMenuPlugin,
45
+ SlashMenuItem,
46
+ SlashMenuList,
47
+ getBuiltinItems,
48
+ collectNodeSlashItems,
49
+ } from '@haklex/rich-plugin-slash-menu'
50
+ import type { SlashMenuPluginProps } from '@haklex/rich-plugin-slash-menu'
51
+
52
+ // Get builtin slash menu items
53
+ const items = getBuiltinItems()
54
+
55
+ // Collect slash items registered by nodes
56
+ const nodeItems = collectNodeSlashItems()
40
57
  ```
41
58
 
59
+ ## Exports
60
+
61
+ | Export | Type | Description |
62
+ | --- | --- | --- |
63
+ | `SlashMenuPlugin` | Component | Main plugin component to render inside `RichEditor` |
64
+ | `SlashMenuItem` | Component | Individual menu item component |
65
+ | `SlashMenuList` | Component | Menu list container component |
66
+ | `getBuiltinItems` | Function | Returns the default set of slash menu items |
67
+ | `collectNodeSlashItems` | Function | Collects slash menu items registered by editor nodes |
68
+ | `SlashMenuPluginProps` | TypeScript type | Props type for `SlashMenuPlugin` |
69
+
70
+ ## Sub-path Exports
71
+
72
+ | Path | Description |
73
+ | --- | --- |
74
+ | `@haklex/rich-plugin-slash-menu` | Plugin component, menu items, utilities, and types |
75
+ | `@haklex/rich-plugin-slash-menu/style.css` | Stylesheet |
76
+
77
+ ## Part of Haklex
78
+
79
+ This package is part of the [Haklex](../../README.md) rich editor ecosystem.
80
+
42
81
  ## License
43
82
 
44
83
  MIT
@@ -1 +1 @@
1
- {"version":3,"file":"SlashMenuList.d.ts","sourceRoot":"","sources":["../src/SlashMenuList.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAGpD,UAAU,kBAAkB;IAC1B,aAAa,EAAE,WAAW,CAAA;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,sBAAsB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAA;IACvD,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7C;AAyBD,wBAAgB,aAAa,CAAC,EAC5B,aAAa,EACb,OAAO,EACP,aAAa,EACb,sBAAsB,EACtB,mBAAmB,GACpB,EAAE,kBAAkB,2CA8EpB"}
1
+ {"version":3,"file":"SlashMenuList.d.ts","sourceRoot":"","sources":["../src/SlashMenuList.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,UAAU,kBAAkB;IAC1B,aAAa,EAAE,WAAW,CAAC;IAC3B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,sBAAsB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IACxD,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C;AAyBD,wBAAgB,aAAa,CAAC,EAC5B,aAAa,EACb,OAAO,EACP,aAAa,EACb,sBAAsB,EACtB,mBAAmB,GACpB,EAAE,kBAAkB,2CA+DpB"}
@@ -1,10 +1,10 @@
1
1
  import { LexicalEditor } from 'lexical';
2
2
  import { SlashMenuItem } from './SlashMenuItem';
3
3
  export interface SlashMenuPluginProps {
4
- items?: SlashMenuItem[];
5
4
  extraItems?: SlashMenuItem[];
5
+ items?: SlashMenuItem[];
6
6
  triggerChar?: string;
7
7
  }
8
8
  export declare function collectNodeSlashItems(editor: LexicalEditor): SlashMenuItem[];
9
- export declare function SlashMenuPlugin({ items, extraItems, triggerChar, }: SlashMenuPluginProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function SlashMenuPlugin({ items, extraItems, triggerChar }: SlashMenuPluginProps): import("react/jsx-runtime").JSX.Element;
10
10
  //# sourceMappingURL=SlashMenuPlugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SlashMenuPlugin.d.ts","sourceRoot":"","sources":["../src/SlashMenuPlugin.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,SAAS,CAAA;AAMtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAIpD,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,aAAa,EAAE,CAAA;IACvB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,EAAE,CAK5E;AAWD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,UAAU,EACV,WAAiB,GAClB,EAAE,oBAAoB,2CAuEtB"}
1
+ {"version":3,"file":"SlashMenuPlugin.d.ts","sourceRoot":"","sources":["../src/SlashMenuPlugin.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,SAAS,CAAC;AAMvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIrD,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,aAAa,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,EAAE,CAK5E;AAWD,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,WAAiB,EAAE,EAAE,oBAAoB,2CAuE7F"}
package/dist/index.mjs CHANGED
@@ -12,7 +12,7 @@ import { createElement, useEffect, useMemo, useState, useCallback } from "react"
12
12
  import { MenuOption, useBasicTypeaheadTriggerMatch, LexicalTypeaheadMenuPlugin } from "@lexical/react/LexicalTypeaheadMenuPlugin";
13
13
  import { jsx, jsxs } from "react/jsx-runtime";
14
14
  import { useFloating, autoUpdate, offset, flip, shift } from "@floating-ui/react-dom";
15
- import { collectCommandItems } from "@haklex/rich-editor";
15
+ import { collectCommandItems } from "@haklex/rich-editor/commands";
16
16
  import { PortalThemeWrapper } from "@haklex/rich-style-token";
17
17
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
18
18
  import { createPortal } from "react-dom";
@@ -218,57 +218,32 @@ function SlashMenuList({
218
218
  }, [anchorElement, refs]);
219
219
  const sections = useMemo(() => groupBySection(options), [options]);
220
220
  if (options.length === 0) {
221
- return /* @__PURE__ */ jsx(
222
- "div",
223
- {
224
- ref: refs.setFloating,
225
- style: floatingStyles,
226
- className: slashMenu,
227
- children: /* @__PURE__ */ jsx("div", { className: slashMenuEmpty, children: "No matching commands" })
228
- }
229
- );
221
+ return /* @__PURE__ */ jsx("div", { className: slashMenu, ref: refs.setFloating, style: floatingStyles, children: /* @__PURE__ */ jsx("div", { className: slashMenuEmpty, children: "No matching commands" }) });
230
222
  }
231
- return /* @__PURE__ */ jsx(
232
- "ul",
233
- {
234
- ref: refs.setFloating,
235
- style: floatingStyles,
236
- className: slashMenu,
237
- role: "listbox",
238
- children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs(
239
- "li",
240
- {
241
- role: "presentation",
242
- className: slashMenuSectionWrapper,
243
- children: [
244
- sectionIndex > 0 && /* @__PURE__ */ jsx("div", { className: slashMenuSectionDivider }),
245
- /* @__PURE__ */ jsx("div", { className: slashMenuSection, children: section.label }),
246
- /* @__PURE__ */ jsx("ul", { className: slashMenuItems, role: "group", children: section.items.map(({ item, globalIndex }) => /* @__PURE__ */ jsxs(
247
- "li",
248
- {
249
- className: slashMenuItem,
250
- role: "option",
251
- "aria-selected": globalIndex === selectedIndex,
252
- onClick: () => selectOptionAndCleanUp(item),
253
- onMouseEnter: () => setHighlightedIndex(globalIndex),
254
- ref: item.setRefElement,
255
- tabIndex: -1,
256
- children: [
257
- /* @__PURE__ */ jsx("span", { className: slashMenuItemIcon, children: item.icon }),
258
- /* @__PURE__ */ jsxs("span", { className: slashMenuItemText, children: [
259
- /* @__PURE__ */ jsx("span", { className: slashMenuItemTitle, children: item.title }),
260
- item.description && /* @__PURE__ */ jsx("span", { className: slashMenuItemDescription, children: item.description })
261
- ] })
262
- ]
263
- },
264
- item.key
265
- )) })
266
- ]
267
- },
268
- section.label
269
- ))
270
- }
271
- );
223
+ return /* @__PURE__ */ jsx("ul", { className: slashMenu, ref: refs.setFloating, role: "listbox", style: floatingStyles, children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs("li", { className: slashMenuSectionWrapper, role: "presentation", children: [
224
+ sectionIndex > 0 && /* @__PURE__ */ jsx("div", { className: slashMenuSectionDivider }),
225
+ /* @__PURE__ */ jsx("div", { className: slashMenuSection, children: section.label }),
226
+ /* @__PURE__ */ jsx("ul", { className: slashMenuItems, role: "group", children: section.items.map(({ item, globalIndex }) => /* @__PURE__ */ jsxs(
227
+ "li",
228
+ {
229
+ "aria-selected": globalIndex === selectedIndex,
230
+ className: slashMenuItem,
231
+ ref: item.setRefElement,
232
+ role: "option",
233
+ tabIndex: -1,
234
+ onClick: () => selectOptionAndCleanUp(item),
235
+ onMouseEnter: () => setHighlightedIndex(globalIndex),
236
+ children: [
237
+ /* @__PURE__ */ jsx("span", { className: slashMenuItemIcon, children: item.icon }),
238
+ /* @__PURE__ */ jsxs("span", { className: slashMenuItemText, children: [
239
+ /* @__PURE__ */ jsx("span", { className: slashMenuItemTitle, children: item.title }),
240
+ item.description && /* @__PURE__ */ jsx("span", { className: slashMenuItemDescription, children: item.description })
241
+ ] })
242
+ ]
243
+ },
244
+ item.key
245
+ )) })
246
+ ] }, section.label)) });
272
247
  }
273
248
  function collectNodeSlashItems(editor) {
274
249
  const configs = collectCommandItems(editor);
@@ -282,11 +257,7 @@ function filterItems(query, items) {
282
257
  return item.keywords.some((kw) => kw.toLowerCase().includes(lower));
283
258
  });
284
259
  }
285
- function SlashMenuPlugin({
286
- items,
287
- extraItems,
288
- triggerChar = "/"
289
- }) {
260
+ function SlashMenuPlugin({ items, extraItems, triggerChar = "/" }) {
290
261
  const [editor] = useLexicalComposerContext();
291
262
  const [queryString, setQueryString] = useState(null);
292
263
  const allItems = useMemo(() => {
@@ -321,10 +292,8 @@ function SlashMenuPlugin({
321
292
  return /* @__PURE__ */ jsx(
322
293
  LexicalTypeaheadMenuPlugin,
323
294
  {
324
- onQueryChange: setQueryString,
325
- onSelectOption,
326
- triggerFn: checkForTriggerMatch,
327
295
  options: filteredItems,
296
+ triggerFn: checkForTriggerMatch,
328
297
  menuRenderFn: (anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => {
329
298
  const anchorElement = anchorElementRef.current;
330
299
  if (!anchorElement || filteredItems.length === 0) {
@@ -336,14 +305,16 @@ function SlashMenuPlugin({
336
305
  {
337
306
  anchorElement,
338
307
  options: filteredItems,
339
- selectedIndex,
340
308
  selectOptionAndCleanUp,
309
+ selectedIndex,
341
310
  setHighlightedIndex
342
311
  }
343
312
  ) }),
344
313
  anchorElement
345
314
  );
346
- }
315
+ },
316
+ onQueryChange: setQueryString,
317
+ onSelectOption
347
318
  }
348
319
  );
349
320
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@haklex/rich-plugin-slash-menu",
3
3
  "type": "module",
4
- "version": "0.0.64",
4
+ "version": "0.0.66",
5
5
  "description": "Slash command menu plugin",
6
6
  "license": "MIT",
7
7
  "exports": {
@@ -28,8 +28,8 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@floating-ui/react-dom": "^2.1.8",
31
- "@haklex/rich-editor": "0.0.64",
32
- "@haklex/rich-style-token": "0.0.64"
31
+ "@haklex/rich-editor": "0.0.66",
32
+ "@haklex/rich-style-token": "0.0.66"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@lexical/list": "^0.41.0",
@@ -52,6 +52,11 @@
52
52
  "publishConfig": {
53
53
  "access": "public"
54
54
  },
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "https://github.com/Innei/haklex.git",
58
+ "directory": "packages/rich-plugin-slash-menu"
59
+ },
55
60
  "scripts": {
56
61
  "build": "vite build",
57
62
  "dev:build": "vite build --watch"
package/LICENSE DELETED
@@ -1,28 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Innei
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
22
-
23
-
24
- Additional Terms and Conditions
25
-
26
- ----------------
27
-
28
- Use of this software is governed by the terms of MIT and, in addition, by the terms and conditions described in the additional file (ADDITIONAL_TERMS.md). By using this software, you agree to abide by these additional terms and conditions.