{"_id":"@emergence-engineering/lexical-slash-menu-plugin","_rev":"6-2169168ba7b71ad5c81892a76c2a7d6a","name":"@emergence-engineering/lexical-slash-menu-plugin","dist-tags":{"latest":"0.0.4"},"versions":{"0.0.2":{"name":"@emergence-engineering/lexical-slash-menu-plugin","version":"0.0.2","keywords":["lexical","slash menu","plugin"],"author":"Emergence Engineering","license":"MIT","_id":"@emergence-engineering/lexical-slash-menu-plugin@0.0.2","maintainers":[{"name":"blaisehorvath","email":"balazs.horvath@emergence-engineering.com"},{"name":"matejcsok","email":"istvan.matejcsok@emergence-engineering.com"},{"name":"viktorvacziee","email":"viktor.vaczi@emergence-engineering.com"}],"homepage":"https://github.com/emergence-engineering/lexical-slash-menu-plugin","bugs":{"url":"https://github.com/emergence-engineering/lexical-slash-menu-plugin/issues"},"dist":{"shasum":"c73cf457073cf827a248b1b1bf1ded195c9d88ca","tarball":"https://registry.npmjs.org/@emergence-engineering/lexical-slash-menu-plugin/-/lexical-slash-menu-plugin-0.0.2.tgz","fileCount":33,"integrity":"sha512-G7oMCKyQmmyk7VQx8zh9TBi+6LJ1jqxJRvLvUuGl04VapXiZYohamIMmB+mDeIGTVZ4ejGXoocOROMZV2WpwTQ==","signatures":[{"sig":"MEQCICiKsIbxVmzmYo7I7onqRsNa/6s8l1MzjCmtTGl6uOPYAiBB4j2s2UwxZ9F1oG6C0ttaWJzYlaL6aV5qJPsD6lQUrw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":111185},"main":"dist/index.js","_from":"file:emergence-engineering-lexical-slash-menu-plugin-0.0.2.tgz","types":"dist/index.d.ts","module":"dist/index.es.js","scripts":{"dev":"rollup -c -w --bundleConfigAsCjs","lint":"tsc --noEmit && eslint src --ext .ts","test":"echo no test","build":"rollup -c --bundleConfigAsCjs"},"_npmUser":{"name":"matejcsok","email":"istvan.matejcsok@emergence-engineering.com"},"_resolved":"/private/var/folders/1h/dyhpky5s52qfj3bwbwc4yg800000gn/T/92c92b12c9d72c3c25ac2eb9299d20b1/emergence-engineering-lexical-slash-menu-plugin-0.0.2.tgz","_integrity":"sha512-G7oMCKyQmmyk7VQx8zh9TBi+6LJ1jqxJRvLvUuGl04VapXiZYohamIMmB+mDeIGTVZ4ejGXoocOROMZV2WpwTQ==","_npmVersion":"8.3.1","description":"A slash-menu plugin for Lexical editor","directories":{},"_nodeVersion":"16.14.0","dependencies":{"react":"^18.2.0","lexical":"^0.11.3","react-dom":"^18.2.0","@lexical/react":"^0.11.3","@floating-ui/react-dom":"^2.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.6.1","eslint":"^8.29.0","rollup":"^3.28.0","postcss":"^8.4.20","ts-node":"^10.9.1","prettier":"^2.8.1","npm-check":"^6.0.1","css-loader":"^6.7.3","typescript":"^5.1.6","@babel/core":"^7.22.9","@types/node":"^18.11.15","@types/react":"^18.0.26","@types/react-dom":"^18.0.9","@babel/preset-env":"^7.22.9","eslint-config-next":"^13.0.7","rollup-plugin-copy":"^3.4.0","@babel/preset-react":"^7.22.5","eslint-plugin-react":"^7.33.0","rollup-plugin-babel":"^4.4.0","eslint-config-airbnb":"^19.0.4","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-sucrase":"^5.0.1","eslint-config-prettier":"^8.5.0","eslint-plugin-prettier":"^4.2.1","@rollup/plugin-commonjs":"^25.0.0","rollup-plugin-import-css":"^3.2.1","@rollup/plugin-typescript":"^11.1.1","@typescript-eslint/parser":"^6.2.0","rollup-plugin-typescript2":"^0.34.1","@rollup/plugin-node-resolve":"^15.1.0","@typescript-eslint/eslint-plugin":"^6.2.0","rollup-plugin-peer-deps-external":"^2.2.4","rollup-plugin-exclude-dependencies-from-bundle":"^1.1.23"},"_npmOperationalInternal":{"tmp":"tmp/lexical-slash-menu-plugin_0.0.2_1693314085326_0.3755066359544099","host":"s3://npm-registry-packages"}},"0.0.3":{"name":"@emergence-engineering/lexical-slash-menu-plugin","version":"0.0.3","keywords":["lexical","slash menu","plugin"],"author":"Emergence Engineering","license":"MIT","_id":"@emergence-engineering/lexical-slash-menu-plugin@0.0.3","maintainers":[{"name":"cskata","email":"katalin.csillag@emergence-engineering.com"},{"name":"blaisehorvath","email":"balazs.horvath@emergence-engineering.com"},{"name":"matejcsok","email":"istvan.matejcsok@emergence-engineering.com"},{"name":"viktorvacziee","email":"viktor.vaczi@emergence-engineering.com"}],"homepage":"https://github.com/emergence-engineering/lexical-slash-menu-plugin","bugs":{"url":"https://github.com/emergence-engineering/lexical-slash-menu-plugin/issues"},"dist":{"shasum":"feffdfc24fe271db553f458c1eb3b5a7b76014b0","tarball":"https://registry.npmjs.org/@emergence-engineering/lexical-slash-menu-plugin/-/lexical-slash-menu-plugin-0.0.3.tgz","fileCount":33,"integrity":"sha512-KfbrCKdI2Xl2cYk1GnHu9Wt9wcVfE8bizItCsHgQbqQdjv9veF8pWxOxHNUX7QlMQvhl+hKu6s13rZjE1wC2kw==","signatures":[{"sig":"MEQCIAjxocQM1w2nlhpHKvMQ2W5LtQm3fZA1fVe4ipNhdL2eAiB2GqPkyWJZPO1Mf+lVJ/ay0yuVsJLZT6FkeCB7ihCXjA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":115777},"main":"dist/index.js","_from":"file:emergence-engineering-lexical-slash-menu-plugin-0.0.3.tgz","types":"dist/index.d.ts","module":"dist/index.es.js","scripts":{"dev":"rollup -c -w --bundleConfigAsCjs","lint":"tsc --noEmit && eslint src --ext .ts","test":"echo no test","build":"rollup -c --bundleConfigAsCjs"},"_npmUser":{"name":"matejcsok","email":"istvan.matejcsok@emergence-engineering.com"},"_resolved":"/private/var/folders/1h/dyhpky5s52qfj3bwbwc4yg800000gn/T/34eaf377fdb69c7cba397147a4fbe586/emergence-engineering-lexical-slash-menu-plugin-0.0.3.tgz","_integrity":"sha512-KfbrCKdI2Xl2cYk1GnHu9Wt9wcVfE8bizItCsHgQbqQdjv9veF8pWxOxHNUX7QlMQvhl+hKu6s13rZjE1wC2kw==","_npmVersion":"8.3.1","description":"A slash-menu plugin for Lexical editor","directories":{},"_nodeVersion":"16.14.0","dependencies":{"react":"^18.2.0","lexical":"^0.11.3","react-dom":"^18.2.0","@lexical/react":"^0.11.3","@floating-ui/react-dom":"^2.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.6.1","eslint":"^8.29.0","rollup":"^3.28.0","postcss":"^8.4.20","ts-node":"^10.9.1","prettier":"^2.8.1","npm-check":"^6.0.1","css-loader":"^6.7.3","typescript":"^5.1.6","@babel/core":"^7.22.9","@types/node":"^18.11.15","@types/react":"^18.0.26","@types/react-dom":"^18.0.9","@babel/preset-env":"^7.22.9","eslint-config-next":"^13.0.7","rollup-plugin-copy":"^3.4.0","@babel/preset-react":"^7.22.5","eslint-plugin-react":"^7.33.0","rollup-plugin-babel":"^4.4.0","eslint-config-airbnb":"^19.0.4","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-sucrase":"^5.0.1","eslint-config-prettier":"^8.5.0","eslint-plugin-prettier":"^4.2.1","@rollup/plugin-commonjs":"^25.0.0","rollup-plugin-import-css":"^3.2.1","@rollup/plugin-typescript":"^11.1.1","@typescript-eslint/parser":"^6.2.0","rollup-plugin-typescript2":"^0.34.1","@rollup/plugin-node-resolve":"^15.1.0","@typescript-eslint/eslint-plugin":"^6.2.0","rollup-plugin-peer-deps-external":"^2.2.4","rollup-plugin-exclude-dependencies-from-bundle":"^1.1.23"},"_npmOperationalInternal":{"tmp":"tmp/lexical-slash-menu-plugin_0.0.3_1693403926830_0.8013202089075555","host":"s3://npm-registry-packages"}},"0.0.4":{"name":"@emergence-engineering/lexical-slash-menu-plugin","version":"0.0.4","keywords":["lexical","slash menu","plugin"],"author":{"name":"Emergence Engineering"},"license":"MIT","_id":"@emergence-engineering/lexical-slash-menu-plugin@0.0.4","maintainers":[{"name":"cskata","email":"katalin.csillag@emergence-engineering.com"},{"name":"blaisehorvath","email":"balazs.horvath@emergence-engineering.com"},{"name":"matejcsok","email":"istvan.matejcsok@emergence-engineering.com"},{"name":"viktorvacziee","email":"viktor.vaczi@emergence-engineering.com"}],"homepage":"https://github.com/emergence-engineering/lexical-slash-menu-plugin","bugs":{"url":"https://github.com/emergence-engineering/lexical-slash-menu-plugin/issues"},"dist":{"shasum":"d6198433a5c385ecc4443f761e5b6a355173e649","tarball":"https://registry.npmjs.org/@emergence-engineering/lexical-slash-menu-plugin/-/lexical-slash-menu-plugin-0.0.4.tgz","fileCount":37,"integrity":"sha512-pl7dzK5oegaZD6gg3PxQs+A8H44XpEmbHmNIKvq0RhaDS6S1gMeT/FLmCoGKyLXe/vuT6ArHAEJO9DOdZ1Ukpg==","signatures":[{"sig":"MEQCIDZVN7LvHv4L6AMN0wFD1q/Eiw4UcicSvuBs4D4PUAw+AiAmXh5MsJAt95fxVMslMJmAZmWS/gkeQ6D5Q49FHEKEWA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":116408},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.es.js","engines":{"node":">=14.0.0"},"gitHead":"4252f44c72e650a56422567e52e1cf5d6737b1d2","scripts":{"dev":"rollup -c -w --bundleConfigAsCjs","lint":"tsc --noEmit && eslint src --ext .ts","test":"echo no test","build":"rollup -c --bundleConfigAsCjs"},"_npmUser":{"name":"viktorvacziee","email":"viktor.vaczi@emergence-engineering.com"},"_npmVersion":"8.13.2","description":"A slash-menu plugin for Lexical editor","directories":{},"_nodeVersion":"18.6.0","dependencies":{"react":"^18.2.0","lexical":"^0.11.3","react-dom":"^18.2.0","@lexical/react":"^0.11.3","@floating-ui/react-dom":"^2.0.1"},"_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.6.1","eslint":"^8.29.0","rollup":"^3.28.0","postcss":"^8.4.20","ts-node":"^10.9.1","prettier":"^2.8.1","npm-check":"^6.0.1","css-loader":"^6.7.3","typescript":"^5.1.6","@babel/core":"^7.22.9","@types/node":"^18.11.15","@types/react":"^18.0.26","@types/react-dom":"^18.0.9","@babel/preset-env":"^7.22.9","eslint-config-next":"^13.0.7","rollup-plugin-copy":"^3.4.0","@babel/preset-react":"^7.22.5","eslint-plugin-react":"^7.33.0","rollup-plugin-babel":"^4.4.0","eslint-config-airbnb":"^19.0.4","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-sucrase":"^5.0.1","eslint-config-prettier":"^8.5.0","eslint-plugin-prettier":"^4.2.1","@rollup/plugin-commonjs":"^25.0.0","rollup-plugin-import-css":"^3.2.1","@rollup/plugin-typescript":"^11.1.1","@typescript-eslint/parser":"^6.2.0","rollup-plugin-typescript2":"^0.34.1","@rollup/plugin-node-resolve":"^15.1.0","@typescript-eslint/eslint-plugin":"^6.2.0","rollup-plugin-peer-deps-external":"^2.2.4","rollup-plugin-exclude-dependencies-from-bundle":"^1.1.23"},"_npmOperationalInternal":{"tmp":"tmp/lexical-slash-menu-plugin_0.0.4_1697635258064_0.3046232908560731","host":"s3://npm-registry-packages"}}},"time":{"created":"2023-08-29T13:01:25.217Z","modified":"2026-02-24T10:30:27.727Z","0.0.2":"2023-08-29T13:01:25.530Z","0.0.3":"2023-08-30T13:58:47.066Z","0.0.4":"2023-10-18T13:20:58.269Z"},"bugs":{"url":"https://github.com/emergence-engineering/lexical-slash-menu-plugin/issues"},"author":{"name":"Emergence Engineering"},"license":"MIT","homepage":"https://github.com/emergence-engineering/lexical-slash-menu-plugin","keywords":["lexical","slash menu","plugin"],"description":"A slash-menu plugin for Lexical editor","maintainers":[{"email":"istvan.matejcsok@emergence-engineering.com","name":"matejcsok"},{"email":"viktor.vaczi@emergence-engineering.com","name":"viktorvacziee"},{"email":"torcsvari.gergo@gmail.com","name":"tg44"},{"email":"katalin.csillag@emergence-engineering.com","name":"cskata"}],"readme":"# lexical-slash-menu-plugin\n\n[![made by Emergence Engineering](https://emergence-engineering.com/ee-logo.svg)](https://emergence-engineering.com)\n\n[**Made by Emergence-Engineering**](https://emergence-engineering.com/)\n\n## Basic usage\n\n- import `SlashMenuPlugin` from `lexical-slash-menu-plugin`\n- import `styles.css` file\n- create your `menuElements` array with commands and with even submenus\n\n```ts\nimport { SlashMenuPlugin } from \"lexical-slash-menu-plugin\";\nimport \"lexical-slash-menu-plugin/dist/styles/style.css\";\n\nimport {\n  $createTextNode,\n  $getSelection,\n  $isParagraphNode,\n  LexicalEditor,\n} from \"lexical\";\n\nconst insertText = (text: string) => {\n  const selection = $getSelection();\n  const nodes = selection?.getNodes();\n  const paragraphNode = $isParagraphNode(nodes?.[0])\n    ? nodes?.[0]\n    : nodes?.[0]?.getParent();\n  const textNode = $createTextNode(text);\n  if (paragraphNode) {\n    paragraphNode.append(textNode);\n  }\n};\n\n<SlashMenuPlugin\n  menuElements={[\n    {\n      id: \"1\",\n      label: \"First\",\n      type: \"command\",\n      command: (editor: LexicalEditor) => {\n        editor.update(() => {\n          insertText(\"First\");\n        });\n      },\n    },\n    {\n      id: \"2\",\n      label: \"Second\",\n      type: \"command\",\n      command: (editor: LexicalEditor) => {\n        editor.update(() => {\n          insertText(\"Second\");\n        });\n      },\n    },\n    {\n      id: \"3\",\n      label: \"Submenu\",\n      type: \"submenu\",\n      elements: [\n        {\n          id: \"4\",\n          label: \"Third\",\n          type: \"command\",\n          command: (editor: LexicalEditor) => {\n            editor.update(() => {\n              insertText(\"Third\");\n            });\n          },\n        },\n        {\n          id: \"5\",\n          label: \"Fourth\",\n          type: \"command\",\n          command: (editor: LexicalEditor) => {\n            editor.update(() => {\n              insertText(\"Fourth\");\n            });\n          },\n        },\n      ],\n    },\n  ]}\n/>;\n```\n\n### Props\n\n```ts\nexport function SlashMenuPlugins(\n  menuElements: MenuElement[],\n  ignoredKeys?: string[],\n  customConditions?: OpeningConditions,\n  openInSelection?: boolean,\n  icons?: {\n    [key: string]: FC;\n  },\n  rightIcons?: {\n    [key: string]: FC;\n  },\n  subMenuIcon?: ReactNode;\n  filterFieldIcon?: ReactNode;\n  filterPlaceHolder?: string;\n  mainMenuLabel?: string;\n  floatingReference?: HTMLElement;\n  floatingOptions?: Partial<ComputePositionConfig>;\n  clickable?: boolean;\n)\n```\n\n### Flexible positioning\n\nthe plugin uses [`floating-ui`](https://floating-ui.com/) for positioning the menu element\n\n- `floatingReference?: HTMLElement` for custom menu element positioning\n- `floatingOptions?: Partial<ComputePositionConfig>` for overriding our `floating-ui` options\n\n### Overriding `customConditions`\n\nopening conditions tell when the menu element can be triggered to be opened\n\n- `defaultConditions`\n\n```ts\nconst defaultConditions = (openInSelection = false): OpeningConditions => {\n  return {\n    shouldOpen: (state: SlashMenuState, event: KeyboardEvent) => {\n      const selection = $getSelection();\n      if (!$isRangeSelection(selection)) {\n        return false;\n      }\n      const to = selection.anchor.offset;\n      const from = selection.focus.offset;\n      const docSize = $getRoot().getTextContentSize();\n\n      const node = selection.getNodes()?.[0];\n      const textContent = node?.getTextContent() || \"\";\n      const parentNode = node.getParent();\n      const inParagraph = $isParagraphNode(parentNode);\n      const inRoot = $isRootNode(parentNode);\n\n      const pos = from < 0 || from > docSize ? null : from;\n      const prevCharacter = pos ? textContent.slice(pos - 1, pos) : null;\n\n      const spaceBeforePos =\n        prevCharacter === \" \" || prevCharacter === \"\" || prevCharacter === \" \";\n\n      return (\n        !state.open &&\n        event.key === \"/\" &&\n        (inParagraph || inRoot) &&\n        (spaceBeforePos || inRoot || (from !== to && openInSelection))\n      );\n    },\n    shouldClose: (state: SlashMenuState, event: KeyboardEvent) =>\n      state.open &&\n      (event.key === \"/\" ||\n        event.key === \"Escape\" ||\n        event.key === \"Backspace\") &&\n      state.filter.length === 0,\n  };\n};\n```\n\n### Styles\n\nyou have full controll over our css classes\n\n- check `src/styles/style.css` for default styles\n- check `src/slashMenu/SlashMenuPlugin.tsx` and `src/slashMenu/ListItem.tsx` for dom structure\n\n### Types\n\n```ts\nexport type MenuElement = CommandItem | SubMenu;\n\nexport type ItemId = string | \"root\";\nexport type ItemType = \"command\" | \"submenu\";\nexport interface CommandItem extends MenuItem {\n  type: \"command\";\n  command: (editor: LexicalEditor) => void;\n}\n\nexport interface SubMenu extends MenuItem {\n  type: \"submenu\";\n  elements: MenuElement[];\n  callbackOnClose?: () => void;\n}\n\nexport interface OpeningConditions {\n  shouldOpen: (state: SlashMenuState, event: KeyboardEvent) => boolean;\n  shouldClose: (state: SlashMenuState, event: KeyboardEvent) => boolean;\n}\n```\n","readmeFilename":"README.md"}