@jackuait/blok 0.4.1-beta.1 → 0.4.1-beta.12

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 (403) hide show
  1. package/README.md +138 -17
  2. package/codemod/README.md +45 -7
  3. package/codemod/migrate-editorjs-to-blok.js +960 -92
  4. package/codemod/test.js +780 -77
  5. package/dist/blok.mjs +5 -2
  6. package/dist/chunks/blok-BU6NwVkN.mjs +13239 -0
  7. package/dist/chunks/i18next-CugVlwWp.mjs +1292 -0
  8. package/dist/chunks/i18next-loader-D8GzSwio.mjs +43 -0
  9. package/dist/{index-CEXLTV6f.mjs → chunks/index-C5e_WLFg.mjs} +2 -2
  10. package/dist/chunks/inline-tool-convert-CLUxkCe_.mjs +1990 -0
  11. package/dist/chunks/messages-0tDXLuyH.mjs +48 -0
  12. package/dist/chunks/messages-2_xedlYw.mjs +48 -0
  13. package/dist/chunks/messages-AHESHJm_.mjs +48 -0
  14. package/dist/chunks/messages-B5hdXZwA.mjs +48 -0
  15. package/dist/chunks/messages-B5jGUnOy.mjs +48 -0
  16. package/dist/chunks/messages-B5puUm7R.mjs +48 -0
  17. package/dist/chunks/messages-B66ZSDCJ.mjs +48 -0
  18. package/dist/chunks/messages-B9Oba7sq.mjs +48 -0
  19. package/dist/chunks/messages-BA0rcTCY.mjs +48 -0
  20. package/dist/chunks/messages-BBJgd5jG.mjs +48 -0
  21. package/dist/chunks/messages-BPqWKx5Z.mjs +48 -0
  22. package/dist/chunks/messages-Bdv-IkfG.mjs +48 -0
  23. package/dist/chunks/messages-BeUhMpsr.mjs +48 -0
  24. package/dist/chunks/messages-Bf6Y3_GI.mjs +48 -0
  25. package/dist/chunks/messages-BiExzWJv.mjs +48 -0
  26. package/dist/chunks/messages-BlpqL8vG.mjs +48 -0
  27. package/dist/chunks/messages-BmKCChWZ.mjs +48 -0
  28. package/dist/chunks/messages-Bn253WWC.mjs +48 -0
  29. package/dist/chunks/messages-BrJHUxQL.mjs +48 -0
  30. package/dist/chunks/messages-C5b7hr_E.mjs +48 -0
  31. package/dist/chunks/messages-C7I_AVH2.mjs +48 -0
  32. package/dist/chunks/messages-CJoBtXU6.mjs +48 -0
  33. package/dist/chunks/messages-CQj2JU2j.mjs +48 -0
  34. package/dist/chunks/messages-CUZ1x1QD.mjs +48 -0
  35. package/dist/chunks/messages-CUy1vn-b.mjs +48 -0
  36. package/dist/chunks/messages-CVeWVKsV.mjs +48 -0
  37. package/dist/chunks/messages-CXHd9SUK.mjs +48 -0
  38. package/dist/chunks/messages-CbMyJSzS.mjs +48 -0
  39. package/dist/chunks/messages-CbhuIWRJ.mjs +48 -0
  40. package/dist/chunks/messages-CeCjVKMW.mjs +48 -0
  41. package/dist/chunks/messages-Cj-t1bdy.mjs +48 -0
  42. package/dist/chunks/messages-CkFT2gle.mjs +48 -0
  43. package/dist/chunks/messages-Cm9aLHeX.mjs +48 -0
  44. package/dist/chunks/messages-CnvW8Slp.mjs +48 -0
  45. package/dist/chunks/messages-Cr-RJ7YB.mjs +48 -0
  46. package/dist/chunks/messages-CrsJ1TEJ.mjs +48 -0
  47. package/dist/chunks/messages-Cu08aLS3.mjs +48 -0
  48. package/dist/chunks/messages-CvaqJFN-.mjs +48 -0
  49. package/dist/chunks/messages-CyDU5lz9.mjs +48 -0
  50. package/dist/chunks/messages-CySyfkMU.mjs +48 -0
  51. package/dist/chunks/messages-Cyi2AMmz.mjs +48 -0
  52. package/dist/chunks/messages-D00OjS2n.mjs +48 -0
  53. package/dist/chunks/messages-DDLgIPDF.mjs +48 -0
  54. package/dist/chunks/messages-DMQIHGRj.mjs +48 -0
  55. package/dist/chunks/messages-DOlC_Tty.mjs +48 -0
  56. package/dist/chunks/messages-DV6shA9b.mjs +48 -0
  57. package/dist/chunks/messages-DY94ykcE.mjs +48 -0
  58. package/dist/chunks/messages-DbVquYKN.mjs +48 -0
  59. package/dist/chunks/messages-DcKOuncK.mjs +48 -0
  60. package/dist/chunks/messages-Dg92dXZ5.mjs +48 -0
  61. package/dist/chunks/messages-DnbbyJT3.mjs +48 -0
  62. package/dist/chunks/messages-DteYq0rv.mjs +48 -0
  63. package/dist/chunks/messages-GC2PhgV3.mjs +48 -0
  64. package/dist/chunks/messages-JGsXAReJ.mjs +48 -0
  65. package/dist/chunks/messages-JZUhXTuV.mjs +48 -0
  66. package/dist/chunks/messages-LvFKBBPa.mjs +48 -0
  67. package/dist/chunks/messages-NP1myMGI.mjs +48 -0
  68. package/dist/chunks/messages-Q4kc_ZtL.mjs +48 -0
  69. package/dist/chunks/messages-RvMHb2Ht.mjs +48 -0
  70. package/dist/chunks/messages-ftMcCEuO.mjs +48 -0
  71. package/dist/chunks/messages-o24dK6CU.mjs +48 -0
  72. package/dist/chunks/messages-pA5TvcAj.mjs +48 -0
  73. package/dist/chunks/messages-rRSHQDCX.mjs +48 -0
  74. package/dist/chunks/messages-srxrv8Yh.mjs +48 -0
  75. package/dist/chunks/messages-wdqp4610.mjs +48 -0
  76. package/dist/chunks/messages-zS1AXZ0y.mjs +48 -0
  77. package/dist/chunks/messages-zSzDzXej.mjs +48 -0
  78. package/dist/full.mjs +50 -0
  79. package/dist/locales.mjs +228 -0
  80. package/dist/messages-0tDXLuyH.mjs +48 -0
  81. package/dist/messages-2_xedlYw.mjs +48 -0
  82. package/dist/messages-AHESHJm_.mjs +48 -0
  83. package/dist/messages-B5hdXZwA.mjs +48 -0
  84. package/dist/messages-B5jGUnOy.mjs +48 -0
  85. package/dist/messages-B5puUm7R.mjs +48 -0
  86. package/dist/messages-B66ZSDCJ.mjs +48 -0
  87. package/dist/messages-B9Oba7sq.mjs +48 -0
  88. package/dist/messages-BA0rcTCY.mjs +48 -0
  89. package/dist/messages-BBJgd5jG.mjs +48 -0
  90. package/dist/messages-BPqWKx5Z.mjs +48 -0
  91. package/dist/messages-Bdv-IkfG.mjs +48 -0
  92. package/dist/messages-BeUhMpsr.mjs +48 -0
  93. package/dist/messages-Bf6Y3_GI.mjs +48 -0
  94. package/dist/messages-BiExzWJv.mjs +48 -0
  95. package/dist/messages-BlpqL8vG.mjs +48 -0
  96. package/dist/messages-BmKCChWZ.mjs +48 -0
  97. package/dist/messages-Bn253WWC.mjs +48 -0
  98. package/dist/messages-BrJHUxQL.mjs +48 -0
  99. package/dist/messages-C5b7hr_E.mjs +48 -0
  100. package/dist/messages-C7I_AVH2.mjs +48 -0
  101. package/dist/messages-CJoBtXU6.mjs +48 -0
  102. package/dist/messages-CQj2JU2j.mjs +48 -0
  103. package/dist/messages-CUZ1x1QD.mjs +48 -0
  104. package/dist/messages-CUy1vn-b.mjs +48 -0
  105. package/dist/messages-CVeWVKsV.mjs +48 -0
  106. package/dist/messages-CXHd9SUK.mjs +48 -0
  107. package/dist/messages-CbMyJSzS.mjs +48 -0
  108. package/dist/messages-CbhuIWRJ.mjs +48 -0
  109. package/dist/messages-CeCjVKMW.mjs +48 -0
  110. package/dist/messages-Cj-t1bdy.mjs +48 -0
  111. package/dist/messages-CkFT2gle.mjs +48 -0
  112. package/dist/messages-Cm9aLHeX.mjs +48 -0
  113. package/dist/messages-CnvW8Slp.mjs +48 -0
  114. package/dist/messages-Cr-RJ7YB.mjs +48 -0
  115. package/dist/messages-CrsJ1TEJ.mjs +48 -0
  116. package/dist/messages-Cu08aLS3.mjs +48 -0
  117. package/dist/messages-CvaqJFN-.mjs +48 -0
  118. package/dist/messages-CyDU5lz9.mjs +48 -0
  119. package/dist/messages-CySyfkMU.mjs +48 -0
  120. package/dist/messages-Cyi2AMmz.mjs +48 -0
  121. package/dist/messages-D00OjS2n.mjs +48 -0
  122. package/dist/messages-DDLgIPDF.mjs +48 -0
  123. package/dist/messages-DMQIHGRj.mjs +48 -0
  124. package/dist/messages-DOlC_Tty.mjs +48 -0
  125. package/dist/messages-DV6shA9b.mjs +48 -0
  126. package/dist/messages-DY94ykcE.mjs +48 -0
  127. package/dist/messages-DbVquYKN.mjs +48 -0
  128. package/dist/messages-DcKOuncK.mjs +48 -0
  129. package/dist/messages-Dg92dXZ5.mjs +48 -0
  130. package/dist/messages-DnbbyJT3.mjs +48 -0
  131. package/dist/messages-DteYq0rv.mjs +48 -0
  132. package/dist/messages-GC2PhgV3.mjs +48 -0
  133. package/dist/messages-JGsXAReJ.mjs +48 -0
  134. package/dist/messages-JZUhXTuV.mjs +48 -0
  135. package/dist/messages-LvFKBBPa.mjs +48 -0
  136. package/dist/messages-NP1myMGI.mjs +48 -0
  137. package/dist/messages-Q4kc_ZtL.mjs +48 -0
  138. package/dist/messages-RvMHb2Ht.mjs +48 -0
  139. package/dist/messages-ftMcCEuO.mjs +48 -0
  140. package/dist/messages-o24dK6CU.mjs +48 -0
  141. package/dist/messages-pA5TvcAj.mjs +48 -0
  142. package/dist/messages-rRSHQDCX.mjs +48 -0
  143. package/dist/messages-srxrv8Yh.mjs +48 -0
  144. package/dist/messages-wdqp4610.mjs +48 -0
  145. package/dist/messages-zS1AXZ0y.mjs +48 -0
  146. package/dist/messages-zSzDzXej.mjs +48 -0
  147. package/dist/tools.mjs +3126 -0
  148. package/dist/vendor.LICENSE.txt +26 -225
  149. package/package.json +63 -24
  150. package/src/blok.ts +267 -0
  151. package/src/components/__module.ts +139 -0
  152. package/src/components/block/api.ts +155 -0
  153. package/src/components/block/index.ts +1428 -0
  154. package/src/components/block-tunes/block-tune-delete.ts +51 -0
  155. package/src/components/blocks.ts +352 -0
  156. package/src/components/constants/data-attributes.ts +344 -0
  157. package/src/components/constants.ts +76 -0
  158. package/src/components/core.ts +392 -0
  159. package/src/components/dom.ts +773 -0
  160. package/src/components/domIterator.ts +189 -0
  161. package/src/components/errors/critical.ts +5 -0
  162. package/src/components/events/BlockChanged.ts +16 -0
  163. package/src/components/events/BlockHovered.ts +21 -0
  164. package/src/components/events/BlockSettingsClosed.ts +12 -0
  165. package/src/components/events/BlockSettingsOpened.ts +12 -0
  166. package/src/components/events/BlokMobileLayoutToggled.ts +15 -0
  167. package/src/components/events/FakeCursorAboutToBeToggled.ts +17 -0
  168. package/src/components/events/FakeCursorHaveBeenSet.ts +17 -0
  169. package/src/components/events/HistoryStateChanged.ts +19 -0
  170. package/src/components/events/RedactorDomChanged.ts +14 -0
  171. package/src/components/events/index.ts +46 -0
  172. package/src/components/flipper.ts +497 -0
  173. package/src/components/i18n/i18next-loader.ts +84 -0
  174. package/src/components/i18n/lightweight-i18n.ts +86 -0
  175. package/src/components/i18n/locales/TRANSLATION_GUIDELINES.md +113 -0
  176. package/src/components/i18n/locales/am/messages.json +45 -0
  177. package/src/components/i18n/locales/ar/messages.json +45 -0
  178. package/src/components/i18n/locales/az/messages.json +45 -0
  179. package/src/components/i18n/locales/bg/messages.json +45 -0
  180. package/src/components/i18n/locales/bn/messages.json +45 -0
  181. package/src/components/i18n/locales/bs/messages.json +45 -0
  182. package/src/components/i18n/locales/cs/messages.json +45 -0
  183. package/src/components/i18n/locales/da/messages.json +45 -0
  184. package/src/components/i18n/locales/de/messages.json +45 -0
  185. package/src/components/i18n/locales/dv/messages.json +45 -0
  186. package/src/components/i18n/locales/el/messages.json +45 -0
  187. package/src/components/i18n/locales/en/messages.json +45 -0
  188. package/src/components/i18n/locales/es/messages.json +45 -0
  189. package/src/components/i18n/locales/et/messages.json +45 -0
  190. package/src/components/i18n/locales/fa/messages.json +45 -0
  191. package/src/components/i18n/locales/fi/messages.json +45 -0
  192. package/src/components/i18n/locales/fil/messages.json +45 -0
  193. package/src/components/i18n/locales/fr/messages.json +45 -0
  194. package/src/components/i18n/locales/gu/messages.json +45 -0
  195. package/src/components/i18n/locales/he/messages.json +45 -0
  196. package/src/components/i18n/locales/hi/messages.json +45 -0
  197. package/src/components/i18n/locales/hr/messages.json +45 -0
  198. package/src/components/i18n/locales/hu/messages.json +45 -0
  199. package/src/components/i18n/locales/hy/messages.json +45 -0
  200. package/src/components/i18n/locales/id/messages.json +45 -0
  201. package/src/components/i18n/locales/index.ts +231 -0
  202. package/src/components/i18n/locales/it/messages.json +45 -0
  203. package/src/components/i18n/locales/ja/messages.json +45 -0
  204. package/src/components/i18n/locales/ka/messages.json +45 -0
  205. package/src/components/i18n/locales/km/messages.json +45 -0
  206. package/src/components/i18n/locales/kn/messages.json +45 -0
  207. package/src/components/i18n/locales/ko/messages.json +45 -0
  208. package/src/components/i18n/locales/ku/messages.json +45 -0
  209. package/src/components/i18n/locales/lo/messages.json +45 -0
  210. package/src/components/i18n/locales/lt/messages.json +45 -0
  211. package/src/components/i18n/locales/lv/messages.json +45 -0
  212. package/src/components/i18n/locales/mk/messages.json +45 -0
  213. package/src/components/i18n/locales/ml/messages.json +45 -0
  214. package/src/components/i18n/locales/mn/messages.json +45 -0
  215. package/src/components/i18n/locales/mr/messages.json +45 -0
  216. package/src/components/i18n/locales/ms/messages.json +45 -0
  217. package/src/components/i18n/locales/my/messages.json +45 -0
  218. package/src/components/i18n/locales/ne/messages.json +45 -0
  219. package/src/components/i18n/locales/nl/messages.json +45 -0
  220. package/src/components/i18n/locales/no/messages.json +45 -0
  221. package/src/components/i18n/locales/pa/messages.json +45 -0
  222. package/src/components/i18n/locales/pl/messages.json +45 -0
  223. package/src/components/i18n/locales/ps/messages.json +45 -0
  224. package/src/components/i18n/locales/pt/messages.json +45 -0
  225. package/src/components/i18n/locales/ro/messages.json +45 -0
  226. package/src/components/i18n/locales/ru/messages.json +45 -0
  227. package/src/components/i18n/locales/sd/messages.json +45 -0
  228. package/src/components/i18n/locales/si/messages.json +45 -0
  229. package/src/components/i18n/locales/sk/messages.json +45 -0
  230. package/src/components/i18n/locales/sl/messages.json +45 -0
  231. package/src/components/i18n/locales/sq/messages.json +45 -0
  232. package/src/components/i18n/locales/sr/messages.json +45 -0
  233. package/src/components/i18n/locales/sv/messages.json +45 -0
  234. package/src/components/i18n/locales/sw/messages.json +45 -0
  235. package/src/components/i18n/locales/ta/messages.json +45 -0
  236. package/src/components/i18n/locales/te/messages.json +45 -0
  237. package/src/components/i18n/locales/th/messages.json +45 -0
  238. package/src/components/i18n/locales/tr/messages.json +45 -0
  239. package/src/components/i18n/locales/ug/messages.json +45 -0
  240. package/src/components/i18n/locales/uk/messages.json +45 -0
  241. package/src/components/i18n/locales/ur/messages.json +45 -0
  242. package/src/components/i18n/locales/vi/messages.json +45 -0
  243. package/src/components/i18n/locales/yi/messages.json +45 -0
  244. package/src/components/i18n/locales/zh/messages.json +45 -0
  245. package/src/components/icons/index.ts +242 -0
  246. package/src/components/inline-tools/inline-tool-bold.ts +2213 -0
  247. package/src/components/inline-tools/inline-tool-convert.ts +142 -0
  248. package/src/components/inline-tools/inline-tool-italic.ts +500 -0
  249. package/src/components/inline-tools/inline-tool-link.ts +540 -0
  250. package/src/components/modules/api/blocks.ts +377 -0
  251. package/src/components/modules/api/caret.ts +125 -0
  252. package/src/components/modules/api/events.ts +51 -0
  253. package/src/components/modules/api/history.ts +73 -0
  254. package/src/components/modules/api/i18n.ts +35 -0
  255. package/src/components/modules/api/index.ts +39 -0
  256. package/src/components/modules/api/inlineToolbar.ts +33 -0
  257. package/src/components/modules/api/listeners.ts +56 -0
  258. package/src/components/modules/api/notifier.ts +46 -0
  259. package/src/components/modules/api/readonly.ts +39 -0
  260. package/src/components/modules/api/sanitizer.ts +30 -0
  261. package/src/components/modules/api/saver.ts +52 -0
  262. package/src/components/modules/api/selection.ts +48 -0
  263. package/src/components/modules/api/styles.ts +72 -0
  264. package/src/components/modules/api/toolbar.ts +79 -0
  265. package/src/components/modules/api/tools.ts +16 -0
  266. package/src/components/modules/api/tooltip.ts +67 -0
  267. package/src/components/modules/api/ui.ts +36 -0
  268. package/src/components/modules/blockEvents.ts +1591 -0
  269. package/src/components/modules/blockManager.ts +1356 -0
  270. package/src/components/modules/blockSelection.ts +708 -0
  271. package/src/components/modules/caret.ts +853 -0
  272. package/src/components/modules/crossBlockSelection.ts +329 -0
  273. package/src/components/modules/dragManager.ts +1204 -0
  274. package/src/components/modules/history.ts +1098 -0
  275. package/src/components/modules/i18n.ts +332 -0
  276. package/src/components/modules/index.ts +139 -0
  277. package/src/components/modules/modificationsObserver.ts +147 -0
  278. package/src/components/modules/paste.ts +1092 -0
  279. package/src/components/modules/readonly.ts +136 -0
  280. package/src/components/modules/rectangleSelection.ts +711 -0
  281. package/src/components/modules/renderer.ts +155 -0
  282. package/src/components/modules/saver.ts +283 -0
  283. package/src/components/modules/toolbar/blockSettings.ts +782 -0
  284. package/src/components/modules/toolbar/index.ts +1296 -0
  285. package/src/components/modules/toolbar/inline.ts +956 -0
  286. package/src/components/modules/tools.ts +625 -0
  287. package/src/components/modules/ui.ts +1283 -0
  288. package/src/components/polyfills.ts +113 -0
  289. package/src/components/selection.ts +1179 -0
  290. package/src/components/tools/base.ts +301 -0
  291. package/src/components/tools/block.ts +339 -0
  292. package/src/components/tools/collection.ts +67 -0
  293. package/src/components/tools/factory.ts +138 -0
  294. package/src/components/tools/inline.ts +71 -0
  295. package/src/components/tools/tune.ts +33 -0
  296. package/src/components/ui/toolbox.ts +610 -0
  297. package/src/components/utils/announcer.ts +205 -0
  298. package/src/components/utils/api.ts +20 -0
  299. package/src/components/utils/bem.ts +26 -0
  300. package/src/components/utils/blocks.ts +284 -0
  301. package/src/components/utils/caret.ts +1067 -0
  302. package/src/components/utils/data-model-transform.ts +382 -0
  303. package/src/components/utils/events.ts +117 -0
  304. package/src/components/utils/keyboard.ts +60 -0
  305. package/src/components/utils/listeners.ts +296 -0
  306. package/src/components/utils/mutations.ts +39 -0
  307. package/src/components/utils/notifier/draw.ts +190 -0
  308. package/src/components/utils/notifier/index.ts +66 -0
  309. package/src/components/utils/notifier/types.ts +1 -0
  310. package/src/components/utils/notifier.ts +77 -0
  311. package/src/components/utils/placeholder.ts +140 -0
  312. package/src/components/utils/popover/components/hint/hint.const.ts +10 -0
  313. package/src/components/utils/popover/components/hint/hint.ts +46 -0
  314. package/src/components/utils/popover/components/hint/index.ts +6 -0
  315. package/src/components/utils/popover/components/popover-header/index.ts +2 -0
  316. package/src/components/utils/popover/components/popover-header/popover-header.const.ts +8 -0
  317. package/src/components/utils/popover/components/popover-header/popover-header.ts +80 -0
  318. package/src/components/utils/popover/components/popover-header/popover-header.types.ts +14 -0
  319. package/src/components/utils/popover/components/popover-item/index.ts +13 -0
  320. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +50 -0
  321. package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +680 -0
  322. package/src/components/utils/popover/components/popover-item/popover-item-html/popover-item-html.const.ts +14 -0
  323. package/src/components/utils/popover/components/popover-item/popover-item-html/popover-item-html.ts +136 -0
  324. package/src/components/utils/popover/components/popover-item/popover-item-separator/popover-item-separator.const.ts +20 -0
  325. package/src/components/utils/popover/components/popover-item/popover-item-separator/popover-item-separator.ts +117 -0
  326. package/src/components/utils/popover/components/popover-item/popover-item.ts +197 -0
  327. package/src/components/utils/popover/components/search-input/index.ts +2 -0
  328. package/src/components/utils/popover/components/search-input/search-input.const.ts +8 -0
  329. package/src/components/utils/popover/components/search-input/search-input.ts +178 -0
  330. package/src/components/utils/popover/components/search-input/search-input.types.ts +59 -0
  331. package/src/components/utils/popover/index.ts +13 -0
  332. package/src/components/utils/popover/popover-abstract.ts +457 -0
  333. package/src/components/utils/popover/popover-desktop.ts +682 -0
  334. package/src/components/utils/popover/popover-inline.ts +338 -0
  335. package/src/components/utils/popover/popover-mobile.ts +201 -0
  336. package/src/components/utils/popover/popover.const.ts +81 -0
  337. package/src/components/utils/popover/utils/popover-states-history.ts +72 -0
  338. package/src/components/utils/promise-queue.ts +43 -0
  339. package/src/components/utils/sanitizer.ts +537 -0
  340. package/src/components/utils/scroll-locker.ts +87 -0
  341. package/src/components/utils/shortcut.ts +231 -0
  342. package/src/components/utils/shortcuts.ts +113 -0
  343. package/src/components/utils/tools.ts +110 -0
  344. package/src/components/utils/tooltip.ts +591 -0
  345. package/src/components/utils/tw.ts +241 -0
  346. package/src/components/utils.ts +1081 -0
  347. package/src/env.d.ts +13 -0
  348. package/src/full.ts +69 -0
  349. package/src/locales.ts +51 -0
  350. package/src/stories/Block.stories.ts +498 -0
  351. package/src/stories/EditorModes.stories.ts +505 -0
  352. package/src/stories/Header.stories.ts +137 -0
  353. package/src/stories/InlineToolbar.stories.ts +498 -0
  354. package/src/stories/List.stories.ts +259 -0
  355. package/src/stories/Notifier.stories.ts +340 -0
  356. package/src/stories/Paragraph.stories.ts +112 -0
  357. package/src/stories/Placeholder.stories.ts +319 -0
  358. package/src/stories/Popover.stories.ts +759 -0
  359. package/src/stories/Selection.stories.ts +250 -0
  360. package/src/stories/StubBlock.stories.ts +156 -0
  361. package/src/stories/Toolbar.stories.ts +223 -0
  362. package/src/stories/Toolbox.stories.ts +166 -0
  363. package/src/stories/Tooltip.stories.ts +198 -0
  364. package/src/stories/helpers.ts +463 -0
  365. package/src/styles/main.css +126 -0
  366. package/src/tools/header/index.ts +647 -0
  367. package/src/tools/index.ts +45 -0
  368. package/src/tools/list/index.ts +1826 -0
  369. package/src/tools/paragraph/index.ts +412 -0
  370. package/src/tools/stub/index.ts +107 -0
  371. package/src/types-internal/blok-modules.d.ts +87 -0
  372. package/src/types-internal/html-janitor.d.ts +28 -0
  373. package/src/types-internal/module-config.d.ts +11 -0
  374. package/src/variants/all-locales.ts +155 -0
  375. package/src/variants/blok-maximum.ts +20 -0
  376. package/src/variants/blok-minimum.ts +243 -0
  377. package/types/api/blocks.d.ts +9 -1
  378. package/types/api/history.d.ts +7 -0
  379. package/types/api/i18n.d.ts +22 -3
  380. package/types/api/selection.d.ts +6 -0
  381. package/types/api/styles.d.ts +23 -10
  382. package/types/configs/blok-config.d.ts +29 -0
  383. package/types/configs/i18n-config.d.ts +52 -2
  384. package/types/configs/i18n-dictionary.d.ts +16 -90
  385. package/types/configs/sanitizer-config.d.ts +25 -1
  386. package/types/data-attributes.d.ts +170 -0
  387. package/types/data-formats/output-data.d.ts +15 -0
  388. package/types/full.d.ts +80 -0
  389. package/types/index.d.ts +30 -13
  390. package/types/locales.d.ts +59 -0
  391. package/types/tools/adapters/inline-tool-adapter.d.ts +10 -0
  392. package/types/tools/block-tool.d.ts +11 -2
  393. package/types/tools/header.d.ts +18 -0
  394. package/types/tools/index.d.ts +1 -0
  395. package/types/tools/list.d.ts +91 -0
  396. package/types/tools/paragraph.d.ts +71 -0
  397. package/types/tools/tool-settings.d.ts +99 -6
  398. package/types/tools/tool.d.ts +6 -0
  399. package/types/tools-entry.d.ts +49 -0
  400. package/types/utils/popover/popover-item.d.ts +24 -5
  401. package/types/utils/popover/popover.d.ts +13 -0
  402. package/dist/blok-C8XbyLHh.mjs +0 -25795
  403. package/dist/blok.umd.js +0 -181
