@payloadcms/richtext-lexical 3.0.0-beta.2 → 3.0.0-beta.20

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.
Files changed (389) hide show
  1. package/dist/cell/index.d.ts +1 -1
  2. package/dist/cell/index.d.ts.map +1 -1
  3. package/dist/cell/index.js +2 -4
  4. package/dist/cell/index.js.map +1 -1
  5. package/dist/field/features/align/feature.client.d.ts.map +1 -1
  6. package/dist/field/features/align/feature.client.js +1 -2
  7. package/dist/field/features/align/feature.client.js.map +1 -1
  8. package/dist/field/features/blockquote/feature.client.d.ts.map +1 -1
  9. package/dist/field/features/blockquote/feature.client.js +3 -6
  10. package/dist/field/features/blockquote/feature.client.js.map +1 -1
  11. package/dist/field/features/blockquote/feature.server.d.ts.map +1 -1
  12. package/dist/field/features/blockquote/feature.server.js +4 -4
  13. package/dist/field/features/blockquote/feature.server.js.map +1 -1
  14. package/dist/field/features/blockquote/markdownTransformer.d.ts.map +1 -1
  15. package/dist/field/features/blockquote/markdownTransformer.js +2 -4
  16. package/dist/field/features/blockquote/markdownTransformer.js.map +1 -1
  17. package/dist/field/features/blocks/component/BlockContent.d.ts.map +1 -1
  18. package/dist/field/features/blocks/component/BlockContent.js +3 -5
  19. package/dist/field/features/blocks/component/BlockContent.js.map +1 -1
  20. package/dist/field/features/blocks/component/index.d.ts.map +1 -1
  21. package/dist/field/features/blocks/component/index.js +36 -3
  22. package/dist/field/features/blocks/component/index.js.map +1 -1
  23. package/dist/field/features/blocks/drawer/index.d.ts.map +1 -1
  24. package/dist/field/features/blocks/drawer/index.js +2 -4
  25. package/dist/field/features/blocks/drawer/index.js.map +1 -1
  26. package/dist/field/features/blocks/feature.server.d.ts.map +1 -1
  27. package/dist/field/features/blocks/feature.server.js +105 -33
  28. package/dist/field/features/blocks/feature.server.js.map +1 -1
  29. package/dist/field/features/blocks/nodes/BlocksNode.d.ts +1 -3
  30. package/dist/field/features/blocks/nodes/BlocksNode.d.ts.map +1 -1
  31. package/dist/field/features/blocks/nodes/BlocksNode.js +1 -2
  32. package/dist/field/features/blocks/nodes/BlocksNode.js.map +1 -1
  33. package/dist/field/features/blocks/plugin/commands.d.ts.map +1 -1
  34. package/dist/field/features/blocks/plugin/commands.js +1 -2
  35. package/dist/field/features/blocks/plugin/commands.js.map +1 -1
  36. package/dist/field/features/blocks/plugin/index.d.ts.map +1 -1
  37. package/dist/field/features/blocks/plugin/index.js +3 -6
  38. package/dist/field/features/blocks/plugin/index.js.map +1 -1
  39. package/dist/field/features/blocks/populationPromise.d.ts.map +1 -1
  40. package/dist/field/features/blocks/populationPromise.js +3 -5
  41. package/dist/field/features/blocks/populationPromise.js.map +1 -1
  42. package/dist/field/features/blocks/validate.d.ts.map +1 -1
  43. package/dist/field/features/blocks/validate.js +21 -23
  44. package/dist/field/features/blocks/validate.js.map +1 -1
  45. package/dist/field/features/converters/html/field/index.d.ts +8 -2
  46. package/dist/field/features/converters/html/field/index.d.ts.map +1 -1
  47. package/dist/field/features/converters/html/field/index.js +6 -3
  48. package/dist/field/features/converters/html/field/index.js.map +1 -1
  49. package/dist/field/features/debug/testrecorder/plugin/index.d.ts.map +1 -1
  50. package/dist/field/features/debug/testrecorder/plugin/index.js +2 -4
  51. package/dist/field/features/debug/testrecorder/plugin/index.js.map +1 -1
  52. package/dist/field/features/debug/treeview/plugin/index.d.ts.map +1 -1
  53. package/dist/field/features/debug/treeview/plugin/index.js +2 -4
  54. package/dist/field/features/debug/treeview/plugin/index.js.map +1 -1
  55. package/dist/field/features/format/bold/feature.client.d.ts.map +1 -1
  56. package/dist/field/features/format/bold/feature.client.js +1 -2
  57. package/dist/field/features/format/bold/feature.client.js.map +1 -1
  58. package/dist/field/features/format/inlinecode/feature.client.d.ts.map +1 -1
  59. package/dist/field/features/format/inlinecode/feature.client.js +1 -2
  60. package/dist/field/features/format/inlinecode/feature.client.js.map +1 -1
  61. package/dist/field/features/format/italic/feature.client.d.ts.map +1 -1
  62. package/dist/field/features/format/italic/feature.client.js +1 -2
  63. package/dist/field/features/format/italic/feature.client.js.map +1 -1
  64. package/dist/field/features/format/strikethrough/feature.client.d.ts.map +1 -1
  65. package/dist/field/features/format/strikethrough/feature.client.js +1 -2
  66. package/dist/field/features/format/strikethrough/feature.client.js.map +1 -1
  67. package/dist/field/features/format/subscript/feature.client.d.ts.map +1 -1
  68. package/dist/field/features/format/subscript/feature.client.js +1 -2
  69. package/dist/field/features/format/subscript/feature.client.js.map +1 -1
  70. package/dist/field/features/format/superscript/feature.client.d.ts.map +1 -1
  71. package/dist/field/features/format/superscript/feature.client.js +1 -2
  72. package/dist/field/features/format/superscript/feature.client.js.map +1 -1
  73. package/dist/field/features/format/underline/feature.client.d.ts.map +1 -1
  74. package/dist/field/features/format/underline/feature.client.js +1 -2
  75. package/dist/field/features/format/underline/feature.client.js.map +1 -1
  76. package/dist/field/features/heading/feature.client.d.ts.map +1 -1
  77. package/dist/field/features/heading/feature.client.js +3 -6
  78. package/dist/field/features/heading/feature.client.js.map +1 -1
  79. package/dist/field/features/heading/feature.server.d.ts.map +1 -1
  80. package/dist/field/features/heading/feature.server.js +5 -5
  81. package/dist/field/features/heading/feature.server.js.map +1 -1
  82. package/dist/field/features/heading/markdownTransformer.d.ts.map +1 -1
  83. package/dist/field/features/heading/markdownTransformer.js +1 -2
  84. package/dist/field/features/heading/markdownTransformer.js.map +1 -1
  85. package/dist/field/features/horizontalrule/component/index.d.ts +10 -0
  86. package/dist/field/features/horizontalrule/component/index.d.ts.map +1 -0
  87. package/dist/field/features/horizontalrule/component/index.js +62 -0
  88. package/dist/field/features/horizontalrule/component/index.js.map +1 -0
  89. package/dist/field/features/horizontalrule/feature.client.d.ts +3 -0
  90. package/dist/field/features/horizontalrule/feature.client.d.ts.map +1 -0
  91. package/dist/field/features/horizontalrule/feature.client.js +53 -0
  92. package/dist/field/features/horizontalrule/feature.client.js.map +1 -0
  93. package/dist/field/features/horizontalrule/feature.server.d.ts +3 -0
  94. package/dist/field/features/horizontalrule/feature.server.d.ts.map +1 -0
  95. package/dist/field/features/horizontalrule/feature.server.js +37 -0
  96. package/dist/field/features/horizontalrule/feature.server.js.map +1 -0
  97. package/dist/field/features/horizontalrule/markdownTransformer.d.ts +3 -0
  98. package/dist/field/features/horizontalrule/markdownTransformer.d.ts.map +1 -0
  99. package/dist/field/features/horizontalrule/markdownTransformer.js +23 -0
  100. package/dist/field/features/horizontalrule/markdownTransformer.js.map +1 -0
  101. package/dist/field/features/horizontalrule/nodes/HorizontalRuleNode.d.ts +53 -0
  102. package/dist/field/features/horizontalrule/nodes/HorizontalRuleNode.d.ts.map +1 -0
  103. package/dist/field/features/horizontalrule/nodes/HorizontalRuleNode.js +88 -0
  104. package/dist/field/features/horizontalrule/nodes/HorizontalRuleNode.js.map +1 -0
  105. package/dist/field/features/horizontalrule/plugin/index.d.ts +6 -0
  106. package/dist/field/features/horizontalrule/plugin/index.d.ts.map +1 -0
  107. package/dist/field/features/horizontalrule/plugin/index.js +31 -0
  108. package/dist/field/features/horizontalrule/plugin/index.js.map +1 -0
  109. package/dist/field/features/horizontalrule/plugin/index.scss +20 -0
  110. package/dist/field/features/indent/feature.client.d.ts.map +1 -1
  111. package/dist/field/features/indent/feature.client.js +1 -2
  112. package/dist/field/features/indent/feature.client.js.map +1 -1
  113. package/dist/field/features/link/drawer/baseFields.js +1 -1
  114. package/dist/field/features/link/drawer/baseFields.js.map +1 -1
  115. package/dist/field/features/link/drawer/index.js +3 -2
  116. package/dist/field/features/link/drawer/index.js.map +1 -1
  117. package/dist/field/features/link/feature.client.d.ts.map +1 -1
  118. package/dist/field/features/link/feature.client.js +2 -4
  119. package/dist/field/features/link/feature.client.js.map +1 -1
  120. package/dist/field/features/link/feature.server.d.ts.map +1 -1
  121. package/dist/field/features/link/feature.server.js +30 -7
  122. package/dist/field/features/link/feature.server.js.map +1 -1
  123. package/dist/field/features/link/nodes/AutoLinkNode.d.ts.map +1 -1
  124. package/dist/field/features/link/nodes/AutoLinkNode.js +1 -2
  125. package/dist/field/features/link/nodes/AutoLinkNode.js.map +1 -1
  126. package/dist/field/features/link/nodes/LinkNode.d.ts +1 -3
  127. package/dist/field/features/link/nodes/LinkNode.d.ts.map +1 -1
  128. package/dist/field/features/link/nodes/LinkNode.js +2 -4
  129. package/dist/field/features/link/nodes/LinkNode.js.map +1 -1
  130. package/dist/field/features/link/plugins/autoLink/index.d.ts.map +1 -1
  131. package/dist/field/features/link/plugins/autoLink/index.js +3 -6
  132. package/dist/field/features/link/plugins/autoLink/index.js.map +1 -1
  133. package/dist/field/features/link/plugins/floatingLinkEditor/LinkEditor/commands.d.ts.map +1 -1
  134. package/dist/field/features/link/plugins/floatingLinkEditor/LinkEditor/commands.js +1 -2
  135. package/dist/field/features/link/plugins/floatingLinkEditor/LinkEditor/commands.js.map +1 -1
  136. package/dist/field/features/link/plugins/floatingLinkEditor/LinkEditor/index.d.ts.map +1 -1
  137. package/dist/field/features/link/plugins/floatingLinkEditor/LinkEditor/index.js +20 -17
  138. package/dist/field/features/link/plugins/floatingLinkEditor/LinkEditor/index.js.map +1 -1
  139. package/dist/field/features/link/plugins/link/index.js +3 -6
  140. package/dist/field/features/link/plugins/link/index.js.map +1 -1
  141. package/dist/field/features/link/populationPromise.d.ts.map +1 -1
  142. package/dist/field/features/link/populationPromise.js +28 -26
  143. package/dist/field/features/link/populationPromise.js.map +1 -1
  144. package/dist/field/features/lists/checklist/feature.client.d.ts.map +1 -1
  145. package/dist/field/features/lists/checklist/feature.client.js +1 -2
  146. package/dist/field/features/lists/checklist/feature.client.js.map +1 -1
  147. package/dist/field/features/lists/checklist/feature.server.d.ts.map +1 -1
  148. package/dist/field/features/lists/checklist/feature.server.js +6 -6
  149. package/dist/field/features/lists/checklist/feature.server.js.map +1 -1
  150. package/dist/field/features/lists/checklist/markdownTransformers.d.ts.map +1 -1
  151. package/dist/field/features/lists/checklist/markdownTransformers.js +1 -2
  152. package/dist/field/features/lists/checklist/markdownTransformers.js.map +1 -1
  153. package/dist/field/features/lists/checklist/plugin/index.d.ts.map +1 -1
  154. package/dist/field/features/lists/checklist/plugin/index.js +1 -2
  155. package/dist/field/features/lists/checklist/plugin/index.js.map +1 -1
  156. package/dist/field/features/lists/common/markdown.d.ts.map +1 -1
  157. package/dist/field/features/lists/common/markdown.js +1 -2
  158. package/dist/field/features/lists/common/markdown.js.map +1 -1
  159. package/dist/field/features/lists/htmlConverter.d.ts.map +1 -1
  160. package/dist/field/features/lists/htmlConverter.js +13 -6
  161. package/dist/field/features/lists/htmlConverter.js.map +1 -1
  162. package/dist/field/features/lists/orderedlist/feature.client.d.ts.map +1 -1
  163. package/dist/field/features/lists/orderedlist/feature.client.js +1 -2
  164. package/dist/field/features/lists/orderedlist/feature.client.js.map +1 -1
  165. package/dist/field/features/lists/orderedlist/feature.server.d.ts.map +1 -1
  166. package/dist/field/features/lists/orderedlist/feature.server.js +6 -6
  167. package/dist/field/features/lists/orderedlist/feature.server.js.map +1 -1
  168. package/dist/field/features/lists/orderedlist/markdownTransformer.d.ts.map +1 -1
  169. package/dist/field/features/lists/orderedlist/markdownTransformer.js +1 -2
  170. package/dist/field/features/lists/orderedlist/markdownTransformer.js.map +1 -1
  171. package/dist/field/features/lists/plugin/index.d.ts.map +1 -1
  172. package/dist/field/features/lists/plugin/index.js +1 -2
  173. package/dist/field/features/lists/plugin/index.js.map +1 -1
  174. package/dist/field/features/lists/unorderedlist/feature.client.d.ts.map +1 -1
  175. package/dist/field/features/lists/unorderedlist/feature.client.js +1 -2
  176. package/dist/field/features/lists/unorderedlist/feature.client.js.map +1 -1
  177. package/dist/field/features/lists/unorderedlist/feature.server.d.ts.map +1 -1
  178. package/dist/field/features/lists/unorderedlist/feature.server.js +6 -6
  179. package/dist/field/features/lists/unorderedlist/feature.server.js.map +1 -1
  180. package/dist/field/features/lists/unorderedlist/markdownTransformer.d.ts.map +1 -1
  181. package/dist/field/features/lists/unorderedlist/markdownTransformer.js +1 -2
  182. package/dist/field/features/lists/unorderedlist/markdownTransformer.js.map +1 -1
  183. package/dist/field/features/migrations/lexicalPluginToLexical/converter/converters/upload/converter.d.ts.map +1 -1
  184. package/dist/field/features/migrations/lexicalPluginToLexical/converter/converters/upload/converter.js +2 -4
  185. package/dist/field/features/migrations/lexicalPluginToLexical/converter/converters/upload/converter.js.map +1 -1
  186. package/dist/field/features/migrations/lexicalPluginToLexical/nodes/unknownConvertedNode/index.d.ts +1 -3
  187. package/dist/field/features/migrations/lexicalPluginToLexical/nodes/unknownConvertedNode/index.d.ts.map +1 -1
  188. package/dist/field/features/migrations/lexicalPluginToLexical/nodes/unknownConvertedNode/index.js +2 -4
  189. package/dist/field/features/migrations/lexicalPluginToLexical/nodes/unknownConvertedNode/index.js.map +1 -1
  190. package/dist/field/features/migrations/slateToLexical/converter/converters/relationship/converter.d.ts.map +1 -1
  191. package/dist/field/features/migrations/slateToLexical/converter/converters/relationship/converter.js +2 -4
  192. package/dist/field/features/migrations/slateToLexical/converter/converters/relationship/converter.js.map +1 -1
  193. package/dist/field/features/migrations/slateToLexical/converter/converters/upload/converter.d.ts.map +1 -1
  194. package/dist/field/features/migrations/slateToLexical/converter/converters/upload/converter.js +2 -4
  195. package/dist/field/features/migrations/slateToLexical/converter/converters/upload/converter.js.map +1 -1
  196. package/dist/field/features/migrations/slateToLexical/converter/index.d.ts.map +1 -1
  197. package/dist/field/features/migrations/slateToLexical/converter/index.js +2 -1
  198. package/dist/field/features/migrations/slateToLexical/converter/index.js.map +1 -1
  199. package/dist/field/features/migrations/slateToLexical/nodes/unknownConvertedNode/index.d.ts +1 -3
  200. package/dist/field/features/migrations/slateToLexical/nodes/unknownConvertedNode/index.d.ts.map +1 -1
  201. package/dist/field/features/migrations/slateToLexical/nodes/unknownConvertedNode/index.js +2 -4
  202. package/dist/field/features/migrations/slateToLexical/nodes/unknownConvertedNode/index.js.map +1 -1
  203. package/dist/field/features/paragraph/feature.client.d.ts.map +1 -1
  204. package/dist/field/features/paragraph/feature.client.js +2 -4
  205. package/dist/field/features/paragraph/feature.client.js.map +1 -1
  206. package/dist/field/features/relationship/drawer/commands.d.ts.map +1 -1
  207. package/dist/field/features/relationship/drawer/commands.js +1 -2
  208. package/dist/field/features/relationship/drawer/commands.js.map +1 -1
  209. package/dist/field/features/relationship/drawer/index.d.ts.map +1 -1
  210. package/dist/field/features/relationship/drawer/index.js +7 -13
  211. package/dist/field/features/relationship/drawer/index.js.map +1 -1
  212. package/dist/field/features/relationship/feature.server.d.ts.map +1 -1
  213. package/dist/field/features/relationship/feature.server.js +3 -2
  214. package/dist/field/features/relationship/feature.server.js.map +1 -1
  215. package/dist/field/features/relationship/nodes/RelationshipNode.d.ts +3 -8
  216. package/dist/field/features/relationship/nodes/RelationshipNode.d.ts.map +1 -1
  217. package/dist/field/features/relationship/nodes/RelationshipNode.js +8 -8
  218. package/dist/field/features/relationship/nodes/RelationshipNode.js.map +1 -1
  219. package/dist/field/features/relationship/nodes/components/RelationshipComponent.d.ts.map +1 -1
  220. package/dist/field/features/relationship/nodes/components/RelationshipComponent.js +3 -5
  221. package/dist/field/features/relationship/nodes/components/RelationshipComponent.js.map +1 -1
  222. package/dist/field/features/relationship/plugins/index.d.ts.map +1 -1
  223. package/dist/field/features/relationship/plugins/index.js +3 -6
  224. package/dist/field/features/relationship/plugins/index.js.map +1 -1
  225. package/dist/field/features/relationship/populationPromise.js +7 -6
  226. package/dist/field/features/relationship/populationPromise.js.map +1 -1
  227. package/dist/field/features/typeUtilities.d.ts +8 -0
  228. package/dist/field/features/typeUtilities.d.ts.map +1 -0
  229. package/dist/field/features/typeUtilities.js +8 -0
  230. package/dist/field/features/typeUtilities.js.map +1 -0
  231. package/dist/field/features/types.d.ts +52 -32
  232. package/dist/field/features/types.d.ts.map +1 -1
  233. package/dist/field/features/types.js.map +1 -1
  234. package/dist/field/features/upload/component/ExtraFieldsDrawer/index.d.ts.map +1 -1
  235. package/dist/field/features/upload/component/ExtraFieldsDrawer/index.js +5 -6
  236. package/dist/field/features/upload/component/ExtraFieldsDrawer/index.js.map +1 -1
  237. package/dist/field/features/upload/component/index.d.ts.map +1 -1
  238. package/dist/field/features/upload/component/index.js +55 -9
  239. package/dist/field/features/upload/component/index.js.map +1 -1
  240. package/dist/field/features/upload/drawer/commands.d.ts.map +1 -1
  241. package/dist/field/features/upload/drawer/commands.js +1 -2
  242. package/dist/field/features/upload/drawer/commands.js.map +1 -1
  243. package/dist/field/features/upload/drawer/index.d.ts.map +1 -1
  244. package/dist/field/features/upload/drawer/index.js +8 -12
  245. package/dist/field/features/upload/drawer/index.js.map +1 -1
  246. package/dist/field/features/upload/feature.server.d.ts.map +1 -1
  247. package/dist/field/features/upload/feature.server.js +25 -9
  248. package/dist/field/features/upload/feature.server.js.map +1 -1
  249. package/dist/field/features/upload/nodes/UploadNode.d.ts +2 -14
  250. package/dist/field/features/upload/nodes/UploadNode.d.ts.map +1 -1
  251. package/dist/field/features/upload/nodes/UploadNode.js +6 -9
  252. package/dist/field/features/upload/nodes/UploadNode.js.map +1 -1
  253. package/dist/field/features/upload/plugin/index.d.ts +2 -2
  254. package/dist/field/features/upload/plugin/index.d.ts.map +1 -1
  255. package/dist/field/features/upload/plugin/index.js +4 -9
  256. package/dist/field/features/upload/plugin/index.js.map +1 -1
  257. package/dist/field/features/upload/populationPromise.d.ts.map +1 -1
  258. package/dist/field/features/upload/populationPromise.js +22 -9
  259. package/dist/field/features/upload/populationPromise.js.map +1 -1
  260. package/dist/field/features/upload/validate.d.ts.map +1 -1
  261. package/dist/field/features/upload/validate.js +7 -7
  262. package/dist/field/features/upload/validate.js.map +1 -1
  263. package/dist/field/index.d.ts +1 -1
  264. package/dist/field/index.d.ts.map +1 -1
  265. package/dist/field/index.js.map +1 -1
  266. package/dist/field/lexical/LexicalEditor.d.ts.map +1 -1
  267. package/dist/field/lexical/LexicalEditor.js +5 -10
  268. package/dist/field/lexical/LexicalEditor.js.map +1 -1
  269. package/dist/field/lexical/LexicalProvider.d.ts +1 -1
  270. package/dist/field/lexical/LexicalProvider.d.ts.map +1 -1
  271. package/dist/field/lexical/LexicalProvider.js +1 -2
  272. package/dist/field/lexical/LexicalProvider.js.map +1 -1
  273. package/dist/field/lexical/config/client/default.d.ts +1 -1
  274. package/dist/field/lexical/config/client/default.d.ts.map +1 -1
  275. package/dist/field/lexical/config/client/default.js.map +1 -1
  276. package/dist/field/lexical/config/client/sanitize.d.ts +1 -1
  277. package/dist/field/lexical/config/client/sanitize.d.ts.map +1 -1
  278. package/dist/field/lexical/config/client/sanitize.js.map +1 -1
  279. package/dist/field/lexical/config/server/default.d.ts +1 -1
  280. package/dist/field/lexical/config/server/default.d.ts.map +1 -1
  281. package/dist/field/lexical/config/server/default.js +3 -1
  282. package/dist/field/lexical/config/server/default.js.map +1 -1
  283. package/dist/field/lexical/config/server/sanitize.d.ts.map +1 -1
  284. package/dist/field/lexical/config/server/sanitize.js +20 -6
  285. package/dist/field/lexical/config/server/sanitize.js.map +1 -1
  286. package/dist/field/lexical/config/types.d.ts +1 -1
  287. package/dist/field/lexical/config/types.d.ts.map +1 -1
  288. package/dist/field/lexical/config/types.js.map +1 -1
  289. package/dist/field/lexical/plugins/FloatingSelectToolbar/ToolbarButton/index.d.ts.map +1 -1
  290. package/dist/field/lexical/plugins/FloatingSelectToolbar/ToolbarButton/index.js +3 -6
  291. package/dist/field/lexical/plugins/FloatingSelectToolbar/ToolbarButton/index.js.map +1 -1
  292. package/dist/field/lexical/plugins/FloatingSelectToolbar/ToolbarDropdown/DropDown.d.ts.map +1 -1
  293. package/dist/field/lexical/plugins/FloatingSelectToolbar/ToolbarDropdown/DropDown.js +3 -6
  294. package/dist/field/lexical/plugins/FloatingSelectToolbar/ToolbarDropdown/DropDown.js.map +1 -1
  295. package/dist/field/lexical/plugins/FloatingSelectToolbar/index.d.ts.map +1 -1
  296. package/dist/field/lexical/plugins/FloatingSelectToolbar/index.js +3 -6
  297. package/dist/field/lexical/plugins/FloatingSelectToolbar/index.js.map +1 -1
  298. package/dist/field/lexical/plugins/MarkdownShortcut/index.d.ts.map +1 -1
  299. package/dist/field/lexical/plugins/MarkdownShortcut/index.js +1 -2
  300. package/dist/field/lexical/plugins/MarkdownShortcut/index.js.map +1 -1
  301. package/dist/field/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/LexicalMenu.d.ts.map +1 -1
  302. package/dist/field/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/LexicalMenu.js +3 -6
  303. package/dist/field/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/LexicalMenu.js.map +1 -1
  304. package/dist/field/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/index.d.ts.map +1 -1
  305. package/dist/field/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/index.js +3 -6
  306. package/dist/field/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/index.js.map +1 -1
  307. package/dist/field/lexical/plugins/SlashMenu/index.d.ts.map +1 -1
  308. package/dist/field/lexical/plugins/SlashMenu/index.js +1 -2
  309. package/dist/field/lexical/plugins/SlashMenu/index.js.map +1 -1
  310. package/dist/field/lexical/plugins/handles/AddBlockHandlePlugin/index.d.ts.map +1 -1
  311. package/dist/field/lexical/plugins/handles/AddBlockHandlePlugin/index.js +13 -10
  312. package/dist/field/lexical/plugins/handles/AddBlockHandlePlugin/index.js.map +1 -1
  313. package/dist/field/lexical/plugins/handles/DraggableBlockPlugin/getNodeCloseToPoint.d.ts.map +1 -1
  314. package/dist/field/lexical/plugins/handles/DraggableBlockPlugin/getNodeCloseToPoint.js +1 -2
  315. package/dist/field/lexical/plugins/handles/DraggableBlockPlugin/getNodeCloseToPoint.js.map +1 -1
  316. package/dist/field/lexical/plugins/handles/DraggableBlockPlugin/index.d.ts.map +1 -1
  317. package/dist/field/lexical/plugins/handles/DraggableBlockPlugin/index.js +10 -7
  318. package/dist/field/lexical/plugins/handles/DraggableBlockPlugin/index.js.map +1 -1
  319. package/dist/field/lexical/plugins/handles/utils/doesLineHeightAffectElement.d.ts +9 -0
  320. package/dist/field/lexical/plugins/handles/utils/doesLineHeightAffectElement.d.ts.map +1 -0
  321. package/dist/field/lexical/plugins/handles/utils/doesLineHeightAffectElement.js +35 -0
  322. package/dist/field/lexical/plugins/handles/utils/doesLineHeightAffectElement.js.map +1 -0
  323. package/dist/field/lexical/plugins/handles/utils/getTopLevelNodeKeys.d.ts.map +1 -1
  324. package/dist/field/lexical/plugins/handles/utils/getTopLevelNodeKeys.js +1 -2
  325. package/dist/field/lexical/plugins/handles/utils/getTopLevelNodeKeys.js.map +1 -1
  326. package/dist/field/lexical/plugins/handles/utils/setHandlePosition.d.ts +1 -1
  327. package/dist/field/lexical/plugins/handles/utils/setHandlePosition.d.ts.map +1 -1
  328. package/dist/field/lexical/plugins/handles/utils/setHandlePosition.js +17 -7
  329. package/dist/field/lexical/plugins/handles/utils/setHandlePosition.js.map +1 -1
  330. package/dist/field/lexical/theme/EditorTheme.scss +11 -8
  331. package/dist/field/lexical/ui/ContentEditable.d.ts.map +1 -1
  332. package/dist/field/lexical/ui/ContentEditable.js +1 -2
  333. package/dist/field/lexical/ui/ContentEditable.js.map +1 -1
  334. package/dist/field/lexical/ui/icons/HorizontalRule/index.d.ts +3 -0
  335. package/dist/field/lexical/ui/icons/HorizontalRule/index.d.ts.map +1 -0
  336. package/dist/field/lexical/ui/icons/HorizontalRule/index.js +19 -0
  337. package/dist/field/lexical/ui/icons/HorizontalRule/index.js.map +1 -0
  338. package/dist/field/lexical/utils/getSelectedNode.d.ts.map +1 -1
  339. package/dist/field/lexical/utils/getSelectedNode.js +1 -2
  340. package/dist/field/lexical/utils/getSelectedNode.js.map +1 -1
  341. package/dist/field/lexical/utils/nodeFormat.d.ts +2 -1
  342. package/dist/field/lexical/utils/nodeFormat.d.ts.map +1 -1
  343. package/dist/field/lexical/utils/nodeFormat.js.map +1 -1
  344. package/dist/field/lexical/utils/url.d.ts.map +1 -1
  345. package/dist/field/lexical/utils/url.js +1 -0
  346. package/dist/field/lexical/utils/url.js.map +1 -1
  347. package/dist/forEachNodeRecursively.d.ts +10 -0
  348. package/dist/forEachNodeRecursively.d.ts.map +1 -0
  349. package/dist/forEachNodeRecursively.js +24 -0
  350. package/dist/forEachNodeRecursively.js.map +1 -0
  351. package/dist/generateComponentMap.d.ts.map +1 -1
  352. package/dist/generateComponentMap.js +22 -19
  353. package/dist/generateComponentMap.js.map +1 -1
  354. package/dist/generateSchemaMap.js +10 -9
  355. package/dist/generateSchemaMap.js.map +1 -1
  356. package/dist/index.d.ts +3 -2
  357. package/dist/index.d.ts.map +1 -1
  358. package/dist/index.js +103 -23
  359. package/dist/index.js.map +1 -1
  360. package/dist/populate/defaultValue.d.ts.map +1 -1
  361. package/dist/populate/defaultValue.js +1 -0
  362. package/dist/populate/defaultValue.js.map +1 -1
  363. package/dist/populate/populate.d.ts +3 -3
  364. package/dist/populate/populate.d.ts.map +1 -1
  365. package/dist/populate/populate.js.map +1 -1
  366. package/dist/populate/populateLexicalPopulationPromises.d.ts +12 -0
  367. package/dist/populate/populateLexicalPopulationPromises.d.ts.map +1 -0
  368. package/dist/populate/populateLexicalPopulationPromises.js +35 -0
  369. package/dist/populate/populateLexicalPopulationPromises.js.map +1 -0
  370. package/dist/populate/recurseNestedFields.d.ts +7 -4
  371. package/dist/populate/recurseNestedFields.d.ts.map +1 -1
  372. package/dist/populate/recurseNestedFields.js +3 -5
  373. package/dist/populate/recurseNestedFields.js.map +1 -1
  374. package/dist/scss/app.scss +2 -3
  375. package/dist/scss/vars.scss +0 -7
  376. package/dist/types.d.ts +3 -4
  377. package/dist/types.d.ts.map +1 -1
  378. package/dist/types.js.map +1 -1
  379. package/dist/validate/index.d.ts +1 -1
  380. package/dist/validate/index.d.ts.map +1 -1
  381. package/package.json +47 -46
  382. package/components.d.ts +0 -6
  383. package/components.js +0 -7
  384. package/dist/populate/richTextRelationshipPromise.d.ts +0 -23
  385. package/dist/populate/richTextRelationshipPromise.d.ts.map +0 -1
  386. package/dist/populate/richTextRelationshipPromise.js +0 -68
  387. package/dist/populate/richTextRelationshipPromise.js.map +0 -1
  388. package/dist/scss/fonts.scss +0 -75
  389. package/src/index.ts +0 -423
@@ -1,6 +1,5 @@
1
1
  'use client';
2
- import lexicalComposerContextImport from '@lexical/react/LexicalComposerContext.js';
3
- const { useLexicalComposerContext } = lexicalComposerContextImport;
2
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js';
4
3
  import { useTranslation } from '@payloadcms/ui/providers/Translation';
5
4
  import { useCallback, useMemo, useState } from 'react';
6
5
  import * as React from 'react';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/field/lexical/plugins/SlashMenu/index.tsx"],"sourcesContent":["'use client'\nimport type { TextNode } from 'lexical'\n\nimport lexicalComposerContextImport from '@lexical/react/LexicalComposerContext.js'\nconst { useLexicalComposerContext } = lexicalComposerContextImport\n\nimport { useTranslation } from '@payloadcms/ui/providers/Translation'\nimport { useCallback, useMemo, useState } from 'react'\nimport * as React from 'react'\nimport * as ReactDOM from 'react-dom'\n\nimport type { SlashMenuGroup, SlashMenuOption } from './LexicalTypeaheadMenuPlugin/types.js'\n\nimport { useEditorConfigContext } from '../../config/client/EditorConfigProvider.js'\nimport { LexicalTypeaheadMenuPlugin } from './LexicalTypeaheadMenuPlugin/index.js'\nimport './index.scss'\nimport { useMenuTriggerMatch } from './useMenuTriggerMatch.js'\n\nconst baseClass = 'slash-menu-popup'\n\nfunction SlashMenuItem({\n isSelected,\n onClick,\n onMouseEnter,\n option,\n}: {\n index: number\n isSelected: boolean\n onClick: () => void\n onMouseEnter: () => void\n option: SlashMenuOption\n}) {\n const { i18n } = useTranslation()\n\n let className = `${baseClass}__item ${baseClass}__item-${option.key}`\n if (isSelected) {\n className += ` ${baseClass}__item--selected`\n }\n\n let title = option.key\n if (option.displayName) {\n title =\n typeof option.displayName === 'function' ? option.displayName({ i18n }) : option.displayName\n }\n // Crop title to max. 50 characters\n if (title.length > 25) {\n title = title.substring(0, 25) + '...'\n }\n\n return (\n <button\n aria-selected={isSelected}\n className={className}\n id={baseClass + '__item-' + option.key}\n key={option.key}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n ref={option.setRefElement}\n role=\"option\"\n tabIndex={-1}\n type=\"button\"\n >\n {option?.Icon && <option.Icon />}\n\n <span className={`${baseClass}__item-text`}>{title}</span>\n </button>\n )\n}\n\nexport function SlashMenuPlugin({\n anchorElem = document.body,\n}: {\n anchorElem?: HTMLElement\n}): JSX.Element {\n const [editor] = useLexicalComposerContext()\n const [queryString, setQueryString] = useState<null | string>(null)\n const { editorConfig } = useEditorConfigContext()\n const { i18n } = useTranslation()\n\n const checkForTriggerMatch = useMenuTriggerMatch('/', {\n minLength: 0,\n })\n\n const getDynamicOptions = useCallback(() => {\n let groupWithOptions: Array<SlashMenuGroup> = []\n\n for (const dynamicOption of editorConfig.features.slashMenu.dynamicOptions) {\n const dynamicGroupWithOptions = dynamicOption({\n editor,\n queryString,\n })\n groupWithOptions = groupWithOptions.concat(dynamicGroupWithOptions)\n }\n\n return groupWithOptions\n }, [editor, queryString, editorConfig?.features])\n\n const groups: SlashMenuGroup[] = useMemo(() => {\n let groupsWithOptions: SlashMenuGroup[] = []\n for (const groupWithOption of editorConfig?.features.slashMenu.groupsWithOptions ?? []) {\n groupsWithOptions.push(groupWithOption)\n }\n\n if (queryString) {\n // Filter current groups first\n groupsWithOptions = groupsWithOptions.map((group) => {\n const filteredOptions = group.options.filter((option) => {\n let optionTitle = option.key\n if (option.displayName) {\n optionTitle =\n typeof option.displayName === 'function'\n ? option.displayName({ i18n })\n : option.displayName\n }\n\n return new RegExp(queryString, 'gi').exec(optionTitle) || option.keywords != null\n ? option.keywords.some((keyword) => new RegExp(queryString, 'gi').exec(keyword))\n : false\n })\n if (filteredOptions.length) {\n return {\n ...group,\n options: filteredOptions,\n }\n }\n return null\n })\n\n groupsWithOptions = groupsWithOptions.filter((group) => group != null)\n\n // Now add dynamic groups\n const dynamicOptionGroups = getDynamicOptions()\n\n // merge dynamic options into groups\n for (const dynamicGroup of dynamicOptionGroups) {\n // 1. find the group with the same name or create new one\n let group = groupsWithOptions.find((group) => group.key === dynamicGroup.key)\n if (!group) {\n group = {\n ...dynamicGroup,\n options: [],\n }\n } else {\n groupsWithOptions = groupsWithOptions.filter((group) => group.key !== dynamicGroup.key)\n }\n\n // 2. Add options to group options array and add to sanitized.slashMenu.groupsWithOptions\n if (group?.options?.length) {\n group.options = group.options.concat(group.options)\n }\n groupsWithOptions.push(group)\n }\n }\n\n return groupsWithOptions\n }, [getDynamicOptions, queryString, editorConfig?.features, i18n])\n\n const onSelectOption = useCallback(\n (\n selectedOption: SlashMenuOption,\n nodeToRemove: TextNode | null,\n closeMenu: () => void,\n matchingString: string,\n ) => {\n editor.update(() => {\n if (nodeToRemove) {\n nodeToRemove.remove()\n }\n selectedOption.onSelect({ editor, queryString: matchingString })\n closeMenu()\n })\n },\n [editor],\n )\n\n return (\n <React.Fragment>\n <LexicalTypeaheadMenuPlugin\n anchorElem={anchorElem}\n groupsWithOptions={groups}\n menuRenderFn={(\n anchorElementRef,\n { selectOptionAndCleanUp, selectedOptionKey, setSelectedOptionKey },\n ) =>\n anchorElementRef.current && groups.length\n ? ReactDOM.createPortal(\n <div className={baseClass}>\n {groups.map((group) => {\n let groupTitle = group.key\n if (group.displayName) {\n groupTitle =\n typeof group.displayName === 'function'\n ? group.displayName({ i18n })\n : group.displayName\n }\n\n return (\n <div\n className={`${baseClass}__group ${baseClass}__group-${group.key}`}\n key={group.key}\n >\n <div className={`${baseClass}__group-title`}>{groupTitle}</div>\n {group.options.map((option, oi: number) => (\n <SlashMenuItem\n index={oi}\n isSelected={selectedOptionKey === option.key}\n key={option.key}\n onClick={() => {\n setSelectedOptionKey(option.key)\n selectOptionAndCleanUp(option)\n }}\n onMouseEnter={() => {\n setSelectedOptionKey(option.key)\n }}\n option={option}\n />\n ))}\n </div>\n )\n })}\n </div>,\n anchorElementRef.current,\n )\n : null\n }\n onQueryChange={setQueryString}\n onSelectOption={onSelectOption}\n triggerFn={checkForTriggerMatch}\n />\n </React.Fragment>\n )\n}\n"],"names":["lexicalComposerContextImport","useLexicalComposerContext","useTranslation","useCallback","useMemo","useState","React","ReactDOM","useEditorConfigContext","LexicalTypeaheadMenuPlugin","useMenuTriggerMatch","baseClass","SlashMenuItem","isSelected","onClick","onMouseEnter","option","i18n","className","key","title","displayName","length","substring","button","aria-selected","id","ref","setRefElement","role","tabIndex","type","Icon","span","SlashMenuPlugin","anchorElem","document","body","editor","queryString","setQueryString","editorConfig","checkForTriggerMatch","minLength","getDynamicOptions","groupWithOptions","dynamicOption","features","slashMenu","dynamicOptions","dynamicGroupWithOptions","concat","groups","groupsWithOptions","groupWithOption","push","map","group","filteredOptions","options","filter","optionTitle","RegExp","exec","keywords","some","keyword","dynamicOptionGroups","dynamicGroup","find","onSelectOption","selectedOption","nodeToRemove","closeMenu","matchingString","update","remove","onSelect","Fragment","menuRenderFn","anchorElementRef","selectOptionAndCleanUp","selectedOptionKey","setSelectedOptionKey","current","createPortal","div","groupTitle","oi","index","onQueryChange","triggerFn"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/field/lexical/plugins/SlashMenu/index.tsx"],"sourcesContent":["'use client'\nimport type { TextNode } from 'lexical'\n\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js'\nimport { useTranslation } from '@payloadcms/ui/providers/Translation'\nimport { useCallback, useMemo, useState } from 'react'\nimport * as React from 'react'\nimport * as ReactDOM from 'react-dom'\n\nimport type { SlashMenuGroup, SlashMenuOption } from './LexicalTypeaheadMenuPlugin/types.js'\n\nimport { useEditorConfigContext } from '../../config/client/EditorConfigProvider.js'\nimport { LexicalTypeaheadMenuPlugin } from './LexicalTypeaheadMenuPlugin/index.js'\nimport './index.scss'\nimport { useMenuTriggerMatch } from './useMenuTriggerMatch.js'\n\nconst baseClass = 'slash-menu-popup'\n\nfunction SlashMenuItem({\n isSelected,\n onClick,\n onMouseEnter,\n option,\n}: {\n index: number\n isSelected: boolean\n onClick: () => void\n onMouseEnter: () => void\n option: SlashMenuOption\n}) {\n const { i18n } = useTranslation()\n\n let className = `${baseClass}__item ${baseClass}__item-${option.key}`\n if (isSelected) {\n className += ` ${baseClass}__item--selected`\n }\n\n let title = option.key\n if (option.displayName) {\n title =\n typeof option.displayName === 'function' ? option.displayName({ i18n }) : option.displayName\n }\n // Crop title to max. 50 characters\n if (title.length > 25) {\n title = title.substring(0, 25) + '...'\n }\n\n return (\n <button\n aria-selected={isSelected}\n className={className}\n id={baseClass + '__item-' + option.key}\n key={option.key}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n ref={option.setRefElement}\n role=\"option\"\n tabIndex={-1}\n type=\"button\"\n >\n {option?.Icon && <option.Icon />}\n\n <span className={`${baseClass}__item-text`}>{title}</span>\n </button>\n )\n}\n\nexport function SlashMenuPlugin({\n anchorElem = document.body,\n}: {\n anchorElem?: HTMLElement\n}): JSX.Element {\n const [editor] = useLexicalComposerContext()\n const [queryString, setQueryString] = useState<null | string>(null)\n const { editorConfig } = useEditorConfigContext()\n const { i18n } = useTranslation()\n\n const checkForTriggerMatch = useMenuTriggerMatch('/', {\n minLength: 0,\n })\n\n const getDynamicOptions = useCallback(() => {\n let groupWithOptions: Array<SlashMenuGroup> = []\n\n for (const dynamicOption of editorConfig.features.slashMenu.dynamicOptions) {\n const dynamicGroupWithOptions = dynamicOption({\n editor,\n queryString,\n })\n groupWithOptions = groupWithOptions.concat(dynamicGroupWithOptions)\n }\n\n return groupWithOptions\n }, [editor, queryString, editorConfig?.features])\n\n const groups: SlashMenuGroup[] = useMemo(() => {\n let groupsWithOptions: SlashMenuGroup[] = []\n for (const groupWithOption of editorConfig?.features.slashMenu.groupsWithOptions ?? []) {\n groupsWithOptions.push(groupWithOption)\n }\n\n if (queryString) {\n // Filter current groups first\n groupsWithOptions = groupsWithOptions.map((group) => {\n const filteredOptions = group.options.filter((option) => {\n let optionTitle = option.key\n if (option.displayName) {\n optionTitle =\n typeof option.displayName === 'function'\n ? option.displayName({ i18n })\n : option.displayName\n }\n\n return new RegExp(queryString, 'gi').exec(optionTitle) || option.keywords != null\n ? option.keywords.some((keyword) => new RegExp(queryString, 'gi').exec(keyword))\n : false\n })\n if (filteredOptions.length) {\n return {\n ...group,\n options: filteredOptions,\n }\n }\n return null\n })\n\n groupsWithOptions = groupsWithOptions.filter((group) => group != null)\n\n // Now add dynamic groups\n const dynamicOptionGroups = getDynamicOptions()\n\n // merge dynamic options into groups\n for (const dynamicGroup of dynamicOptionGroups) {\n // 1. find the group with the same name or create new one\n let group = groupsWithOptions.find((group) => group.key === dynamicGroup.key)\n if (!group) {\n group = {\n ...dynamicGroup,\n options: [],\n }\n } else {\n groupsWithOptions = groupsWithOptions.filter((group) => group.key !== dynamicGroup.key)\n }\n\n // 2. Add options to group options array and add to sanitized.slashMenu.groupsWithOptions\n if (group?.options?.length) {\n group.options = group.options.concat(group.options)\n }\n groupsWithOptions.push(group)\n }\n }\n\n return groupsWithOptions\n }, [getDynamicOptions, queryString, editorConfig?.features, i18n])\n\n const onSelectOption = useCallback(\n (\n selectedOption: SlashMenuOption,\n nodeToRemove: TextNode | null,\n closeMenu: () => void,\n matchingString: string,\n ) => {\n editor.update(() => {\n if (nodeToRemove) {\n nodeToRemove.remove()\n }\n selectedOption.onSelect({ editor, queryString: matchingString })\n closeMenu()\n })\n },\n [editor],\n )\n\n return (\n <React.Fragment>\n <LexicalTypeaheadMenuPlugin\n anchorElem={anchorElem}\n groupsWithOptions={groups}\n menuRenderFn={(\n anchorElementRef,\n { selectOptionAndCleanUp, selectedOptionKey, setSelectedOptionKey },\n ) =>\n anchorElementRef.current && groups.length\n ? ReactDOM.createPortal(\n <div className={baseClass}>\n {groups.map((group) => {\n let groupTitle = group.key\n if (group.displayName) {\n groupTitle =\n typeof group.displayName === 'function'\n ? group.displayName({ i18n })\n : group.displayName\n }\n\n return (\n <div\n className={`${baseClass}__group ${baseClass}__group-${group.key}`}\n key={group.key}\n >\n <div className={`${baseClass}__group-title`}>{groupTitle}</div>\n {group.options.map((option, oi: number) => (\n <SlashMenuItem\n index={oi}\n isSelected={selectedOptionKey === option.key}\n key={option.key}\n onClick={() => {\n setSelectedOptionKey(option.key)\n selectOptionAndCleanUp(option)\n }}\n onMouseEnter={() => {\n setSelectedOptionKey(option.key)\n }}\n option={option}\n />\n ))}\n </div>\n )\n })}\n </div>,\n anchorElementRef.current,\n )\n : null\n }\n onQueryChange={setQueryString}\n onSelectOption={onSelectOption}\n triggerFn={checkForTriggerMatch}\n />\n </React.Fragment>\n )\n}\n"],"names":["useLexicalComposerContext","useTranslation","useCallback","useMemo","useState","React","ReactDOM","useEditorConfigContext","LexicalTypeaheadMenuPlugin","useMenuTriggerMatch","baseClass","SlashMenuItem","isSelected","onClick","onMouseEnter","option","i18n","className","key","title","displayName","length","substring","button","aria-selected","id","ref","setRefElement","role","tabIndex","type","Icon","span","SlashMenuPlugin","anchorElem","document","body","editor","queryString","setQueryString","editorConfig","checkForTriggerMatch","minLength","getDynamicOptions","groupWithOptions","dynamicOption","features","slashMenu","dynamicOptions","dynamicGroupWithOptions","concat","groups","groupsWithOptions","groupWithOption","push","map","group","filteredOptions","options","filter","optionTitle","RegExp","exec","keywords","some","keyword","dynamicOptionGroups","dynamicGroup","find","onSelectOption","selectedOption","nodeToRemove","closeMenu","matchingString","update","remove","onSelect","Fragment","menuRenderFn","anchorElementRef","selectOptionAndCleanUp","selectedOptionKey","setSelectedOptionKey","current","createPortal","div","groupTitle","oi","index","onQueryChange","triggerFn"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/AddBlockHandlePlugin/index.tsx"],"names":[],"mappings":";AAoBA,OAAO,cAAc,CAAA;AAwSrB,wBAAgB,oBAAoB,CAAC,EACnC,UAA0B,GAC3B,EAAE;IACD,UAAU,CAAC,EAAE,WAAW,CAAA;CACzB,GAAG,GAAG,CAAC,OAAO,CAGd"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/AddBlockHandlePlugin/index.tsx"],"names":[],"mappings":";AAiBA,OAAO,cAAc,CAAA;AA4SrB,wBAAgB,oBAAoB,CAAC,EACnC,UAA0B,GAC3B,EAAE;IACD,UAAU,CAAC,EAAE,WAAW,CAAA;CACzB,GAAG,GAAG,CAAC,OAAO,CAGd"}
@@ -1,8 +1,6 @@
1
1
  'use client';
2
- import lexicalComposerContextImport from '@lexical/react/LexicalComposerContext.js';
3
- const { useLexicalComposerContext } = lexicalComposerContextImport;
4
- import lexicalImport from 'lexical';
5
- const { $createParagraphNode, $getNodeByKey } = lexicalImport;
2
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js';
3
+ import { $createParagraphNode, $getNodeByKey } from 'lexical';
6
4
  import * as React from 'react';
7
5
  import { useCallback, useEffect, useRef, useState } from 'react';
8
6
  import { createPortal } from 'react-dom';
@@ -122,7 +120,9 @@ function useAddBlockHandle(editor, anchorElem, isEditable) {
122
120
  const adjustedTop = top + window.scrollY;
123
121
  const adjustedBottom = bottom + window.scrollY;
124
122
  if (pageY < adjustedTop - verticalBuffer || pageY > adjustedBottom + verticalBuffer || pageX < left - horizontalBuffer || pageX > right + horizontalBuffer) {
125
- setHoveredElement(null);
123
+ if (hoveredElement !== null) {
124
+ setHoveredElement(null);
125
+ }
126
126
  return;
127
127
  }
128
128
  // This is used to allow the _emptyBlockElem to be found when the mouse is in the
@@ -138,10 +138,12 @@ function useAddBlockHandle(editor, anchorElem, isEditable) {
138
138
  if (!_emptyBlockElem) {
139
139
  return;
140
140
  }
141
- setHoveredElement({
142
- elem: _emptyBlockElem,
143
- node: blockNode
144
- });
141
+ if (hoveredElement?.node !== blockNode || hoveredElement?.elem !== _emptyBlockElem) {
142
+ setHoveredElement({
143
+ elem: _emptyBlockElem,
144
+ node: blockNode
145
+ });
146
+ }
145
147
  }
146
148
  // Since the draggableBlockElem is outside the actual editor, we need to listen to the document
147
149
  // to be able to detect when the mouse is outside the editor and respect a buffer around
@@ -153,7 +155,8 @@ function useAddBlockHandle(editor, anchorElem, isEditable) {
153
155
  }, [
154
156
  scrollerElem,
155
157
  anchorElem,
156
- editor
158
+ editor,
159
+ hoveredElement
157
160
  ]);
158
161
  useEffect(()=>{
159
162
  if (menuRef.current && hoveredElement?.node) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/field/lexical/plugins/handles/AddBlockHandlePlugin/index.tsx"],"sourcesContent":["'use client'\nimport type { LexicalEditor, LexicalNode, ParagraphNode } from 'lexical'\n\nimport lexicalComposerContextImport from '@lexical/react/LexicalComposerContext.js'\nconst { useLexicalComposerContext } = lexicalComposerContextImport\nimport lexicalImport from 'lexical'\nconst { $createParagraphNode, $getNodeByKey } = lexicalImport\n\nimport * as React from 'react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { isHTMLElement } from '../../../utils/guard.js'\nimport { Point } from '../../../utils/point.js'\nimport { Rect } from '../../../utils/rect.js'\nimport { ENABLE_SLASH_MENU_COMMAND } from '../../SlashMenu/LexicalTypeaheadMenuPlugin/index.js'\nimport { getCollapsedMargins } from '../utils/getCollapsedMargins.js'\nimport { getTopLevelNodeKeys } from '../utils/getTopLevelNodeKeys.js'\nimport { isOnHandleElement } from '../utils/isOnHandleElement.js'\nimport { setHandlePosition } from '../utils/setHandlePosition.js'\nimport './index.scss'\n\nconst SPACE = -24\nconst ADD_BLOCK_MENU_CLASSNAME = 'add-block-menu'\n\nconst Downward = 1\nconst Upward = -1\nconst Indeterminate = 0\n\nlet prevIndex = Infinity\n\nfunction getCurrentIndex(keysLength: number): number {\n if (keysLength === 0) {\n return Infinity\n }\n if (prevIndex >= 0 && prevIndex < keysLength) {\n return prevIndex\n }\n\n return Math.floor(keysLength / 2)\n}\n\nfunction getBlockElement(\n anchorElem: HTMLElement,\n editor: LexicalEditor,\n event: MouseEvent,\n useEdgeAsDefault = false,\n horizontalOffset = 0,\n): {\n blockElem: HTMLElement | null\n blockNode: LexicalNode | null\n} {\n const anchorElementRect = anchorElem.getBoundingClientRect()\n const topLevelNodeKeys = getTopLevelNodeKeys(editor)\n\n let blockElem: HTMLElement | null = null\n let blockNode: LexicalNode | null = null\n\n // Return null if matching block element is the first or last node\n editor.getEditorState().read(() => {\n if (useEdgeAsDefault) {\n const [firstNode, lastNode] = [\n editor.getElementByKey(topLevelNodeKeys[0]),\n editor.getElementByKey(topLevelNodeKeys[topLevelNodeKeys.length - 1]),\n ]\n\n const [firstNodeRect, lastNodeRect] = [\n firstNode?.getBoundingClientRect(),\n lastNode?.getBoundingClientRect(),\n ]\n\n if (firstNodeRect && lastNodeRect) {\n if (event.y < firstNodeRect.top) {\n blockElem = firstNode\n } else if (event.y > lastNodeRect.bottom) {\n blockElem = lastNode\n }\n\n if (blockElem) {\n return {\n blockElem: null,\n }\n }\n }\n }\n\n // Find matching block element\n let index = getCurrentIndex(topLevelNodeKeys.length)\n let direction = Indeterminate\n\n while (index >= 0 && index < topLevelNodeKeys.length) {\n const key = topLevelNodeKeys[index]\n const elem = editor.getElementByKey(key)\n if (elem === null) {\n break\n }\n const point = new Point(event.x + horizontalOffset, event.y)\n const domRect = Rect.fromDOM(elem)\n const { marginBottom, marginTop } = getCollapsedMargins(elem)\n\n const rect = domRect.generateNewRect({\n bottom: domRect.bottom + marginBottom,\n left: anchorElementRect.left,\n right: anchorElementRect.right,\n top: domRect.top - marginTop,\n })\n\n const {\n reason: { isOnBottomSide, isOnTopSide },\n result,\n } = rect.contains(point)\n\n if (result) {\n blockElem = elem\n blockNode = $getNodeByKey(key)\n prevIndex = index\n break\n }\n\n if (direction === Indeterminate) {\n if (isOnTopSide) {\n direction = Upward\n } else if (isOnBottomSide) {\n direction = Downward\n } else {\n // stop search block element\n direction = Infinity\n }\n }\n\n index += direction\n }\n })\n\n return {\n blockElem,\n blockNode,\n }\n}\n\nfunction useAddBlockHandle(\n editor: LexicalEditor,\n anchorElem: HTMLElement,\n isEditable: boolean,\n): JSX.Element {\n const scrollerElem = anchorElem.parentElement\n\n const menuRef = useRef<HTMLButtonElement>(null)\n const [hoveredElement, setHoveredElement] = useState<{\n elem: HTMLElement\n node: LexicalNode\n } | null>(null)\n\n useEffect(() => {\n function onDocumentMouseMove(event: MouseEvent) {\n const target = event.target\n if (!isHTMLElement(target)) {\n return\n }\n\n let distanceFromScrollerElem = 0\n // Calculate distance between scrollerElem and target if target is not in scrollerElem\n if (scrollerElem && !scrollerElem.contains(target)) {\n const { bottom, left, right, top } = scrollerElem.getBoundingClientRect()\n const { pageX, pageY } = event\n const horizontalBuffer = 50\n const verticalBuffer = 25\n const adjustedTop = top + window.scrollY\n const adjustedBottom = bottom + window.scrollY\n\n if (\n pageY < adjustedTop - verticalBuffer ||\n pageY > adjustedBottom + verticalBuffer ||\n pageX < left - horizontalBuffer ||\n pageX > right + horizontalBuffer\n ) {\n setHoveredElement(null)\n return\n }\n\n // This is used to allow the _emptyBlockElem to be found when the mouse is in the\n // buffer zone around the scrollerElem.\n if (pageX < left || pageX > right) {\n distanceFromScrollerElem = pageX < left ? pageX - left : pageX - right\n }\n }\n\n if (isOnHandleElement(target, ADD_BLOCK_MENU_CLASSNAME)) {\n return\n }\n const { blockElem: _emptyBlockElem, blockNode } = getBlockElement(\n anchorElem,\n editor,\n event,\n false,\n -distanceFromScrollerElem,\n )\n if (!_emptyBlockElem) {\n return\n }\n setHoveredElement({\n elem: _emptyBlockElem,\n node: blockNode,\n })\n }\n\n // Since the draggableBlockElem is outside the actual editor, we need to listen to the document\n // to be able to detect when the mouse is outside the editor and respect a buffer around\n // the scrollerElem to avoid the draggableBlockElem disappearing too early.\n document?.addEventListener('mousemove', onDocumentMouseMove)\n\n return () => {\n document?.removeEventListener('mousemove', onDocumentMouseMove)\n }\n }, [scrollerElem, anchorElem, editor])\n\n useEffect(() => {\n if (menuRef.current && hoveredElement?.node) {\n editor.getEditorState().read(() => {\n // Check if blockNode is an empty text node\n let isEmptyParagraph = true\n if (\n hoveredElement.node.getType() !== 'paragraph' ||\n hoveredElement.node.getTextContent() !== ''\n ) {\n isEmptyParagraph = false\n }\n\n setHandlePosition(\n hoveredElement?.elem,\n menuRef.current,\n anchorElem,\n isEmptyParagraph ? SPACE : SPACE - 20,\n )\n })\n }\n }, [anchorElem, hoveredElement, editor])\n\n const handleAddClick = useCallback(\n (event) => {\n let hoveredElementToUse = hoveredElement\n if (!hoveredElementToUse?.node) {\n return\n }\n\n // 1. Update hoveredElement.node to a new paragraph node if the hoveredElement.node is not a paragraph node\n editor.update(() => {\n // Check if blockNode is an empty text node\n let isEmptyParagraph = true\n if (\n hoveredElementToUse.node.getType() !== 'paragraph' ||\n hoveredElementToUse.node.getTextContent() !== ''\n ) {\n isEmptyParagraph = false\n }\n\n if (!isEmptyParagraph) {\n const newParagraph = $createParagraphNode()\n hoveredElementToUse.node.insertAfter(newParagraph)\n\n setTimeout(() => {\n hoveredElementToUse = {\n elem: editor.getElementByKey(newParagraph.getKey()),\n node: newParagraph,\n }\n setHoveredElement(hoveredElementToUse)\n }, 0)\n }\n })\n\n // 2. Focus on the new paragraph node\n setTimeout(() => {\n editor.update(() => {\n editor.focus()\n\n if (\n hoveredElementToUse.node &&\n 'select' in hoveredElementToUse.node &&\n typeof hoveredElementToUse.node.select === 'function'\n ) {\n hoveredElementToUse.node.select()\n }\n })\n }, 1)\n\n // Make sure this is called AFTER the focusing has been processed by the browser\n // Otherwise, this won't work\n setTimeout(() => {\n editor.dispatchCommand(ENABLE_SLASH_MENU_COMMAND, {\n node: hoveredElementToUse.node as ParagraphNode,\n })\n }, 2)\n\n event.stopPropagation()\n event.preventDefault()\n },\n [editor, hoveredElement],\n )\n\n return createPortal(\n <React.Fragment>\n <button\n className=\"icon add-block-menu\"\n onClick={(event) => {\n handleAddClick(event)\n }}\n ref={menuRef}\n type=\"button\"\n >\n <div className={isEditable ? 'icon' : ''} />\n </button>\n </React.Fragment>,\n anchorElem,\n )\n}\n\nexport function AddBlockHandlePlugin({\n anchorElem = document.body,\n}: {\n anchorElem?: HTMLElement\n}): JSX.Element {\n const [editor] = useLexicalComposerContext()\n return useAddBlockHandle(editor, anchorElem, editor._editable)\n}\n"],"names":["lexicalComposerContextImport","useLexicalComposerContext","lexicalImport","$createParagraphNode","$getNodeByKey","React","useCallback","useEffect","useRef","useState","createPortal","isHTMLElement","Point","Rect","ENABLE_SLASH_MENU_COMMAND","getCollapsedMargins","getTopLevelNodeKeys","isOnHandleElement","setHandlePosition","SPACE","ADD_BLOCK_MENU_CLASSNAME","Downward","Upward","Indeterminate","prevIndex","Infinity","getCurrentIndex","keysLength","Math","floor","getBlockElement","anchorElem","editor","event","useEdgeAsDefault","horizontalOffset","anchorElementRect","getBoundingClientRect","topLevelNodeKeys","blockElem","blockNode","getEditorState","read","firstNode","lastNode","getElementByKey","length","firstNodeRect","lastNodeRect","y","top","bottom","index","direction","key","elem","point","x","domRect","fromDOM","marginBottom","marginTop","rect","generateNewRect","left","right","reason","isOnBottomSide","isOnTopSide","result","contains","useAddBlockHandle","isEditable","scrollerElem","parentElement","menuRef","hoveredElement","setHoveredElement","onDocumentMouseMove","target","distanceFromScrollerElem","pageX","pageY","horizontalBuffer","verticalBuffer","adjustedTop","window","scrollY","adjustedBottom","_emptyBlockElem","node","document","addEventListener","removeEventListener","current","isEmptyParagraph","getType","getTextContent","handleAddClick","hoveredElementToUse","update","newParagraph","insertAfter","setTimeout","getKey","focus","select","dispatchCommand","stopPropagation","preventDefault","Fragment","button","className","onClick","ref","type","div","AddBlockHandlePlugin","body","_editable"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../src/field/lexical/plugins/handles/AddBlockHandlePlugin/index.tsx"],"sourcesContent":["'use client'\nimport type { LexicalEditor, LexicalNode, ParagraphNode } from 'lexical'\n\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js'\nimport { $createParagraphNode, $getNodeByKey } from 'lexical'\nimport * as React from 'react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { isHTMLElement } from '../../../utils/guard.js'\nimport { Point } from '../../../utils/point.js'\nimport { Rect } from '../../../utils/rect.js'\nimport { ENABLE_SLASH_MENU_COMMAND } from '../../SlashMenu/LexicalTypeaheadMenuPlugin/index.js'\nimport { getCollapsedMargins } from '../utils/getCollapsedMargins.js'\nimport { getTopLevelNodeKeys } from '../utils/getTopLevelNodeKeys.js'\nimport { isOnHandleElement } from '../utils/isOnHandleElement.js'\nimport { setHandlePosition } from '../utils/setHandlePosition.js'\nimport './index.scss'\n\nconst SPACE = -24\nconst ADD_BLOCK_MENU_CLASSNAME = 'add-block-menu'\n\nconst Downward = 1\nconst Upward = -1\nconst Indeterminate = 0\n\nlet prevIndex = Infinity\n\nfunction getCurrentIndex(keysLength: number): number {\n if (keysLength === 0) {\n return Infinity\n }\n if (prevIndex >= 0 && prevIndex < keysLength) {\n return prevIndex\n }\n\n return Math.floor(keysLength / 2)\n}\n\nfunction getBlockElement(\n anchorElem: HTMLElement,\n editor: LexicalEditor,\n event: MouseEvent,\n useEdgeAsDefault = false,\n horizontalOffset = 0,\n): {\n blockElem: HTMLElement | null\n blockNode: LexicalNode | null\n} {\n const anchorElementRect = anchorElem.getBoundingClientRect()\n const topLevelNodeKeys = getTopLevelNodeKeys(editor)\n\n let blockElem: HTMLElement | null = null\n let blockNode: LexicalNode | null = null\n\n // Return null if matching block element is the first or last node\n editor.getEditorState().read(() => {\n if (useEdgeAsDefault) {\n const [firstNode, lastNode] = [\n editor.getElementByKey(topLevelNodeKeys[0]),\n editor.getElementByKey(topLevelNodeKeys[topLevelNodeKeys.length - 1]),\n ]\n\n const [firstNodeRect, lastNodeRect] = [\n firstNode?.getBoundingClientRect(),\n lastNode?.getBoundingClientRect(),\n ]\n\n if (firstNodeRect && lastNodeRect) {\n if (event.y < firstNodeRect.top) {\n blockElem = firstNode\n } else if (event.y > lastNodeRect.bottom) {\n blockElem = lastNode\n }\n\n if (blockElem) {\n return {\n blockElem: null,\n }\n }\n }\n }\n\n // Find matching block element\n let index = getCurrentIndex(topLevelNodeKeys.length)\n let direction = Indeterminate\n\n while (index >= 0 && index < topLevelNodeKeys.length) {\n const key = topLevelNodeKeys[index]\n const elem = editor.getElementByKey(key)\n if (elem === null) {\n break\n }\n const point = new Point(event.x + horizontalOffset, event.y)\n const domRect = Rect.fromDOM(elem)\n const { marginBottom, marginTop } = getCollapsedMargins(elem)\n\n const rect = domRect.generateNewRect({\n bottom: domRect.bottom + marginBottom,\n left: anchorElementRect.left,\n right: anchorElementRect.right,\n top: domRect.top - marginTop,\n })\n\n const {\n reason: { isOnBottomSide, isOnTopSide },\n result,\n } = rect.contains(point)\n\n if (result) {\n blockElem = elem\n blockNode = $getNodeByKey(key)\n prevIndex = index\n break\n }\n\n if (direction === Indeterminate) {\n if (isOnTopSide) {\n direction = Upward\n } else if (isOnBottomSide) {\n direction = Downward\n } else {\n // stop search block element\n direction = Infinity\n }\n }\n\n index += direction\n }\n })\n\n return {\n blockElem,\n blockNode,\n }\n}\n\nfunction useAddBlockHandle(\n editor: LexicalEditor,\n anchorElem: HTMLElement,\n isEditable: boolean,\n): JSX.Element {\n const scrollerElem = anchorElem.parentElement\n\n const menuRef = useRef<HTMLButtonElement>(null)\n const [hoveredElement, setHoveredElement] = useState<{\n elem: HTMLElement\n node: LexicalNode\n } | null>(null)\n\n useEffect(() => {\n function onDocumentMouseMove(event: MouseEvent) {\n const target = event.target\n if (!isHTMLElement(target)) {\n return\n }\n\n let distanceFromScrollerElem = 0\n // Calculate distance between scrollerElem and target if target is not in scrollerElem\n if (scrollerElem && !scrollerElem.contains(target)) {\n const { bottom, left, right, top } = scrollerElem.getBoundingClientRect()\n const { pageX, pageY } = event\n const horizontalBuffer = 50\n const verticalBuffer = 25\n const adjustedTop = top + window.scrollY\n const adjustedBottom = bottom + window.scrollY\n\n if (\n pageY < adjustedTop - verticalBuffer ||\n pageY > adjustedBottom + verticalBuffer ||\n pageX < left - horizontalBuffer ||\n pageX > right + horizontalBuffer\n ) {\n if (hoveredElement !== null) {\n setHoveredElement(null)\n }\n return\n }\n\n // This is used to allow the _emptyBlockElem to be found when the mouse is in the\n // buffer zone around the scrollerElem.\n if (pageX < left || pageX > right) {\n distanceFromScrollerElem = pageX < left ? pageX - left : pageX - right\n }\n }\n\n if (isOnHandleElement(target, ADD_BLOCK_MENU_CLASSNAME)) {\n return\n }\n const { blockElem: _emptyBlockElem, blockNode } = getBlockElement(\n anchorElem,\n editor,\n event,\n false,\n -distanceFromScrollerElem,\n )\n if (!_emptyBlockElem) {\n return\n }\n if (hoveredElement?.node !== blockNode || hoveredElement?.elem !== _emptyBlockElem) {\n setHoveredElement({\n elem: _emptyBlockElem,\n node: blockNode,\n })\n }\n }\n\n // Since the draggableBlockElem is outside the actual editor, we need to listen to the document\n // to be able to detect when the mouse is outside the editor and respect a buffer around\n // the scrollerElem to avoid the draggableBlockElem disappearing too early.\n document?.addEventListener('mousemove', onDocumentMouseMove)\n\n return () => {\n document?.removeEventListener('mousemove', onDocumentMouseMove)\n }\n }, [scrollerElem, anchorElem, editor, hoveredElement])\n\n useEffect(() => {\n if (menuRef.current && hoveredElement?.node) {\n editor.getEditorState().read(() => {\n // Check if blockNode is an empty text node\n let isEmptyParagraph = true\n if (\n hoveredElement.node.getType() !== 'paragraph' ||\n hoveredElement.node.getTextContent() !== ''\n ) {\n isEmptyParagraph = false\n }\n\n setHandlePosition(\n hoveredElement?.elem,\n menuRef.current,\n anchorElem,\n isEmptyParagraph ? SPACE : SPACE - 20,\n )\n })\n }\n }, [anchorElem, hoveredElement, editor])\n\n const handleAddClick = useCallback(\n (event) => {\n let hoveredElementToUse = hoveredElement\n if (!hoveredElementToUse?.node) {\n return\n }\n\n // 1. Update hoveredElement.node to a new paragraph node if the hoveredElement.node is not a paragraph node\n editor.update(() => {\n // Check if blockNode is an empty text node\n let isEmptyParagraph = true\n if (\n hoveredElementToUse.node.getType() !== 'paragraph' ||\n hoveredElementToUse.node.getTextContent() !== ''\n ) {\n isEmptyParagraph = false\n }\n\n if (!isEmptyParagraph) {\n const newParagraph = $createParagraphNode()\n hoveredElementToUse.node.insertAfter(newParagraph)\n\n setTimeout(() => {\n hoveredElementToUse = {\n elem: editor.getElementByKey(newParagraph.getKey()),\n node: newParagraph,\n }\n setHoveredElement(hoveredElementToUse)\n }, 0)\n }\n })\n\n // 2. Focus on the new paragraph node\n setTimeout(() => {\n editor.update(() => {\n editor.focus()\n\n if (\n hoveredElementToUse.node &&\n 'select' in hoveredElementToUse.node &&\n typeof hoveredElementToUse.node.select === 'function'\n ) {\n hoveredElementToUse.node.select()\n }\n })\n }, 1)\n\n // Make sure this is called AFTER the focusing has been processed by the browser\n // Otherwise, this won't work\n setTimeout(() => {\n editor.dispatchCommand(ENABLE_SLASH_MENU_COMMAND, {\n node: hoveredElementToUse.node as ParagraphNode,\n })\n }, 2)\n\n event.stopPropagation()\n event.preventDefault()\n },\n [editor, hoveredElement],\n )\n\n return createPortal(\n <React.Fragment>\n <button\n className=\"icon add-block-menu\"\n onClick={(event) => {\n handleAddClick(event)\n }}\n ref={menuRef}\n type=\"button\"\n >\n <div className={isEditable ? 'icon' : ''} />\n </button>\n </React.Fragment>,\n anchorElem,\n )\n}\n\nexport function AddBlockHandlePlugin({\n anchorElem = document.body,\n}: {\n anchorElem?: HTMLElement\n}): JSX.Element {\n const [editor] = useLexicalComposerContext()\n return useAddBlockHandle(editor, anchorElem, editor._editable)\n}\n"],"names":["useLexicalComposerContext","$createParagraphNode","$getNodeByKey","React","useCallback","useEffect","useRef","useState","createPortal","isHTMLElement","Point","Rect","ENABLE_SLASH_MENU_COMMAND","getCollapsedMargins","getTopLevelNodeKeys","isOnHandleElement","setHandlePosition","SPACE","ADD_BLOCK_MENU_CLASSNAME","Downward","Upward","Indeterminate","prevIndex","Infinity","getCurrentIndex","keysLength","Math","floor","getBlockElement","anchorElem","editor","event","useEdgeAsDefault","horizontalOffset","anchorElementRect","getBoundingClientRect","topLevelNodeKeys","blockElem","blockNode","getEditorState","read","firstNode","lastNode","getElementByKey","length","firstNodeRect","lastNodeRect","y","top","bottom","index","direction","key","elem","point","x","domRect","fromDOM","marginBottom","marginTop","rect","generateNewRect","left","right","reason","isOnBottomSide","isOnTopSide","result","contains","useAddBlockHandle","isEditable","scrollerElem","parentElement","menuRef","hoveredElement","setHoveredElement","onDocumentMouseMove","target","distanceFromScrollerElem","pageX","pageY","horizontalBuffer","verticalBuffer","adjustedTop","window","scrollY","adjustedBottom","_emptyBlockElem","node","document","addEventListener","removeEventListener","current","isEmptyParagraph","getType","getTextContent","handleAddClick","hoveredElementToUse","update","newParagraph","insertAfter","setTimeout","getKey","focus","select","dispatchCommand","stopPropagation","preventDefault","Fragment","button","className","onClick","ref","type","div","AddBlockHandlePlugin","body","_editable"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"getNodeCloseToPoint.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/DraggableBlockPlugin/getNodeCloseToPoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAKzD,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAW/C,KAAK,KAAK,GAAG;IACX,UAAU,EAAE,WAAW,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,aAAa,CAAA;IACrB,gHAAgH;IAChH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,KAAK,EAAE,KAAK,CAAA;IACZ;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,KAAK,MAAM,GAAG;IACZ,SAAS,EAAE,WAAW,GAAG,IAAI,CAAA;IAC7B,SAAS,EAAE,WAAW,GAAG,IAAI,CAAA;IAC7B,YAAY,EAAE,MAAM,CAAA;IACpB,yBAAyB,EAAE,OAAO,CAAA;CACnC,CAAA;AAaD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAkLxD"}
1
+ {"version":3,"file":"getNodeCloseToPoint.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/DraggableBlockPlugin/getNodeCloseToPoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAIzD,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAW/C,KAAK,KAAK,GAAG;IACX,UAAU,EAAE,WAAW,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,aAAa,CAAA;IACrB,gHAAgH;IAChH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,KAAK,EAAE,KAAK,CAAA;IACZ;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,KAAK,MAAM,GAAG;IACZ,SAAS,EAAE,WAAW,GAAG,IAAI,CAAA;IAC7B,SAAS,EAAE,WAAW,GAAG,IAAI,CAAA;IAC7B,YAAY,EAAE,MAAM,CAAA;IACpB,yBAAyB,EAAE,OAAO,CAAA;CACnC,CAAA;AAaD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAkLxD"}
@@ -1,5 +1,4 @@
1
- import lexicalImport from 'lexical';
2
- const { $getNodeByKey } = lexicalImport;
1
+ import { $getNodeByKey } from 'lexical';
3
2
  import { Point } from '../../../utils/point.js';
4
3
  import { Rect } from '../../../utils/rect.js';
5
4
  import { getCollapsedMargins } from '../utils/getCollapsedMargins.js';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/field/lexical/plugins/handles/DraggableBlockPlugin/getNodeCloseToPoint.ts"],"sourcesContent":["import type { LexicalEditor, LexicalNode } from 'lexical'\n\nimport lexicalImport from 'lexical'\nconst { $getNodeByKey } = lexicalImport\n\nimport { Point } from '../../../utils/point.js'\nimport { Rect } from '../../../utils/rect.js'\nimport { getCollapsedMargins } from '../utils/getCollapsedMargins.js'\nimport { getTopLevelNodeKeys } from '../utils/getTopLevelNodeKeys.js'\nimport { getBoundingClientRectWithoutTransform } from './getBoundingRectWithoutTransform.js'\n\n// Directions\nconst Downward = 1\nconst Upward = -1\nconst Indeterminate = 0\n\ntype Props = {\n anchorElem: HTMLElement\n cache_treshold?: number\n editor: LexicalEditor\n /** fuzzy makes the search not exact. If no exact match found, find the closes node instead of returning null */\n fuzzy?: boolean\n horizontalOffset?: number\n point: Point\n /**\n * The index to start searching from. It can be a considerable performance optimization to start searching from the index of the\n * previously found node, as the node is likely to be close to the next node.\n */\n startIndex?: number\n useEdgeAsDefault?: boolean\n verbose?: boolean\n}\n\ntype Output = {\n blockElem: HTMLElement | null\n blockNode: LexicalNode | null\n foundAtIndex: number\n isFoundNodeEmptyParagraph: boolean\n}\n\nconst cache = {\n props: null as Props | null,\n result: null as Output | null,\n}\n\nfunction isPointClose(previous: Point, current: Point, threshold: number = 20): boolean {\n const dx = previous.x - current.x\n const dy = previous.y - current.y\n return dx * dx + dy * dy <= threshold * threshold\n}\n\nexport function getNodeCloseToPoint(props: Props): Output {\n const {\n anchorElem,\n cache_treshold = 20,\n editor,\n fuzzy = false,\n horizontalOffset = 0,\n point: { x, y },\n startIndex = 0,\n useEdgeAsDefault = false,\n verbose = false,\n } = props\n\n // Use cache\n if (\n cache_treshold > 0 &&\n cache.props &&\n cache.result &&\n cache.props.fuzzy === props.fuzzy &&\n cache.props.horizontalOffset === props.horizontalOffset &&\n cache.props.useEdgeAsDefault === props.useEdgeAsDefault &&\n isPointClose(cache.props.point, props.point, cache_treshold)\n ) {\n if (verbose) {\n //console.log('Returning cached result')\n }\n return cache.result\n }\n\n const anchorElementRect = anchorElem.getBoundingClientRect()\n const topLevelNodeKeys = getTopLevelNodeKeys(editor)\n\n const closestBlockElem: {\n blockElem: HTMLElement | null\n blockNode: LexicalNode | null\n distance: number\n foundAtIndex: number\n isFoundNodeEmptyParagraph: boolean\n } = {\n blockElem: null,\n blockNode: null,\n distance: Infinity,\n foundAtIndex: -1,\n isFoundNodeEmptyParagraph: false,\n }\n\n // Return null if matching block element is the first or last node\n editor.getEditorState().read(() => {\n if (useEdgeAsDefault) {\n const [firstNode, lastNode] = [\n editor.getElementByKey(topLevelNodeKeys[0]),\n editor.getElementByKey(topLevelNodeKeys[topLevelNodeKeys.length - 1]),\n ]\n\n const [firstNodeRect, lastNodeRect] = [\n getBoundingClientRectWithoutTransform(firstNode),\n getBoundingClientRectWithoutTransform(lastNode),\n ]\n\n if (firstNodeRect && lastNodeRect) {\n if (y < firstNodeRect.top) {\n closestBlockElem.blockElem = firstNode\n closestBlockElem.distance = firstNodeRect.top - y\n closestBlockElem.blockNode = $getNodeByKey(topLevelNodeKeys[0])\n closestBlockElem.foundAtIndex = 0\n } else if (y > lastNodeRect.bottom) {\n closestBlockElem.distance = y - lastNodeRect.bottom\n closestBlockElem.blockNode = $getNodeByKey(topLevelNodeKeys[topLevelNodeKeys.length - 1])\n closestBlockElem.blockElem = lastNode\n closestBlockElem.foundAtIndex = topLevelNodeKeys.length - 1\n }\n\n if (closestBlockElem?.blockElem) {\n if (verbose) {\n //console.log('useEdgeAsDefault', useEdgeAsDefault)\n }\n\n return {\n blockElem: null,\n isFoundNodeEmptyParagraph: false,\n } as Output\n }\n }\n }\n\n // Find matching block element\n let index = startIndex\n let direction = Indeterminate\n\n if (verbose) {\n //console.log('start index', startIndex)\n }\n\n while (index >= 0 && index < topLevelNodeKeys.length) {\n const key = topLevelNodeKeys[index]\n const elem = editor.getElementByKey(key)\n if (elem === null) {\n break\n }\n const point = new Point(x + horizontalOffset, y)\n //const domRect = Rect.fromDOM(elem)\n // Do not consider transform of blocks when calculating distance\n const domRect = Rect.fromDOMRect(getBoundingClientRectWithoutTransform(elem))\n\n const { marginBottom, marginTop } = getCollapsedMargins(elem)\n\n const rect = domRect.generateNewRect({\n bottom: domRect.bottom + marginBottom,\n left: anchorElementRect.left,\n right: anchorElementRect.right,\n top: domRect.top - marginTop,\n })\n\n const { distance, isOnBottomSide, isOnTopSide } = rect.distanceFromPoint(point)\n\n if (verbose) {\n //console.log('distance', distance)\n }\n\n if (distance === 0) {\n closestBlockElem.blockElem = elem\n closestBlockElem.blockNode = $getNodeByKey(key)\n closestBlockElem.foundAtIndex = index\n closestBlockElem.distance = distance\n\n // Check if blockNode is an empty text node\n if (\n closestBlockElem.blockNode &&\n closestBlockElem.blockNode.getType() === 'paragraph' &&\n closestBlockElem.blockNode.getTextContent() === ''\n ) {\n if (!fuzzy) {\n closestBlockElem.blockElem = null\n closestBlockElem.blockNode = null\n }\n\n closestBlockElem.isFoundNodeEmptyParagraph = true\n }\n break\n } else if (fuzzy) {\n if (distance < closestBlockElem.distance) {\n closestBlockElem.blockElem = elem\n closestBlockElem.blockNode = $getNodeByKey(key)\n closestBlockElem.distance = distance\n closestBlockElem.foundAtIndex = index\n }\n }\n\n if (direction === Indeterminate) {\n if (isOnTopSide) {\n direction = Upward\n } else if (isOnBottomSide) {\n direction = Downward\n } else {\n // stop search block element\n direction = Infinity\n }\n }\n\n index += direction\n }\n })\n\n // Store in cache before returning\n cache.props = props\n cache.result = {\n blockElem: closestBlockElem.blockElem,\n blockNode: closestBlockElem.blockNode,\n foundAtIndex: closestBlockElem.foundAtIndex,\n isFoundNodeEmptyParagraph: closestBlockElem.isFoundNodeEmptyParagraph,\n }\n\n return {\n blockElem: closestBlockElem.blockElem,\n blockNode: closestBlockElem.blockNode,\n foundAtIndex: closestBlockElem.foundAtIndex,\n isFoundNodeEmptyParagraph: closestBlockElem.isFoundNodeEmptyParagraph,\n }\n}\n"],"names":["lexicalImport","$getNodeByKey","Point","Rect","getCollapsedMargins","getTopLevelNodeKeys","getBoundingClientRectWithoutTransform","Downward","Upward","Indeterminate","cache","props","result","isPointClose","previous","current","threshold","dx","x","dy","y","getNodeCloseToPoint","anchorElem","cache_treshold","editor","fuzzy","horizontalOffset","point","startIndex","useEdgeAsDefault","verbose","anchorElementRect","getBoundingClientRect","topLevelNodeKeys","closestBlockElem","blockElem","blockNode","distance","Infinity","foundAtIndex","isFoundNodeEmptyParagraph","getEditorState","read","firstNode","lastNode","getElementByKey","length","firstNodeRect","lastNodeRect","top","bottom","index","direction","key","elem","domRect","fromDOMRect","marginBottom","marginTop","rect","generateNewRect","left","right","isOnBottomSide","isOnTopSide","distanceFromPoint","getType","getTextContent"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAEA,OAAOA,mBAAmB,UAAS;AACnC,MAAM,EAAEC,aAAa,EAAE,GAAGD;AAE1B,SAASE,KAAK,QAAQ,0BAAyB;AAC/C,SAASC,IAAI,QAAQ,yBAAwB;AAC7C,SAASC,mBAAmB,QAAQ,kCAAiC;AACrE,SAASC,mBAAmB,QAAQ,kCAAiC;AACrE,SAASC,qCAAqC,QAAQ,uCAAsC;AAE5F,aAAa;AACb,MAAMC,WAAW;AACjB,MAAMC,SAAS,CAAC;AAChB,MAAMC,gBAAgB;AA0BtB,MAAMC,QAAQ;IACZC,OAAO;IACPC,QAAQ;AACV;AAEA,SAASC,aAAaC,QAAe,EAAEC,OAAc,EAAEC,YAAoB,EAAE;IAC3E,MAAMC,KAAKH,SAASI,CAAC,GAAGH,QAAQG,CAAC;IACjC,MAAMC,KAAKL,SAASM,CAAC,GAAGL,QAAQK,CAAC;IACjC,OAAOH,KAAKA,KAAKE,KAAKA,MAAMH,YAAYA;AAC1C;AAEA,OAAO,SAASK,oBAAoBV,KAAY;IAC9C,MAAM,EACJW,UAAU,EACVC,iBAAiB,EAAE,EACnBC,MAAM,EACNC,QAAQ,KAAK,EACbC,mBAAmB,CAAC,EACpBC,OAAO,EAAET,CAAC,EAAEE,CAAC,EAAE,EACfQ,aAAa,CAAC,EACdC,mBAAmB,KAAK,EACxBC,UAAU,KAAK,EAChB,GAAGnB;IAEJ,YAAY;IACZ,IACEY,iBAAiB,KACjBb,MAAMC,KAAK,IACXD,MAAME,MAAM,IACZF,MAAMC,KAAK,CAACc,KAAK,KAAKd,MAAMc,KAAK,IACjCf,MAAMC,KAAK,CAACe,gBAAgB,KAAKf,MAAMe,gBAAgB,IACvDhB,MAAMC,KAAK,CAACkB,gBAAgB,KAAKlB,MAAMkB,gBAAgB,IACvDhB,aAAaH,MAAMC,KAAK,CAACgB,KAAK,EAAEhB,MAAMgB,KAAK,EAAEJ,iBAC7C;QACA,IAAIO,SAAS;QACX,wCAAwC;QAC1C;QACA,OAAOpB,MAAME,MAAM;IACrB;IAEA,MAAMmB,oBAAoBT,WAAWU,qBAAqB;IAC1D,MAAMC,mBAAmB5B,oBAAoBmB;IAE7C,MAAMU,mBAMF;QACFC,WAAW;QACXC,WAAW;QACXC,UAAUC;QACVC,cAAc,CAAC;QACfC,2BAA2B;IAC7B;IAEA,kEAAkE;IAClEhB,OAAOiB,cAAc,GAAGC,IAAI,CAAC;QAC3B,IAAIb,kBAAkB;YACpB,MAAM,CAACc,WAAWC,SAAS,GAAG;gBAC5BpB,OAAOqB,eAAe,CAACZ,gBAAgB,CAAC,EAAE;gBAC1CT,OAAOqB,eAAe,CAACZ,gBAAgB,CAACA,iBAAiBa,MAAM,GAAG,EAAE;aACrE;YAED,MAAM,CAACC,eAAeC,aAAa,GAAG;gBACpC1C,sCAAsCqC;gBACtCrC,sCAAsCsC;aACvC;YAED,IAAIG,iBAAiBC,cAAc;gBACjC,IAAI5B,IAAI2B,cAAcE,GAAG,EAAE;oBACzBf,iBAAiBC,SAAS,GAAGQ;oBAC7BT,iBAAiBG,QAAQ,GAAGU,cAAcE,GAAG,GAAG7B;oBAChDc,iBAAiBE,SAAS,GAAGnC,cAAcgC,gBAAgB,CAAC,EAAE;oBAC9DC,iBAAiBK,YAAY,GAAG;gBAClC,OAAO,IAAInB,IAAI4B,aAAaE,MAAM,EAAE;oBAClChB,iBAAiBG,QAAQ,GAAGjB,IAAI4B,aAAaE,MAAM;oBACnDhB,iBAAiBE,SAAS,GAAGnC,cAAcgC,gBAAgB,CAACA,iBAAiBa,MAAM,GAAG,EAAE;oBACxFZ,iBAAiBC,SAAS,GAAGS;oBAC7BV,iBAAiBK,YAAY,GAAGN,iBAAiBa,MAAM,GAAG;gBAC5D;gBAEA,IAAIZ,kBAAkBC,WAAW;oBAC/B,IAAIL,SAAS;oBACX,mDAAmD;oBACrD;oBAEA,OAAO;wBACLK,WAAW;wBACXK,2BAA2B;oBAC7B;gBACF;YACF;QACF;QAEA,8BAA8B;QAC9B,IAAIW,QAAQvB;QACZ,IAAIwB,YAAY3C;QAEhB,IAAIqB,SAAS;QACX,wCAAwC;QAC1C;QAEA,MAAOqB,SAAS,KAAKA,QAAQlB,iBAAiBa,MAAM,CAAE;YACpD,MAAMO,MAAMpB,gBAAgB,CAACkB,MAAM;YACnC,MAAMG,OAAO9B,OAAOqB,eAAe,CAACQ;YACpC,IAAIC,SAAS,MAAM;gBACjB;YACF;YACA,MAAM3B,QAAQ,IAAIzB,MAAMgB,IAAIQ,kBAAkBN;YAC9C,oCAAoC;YACpC,gEAAgE;YAChE,MAAMmC,UAAUpD,KAAKqD,WAAW,CAAClD,sCAAsCgD;YAEvE,MAAM,EAAEG,YAAY,EAAEC,SAAS,EAAE,GAAGtD,oBAAoBkD;YAExD,MAAMK,OAAOJ,QAAQK,eAAe,CAAC;gBACnCV,QAAQK,QAAQL,MAAM,GAAGO;gBACzBI,MAAM9B,kBAAkB8B,IAAI;gBAC5BC,OAAO/B,kBAAkB+B,KAAK;gBAC9Bb,KAAKM,QAAQN,GAAG,GAAGS;YACrB;YAEA,MAAM,EAAErB,QAAQ,EAAE0B,cAAc,EAAEC,WAAW,EAAE,GAAGL,KAAKM,iBAAiB,CAACtC;YAEzE,IAAIG,SAAS;YACX,mCAAmC;YACrC;YAEA,IAAIO,aAAa,GAAG;gBAClBH,iBAAiBC,SAAS,GAAGmB;gBAC7BpB,iBAAiBE,SAAS,GAAGnC,cAAcoD;gBAC3CnB,iBAAiBK,YAAY,GAAGY;gBAChCjB,iBAAiBG,QAAQ,GAAGA;gBAE5B,2CAA2C;gBAC3C,IACEH,iBAAiBE,SAAS,IAC1BF,iBAAiBE,SAAS,CAAC8B,OAAO,OAAO,eACzChC,iBAAiBE,SAAS,CAAC+B,cAAc,OAAO,IAChD;oBACA,IAAI,CAAC1C,OAAO;wBACVS,iBAAiBC,SAAS,GAAG;wBAC7BD,iBAAiBE,SAAS,GAAG;oBAC/B;oBAEAF,iBAAiBM,yBAAyB,GAAG;gBAC/C;gBACA;YACF,OAAO,IAAIf,OAAO;gBAChB,IAAIY,WAAWH,iBAAiBG,QAAQ,EAAE;oBACxCH,iBAAiBC,SAAS,GAAGmB;oBAC7BpB,iBAAiBE,SAAS,GAAGnC,cAAcoD;oBAC3CnB,iBAAiBG,QAAQ,GAAGA;oBAC5BH,iBAAiBK,YAAY,GAAGY;gBAClC;YACF;YAEA,IAAIC,cAAc3C,eAAe;gBAC/B,IAAIuD,aAAa;oBACfZ,YAAY5C;gBACd,OAAO,IAAIuD,gBAAgB;oBACzBX,YAAY7C;gBACd,OAAO;oBACL,4BAA4B;oBAC5B6C,YAAYd;gBACd;YACF;YAEAa,SAASC;QACX;IACF;IAEA,kCAAkC;IAClC1C,MAAMC,KAAK,GAAGA;IACdD,MAAME,MAAM,GAAG;QACbuB,WAAWD,iBAAiBC,SAAS;QACrCC,WAAWF,iBAAiBE,SAAS;QACrCG,cAAcL,iBAAiBK,YAAY;QAC3CC,2BAA2BN,iBAAiBM,yBAAyB;IACvE;IAEA,OAAO;QACLL,WAAWD,iBAAiBC,SAAS;QACrCC,WAAWF,iBAAiBE,SAAS;QACrCG,cAAcL,iBAAiBK,YAAY;QAC3CC,2BAA2BN,iBAAiBM,yBAAyB;IACvE;AACF"}
1
+ {"version":3,"sources":["../../../../../../src/field/lexical/plugins/handles/DraggableBlockPlugin/getNodeCloseToPoint.ts"],"sourcesContent":["import type { LexicalEditor, LexicalNode } from 'lexical'\n\nimport { $getNodeByKey } from 'lexical'\n\nimport { Point } from '../../../utils/point.js'\nimport { Rect } from '../../../utils/rect.js'\nimport { getCollapsedMargins } from '../utils/getCollapsedMargins.js'\nimport { getTopLevelNodeKeys } from '../utils/getTopLevelNodeKeys.js'\nimport { getBoundingClientRectWithoutTransform } from './getBoundingRectWithoutTransform.js'\n\n// Directions\nconst Downward = 1\nconst Upward = -1\nconst Indeterminate = 0\n\ntype Props = {\n anchorElem: HTMLElement\n cache_treshold?: number\n editor: LexicalEditor\n /** fuzzy makes the search not exact. If no exact match found, find the closes node instead of returning null */\n fuzzy?: boolean\n horizontalOffset?: number\n point: Point\n /**\n * The index to start searching from. It can be a considerable performance optimization to start searching from the index of the\n * previously found node, as the node is likely to be close to the next node.\n */\n startIndex?: number\n useEdgeAsDefault?: boolean\n verbose?: boolean\n}\n\ntype Output = {\n blockElem: HTMLElement | null\n blockNode: LexicalNode | null\n foundAtIndex: number\n isFoundNodeEmptyParagraph: boolean\n}\n\nconst cache = {\n props: null as Props | null,\n result: null as Output | null,\n}\n\nfunction isPointClose(previous: Point, current: Point, threshold: number = 20): boolean {\n const dx = previous.x - current.x\n const dy = previous.y - current.y\n return dx * dx + dy * dy <= threshold * threshold\n}\n\nexport function getNodeCloseToPoint(props: Props): Output {\n const {\n anchorElem,\n cache_treshold = 20,\n editor,\n fuzzy = false,\n horizontalOffset = 0,\n point: { x, y },\n startIndex = 0,\n useEdgeAsDefault = false,\n verbose = false,\n } = props\n\n // Use cache\n if (\n cache_treshold > 0 &&\n cache.props &&\n cache.result &&\n cache.props.fuzzy === props.fuzzy &&\n cache.props.horizontalOffset === props.horizontalOffset &&\n cache.props.useEdgeAsDefault === props.useEdgeAsDefault &&\n isPointClose(cache.props.point, props.point, cache_treshold)\n ) {\n if (verbose) {\n //console.log('Returning cached result')\n }\n return cache.result\n }\n\n const anchorElementRect = anchorElem.getBoundingClientRect()\n const topLevelNodeKeys = getTopLevelNodeKeys(editor)\n\n const closestBlockElem: {\n blockElem: HTMLElement | null\n blockNode: LexicalNode | null\n distance: number\n foundAtIndex: number\n isFoundNodeEmptyParagraph: boolean\n } = {\n blockElem: null,\n blockNode: null,\n distance: Infinity,\n foundAtIndex: -1,\n isFoundNodeEmptyParagraph: false,\n }\n\n // Return null if matching block element is the first or last node\n editor.getEditorState().read(() => {\n if (useEdgeAsDefault) {\n const [firstNode, lastNode] = [\n editor.getElementByKey(topLevelNodeKeys[0]),\n editor.getElementByKey(topLevelNodeKeys[topLevelNodeKeys.length - 1]),\n ]\n\n const [firstNodeRect, lastNodeRect] = [\n getBoundingClientRectWithoutTransform(firstNode),\n getBoundingClientRectWithoutTransform(lastNode),\n ]\n\n if (firstNodeRect && lastNodeRect) {\n if (y < firstNodeRect.top) {\n closestBlockElem.blockElem = firstNode\n closestBlockElem.distance = firstNodeRect.top - y\n closestBlockElem.blockNode = $getNodeByKey(topLevelNodeKeys[0])\n closestBlockElem.foundAtIndex = 0\n } else if (y > lastNodeRect.bottom) {\n closestBlockElem.distance = y - lastNodeRect.bottom\n closestBlockElem.blockNode = $getNodeByKey(topLevelNodeKeys[topLevelNodeKeys.length - 1])\n closestBlockElem.blockElem = lastNode\n closestBlockElem.foundAtIndex = topLevelNodeKeys.length - 1\n }\n\n if (closestBlockElem?.blockElem) {\n if (verbose) {\n //console.log('useEdgeAsDefault', useEdgeAsDefault)\n }\n\n return {\n blockElem: null,\n isFoundNodeEmptyParagraph: false,\n } as Output\n }\n }\n }\n\n // Find matching block element\n let index = startIndex\n let direction = Indeterminate\n\n if (verbose) {\n //console.log('start index', startIndex)\n }\n\n while (index >= 0 && index < topLevelNodeKeys.length) {\n const key = topLevelNodeKeys[index]\n const elem = editor.getElementByKey(key)\n if (elem === null) {\n break\n }\n const point = new Point(x + horizontalOffset, y)\n //const domRect = Rect.fromDOM(elem)\n // Do not consider transform of blocks when calculating distance\n const domRect = Rect.fromDOMRect(getBoundingClientRectWithoutTransform(elem))\n\n const { marginBottom, marginTop } = getCollapsedMargins(elem)\n\n const rect = domRect.generateNewRect({\n bottom: domRect.bottom + marginBottom,\n left: anchorElementRect.left,\n right: anchorElementRect.right,\n top: domRect.top - marginTop,\n })\n\n const { distance, isOnBottomSide, isOnTopSide } = rect.distanceFromPoint(point)\n\n if (verbose) {\n //console.log('distance', distance)\n }\n\n if (distance === 0) {\n closestBlockElem.blockElem = elem\n closestBlockElem.blockNode = $getNodeByKey(key)\n closestBlockElem.foundAtIndex = index\n closestBlockElem.distance = distance\n\n // Check if blockNode is an empty text node\n if (\n closestBlockElem.blockNode &&\n closestBlockElem.blockNode.getType() === 'paragraph' &&\n closestBlockElem.blockNode.getTextContent() === ''\n ) {\n if (!fuzzy) {\n closestBlockElem.blockElem = null\n closestBlockElem.blockNode = null\n }\n\n closestBlockElem.isFoundNodeEmptyParagraph = true\n }\n break\n } else if (fuzzy) {\n if (distance < closestBlockElem.distance) {\n closestBlockElem.blockElem = elem\n closestBlockElem.blockNode = $getNodeByKey(key)\n closestBlockElem.distance = distance\n closestBlockElem.foundAtIndex = index\n }\n }\n\n if (direction === Indeterminate) {\n if (isOnTopSide) {\n direction = Upward\n } else if (isOnBottomSide) {\n direction = Downward\n } else {\n // stop search block element\n direction = Infinity\n }\n }\n\n index += direction\n }\n })\n\n // Store in cache before returning\n cache.props = props\n cache.result = {\n blockElem: closestBlockElem.blockElem,\n blockNode: closestBlockElem.blockNode,\n foundAtIndex: closestBlockElem.foundAtIndex,\n isFoundNodeEmptyParagraph: closestBlockElem.isFoundNodeEmptyParagraph,\n }\n\n return {\n blockElem: closestBlockElem.blockElem,\n blockNode: closestBlockElem.blockNode,\n foundAtIndex: closestBlockElem.foundAtIndex,\n isFoundNodeEmptyParagraph: closestBlockElem.isFoundNodeEmptyParagraph,\n }\n}\n"],"names":["$getNodeByKey","Point","Rect","getCollapsedMargins","getTopLevelNodeKeys","getBoundingClientRectWithoutTransform","Downward","Upward","Indeterminate","cache","props","result","isPointClose","previous","current","threshold","dx","x","dy","y","getNodeCloseToPoint","anchorElem","cache_treshold","editor","fuzzy","horizontalOffset","point","startIndex","useEdgeAsDefault","verbose","anchorElementRect","getBoundingClientRect","topLevelNodeKeys","closestBlockElem","blockElem","blockNode","distance","Infinity","foundAtIndex","isFoundNodeEmptyParagraph","getEditorState","read","firstNode","lastNode","getElementByKey","length","firstNodeRect","lastNodeRect","top","bottom","index","direction","key","elem","domRect","fromDOMRect","marginBottom","marginTop","rect","generateNewRect","left","right","isOnBottomSide","isOnTopSide","distanceFromPoint","getType","getTextContent"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/DraggableBlockPlugin/index.tsx"],"names":[],"mappings":";AAqBA,OAAO,cAAc,CAAA;AAgXrB,wBAAgB,oBAAoB,CAAC,EACnC,UAA0B,GAC3B,EAAE;IACD,UAAU,CAAC,EAAE,WAAW,CAAA;CACzB,GAAG,GAAG,CAAC,OAAO,CAGd"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/DraggableBlockPlugin/index.tsx"],"names":[],"mappings":";AAkBA,OAAO,cAAc,CAAA;AAoXrB,wBAAgB,oBAAoB,CAAC,EACnC,UAA0B,GAC3B,EAAE;IACD,UAAU,CAAC,EAAE,WAAW,CAAA;CACzB,GAAG,GAAG,CAAC,OAAO,CAGd"}
@@ -1,9 +1,7 @@
1
1
  'use client';
2
- import lexicalComposerContextImport from '@lexical/react/LexicalComposerContext.js';
3
- const { useLexicalComposerContext } = lexicalComposerContextImport;
2
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js';
4
3
  import { eventFiles } from '@lexical/rich-text';
5
- import lexicalImport from 'lexical';
6
- const { $getNearestNodeFromDOMNode, $getNodeByKey } = lexicalImport;
4
+ import { $getNearestNodeFromDOMNode, $getNodeByKey } from 'lexical';
7
5
  import * as React from 'react';
8
6
  import { useCallback, useEffect, useRef, useState } from 'react';
9
7
  import { createPortal } from 'react-dom';
@@ -106,7 +104,9 @@ function useDraggableBlockMenu(editor, anchorElem, isEditable) {
106
104
  if (!_draggableBlockElem && !isFoundNodeEmptyParagraph) {
107
105
  return;
108
106
  }
109
- setDraggableBlockElem(_draggableBlockElem);
107
+ if (draggableBlockElem !== _draggableBlockElem) {
108
+ setDraggableBlockElem(_draggableBlockElem);
109
+ }
110
110
  }
111
111
  // Since the draggableBlockElem is outside the actual editor, we need to listen to the document
112
112
  // to be able to detect when the mouse is outside the editor and respect a buffer around the
@@ -119,7 +119,8 @@ function useDraggableBlockMenu(editor, anchorElem, isEditable) {
119
119
  scrollerElem,
120
120
  anchorElem,
121
121
  editor,
122
- calculateDistanceFromScrollerElem
122
+ calculateDistanceFromScrollerElem,
123
+ draggableBlockElem
123
124
  ]);
124
125
  useEffect(()=>{
125
126
  if (menuRef.current) {
@@ -230,7 +231,9 @@ function useDraggableBlockMenu(editor, anchorElem, isEditable) {
230
231
  targetNode.insertAfter(draggedNode)
231
232
  } else {
232
233
  targetNode.insertBefore(draggedNode)
233
- }*/ setDraggableBlockElem(null);
234
+ }*/ if (draggableBlockElem !== null) {
235
+ setDraggableBlockElem(null);
236
+ }
234
237
  });
235
238
  return true;
236
239
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/field/lexical/plugins/handles/DraggableBlockPlugin/index.tsx"],"sourcesContent":["'use client'\nimport type { LexicalEditor } from 'lexical'\nimport type { DragEvent as ReactDragEvent } from 'react'\n\nimport lexicalComposerContextImport from '@lexical/react/LexicalComposerContext.js'\nconst { useLexicalComposerContext } = lexicalComposerContextImport\n\nimport { eventFiles } from '@lexical/rich-text'\nimport lexicalImport from 'lexical'\nconst { $getNearestNodeFromDOMNode, $getNodeByKey } = lexicalImport\nimport * as React from 'react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { isHTMLElement } from '../../../utils/guard.js'\nimport { Point } from '../../../utils/point.js'\nimport { getTopLevelNodeKeys } from '../utils/getTopLevelNodeKeys.js'\nimport { isOnHandleElement } from '../utils/isOnHandleElement.js'\nimport { setHandlePosition } from '../utils/setHandlePosition.js'\nimport { getBoundingClientRectWithoutTransform } from './getBoundingRectWithoutTransform.js'\nimport { getNodeCloseToPoint } from './getNodeCloseToPoint.js'\nimport './index.scss'\nimport { setTargetLine } from './setTargetLine.js'\n\nconst SPACE = -24\nconst DRAGGABLE_BLOCK_MENU_CLASSNAME = 'draggable-block-menu'\nconst DRAG_DATA_FORMAT = 'application/x-lexical-drag-block'\n\nlet prevIndex = Infinity\n\nfunction getCurrentIndex(keysLength: number): number {\n if (keysLength === 0) {\n return Infinity\n }\n if (prevIndex >= 0 && prevIndex < keysLength) {\n return prevIndex\n }\n\n return Math.floor(keysLength / 2)\n}\n\nfunction setDragImage(dataTransfer: DataTransfer, draggableBlockElem: HTMLElement) {\n const { transform } = draggableBlockElem.style\n\n // Remove dragImage borders\n dataTransfer.setDragImage(draggableBlockElem, 0, 0)\n\n setTimeout(() => {\n draggableBlockElem.style.transform = transform\n })\n}\n\nfunction hideTargetLine(\n targetLineElem: HTMLElement | null,\n lastTargetBlockElem: HTMLElement | null,\n) {\n if (targetLineElem) {\n targetLineElem.style.opacity = '0'\n }\n if (lastTargetBlockElem) {\n lastTargetBlockElem.style.opacity = '1'\n lastTargetBlockElem.style.transform = 'translate(0, 0)'\n //lastTargetBlockElem.style.border = 'none'\n }\n}\n\nfunction useDraggableBlockMenu(\n editor: LexicalEditor,\n anchorElem: HTMLElement,\n isEditable: boolean,\n): JSX.Element {\n const scrollerElem = anchorElem.parentElement\n\n const menuRef = useRef<HTMLDivElement>(null)\n const targetLineRef = useRef<HTMLDivElement>(null)\n const debugHighlightRef = useRef<HTMLDivElement>(null)\n const isDraggingBlockRef = useRef<boolean>(false)\n const [draggableBlockElem, setDraggableBlockElem] = useState<HTMLElement | null>(null)\n const [lastTargetBlockElem, setLastTargetBlockElem] = useState<HTMLElement | null>(null)\n\n const calculateDistanceFromScrollerElem = useCallback(\n (\n pageX: number,\n pageY: number,\n target: HTMLElement,\n horizontalBuffer: number = 50,\n verticalBuffer: number = 25,\n ): number => {\n let distanceFromScrollerElem = 0\n // Calculate distance between scrollerElem and target if target is not in scrollerElem\n if (scrollerElem && !scrollerElem.contains(target)) {\n const { bottom, left, right, top } = scrollerElem.getBoundingClientRect()\n\n const adjustedTop = top + window.scrollY\n const adjustedBottom = bottom + window.scrollY\n\n if (\n pageY < adjustedTop - verticalBuffer ||\n pageY > adjustedBottom + verticalBuffer ||\n pageX < left - horizontalBuffer ||\n pageX > right + horizontalBuffer\n ) {\n setDraggableBlockElem(null)\n return distanceFromScrollerElem\n }\n\n // This is used to allow the _draggableBlockElem to be found when the mouse is in the\n // buffer zone around the scrollerElem.\n if (pageX < left || pageX > right) {\n distanceFromScrollerElem = pageX < left ? pageX - left : pageX - right\n }\n }\n return distanceFromScrollerElem\n },\n [scrollerElem],\n )\n\n useEffect(() => {\n /**\n * Handles positioning of the drag handle\n */\n function onDocumentMouseMove(event: MouseEvent) {\n const target = event.target\n if (!isHTMLElement(target)) {\n return\n }\n\n const distanceFromScrollerElem = calculateDistanceFromScrollerElem(\n event.pageX,\n event.pageY,\n target,\n )\n\n if (isOnHandleElement(target, DRAGGABLE_BLOCK_MENU_CLASSNAME)) {\n return\n }\n\n const topLevelNodeKeys = getTopLevelNodeKeys(editor)\n const {\n blockElem: _draggableBlockElem,\n foundAtIndex,\n isFoundNodeEmptyParagraph,\n } = getNodeCloseToPoint({\n anchorElem,\n cache_treshold: 0,\n editor,\n horizontalOffset: -distanceFromScrollerElem,\n point: new Point(event.x, event.y),\n startIndex: getCurrentIndex(topLevelNodeKeys.length),\n useEdgeAsDefault: false,\n })\n //if (DEBUG && _draggableBlockElem) {\n //targetBlockElem.style.border = '3px solid red'\n // highlightElemOriginalPosition(debugHighlightRef, _draggableBlockElem, anchorElem)\n //}\n prevIndex = foundAtIndex\n\n if (!_draggableBlockElem && !isFoundNodeEmptyParagraph) {\n return\n }\n\n setDraggableBlockElem(_draggableBlockElem)\n }\n\n // Since the draggableBlockElem is outside the actual editor, we need to listen to the document\n // to be able to detect when the mouse is outside the editor and respect a buffer around the\n // the scrollerElem to avoid the draggableBlockElem disappearing too early.\n document?.addEventListener('mousemove', onDocumentMouseMove)\n\n return () => {\n document?.removeEventListener('mousemove', onDocumentMouseMove)\n }\n }, [scrollerElem, anchorElem, editor, calculateDistanceFromScrollerElem])\n\n useEffect(() => {\n if (menuRef.current) {\n setHandlePosition(draggableBlockElem, menuRef.current, anchorElem, SPACE)\n }\n }, [anchorElem, draggableBlockElem])\n\n useEffect(() => {\n function onDragover(event: DragEvent): boolean {\n if (!isDraggingBlockRef.current) {\n return false\n }\n const [isFileTransfer] = eventFiles(event)\n if (isFileTransfer) {\n return false\n }\n\n const { pageY, target } = event\n if (!isHTMLElement(target)) {\n return false\n }\n\n const distanceFromScrollerElem = calculateDistanceFromScrollerElem(\n event.pageX,\n event.pageY,\n target,\n 100,\n 50,\n )\n\n const topLevelNodeKeys = getTopLevelNodeKeys(editor)\n\n const {\n blockElem: targetBlockElem,\n foundAtIndex,\n isFoundNodeEmptyParagraph,\n } = getNodeCloseToPoint({\n anchorElem,\n editor,\n fuzzy: true,\n horizontalOffset: -distanceFromScrollerElem,\n point: new Point(event.x, event.y),\n startIndex: getCurrentIndex(topLevelNodeKeys.length),\n useEdgeAsDefault: true,\n verbose: true,\n })\n prevIndex = foundAtIndex\n\n const targetLineElem = targetLineRef.current\n // targetBlockElem === null shouldn't happen\n if (targetBlockElem === null || targetLineElem === null) {\n return false\n }\n\n if (draggableBlockElem !== targetBlockElem) {\n setTargetLine(\n SPACE,\n targetLineElem,\n targetBlockElem,\n lastTargetBlockElem,\n pageY,\n anchorElem,\n event,\n debugHighlightRef,\n isFoundNodeEmptyParagraph,\n )\n\n // Prevent default event to be able to trigger onDrop events\n // Calling preventDefault() adds the green plus icon to the cursor,\n // indicating that the drop is allowed.\n event.preventDefault()\n } else {\n hideTargetLine(targetLineElem, lastTargetBlockElem)\n }\n\n setLastTargetBlockElem(targetBlockElem)\n\n return true\n }\n\n function onDrop(event: DragEvent): boolean {\n if (!isDraggingBlockRef.current) {\n return false\n }\n const [isFileTransfer] = eventFiles(event)\n if (isFileTransfer) {\n return false\n }\n const { dataTransfer, pageY, target } = event\n const dragData = dataTransfer?.getData(DRAG_DATA_FORMAT) || ''\n\n editor.update(() => {\n const draggedNode = $getNodeByKey(dragData)\n if (!draggedNode) {\n return false\n }\n if (!isHTMLElement(target)) {\n return false\n }\n const distanceFromScrollerElem = calculateDistanceFromScrollerElem(\n event.pageX,\n event.pageY,\n target,\n 100,\n 50,\n )\n\n const { blockElem: targetBlockElem, isFoundNodeEmptyParagraph } = getNodeCloseToPoint({\n anchorElem,\n editor,\n fuzzy: true,\n horizontalOffset: -distanceFromScrollerElem,\n point: new Point(event.x, event.y),\n useEdgeAsDefault: true,\n })\n\n if (!targetBlockElem) {\n return false\n }\n const targetNode = $getNearestNodeFromDOMNode(targetBlockElem)\n if (!targetNode) {\n return false\n }\n if (targetNode === draggedNode) {\n return true\n }\n\n const { height: targetBlockElemHeight, top: targetBlockElemTop } =\n getBoundingClientRectWithoutTransform(targetBlockElem)\n\n const mouseY = pageY\n const isBelow = mouseY >= targetBlockElemTop + targetBlockElemHeight / 2 + window.scrollY\n\n if (!isFoundNodeEmptyParagraph) {\n if (isBelow) {\n // below targetBlockElem\n targetNode.insertAfter(draggedNode)\n } else {\n // above targetBlockElem\n targetNode.insertBefore(draggedNode)\n }\n } else {\n //\n targetNode.insertBefore(draggedNode)\n targetNode.remove()\n }\n\n /*\n if (pageY >= targetBlockElemTop + targetBlockElemHeight / 2) {\n targetNode.insertAfter(draggedNode)\n } else {\n targetNode.insertBefore(draggedNode)\n }*/\n setDraggableBlockElem(null)\n })\n\n return true\n }\n\n // register onDragover event listeners:\n document.addEventListener('dragover', onDragover)\n // register onDrop event listeners:\n document.addEventListener('drop', onDrop)\n\n return () => {\n document.removeEventListener('dragover', onDragover)\n document.removeEventListener('drop', onDrop)\n }\n }, [\n anchorElem,\n editor,\n lastTargetBlockElem,\n calculateDistanceFromScrollerElem,\n draggableBlockElem,\n ])\n\n function onDragStart(event: ReactDragEvent<HTMLDivElement>): void {\n const dataTransfer = event.dataTransfer\n if (!dataTransfer || !draggableBlockElem) {\n return\n }\n setDragImage(dataTransfer, draggableBlockElem)\n let nodeKey = ''\n editor.update(() => {\n const node = $getNearestNodeFromDOMNode(draggableBlockElem)\n if (node) {\n nodeKey = node.getKey()\n }\n })\n isDraggingBlockRef.current = true\n dataTransfer.setData(DRAG_DATA_FORMAT, nodeKey)\n }\n\n function onDragEnd(): void {\n isDraggingBlockRef.current = false\n hideTargetLine(targetLineRef.current, lastTargetBlockElem)\n }\n\n return createPortal(\n <React.Fragment>\n <div\n className=\"icon draggable-block-menu\"\n draggable\n onDragEnd={onDragEnd}\n onDragStart={onDragStart}\n ref={menuRef}\n >\n <div className={isEditable ? 'icon' : ''} />\n </div>\n <div className=\"draggable-block-target-line\" ref={targetLineRef} />\n <div className=\"debug-highlight\" ref={debugHighlightRef} />\n </React.Fragment>,\n anchorElem,\n )\n}\n\nexport function DraggableBlockPlugin({\n anchorElem = document.body,\n}: {\n anchorElem?: HTMLElement\n}): JSX.Element {\n const [editor] = useLexicalComposerContext()\n return useDraggableBlockMenu(editor, anchorElem, editor._editable)\n}\n"],"names":["lexicalComposerContextImport","useLexicalComposerContext","eventFiles","lexicalImport","$getNearestNodeFromDOMNode","$getNodeByKey","React","useCallback","useEffect","useRef","useState","createPortal","isHTMLElement","Point","getTopLevelNodeKeys","isOnHandleElement","setHandlePosition","getBoundingClientRectWithoutTransform","getNodeCloseToPoint","setTargetLine","SPACE","DRAGGABLE_BLOCK_MENU_CLASSNAME","DRAG_DATA_FORMAT","prevIndex","Infinity","getCurrentIndex","keysLength","Math","floor","setDragImage","dataTransfer","draggableBlockElem","transform","style","setTimeout","hideTargetLine","targetLineElem","lastTargetBlockElem","opacity","useDraggableBlockMenu","editor","anchorElem","isEditable","scrollerElem","parentElement","menuRef","targetLineRef","debugHighlightRef","isDraggingBlockRef","setDraggableBlockElem","setLastTargetBlockElem","calculateDistanceFromScrollerElem","pageX","pageY","target","horizontalBuffer","verticalBuffer","distanceFromScrollerElem","contains","bottom","left","right","top","getBoundingClientRect","adjustedTop","window","scrollY","adjustedBottom","onDocumentMouseMove","event","topLevelNodeKeys","blockElem","_draggableBlockElem","foundAtIndex","isFoundNodeEmptyParagraph","cache_treshold","horizontalOffset","point","x","y","startIndex","length","useEdgeAsDefault","document","addEventListener","removeEventListener","current","onDragover","isFileTransfer","targetBlockElem","fuzzy","verbose","preventDefault","onDrop","dragData","getData","update","draggedNode","targetNode","height","targetBlockElemHeight","targetBlockElemTop","mouseY","isBelow","insertAfter","insertBefore","remove","onDragStart","nodeKey","node","getKey","setData","onDragEnd","Fragment","div","className","draggable","ref","DraggableBlockPlugin","body","_editable"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA;AAIA,OAAOA,kCAAkC,2CAA0C;AACnF,MAAM,EAAEC,yBAAyB,EAAE,GAAGD;AAEtC,SAASE,UAAU,QAAQ,qBAAoB;AAC/C,OAAOC,mBAAmB,UAAS;AACnC,MAAM,EAAEC,0BAA0B,EAAEC,aAAa,EAAE,GAAGF;AACtD,YAAYG,WAAW,QAAO;AAC9B,SAASC,WAAW,EAAEC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAChE,SAASC,YAAY,QAAQ,YAAW;AAExC,SAASC,aAAa,QAAQ,0BAAyB;AACvD,SAASC,KAAK,QAAQ,0BAAyB;AAC/C,SAASC,mBAAmB,QAAQ,kCAAiC;AACrE,SAASC,iBAAiB,QAAQ,gCAA+B;AACjE,SAASC,iBAAiB,QAAQ,gCAA+B;AACjE,SAASC,qCAAqC,QAAQ,uCAAsC;AAC5F,SAASC,mBAAmB,QAAQ,2BAA0B;AAC9D,OAAO,eAAc;AACrB,SAASC,aAAa,QAAQ,qBAAoB;AAElD,MAAMC,QAAQ,CAAC;AACf,MAAMC,iCAAiC;AACvC,MAAMC,mBAAmB;AAEzB,IAAIC,YAAYC;AAEhB,SAASC,gBAAgBC,UAAkB;IACzC,IAAIA,eAAe,GAAG;QACpB,OAAOF;IACT;IACA,IAAID,aAAa,KAAKA,YAAYG,YAAY;QAC5C,OAAOH;IACT;IAEA,OAAOI,KAAKC,KAAK,CAACF,aAAa;AACjC;AAEA,SAASG,aAAaC,YAA0B,EAAEC,kBAA+B;IAC/E,MAAM,EAAEC,SAAS,EAAE,GAAGD,mBAAmBE,KAAK;IAE9C,2BAA2B;IAC3BH,aAAaD,YAAY,CAACE,oBAAoB,GAAG;IAEjDG,WAAW;QACTH,mBAAmBE,KAAK,CAACD,SAAS,GAAGA;IACvC;AACF;AAEA,SAASG,eACPC,cAAkC,EAClCC,mBAAuC;IAEvC,IAAID,gBAAgB;QAClBA,eAAeH,KAAK,CAACK,OAAO,GAAG;IACjC;IACA,IAAID,qBAAqB;QACvBA,oBAAoBJ,KAAK,CAACK,OAAO,GAAG;QACpCD,oBAAoBJ,KAAK,CAACD,SAAS,GAAG;IACtC,2CAA2C;IAC7C;AACF;AAEA,SAASO,sBACPC,MAAqB,EACrBC,UAAuB,EACvBC,UAAmB;IAEnB,MAAMC,eAAeF,WAAWG,aAAa;IAE7C,MAAMC,UAAUpC,OAAuB;IACvC,MAAMqC,gBAAgBrC,OAAuB;IAC7C,MAAMsC,oBAAoBtC,OAAuB;IACjD,MAAMuC,qBAAqBvC,OAAgB;IAC3C,MAAM,CAACsB,oBAAoBkB,sBAAsB,GAAGvC,SAA6B;IACjF,MAAM,CAAC2B,qBAAqBa,uBAAuB,GAAGxC,SAA6B;IAEnF,MAAMyC,oCAAoC5C,YACxC,CACE6C,OACAC,OACAC,QACAC,mBAA2B,EAAE,EAC7BC,iBAAyB,EAAE;QAE3B,IAAIC,2BAA2B;QAC/B,sFAAsF;QACtF,IAAId,gBAAgB,CAACA,aAAae,QAAQ,CAACJ,SAAS;YAClD,MAAM,EAAEK,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAEC,GAAG,EAAE,GAAGnB,aAAaoB,qBAAqB;YAEvE,MAAMC,cAAcF,MAAMG,OAAOC,OAAO;YACxC,MAAMC,iBAAiBR,SAASM,OAAOC,OAAO;YAE9C,IACEb,QAAQW,cAAcR,kBACtBH,QAAQc,iBAAiBX,kBACzBJ,QAAQQ,OAAOL,oBACfH,QAAQS,QAAQN,kBAChB;gBACAN,sBAAsB;gBACtB,OAAOQ;YACT;YAEA,qFAAqF;YACrF,uCAAuC;YACvC,IAAIL,QAAQQ,QAAQR,QAAQS,OAAO;gBACjCJ,2BAA2BL,QAAQQ,OAAOR,QAAQQ,OAAOR,QAAQS;YACnE;QACF;QACA,OAAOJ;IACT,GACA;QAACd;KAAa;IAGhBnC,UAAU;QACR;;KAEC,GACD,SAAS4D,oBAAoBC,KAAiB;YAC5C,MAAMf,SAASe,MAAMf,MAAM;YAC3B,IAAI,CAAC1C,cAAc0C,SAAS;gBAC1B;YACF;YAEA,MAAMG,2BAA2BN,kCAC/BkB,MAAMjB,KAAK,EACXiB,MAAMhB,KAAK,EACXC;YAGF,IAAIvC,kBAAkBuC,QAAQjC,iCAAiC;gBAC7D;YACF;YAEA,MAAMiD,mBAAmBxD,oBAAoB0B;YAC7C,MAAM,EACJ+B,WAAWC,mBAAmB,EAC9BC,YAAY,EACZC,yBAAyB,EAC1B,GAAGxD,oBAAoB;gBACtBuB;gBACAkC,gBAAgB;gBAChBnC;gBACAoC,kBAAkB,CAACnB;gBACnBoB,OAAO,IAAIhE,MAAMwD,MAAMS,CAAC,EAAET,MAAMU,CAAC;gBACjCC,YAAYvD,gBAAgB6C,iBAAiBW,MAAM;gBACnDC,kBAAkB;YACpB;YACA,qCAAqC;YACrC,gDAAgD;YAChD,oFAAoF;YACpF,GAAG;YACH3D,YAAYkD;YAEZ,IAAI,CAACD,uBAAuB,CAACE,2BAA2B;gBACtD;YACF;YAEAzB,sBAAsBuB;QACxB;QAEA,+FAA+F;QAC/F,4FAA4F;QAC5F,2EAA2E;QAC3EW,UAAUC,iBAAiB,aAAahB;QAExC,OAAO;YACLe,UAAUE,oBAAoB,aAAajB;QAC7C;IACF,GAAG;QAACzB;QAAcF;QAAYD;QAAQW;KAAkC;IAExE3C,UAAU;QACR,IAAIqC,QAAQyC,OAAO,EAAE;YACnBtE,kBAAkBe,oBAAoBc,QAAQyC,OAAO,EAAE7C,YAAYrB;QACrE;IACF,GAAG;QAACqB;QAAYV;KAAmB;IAEnCvB,UAAU;QACR,SAAS+E,WAAWlB,KAAgB;YAClC,IAAI,CAACrB,mBAAmBsC,OAAO,EAAE;gBAC/B,OAAO;YACT;YACA,MAAM,CAACE,eAAe,GAAGtF,WAAWmE;YACpC,IAAImB,gBAAgB;gBAClB,OAAO;YACT;YAEA,MAAM,EAAEnC,KAAK,EAAEC,MAAM,EAAE,GAAGe;YAC1B,IAAI,CAACzD,cAAc0C,SAAS;gBAC1B,OAAO;YACT;YAEA,MAAMG,2BAA2BN,kCAC/BkB,MAAMjB,KAAK,EACXiB,MAAMhB,KAAK,EACXC,QACA,KACA;YAGF,MAAMgB,mBAAmBxD,oBAAoB0B;YAE7C,MAAM,EACJ+B,WAAWkB,eAAe,EAC1BhB,YAAY,EACZC,yBAAyB,EAC1B,GAAGxD,oBAAoB;gBACtBuB;gBACAD;gBACAkD,OAAO;gBACPd,kBAAkB,CAACnB;gBACnBoB,OAAO,IAAIhE,MAAMwD,MAAMS,CAAC,EAAET,MAAMU,CAAC;gBACjCC,YAAYvD,gBAAgB6C,iBAAiBW,MAAM;gBACnDC,kBAAkB;gBAClBS,SAAS;YACX;YACApE,YAAYkD;YAEZ,MAAMrC,iBAAiBU,cAAcwC,OAAO;YAC5C,4CAA4C;YAC5C,IAAIG,oBAAoB,QAAQrD,mBAAmB,MAAM;gBACvD,OAAO;YACT;YAEA,IAAIL,uBAAuB0D,iBAAiB;gBAC1CtE,cACEC,OACAgB,gBACAqD,iBACApD,qBACAgB,OACAZ,YACA4B,OACAtB,mBACA2B;gBAGF,4DAA4D;gBAC5D,mEAAmE;gBACnE,uCAAuC;gBACvCL,MAAMuB,cAAc;YACtB,OAAO;gBACLzD,eAAeC,gBAAgBC;YACjC;YAEAa,uBAAuBuC;YAEvB,OAAO;QACT;QAEA,SAASI,OAAOxB,KAAgB;YAC9B,IAAI,CAACrB,mBAAmBsC,OAAO,EAAE;gBAC/B,OAAO;YACT;YACA,MAAM,CAACE,eAAe,GAAGtF,WAAWmE;YACpC,IAAImB,gBAAgB;gBAClB,OAAO;YACT;YACA,MAAM,EAAE1D,YAAY,EAAEuB,KAAK,EAAEC,MAAM,EAAE,GAAGe;YACxC,MAAMyB,WAAWhE,cAAciE,QAAQzE,qBAAqB;YAE5DkB,OAAOwD,MAAM,CAAC;gBACZ,MAAMC,cAAc5F,cAAcyF;gBAClC,IAAI,CAACG,aAAa;oBAChB,OAAO;gBACT;gBACA,IAAI,CAACrF,cAAc0C,SAAS;oBAC1B,OAAO;gBACT;gBACA,MAAMG,2BAA2BN,kCAC/BkB,MAAMjB,KAAK,EACXiB,MAAMhB,KAAK,EACXC,QACA,KACA;gBAGF,MAAM,EAAEiB,WAAWkB,eAAe,EAAEf,yBAAyB,EAAE,GAAGxD,oBAAoB;oBACpFuB;oBACAD;oBACAkD,OAAO;oBACPd,kBAAkB,CAACnB;oBACnBoB,OAAO,IAAIhE,MAAMwD,MAAMS,CAAC,EAAET,MAAMU,CAAC;oBACjCG,kBAAkB;gBACpB;gBAEA,IAAI,CAACO,iBAAiB;oBACpB,OAAO;gBACT;gBACA,MAAMS,aAAa9F,2BAA2BqF;gBAC9C,IAAI,CAACS,YAAY;oBACf,OAAO;gBACT;gBACA,IAAIA,eAAeD,aAAa;oBAC9B,OAAO;gBACT;gBAEA,MAAM,EAAEE,QAAQC,qBAAqB,EAAEtC,KAAKuC,kBAAkB,EAAE,GAC9DpF,sCAAsCwE;gBAExC,MAAMa,SAASjD;gBACf,MAAMkD,UAAUD,UAAUD,qBAAqBD,wBAAwB,IAAInC,OAAOC,OAAO;gBAEzF,IAAI,CAACQ,2BAA2B;oBAC9B,IAAI6B,SAAS;wBACX,wBAAwB;wBACxBL,WAAWM,WAAW,CAACP;oBACzB,OAAO;wBACL,wBAAwB;wBACxBC,WAAWO,YAAY,CAACR;oBAC1B;gBACF,OAAO;oBACL,EAAE;oBACFC,WAAWO,YAAY,CAACR;oBACxBC,WAAWQ,MAAM;gBACnB;gBAEA;;;;;SAKC,GACDzD,sBAAsB;YACxB;YAEA,OAAO;QACT;QAEA,uCAAuC;QACvCkC,SAASC,gBAAgB,CAAC,YAAYG;QACtC,mCAAmC;QACnCJ,SAASC,gBAAgB,CAAC,QAAQS;QAElC,OAAO;YACLV,SAASE,mBAAmB,CAAC,YAAYE;YACzCJ,SAASE,mBAAmB,CAAC,QAAQQ;QACvC;IACF,GAAG;QACDpD;QACAD;QACAH;QACAc;QACApB;KACD;IAED,SAAS4E,YAAYtC,KAAqC;QACxD,MAAMvC,eAAeuC,MAAMvC,YAAY;QACvC,IAAI,CAACA,gBAAgB,CAACC,oBAAoB;YACxC;QACF;QACAF,aAAaC,cAAcC;QAC3B,IAAI6E,UAAU;QACdpE,OAAOwD,MAAM,CAAC;YACZ,MAAMa,OAAOzG,2BAA2B2B;YACxC,IAAI8E,MAAM;gBACRD,UAAUC,KAAKC,MAAM;YACvB;QACF;QACA9D,mBAAmBsC,OAAO,GAAG;QAC7BxD,aAAaiF,OAAO,CAACzF,kBAAkBsF;IACzC;IAEA,SAASI;QACPhE,mBAAmBsC,OAAO,GAAG;QAC7BnD,eAAeW,cAAcwC,OAAO,EAAEjD;IACxC;IAEA,qBAAO1B,2BACL,oBAACL,MAAM2G,QAAQ,sBACb,oBAACC;QACCC,WAAU;QACVC,WAAAA;QACAJ,WAAWA;QACXL,aAAaA;QACbU,KAAKxE;qBAEL,oBAACqE;QAAIC,WAAWzE,aAAa,SAAS;uBAExC,oBAACwE;QAAIC,WAAU;QAA8BE,KAAKvE;sBAClD,oBAACoE;QAAIC,WAAU;QAAkBE,KAAKtE;SAExCN;AAEJ;AAEA,OAAO,SAAS6E,qBAAqB,EACnC7E,aAAa0C,SAASoC,IAAI,EAG3B;IACC,MAAM,CAAC/E,OAAO,GAAGvC;IACjB,OAAOsC,sBAAsBC,QAAQC,YAAYD,OAAOgF,SAAS;AACnE"}
1
+ {"version":3,"sources":["../../../../../../src/field/lexical/plugins/handles/DraggableBlockPlugin/index.tsx"],"sourcesContent":["'use client'\nimport type { LexicalEditor } from 'lexical'\nimport type { DragEvent as ReactDragEvent } from 'react'\n\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js'\nimport { eventFiles } from '@lexical/rich-text'\nimport { $getNearestNodeFromDOMNode, $getNodeByKey } from 'lexical'\nimport * as React from 'react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { isHTMLElement } from '../../../utils/guard.js'\nimport { Point } from '../../../utils/point.js'\nimport { getTopLevelNodeKeys } from '../utils/getTopLevelNodeKeys.js'\nimport { isOnHandleElement } from '../utils/isOnHandleElement.js'\nimport { setHandlePosition } from '../utils/setHandlePosition.js'\nimport { getBoundingClientRectWithoutTransform } from './getBoundingRectWithoutTransform.js'\nimport { getNodeCloseToPoint } from './getNodeCloseToPoint.js'\nimport './index.scss'\nimport { setTargetLine } from './setTargetLine.js'\n\nconst SPACE = -24\nconst DRAGGABLE_BLOCK_MENU_CLASSNAME = 'draggable-block-menu'\nconst DRAG_DATA_FORMAT = 'application/x-lexical-drag-block'\n\nlet prevIndex = Infinity\n\nfunction getCurrentIndex(keysLength: number): number {\n if (keysLength === 0) {\n return Infinity\n }\n if (prevIndex >= 0 && prevIndex < keysLength) {\n return prevIndex\n }\n\n return Math.floor(keysLength / 2)\n}\n\nfunction setDragImage(dataTransfer: DataTransfer, draggableBlockElem: HTMLElement) {\n const { transform } = draggableBlockElem.style\n\n // Remove dragImage borders\n dataTransfer.setDragImage(draggableBlockElem, 0, 0)\n\n setTimeout(() => {\n draggableBlockElem.style.transform = transform\n })\n}\n\nfunction hideTargetLine(\n targetLineElem: HTMLElement | null,\n lastTargetBlockElem: HTMLElement | null,\n) {\n if (targetLineElem) {\n targetLineElem.style.opacity = '0'\n }\n if (lastTargetBlockElem) {\n lastTargetBlockElem.style.opacity = '1'\n lastTargetBlockElem.style.transform = 'translate(0, 0)'\n //lastTargetBlockElem.style.border = 'none'\n }\n}\n\nfunction useDraggableBlockMenu(\n editor: LexicalEditor,\n anchorElem: HTMLElement,\n isEditable: boolean,\n): JSX.Element {\n const scrollerElem = anchorElem.parentElement\n\n const menuRef = useRef<HTMLDivElement>(null)\n const targetLineRef = useRef<HTMLDivElement>(null)\n const debugHighlightRef = useRef<HTMLDivElement>(null)\n const isDraggingBlockRef = useRef<boolean>(false)\n const [draggableBlockElem, setDraggableBlockElem] = useState<HTMLElement | null>(null)\n const [lastTargetBlockElem, setLastTargetBlockElem] = useState<HTMLElement | null>(null)\n\n const calculateDistanceFromScrollerElem = useCallback(\n (\n pageX: number,\n pageY: number,\n target: HTMLElement,\n horizontalBuffer: number = 50,\n verticalBuffer: number = 25,\n ): number => {\n let distanceFromScrollerElem = 0\n // Calculate distance between scrollerElem and target if target is not in scrollerElem\n if (scrollerElem && !scrollerElem.contains(target)) {\n const { bottom, left, right, top } = scrollerElem.getBoundingClientRect()\n\n const adjustedTop = top + window.scrollY\n const adjustedBottom = bottom + window.scrollY\n\n if (\n pageY < adjustedTop - verticalBuffer ||\n pageY > adjustedBottom + verticalBuffer ||\n pageX < left - horizontalBuffer ||\n pageX > right + horizontalBuffer\n ) {\n setDraggableBlockElem(null)\n return distanceFromScrollerElem\n }\n\n // This is used to allow the _draggableBlockElem to be found when the mouse is in the\n // buffer zone around the scrollerElem.\n if (pageX < left || pageX > right) {\n distanceFromScrollerElem = pageX < left ? pageX - left : pageX - right\n }\n }\n return distanceFromScrollerElem\n },\n [scrollerElem],\n )\n\n useEffect(() => {\n /**\n * Handles positioning of the drag handle\n */\n function onDocumentMouseMove(event: MouseEvent) {\n const target = event.target\n if (!isHTMLElement(target)) {\n return\n }\n\n const distanceFromScrollerElem = calculateDistanceFromScrollerElem(\n event.pageX,\n event.pageY,\n target,\n )\n\n if (isOnHandleElement(target, DRAGGABLE_BLOCK_MENU_CLASSNAME)) {\n return\n }\n\n const topLevelNodeKeys = getTopLevelNodeKeys(editor)\n const {\n blockElem: _draggableBlockElem,\n foundAtIndex,\n isFoundNodeEmptyParagraph,\n } = getNodeCloseToPoint({\n anchorElem,\n cache_treshold: 0,\n editor,\n horizontalOffset: -distanceFromScrollerElem,\n point: new Point(event.x, event.y),\n startIndex: getCurrentIndex(topLevelNodeKeys.length),\n useEdgeAsDefault: false,\n })\n //if (DEBUG && _draggableBlockElem) {\n //targetBlockElem.style.border = '3px solid red'\n // highlightElemOriginalPosition(debugHighlightRef, _draggableBlockElem, anchorElem)\n //}\n prevIndex = foundAtIndex\n\n if (!_draggableBlockElem && !isFoundNodeEmptyParagraph) {\n return\n }\n\n if (draggableBlockElem !== _draggableBlockElem) {\n setDraggableBlockElem(_draggableBlockElem)\n }\n }\n\n // Since the draggableBlockElem is outside the actual editor, we need to listen to the document\n // to be able to detect when the mouse is outside the editor and respect a buffer around the\n // the scrollerElem to avoid the draggableBlockElem disappearing too early.\n document?.addEventListener('mousemove', onDocumentMouseMove)\n\n return () => {\n document?.removeEventListener('mousemove', onDocumentMouseMove)\n }\n }, [scrollerElem, anchorElem, editor, calculateDistanceFromScrollerElem, draggableBlockElem])\n\n useEffect(() => {\n if (menuRef.current) {\n setHandlePosition(draggableBlockElem, menuRef.current, anchorElem, SPACE)\n }\n }, [anchorElem, draggableBlockElem])\n\n useEffect(() => {\n function onDragover(event: DragEvent): boolean {\n if (!isDraggingBlockRef.current) {\n return false\n }\n const [isFileTransfer] = eventFiles(event)\n if (isFileTransfer) {\n return false\n }\n\n const { pageY, target } = event\n if (!isHTMLElement(target)) {\n return false\n }\n\n const distanceFromScrollerElem = calculateDistanceFromScrollerElem(\n event.pageX,\n event.pageY,\n target,\n 100,\n 50,\n )\n\n const topLevelNodeKeys = getTopLevelNodeKeys(editor)\n\n const {\n blockElem: targetBlockElem,\n foundAtIndex,\n isFoundNodeEmptyParagraph,\n } = getNodeCloseToPoint({\n anchorElem,\n editor,\n fuzzy: true,\n horizontalOffset: -distanceFromScrollerElem,\n point: new Point(event.x, event.y),\n startIndex: getCurrentIndex(topLevelNodeKeys.length),\n useEdgeAsDefault: true,\n verbose: true,\n })\n prevIndex = foundAtIndex\n\n const targetLineElem = targetLineRef.current\n // targetBlockElem === null shouldn't happen\n if (targetBlockElem === null || targetLineElem === null) {\n return false\n }\n\n if (draggableBlockElem !== targetBlockElem) {\n setTargetLine(\n SPACE,\n targetLineElem,\n targetBlockElem,\n lastTargetBlockElem,\n pageY,\n anchorElem,\n event,\n debugHighlightRef,\n isFoundNodeEmptyParagraph,\n )\n\n // Prevent default event to be able to trigger onDrop events\n // Calling preventDefault() adds the green plus icon to the cursor,\n // indicating that the drop is allowed.\n event.preventDefault()\n } else {\n hideTargetLine(targetLineElem, lastTargetBlockElem)\n }\n\n setLastTargetBlockElem(targetBlockElem)\n\n return true\n }\n\n function onDrop(event: DragEvent): boolean {\n if (!isDraggingBlockRef.current) {\n return false\n }\n const [isFileTransfer] = eventFiles(event)\n if (isFileTransfer) {\n return false\n }\n const { dataTransfer, pageY, target } = event\n const dragData = dataTransfer?.getData(DRAG_DATA_FORMAT) || ''\n\n editor.update(() => {\n const draggedNode = $getNodeByKey(dragData)\n if (!draggedNode) {\n return false\n }\n if (!isHTMLElement(target)) {\n return false\n }\n const distanceFromScrollerElem = calculateDistanceFromScrollerElem(\n event.pageX,\n event.pageY,\n target,\n 100,\n 50,\n )\n\n const { blockElem: targetBlockElem, isFoundNodeEmptyParagraph } = getNodeCloseToPoint({\n anchorElem,\n editor,\n fuzzy: true,\n horizontalOffset: -distanceFromScrollerElem,\n point: new Point(event.x, event.y),\n useEdgeAsDefault: true,\n })\n\n if (!targetBlockElem) {\n return false\n }\n const targetNode = $getNearestNodeFromDOMNode(targetBlockElem)\n if (!targetNode) {\n return false\n }\n if (targetNode === draggedNode) {\n return true\n }\n\n const { height: targetBlockElemHeight, top: targetBlockElemTop } =\n getBoundingClientRectWithoutTransform(targetBlockElem)\n\n const mouseY = pageY\n const isBelow = mouseY >= targetBlockElemTop + targetBlockElemHeight / 2 + window.scrollY\n\n if (!isFoundNodeEmptyParagraph) {\n if (isBelow) {\n // below targetBlockElem\n targetNode.insertAfter(draggedNode)\n } else {\n // above targetBlockElem\n targetNode.insertBefore(draggedNode)\n }\n } else {\n //\n targetNode.insertBefore(draggedNode)\n targetNode.remove()\n }\n\n /*\n if (pageY >= targetBlockElemTop + targetBlockElemHeight / 2) {\n targetNode.insertAfter(draggedNode)\n } else {\n targetNode.insertBefore(draggedNode)\n }*/\n if (draggableBlockElem !== null) {\n setDraggableBlockElem(null)\n }\n })\n\n return true\n }\n\n // register onDragover event listeners:\n document.addEventListener('dragover', onDragover)\n // register onDrop event listeners:\n document.addEventListener('drop', onDrop)\n\n return () => {\n document.removeEventListener('dragover', onDragover)\n document.removeEventListener('drop', onDrop)\n }\n }, [\n anchorElem,\n editor,\n lastTargetBlockElem,\n calculateDistanceFromScrollerElem,\n draggableBlockElem,\n ])\n\n function onDragStart(event: ReactDragEvent<HTMLDivElement>): void {\n const dataTransfer = event.dataTransfer\n if (!dataTransfer || !draggableBlockElem) {\n return\n }\n setDragImage(dataTransfer, draggableBlockElem)\n let nodeKey = ''\n editor.update(() => {\n const node = $getNearestNodeFromDOMNode(draggableBlockElem)\n if (node) {\n nodeKey = node.getKey()\n }\n })\n isDraggingBlockRef.current = true\n dataTransfer.setData(DRAG_DATA_FORMAT, nodeKey)\n }\n\n function onDragEnd(): void {\n isDraggingBlockRef.current = false\n hideTargetLine(targetLineRef.current, lastTargetBlockElem)\n }\n\n return createPortal(\n <React.Fragment>\n <div\n className=\"icon draggable-block-menu\"\n draggable\n onDragEnd={onDragEnd}\n onDragStart={onDragStart}\n ref={menuRef}\n >\n <div className={isEditable ? 'icon' : ''} />\n </div>\n <div className=\"draggable-block-target-line\" ref={targetLineRef} />\n <div className=\"debug-highlight\" ref={debugHighlightRef} />\n </React.Fragment>,\n anchorElem,\n )\n}\n\nexport function DraggableBlockPlugin({\n anchorElem = document.body,\n}: {\n anchorElem?: HTMLElement\n}): JSX.Element {\n const [editor] = useLexicalComposerContext()\n return useDraggableBlockMenu(editor, anchorElem, editor._editable)\n}\n"],"names":["useLexicalComposerContext","eventFiles","$getNearestNodeFromDOMNode","$getNodeByKey","React","useCallback","useEffect","useRef","useState","createPortal","isHTMLElement","Point","getTopLevelNodeKeys","isOnHandleElement","setHandlePosition","getBoundingClientRectWithoutTransform","getNodeCloseToPoint","setTargetLine","SPACE","DRAGGABLE_BLOCK_MENU_CLASSNAME","DRAG_DATA_FORMAT","prevIndex","Infinity","getCurrentIndex","keysLength","Math","floor","setDragImage","dataTransfer","draggableBlockElem","transform","style","setTimeout","hideTargetLine","targetLineElem","lastTargetBlockElem","opacity","useDraggableBlockMenu","editor","anchorElem","isEditable","scrollerElem","parentElement","menuRef","targetLineRef","debugHighlightRef","isDraggingBlockRef","setDraggableBlockElem","setLastTargetBlockElem","calculateDistanceFromScrollerElem","pageX","pageY","target","horizontalBuffer","verticalBuffer","distanceFromScrollerElem","contains","bottom","left","right","top","getBoundingClientRect","adjustedTop","window","scrollY","adjustedBottom","onDocumentMouseMove","event","topLevelNodeKeys","blockElem","_draggableBlockElem","foundAtIndex","isFoundNodeEmptyParagraph","cache_treshold","horizontalOffset","point","x","y","startIndex","length","useEdgeAsDefault","document","addEventListener","removeEventListener","current","onDragover","isFileTransfer","targetBlockElem","fuzzy","verbose","preventDefault","onDrop","dragData","getData","update","draggedNode","targetNode","height","targetBlockElemHeight","targetBlockElemTop","mouseY","isBelow","insertAfter","insertBefore","remove","onDragStart","nodeKey","node","getKey","setData","onDragEnd","Fragment","div","className","draggable","ref","DraggableBlockPlugin","body","_editable"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * From ChatGPT, only that verified it works for HR elements.
3
+ *
4
+ * HTML Elements can have CSS lineHeight applied to them, but it doesn't always affect the visual layout.
5
+ * This function checks if the line-height property has an effect on the element's layout.
6
+ * @param htmlElem
7
+ */
8
+ export declare function doesLineHeightAffectElement(htmlElem: HTMLElement): boolean;
9
+ //# sourceMappingURL=doesLineHeightAffectElement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doesLineHeightAffectElement.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/utils/doesLineHeightAffectElement.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,WAAW,WA2BhE"}
@@ -0,0 +1,35 @@
1
+ const replacedElements = [
2
+ 'IMG',
3
+ 'INPUT',
4
+ 'TEXTAREA',
5
+ 'SELECT',
6
+ 'BUTTON',
7
+ 'VIDEO',
8
+ 'OBJECT',
9
+ 'EMBED',
10
+ 'IFRAME',
11
+ 'HR'
12
+ ];
13
+ /**
14
+ * From ChatGPT, only that verified it works for HR elements.
15
+ *
16
+ * HTML Elements can have CSS lineHeight applied to them, but it doesn't always affect the visual layout.
17
+ * This function checks if the line-height property has an effect on the element's layout.
18
+ * @param htmlElem
19
+ */ export function doesLineHeightAffectElement(htmlElem) {
20
+ if (!htmlElem) return false;
21
+ // Check for replaced elements, elements that typically don't support line-height adjustments,
22
+ // and elements without visible content
23
+ if (replacedElements.includes(htmlElem.tagName) || htmlElem.offsetHeight === 0 || htmlElem.offsetWidth === 0) {
24
+ return false;
25
+ }
26
+ // Check for specific CSS properties that negate line-height's visual effects
27
+ const style = window.getComputedStyle(htmlElem);
28
+ if (style.display === 'table-cell' || style.position === 'absolute' || style.visibility === 'hidden' || style.opacity === '0') {
29
+ return false;
30
+ }
31
+ // This is a basic check, and there can be more complex scenarios where line-height doesn't have an effect.
32
+ return true;
33
+ }
34
+
35
+ //# sourceMappingURL=doesLineHeightAffectElement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/field/lexical/plugins/handles/utils/doesLineHeightAffectElement.ts"],"sourcesContent":["const replacedElements = [\n 'IMG',\n 'INPUT',\n 'TEXTAREA',\n 'SELECT',\n 'BUTTON',\n 'VIDEO',\n 'OBJECT',\n 'EMBED',\n 'IFRAME',\n 'HR',\n]\n\n/**\n * From ChatGPT, only that verified it works for HR elements.\n *\n * HTML Elements can have CSS lineHeight applied to them, but it doesn't always affect the visual layout.\n * This function checks if the line-height property has an effect on the element's layout.\n * @param htmlElem\n */\nexport function doesLineHeightAffectElement(htmlElem: HTMLElement) {\n if (!htmlElem) return false\n\n // Check for replaced elements, elements that typically don't support line-height adjustments,\n // and elements without visible content\n\n if (\n replacedElements.includes(htmlElem.tagName) ||\n htmlElem.offsetHeight === 0 ||\n htmlElem.offsetWidth === 0\n ) {\n return false\n }\n\n // Check for specific CSS properties that negate line-height's visual effects\n const style = window.getComputedStyle(htmlElem)\n if (\n style.display === 'table-cell' ||\n style.position === 'absolute' ||\n style.visibility === 'hidden' ||\n style.opacity === '0'\n ) {\n return false\n }\n\n // This is a basic check, and there can be more complex scenarios where line-height doesn't have an effect.\n return true\n}\n"],"names":["replacedElements","doesLineHeightAffectElement","htmlElem","includes","tagName","offsetHeight","offsetWidth","style","window","getComputedStyle","display","position","visibility","opacity"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,MAAMA,mBAAmB;IACvB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED;;;;;;CAMC,GACD,OAAO,SAASC,4BAA4BC,QAAqB;IAC/D,IAAI,CAACA,UAAU,OAAO;IAEtB,8FAA8F;IAC9F,uCAAuC;IAEvC,IACEF,iBAAiBG,QAAQ,CAACD,SAASE,OAAO,KAC1CF,SAASG,YAAY,KAAK,KAC1BH,SAASI,WAAW,KAAK,GACzB;QACA,OAAO;IACT;IAEA,6EAA6E;IAC7E,MAAMC,QAAQC,OAAOC,gBAAgB,CAACP;IACtC,IACEK,MAAMG,OAAO,KAAK,gBAClBH,MAAMI,QAAQ,KAAK,cACnBJ,MAAMK,UAAU,KAAK,YACrBL,MAAMM,OAAO,KAAK,KAClB;QACA,OAAO;IACT;IAEA,2GAA2G;IAC3G,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"getTopLevelNodeKeys.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/utils/getTopLevelNodeKeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAK5C,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CAEnE"}
1
+ {"version":3,"file":"getTopLevelNodeKeys.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/utils/getTopLevelNodeKeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAI5C,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CAEnE"}
@@ -1,5 +1,4 @@
1
- import lexicalImport from 'lexical';
2
- const { $getRoot } = lexicalImport;
1
+ import { $getRoot } from 'lexical';
3
2
  export function getTopLevelNodeKeys(editor) {
4
3
  return editor.getEditorState().read(()=>$getRoot().getChildrenKeys());
5
4
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/field/lexical/plugins/handles/utils/getTopLevelNodeKeys.ts"],"sourcesContent":["import type { LexicalEditor } from 'lexical'\n\nimport lexicalImport from 'lexical'\nconst { $getRoot } = lexicalImport\n\nexport function getTopLevelNodeKeys(editor: LexicalEditor): string[] {\n return editor.getEditorState().read(() => $getRoot().getChildrenKeys())\n}\n"],"names":["lexicalImport","$getRoot","getTopLevelNodeKeys","editor","getEditorState","read","getChildrenKeys"],"rangeMappings":";;;;","mappings":"AAEA,OAAOA,mBAAmB,UAAS;AACnC,MAAM,EAAEC,QAAQ,EAAE,GAAGD;AAErB,OAAO,SAASE,oBAAoBC,MAAqB;IACvD,OAAOA,OAAOC,cAAc,GAAGC,IAAI,CAAC,IAAMJ,WAAWK,eAAe;AACtE"}
1
+ {"version":3,"sources":["../../../../../../src/field/lexical/plugins/handles/utils/getTopLevelNodeKeys.ts"],"sourcesContent":["import type { LexicalEditor } from 'lexical'\n\nimport { $getRoot } from 'lexical'\n\nexport function getTopLevelNodeKeys(editor: LexicalEditor): string[] {\n return editor.getEditorState().read(() => $getRoot().getChildrenKeys())\n}\n"],"names":["$getRoot","getTopLevelNodeKeys","editor","getEditorState","read","getChildrenKeys"],"rangeMappings":";;;","mappings":"AAEA,SAASA,QAAQ,QAAQ,UAAS;AAElC,OAAO,SAASC,oBAAoBC,MAAqB;IACvD,OAAOA,OAAOC,cAAc,GAAGC,IAAI,CAAC,IAAMJ,WAAWK,eAAe;AACtE"}
@@ -1,2 +1,2 @@
1
- export declare function setHandlePosition(targetElem: HTMLElement | null, floatingElem: HTMLElement, anchorElem: HTMLElement, leftOffset?: number): void;
1
+ export declare function setHandlePosition(targetElem: HTMLElement | null, handleElem: HTMLElement, anchorElem: HTMLElement, leftOffset?: number): void;
2
2
  //# sourceMappingURL=setHandlePosition.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"setHandlePosition.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/utils/setHandlePosition.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,WAAW,GAAG,IAAI,EAC9B,YAAY,EAAE,WAAW,EACzB,UAAU,EAAE,WAAW,EACvB,UAAU,GAAE,MAAU,QAsBvB"}
1
+ {"version":3,"file":"setHandlePosition.d.ts","sourceRoot":"","sources":["../../../../../../src/field/lexical/plugins/handles/utils/setHandlePosition.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,WAAW,GAAG,IAAI,EAC9B,UAAU,EAAE,WAAW,EACvB,UAAU,EAAE,WAAW,EACvB,UAAU,GAAE,MAAU,QAkCvB"}
@@ -1,17 +1,27 @@
1
- export function setHandlePosition(targetElem, floatingElem, anchorElem, leftOffset = 0) {
1
+ import { doesLineHeightAffectElement } from './doesLineHeightAffectElement.js';
2
+ export function setHandlePosition(targetElem, handleElem, anchorElem, leftOffset = 0) {
2
3
  if (!targetElem) {
3
- floatingElem.style.opacity = '0';
4
- floatingElem.style.transform = 'translate(-10000px, -10000px)';
4
+ handleElem.style.opacity = '0';
5
+ handleElem.style.transform = 'translate(-10000px, -10000px)';
5
6
  return;
6
7
  }
7
8
  const targetRect = targetElem.getBoundingClientRect();
8
9
  const targetStyle = window.getComputedStyle(targetElem);
9
- const floatingElemRect = floatingElem.getBoundingClientRect();
10
+ const floatingElemRect = handleElem.getBoundingClientRect();
10
11
  const anchorElementRect = anchorElem.getBoundingClientRect();
11
- const top = targetRect.top + (parseInt(targetStyle.lineHeight, 10) - floatingElemRect.height) / 2 - anchorElementRect.top;
12
+ let top;
13
+ const shouldDisplayHandleInCenter = targetRect.height < 60;
14
+ if (!shouldDisplayHandleInCenter) {
15
+ // No need to let line height affect the re-positioning of the floating element if line height has no
16
+ // visual effect on the element. Otherwise, the floating element will be positioned incorrectly.
17
+ const actualLineHeight = doesLineHeightAffectElement(targetElem) ? parseInt(targetStyle.lineHeight, 10) : 0;
18
+ top = targetRect.top + (actualLineHeight - floatingElemRect.height) / 2 - anchorElementRect.top;
19
+ } else {
20
+ top = targetRect.top - floatingElemRect.height / 2 - anchorElementRect.top + targetRect.height / 2;
21
+ }
12
22
  const left = leftOffset;
13
- floatingElem.style.opacity = '1';
14
- floatingElem.style.transform = `translate(${left}px, ${top}px)`;
23
+ handleElem.style.opacity = '1';
24
+ handleElem.style.transform = `translate(${left}px, ${top}px)`;
15
25
  }
16
26
 
17
27
  //# sourceMappingURL=setHandlePosition.js.map