@@ -0,0 +1,711 @@
1
+ /**
2
+ * @class RectangleSelection
3
+ * @classdesc Manages Block selection with mouse
4
+ * @module RectangleSelection
5
+ * @version 1.0.0
6
+ */
7
+ import { Module } from '../__module';
8
+ import { Dom as $ } from '../dom';
9
+
10
+ import { SelectionUtils } from '../selection';
11
+ import { throttle } from '../utils';
12
+ import {
13
+ INLINE_TOOLBAR_INTERFACE_SELECTOR,
14
+ DATA_ATTR,
15
+ createSelector,
16
+ } from '../constants';
17
+
18
+ /**
19
+ *
20
+ */
21
+ export class RectangleSelection extends Module {
22
+ /**
23
+ * CSS classes for the Block - kept for backward compatibility
24
+ * @returns {{wrapper: string, content: string}}
25
+ * @deprecated Use data attributes via constants instead (BLOK_OVERLAY_ATTR, BLOK_OVERLAY_CONTAINER_ATTR, etc.)
26
+ */
27
+ public static get CSS(): {[name: string]: string} {
28
+ return {
29
+ overlay: '',
30
+ overlayContainer: '',
31
+ rect: '',
32
+ topScrollZone: '',
33
+ bottomScrollZone: '',
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Using the selection rectangle
39
+ * @type {boolean}
40
+ */
41
+ private isRectSelectionActivated = false;
42
+
43
+ /**
44
+ * Speed of Scrolling
45
+ */
46
+ private readonly SCROLL_SPEED: number = 3;
47
+
48
+ /**
49
+ * Height of scroll zone on boundary of screen
50
+ */
51
+ private readonly HEIGHT_OF_SCROLL_ZONE = 40;
52
+
53
+ /**
54
+ * Scroll zone type indicators
55
+ */
56
+ private readonly BOTTOM_SCROLL_ZONE = 1;
57
+ private readonly TOP_SCROLL_ZONE = 2;
58
+
59
+ /**
60
+ * Id of main button for event.button
61
+ */
62
+ private readonly MAIN_MOUSE_BUTTON = 0;
63
+
64
+ /**
65
+ * Mouse is clamped
66
+ */
67
+ private mousedown = false;
68
+
69
+ /**
70
+ * Is scrolling now
71
+ */
72
+ private isScrolling = false;
73
+
74
+ /**
75
+ * Mouse is in scroll zone
76
+ */
77
+ private inScrollZone: number | null = null;
78
+
79
+ /**
80
+ * Coords of rect
81
+ */
82
+ private startX = 0;
83
+ private startY = 0;
84
+ private mouseX = 0;
85
+ private mouseY = 0;
86
+
87
+ /**
88
+ * Selected blocks
89
+ */
90
+ private stackOfSelected: number[] = [];
91
+
92
+ /**
93
+ * Does the rectangle intersect blocks
94
+ */
95
+ private rectCrossesBlocks = false;
96
+
97
+ /**
98
+ * Selection rectangle
99
+ */
100
+ private overlayRectangle: HTMLDivElement | null = null;
101
+
102
+ /**
103
+ * Listener identifiers
104
+ */
105
+ private listenerIds: string[] = [];
106
+
107
+ /**
108
+ * Module Preparation
109
+ * Creating rect and hang handlers
110
+ */
111
+ public prepare(): void {
112
+ this.enableModuleBindings();
113
+ }
114
+
115
+ /**
116
+ * Init rect params
117
+ * @param {number} pageX - X coord of mouse
118
+ * @param {number} pageY - Y coord of mouse
119
+ * @param {boolean} shiftKey - whether Shift key is held for additive selection
120
+ */
121
+ public startSelection(pageX: number, pageY: number, shiftKey = false): void {
122
+ const { UI } = this.Blok;
123
+ const redactor = UI.nodes.redactor;
124
+
125
+ if (!redactor) {
126
+ return;
127
+ }
128
+
129
+ const editorRect = redactor.getBoundingClientRect();
130
+ const scrollTop = this.getScrollTop();
131
+ const pointerY = pageY - scrollTop;
132
+
133
+ // Check if pointer is within editor's vertical bounds
134
+ const withinEditorVertically = pointerY >= editorRect.top && pointerY <= editorRect.bottom;
135
+
136
+ if (!withinEditorVertically) {
137
+ return;
138
+ }
139
+
140
+ const scrollLeft = this.getScrollLeft();
141
+ const elemWhereSelectionStart = document.elementFromPoint(pageX - scrollLeft, pointerY);
142
+
143
+ if (!elemWhereSelectionStart) {
144
+ return;
145
+ }
146
+
147
+ /**
148
+ * Don't clear selected block by clicks on the Block settings
149
+ * because we need to keep highlighting working block
150
+ */
151
+ const startsInsideToolbar = elemWhereSelectionStart.closest(createSelector(DATA_ATTR.toolbar));
152
+
153
+ /**
154
+ * When Shift is held, preserve existing selection for additive behavior.
155
+ * Otherwise, clear selection state.
156
+ */
157
+ if (!startsInsideToolbar && !shiftKey) {
158
+ this.Blok.BlockSelection.allBlocksSelected = false;
159
+ this.clearSelection();
160
+ this.stackOfSelected = [];
161
+ }
162
+
163
+ const selectorsToAvoid = [
164
+ createSelector(DATA_ATTR.elementContent),
165
+ createSelector(DATA_ATTR.toolbar),
166
+ createSelector(DATA_ATTR.popover),
167
+ INLINE_TOOLBAR_INTERFACE_SELECTOR,
168
+ ];
169
+
170
+ const startsInSelectorToAvoid = selectorsToAvoid.some((selector) => !!elemWhereSelectionStart.closest(selector));
171
+
172
+ /**
173
+ * If selection starts inside the blocks content or on Blok UI elements, do not handle it
174
+ */
175
+ if (startsInSelectorToAvoid) {
176
+ return;
177
+ }
178
+
179
+ /**
180
+ * Hide the toolbar immediately so it does not obstruct drag selection.
181
+ */
182
+ this.Blok.Toolbar.close();
183
+
184
+ this.mousedown = true;
185
+ this.startX = pageX;
186
+ this.startY = pageY;
187
+ }
188
+
189
+ /**
190
+ * Clear all params to end selection
191
+ */
192
+ public endSelection(): void {
193
+ this.mousedown = false;
194
+ this.startX = 0;
195
+ this.startY = 0;
196
+ if (this.overlayRectangle !== null) {
197
+ this.overlayRectangle.style.display = 'none';
198
+ }
199
+ }
200
+
201
+ /**
202
+ * is RectSelection Activated
203
+ */
204
+ public isRectActivated(): boolean {
205
+ return this.isRectSelectionActivated;
206
+ }
207
+
208
+ /**
209
+ * Mark that selection is end
210
+ */
211
+ public clearSelection(): void {
212
+ this.isRectSelectionActivated = false;
213
+ }
214
+
215
+ /**
216
+ * Sets Module necessary event handlers
217
+ */
218
+ private enableModuleBindings(): void {
219
+ this.genHTML();
220
+
221
+ this.listeners.on(document.body, 'mousedown', (event: Event) => {
222
+ this.processMouseDown(event as MouseEvent);
223
+ }, false);
224
+
225
+ const throttledMouseMove = throttle((event: unknown) => {
226
+ if (event instanceof MouseEvent) {
227
+ this.processMouseMove(event);
228
+ }
229
+
230
+ }, 10) as EventListener;
231
+
232
+ this.listeners.on(document.body, 'mousemove', throttledMouseMove, {
233
+ passive: true,
234
+ });
235
+
236
+ this.listeners.on(document.body, 'mouseleave', () => {
237
+ this.processMouseLeave();
238
+ });
239
+
240
+ const throttledScroll = throttle((event: unknown) => {
241
+ this.processScroll(event as MouseEvent);
242
+
243
+ }, 10) as EventListener;
244
+
245
+ this.listeners.on(window, 'scroll', throttledScroll, {
246
+ passive: true,
247
+ });
248
+
249
+ this.listeners.on(document.body, 'mouseup', () => {
250
+ this.processMouseUp();
251
+ }, false);
252
+ }
253
+
254
+ /**
255
+ * Handle mouse down events
256
+ * @param {MouseEvent} mouseEvent - mouse event payload
257
+ */
258
+ private processMouseDown(mouseEvent: MouseEvent): void {
259
+ if (mouseEvent.button !== this.MAIN_MOUSE_BUTTON) {
260
+ return;
261
+ }
262
+
263
+ /**
264
+ * Do not enable the Rectangle Selection when mouse dragging started some editable input
265
+ * Used to prevent Rectangle Selection on Block Tune wrappers' inputs that also can be inside the Block
266
+ */
267
+ const startedFromContentEditable = (mouseEvent.target as Element).closest($.allInputsSelector) !== null;
268
+
269
+ if (!startedFromContentEditable) {
270
+ this.startSelection(mouseEvent.pageX, mouseEvent.pageY, mouseEvent.shiftKey);
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Handle mouse move events
276
+ * @param {MouseEvent} mouseEvent - mouse event payload
277
+ */
278
+ private processMouseMove(mouseEvent: MouseEvent): void {
279
+ this.changingRectangle(mouseEvent);
280
+ this.scrollByZones(mouseEvent.clientY);
281
+ }
282
+
283
+ /**
284
+ * Handle mouse leave
285
+ */
286
+ private processMouseLeave(): void {
287
+ this.clearSelection();
288
+ this.endSelection();
289
+ }
290
+
291
+ /**
292
+ * @param {MouseEvent} mouseEvent - mouse event payload
293
+ */
294
+ private processScroll(mouseEvent: MouseEvent): void {
295
+ this.changingRectangle(mouseEvent);
296
+ }
297
+
298
+ /**
299
+ * Handle mouse up
300
+ */
301
+ private processMouseUp(): void {
302
+ /**
303
+ * Show toolbar for multi-block selection after mouse up
304
+ */
305
+ const selectedBlocks = this.Blok.BlockSelection.selectedBlocks;
306
+
307
+ if (selectedBlocks.length > 1) {
308
+ this.Blok.Toolbar.moveAndOpenForMultipleBlocks();
309
+ }
310
+
311
+ this.clearSelection();
312
+ this.endSelection();
313
+ }
314
+
315
+ /**
316
+ * Scroll If mouse in scroll zone
317
+ * @param {number} clientY - Y coord of mouse
318
+ */
319
+ private scrollByZones(clientY: number): void {
320
+ this.inScrollZone = null;
321
+ if (clientY <= this.HEIGHT_OF_SCROLL_ZONE) {
322
+ this.inScrollZone = this.TOP_SCROLL_ZONE;
323
+ }
324
+ if (document.documentElement.clientHeight - clientY <= this.HEIGHT_OF_SCROLL_ZONE) {
325
+ this.inScrollZone = this.BOTTOM_SCROLL_ZONE;
326
+ }
327
+
328
+ if (!this.inScrollZone) {
329
+ this.isScrolling = false;
330
+
331
+ return;
332
+ }
333
+
334
+ if (!this.isScrolling) {
335
+ this.scrollVertical(this.inScrollZone === this.TOP_SCROLL_ZONE ? -this.SCROLL_SPEED : this.SCROLL_SPEED);
336
+ this.isScrolling = true;
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Generates required HTML elements
342
+ * @returns {Record<string, Element>}
343
+ */
344
+ private genHTML(): {container: Element; overlay: Element} {
345
+ const { UI } = this.Blok;
346
+
347
+ const container = UI.nodes.holder.querySelector(createSelector(DATA_ATTR.editor));
348
+ const overlay = $.make('div', [
349
+ 'fixed',
350
+ 'inset-0',
351
+ 'z-overlay',
352
+ 'pointer-events-none',
353
+ 'overflow-hidden',
354
+ ], {});
355
+ const overlayContainer = $.make('div', [
356
+ 'relative',
357
+ 'pointer-events-auto',
358
+ 'z-0',
359
+ ], {});
360
+ const overlayRectangle = $.make('div', [
361
+ 'absolute',
362
+ 'pointer-events-none',
363
+ 'bg-selection-highlight',
364
+ 'border',
365
+ 'border-transparent',
366
+ ], {});
367
+
368
+ overlay.setAttribute(DATA_ATTR.overlay, '');
369
+ overlayContainer.setAttribute(DATA_ATTR.overlayContainer, '');
370
+ overlayRectangle.setAttribute(DATA_ATTR.overlayRectangle, '');
371
+ overlay.setAttribute('data-blok-testid', 'overlay');
372
+ overlayRectangle.setAttribute('data-blok-testid', 'overlay-rectangle');
373
+
374
+ if (!container) {
375
+ throw new Error('RectangleSelection: blok wrapper not found');
376
+ }
377
+
378
+ overlayContainer.appendChild(overlayRectangle);
379
+ overlay.appendChild(overlayContainer);
380
+ container.appendChild(overlay);
381
+
382
+ this.overlayRectangle = overlayRectangle as HTMLDivElement;
383
+
384
+ return {
385
+ container,
386
+ overlay,
387
+ };
388
+ }
389
+
390
+ /**
391
+ * Activates scrolling if blockSelection is active and mouse is in scroll zone
392
+ * @param {number} speed - speed of scrolling
393
+ */
394
+ private scrollVertical(speed: number): void {
395
+ if (!(this.inScrollZone && this.mousedown)) {
396
+ return;
397
+ }
398
+ const lastOffset = this.getScrollTop();
399
+
400
+ window.scrollBy(0, speed);
401
+ this.mouseY += this.getScrollTop() - lastOffset;
402
+ setTimeout(() => {
403
+ this.scrollVertical(speed);
404
+ }, 0);
405
+ }
406
+
407
+ /**
408
+ * Handles the change in the rectangle and its effect
409
+ * @param {MouseEvent} event - mouse event
410
+ */
411
+ private changingRectangle(event: MouseEvent): void {
412
+ if (!this.mousedown) {
413
+ return;
414
+ }
415
+
416
+ const overlayRectangle = this.overlayRectangle;
417
+
418
+ if (overlayRectangle === null) {
419
+ return;
420
+ }
421
+
422
+ if (event.pageY !== undefined) {
423
+ this.mouseX = event.pageX;
424
+ this.mouseY = event.pageY;
425
+ }
426
+
427
+ if (!this.isRectSelectionActivated) {
428
+ this.isRectSelectionActivated = true;
429
+ this.shrinkRectangleToPoint();
430
+ overlayRectangle.style.display = 'block';
431
+ }
432
+
433
+ const { index } = this.genInfoForMouseSelection();
434
+
435
+ /**
436
+ * Check if the selection rectangle intersects the block holder horizontally.
437
+ * For page-wide selection, we need to verify the rectangle actually reaches the block,
438
+ * not just that the mouse Y position is at the same height as a block.
439
+ */
440
+ this.rectCrossesBlocks = false;
441
+ const block = index !== undefined ? this.Blok.BlockManager.getBlockByIndex(index) : undefined;
442
+
443
+ if (block) {
444
+ const holderRect = block.holder.getBoundingClientRect();
445
+ const scrollLeft = this.getScrollLeft();
446
+
447
+ // Selection rectangle horizontal bounds (in page coordinates)
448
+ const rectLeft = Math.min(this.startX, this.mouseX);
449
+ const rectRight = Math.max(this.startX, this.mouseX);
450
+
451
+ // Block holder horizontal bounds (convert from viewport to page coordinates)
452
+ const holderLeft = holderRect.left + scrollLeft;
453
+ const holderRight = holderRect.right + scrollLeft;
454
+
455
+ // Check for horizontal intersection
456
+ this.rectCrossesBlocks = rectRight >= holderLeft && rectLeft <= holderRight;
457
+ }
458
+
459
+ this.updateRectangleSize();
460
+
461
+ /**
462
+ * Hide Block Settings Toggler (along with the Toolbar) (if showed) when the Rectangle Selection is activated
463
+ */
464
+ this.Blok.Toolbar.close();
465
+
466
+ if (index === undefined) {
467
+ return;
468
+ }
469
+
470
+ this.trySelectNextBlock(index);
471
+ // For case, when rect is out from blocks
472
+ this.inverseSelection();
473
+
474
+ const selection = SelectionUtils.get();
475
+
476
+ if (selection) {
477
+ selection.removeAllRanges();
478
+ }
479
+ }
480
+
481
+ /**
482
+ * Shrink rect to singular point
483
+ */
484
+ private shrinkRectangleToPoint(): void {
485
+ if (this.overlayRectangle === null) {
486
+ return;
487
+ }
488
+
489
+ const scrollLeft = this.getScrollLeft();
490
+ const scrollTop = this.getScrollTop();
491
+
492
+ this.overlayRectangle.style.left = `${this.startX - scrollLeft}px`;
493
+ this.overlayRectangle.style.top = `${this.startY - scrollTop}px`;
494
+ this.overlayRectangle.style.bottom = `calc(100% - ${this.startY - scrollTop}px)`;
495
+ this.overlayRectangle.style.right = `calc(100% - ${this.startX - scrollLeft}px)`;
496
+ }
497
+
498
+ /**
499
+ * Select or unselect all of blocks in array if rect is out or in selectable area
500
+ */
501
+ private inverseSelection(): void {
502
+ if (this.stackOfSelected.length === 0) {
503
+ return;
504
+ }
505
+
506
+ const firstBlockInStack = this.Blok.BlockManager.getBlockByIndex(this.stackOfSelected[0]);
507
+
508
+ if (!firstBlockInStack) {
509
+ return;
510
+ }
511
+
512
+ const isSelectedMode = firstBlockInStack.selected;
513
+
514
+ if (this.rectCrossesBlocks && !isSelectedMode) {
515
+ for (const it of this.stackOfSelected) {
516
+ this.Blok.BlockSelection.selectBlockByIndex(it);
517
+ }
518
+ }
519
+
520
+ if (!this.rectCrossesBlocks && isSelectedMode) {
521
+ for (const it of this.stackOfSelected) {
522
+ this.Blok.BlockSelection.unSelectBlockByIndex(it);
523
+ }
524
+ }
525
+ }
526
+
527
+ /**
528
+ * Updates size of rectangle
529
+ */
530
+ private updateRectangleSize(): void {
531
+ if (this.overlayRectangle === null) {
532
+ return;
533
+ }
534
+
535
+ const scrollLeft = this.getScrollLeft();
536
+ const scrollTop = this.getScrollTop();
537
+
538
+ // Depending on the position of the mouse relative to the starting point,
539
+ // change this.e distance from the desired edge of the screen*/
540
+ if (this.mouseY >= this.startY) {
541
+ this.overlayRectangle.style.top = `${this.startY - scrollTop}px`;
542
+ this.overlayRectangle.style.bottom = `calc(100% - ${this.mouseY - scrollTop}px)`;
543
+ } else {
544
+ this.overlayRectangle.style.bottom = `calc(100% - ${this.startY - scrollTop}px)`;
545
+ this.overlayRectangle.style.top = `${this.mouseY - scrollTop}px`;
546
+ }
547
+
548
+ if (this.mouseX >= this.startX) {
549
+ this.overlayRectangle.style.left = `${this.startX - scrollLeft}px`;
550
+ this.overlayRectangle.style.right = `calc(100% - ${this.mouseX - scrollLeft}px)`;
551
+ } else {
552
+ this.overlayRectangle.style.right = `calc(100% - ${this.startX - scrollLeft}px)`;
553
+ this.overlayRectangle.style.left = `${this.mouseX - scrollLeft}px`;
554
+ }
555
+ }
556
+
557
+ /**
558
+ * Collects information needed to determine the behavior of the rectangle
559
+ * For page-wide selection, we check blocks at the center X position but at the actual mouse Y position
560
+ * @returns {object} index - index next Block, leftPos - start of left border of Block, rightPos - right border
561
+ */
562
+ private genInfoForMouseSelection(): {index: number | undefined; leftPos: number; rightPos: number} {
563
+ const widthOfRedactor = document.body.offsetWidth;
564
+ const centerOfRedactor = widthOfRedactor / 2;
565
+ const scrollTop = this.getScrollTop();
566
+ const y = this.mouseY - scrollTop;
567
+
568
+ // For page-wide selection: check what block is at the center X, but at the mouse's Y position
569
+ // This allows selection to work even when mouse is in the left/right margins
570
+ const elementUnderMouse = document.elementFromPoint(centerOfRedactor, y);
571
+ const lastBlockHolder = this.Blok.BlockManager.lastBlock?.holder;
572
+ const contentElement = lastBlockHolder?.querySelector(createSelector(DATA_ATTR.elementContent));
573
+ const contentWidth = contentElement ? Number.parseInt(window.getComputedStyle(contentElement).width, 10) : 0;
574
+ const centerOfBlock = contentWidth / 2;
575
+ const leftPos = centerOfRedactor - centerOfBlock;
576
+ const rightPos = centerOfRedactor + centerOfBlock;
577
+
578
+ if (!elementUnderMouse) {
579
+ return {
580
+ index: undefined,
581
+ leftPos,
582
+ rightPos,
583
+ };
584
+ }
585
+ const blockInCurrentPos = this.Blok.BlockManager.getBlockByChildNode(elementUnderMouse);
586
+
587
+ const index = blockInCurrentPos !== undefined
588
+ ? this.Blok.BlockManager.blocks.findIndex((block) => block.holder === blockInCurrentPos.holder)
589
+ : undefined;
590
+
591
+ return {
592
+ index,
593
+ leftPos,
594
+ rightPos,
595
+ };
596
+ }
597
+
598
+ /**
599
+ * Normalized vertical scroll value that does not rely on deprecated APIs.
600
+ */
601
+ private getScrollTop(): number {
602
+ if (typeof window.scrollY === 'number') {
603
+ return window.scrollY;
604
+ }
605
+
606
+ return document.documentElement?.scrollTop ?? document.body?.scrollTop ?? 0;
607
+ }
608
+
609
+ /**
610
+ * Normalized horizontal scroll value that does not rely on deprecated APIs.
611
+ */
612
+ private getScrollLeft(): number {
613
+ if (typeof window.scrollX === 'number') {
614
+ return window.scrollX;
615
+ }
616
+
617
+ return document.documentElement?.scrollLeft ?? document.body?.scrollLeft ?? 0;
618
+ }
619
+
620
+ /**
621
+ * Select block with index index
622
+ * @param index - index of block in redactor
623
+ */
624
+ private addBlockInSelection(index: number): void {
625
+ if (this.rectCrossesBlocks) {
626
+ this.Blok.BlockSelection.selectBlockByIndex(index);
627
+ }
628
+ this.stackOfSelected.push(index);
629
+ }
630
+
631
+ /**
632
+ * Adds a block to the selection and determines which blocks should be selected
633
+ * @param {object} index - index of new block in the reactor
634
+ */
635
+ private trySelectNextBlock(index: number): void {
636
+ const sizeStack = this.stackOfSelected.length;
637
+ const lastSelected = this.stackOfSelected[sizeStack - 1];
638
+ const sameBlock = lastSelected === index;
639
+
640
+ if (sameBlock) {
641
+ return;
642
+ }
643
+
644
+ const previousSelected = this.stackOfSelected[sizeStack - 2];
645
+ const blockNumbersIncrease = previousSelected !== undefined && lastSelected !== undefined
646
+ ? lastSelected - previousSelected > 0
647
+ : false;
648
+ const isInitialSelection = sizeStack <= 1;
649
+ const selectionInDownDirection = lastSelected !== undefined && index > lastSelected && blockNumbersIncrease;
650
+ const selectionInUpDirection = lastSelected !== undefined && index < lastSelected && sizeStack > 1 && !blockNumbersIncrease;
651
+ const generalSelection = selectionInDownDirection || selectionInUpDirection || isInitialSelection;
652
+ const reduction = !generalSelection;
653
+
654
+ // When the selection is too fast, some blocks do not have time to be noticed. Fix it.
655
+ if (!reduction && (lastSelected === undefined || index > lastSelected)) {
656
+ const startIndex = lastSelected !== undefined ? lastSelected + 1 : index;
657
+
658
+ Array.from({ length: index - startIndex + 1 }, (_unused, offset) => startIndex + offset)
659
+ .forEach((ind) => {
660
+ this.addBlockInSelection(ind);
661
+ });
662
+
663
+ return;
664
+ }
665
+
666
+ // for both directions
667
+ if (!reduction && lastSelected !== undefined && index < lastSelected) {
668
+ Array.from(
669
+ { length: lastSelected - index },
670
+ (_unused, offset) => lastSelected - 1 - offset
671
+ ).forEach((ind) => {
672
+ this.addBlockInSelection(ind);
673
+ });
674
+
675
+ return;
676
+ }
677
+
678
+ if (!reduction) {
679
+ return;
680
+ }
681
+
682
+ const shouldRemove = (stackIndex: number): boolean => {
683
+ if (lastSelected === undefined) {
684
+ return false;
685
+ }
686
+
687
+ if (index > lastSelected) {
688
+ return index > stackIndex;
689
+ }
690
+
691
+ return index < stackIndex;
692
+ };
693
+
694
+ const indicesToRemove: number[] = [];
695
+
696
+ for (const stackIndex of [ ...this.stackOfSelected ].reverse()) {
697
+ if (!shouldRemove(stackIndex)) {
698
+ break;
699
+ }
700
+
701
+ if (this.rectCrossesBlocks) {
702
+ this.Blok.BlockSelection.unSelectBlockByIndex(stackIndex);
703
+ }
704
+ indicesToRemove.push(stackIndex);
705
+ }
706
+
707
+ if (indicesToRemove.length > 0) {
708
+ this.stackOfSelected.splice(this.stackOfSelected.length - indicesToRemove.length, indicesToRemove.length);
709
+ }
710
+ }
711
+ }