@jackuait/blok 0.4.1-beta.4 → 0.4.1-beta.6

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 (400) hide show
  1. package/README.md +136 -17
  2. package/codemod/README.md +16 -0
  3. package/codemod/migrate-editorjs-to-blok.js +868 -92
  4. package/codemod/test.js +682 -77
  5. package/dist/blok.mjs +5 -2
  6. package/dist/chunks/blok-B5qs7C5l.mjs +12838 -0
  7. package/dist/chunks/i18next-CugVlwWp.mjs +1292 -0
  8. package/dist/chunks/i18next-loader-CTrK3HzG.mjs +43 -0
  9. package/dist/{index-XWGz4gev.mjs → chunks/index-DDpzQn-0.mjs} +2 -2
  10. package/dist/chunks/inline-tool-convert-RBcopmCh.mjs +1988 -0
  11. package/dist/chunks/messages-2434tVOK.mjs +47 -0
  12. package/dist/chunks/messages-3DcCwXMF.mjs +47 -0
  13. package/dist/chunks/messages-4kMwVAKY.mjs +47 -0
  14. package/dist/chunks/messages-57uL5htT.mjs +47 -0
  15. package/dist/chunks/messages-76-iJV9Q.mjs +47 -0
  16. package/dist/chunks/messages-8p86Eyf2.mjs +47 -0
  17. package/dist/chunks/messages-BBX0p0Pi.mjs +47 -0
  18. package/dist/chunks/messages-BCm2eudQ.mjs +47 -0
  19. package/dist/chunks/messages-BFiUomgG.mjs +47 -0
  20. package/dist/chunks/messages-BIPNHHAV.mjs +47 -0
  21. package/dist/chunks/messages-BUlwu9mo.mjs +47 -0
  22. package/dist/chunks/messages-BX-DPa-z.mjs +47 -0
  23. package/dist/chunks/messages-BextV3Qh.mjs +47 -0
  24. package/dist/chunks/messages-BiPSFlUG.mjs +47 -0
  25. package/dist/chunks/messages-BiXe9G-O.mjs +47 -0
  26. package/dist/chunks/messages-Bl5z_Igo.mjs +47 -0
  27. package/dist/chunks/messages-BnsE97ku.mjs +47 -0
  28. package/dist/chunks/messages-BoO8gsVD.mjs +47 -0
  29. package/dist/chunks/messages-BqWaOGMn.mjs +47 -0
  30. package/dist/chunks/messages-BqkL2_Ro.mjs +47 -0
  31. package/dist/chunks/messages-BvCkXKX-.mjs +47 -0
  32. package/dist/chunks/messages-C6tbPLoj.mjs +47 -0
  33. package/dist/chunks/messages-CA6T3-gQ.mjs +47 -0
  34. package/dist/chunks/messages-CFFPFdWP.mjs +47 -0
  35. package/dist/chunks/messages-CFrKE-TN.mjs +47 -0
  36. package/dist/chunks/messages-CHz8VlG-.mjs +47 -0
  37. package/dist/chunks/messages-CLixzySl.mjs +47 -0
  38. package/dist/chunks/messages-CV7OM_qk.mjs +47 -0
  39. package/dist/chunks/messages-CXHt3eCC.mjs +47 -0
  40. package/dist/chunks/messages-CbmsBrB0.mjs +47 -0
  41. package/dist/chunks/messages-Ceo1KtFx.mjs +47 -0
  42. package/dist/chunks/messages-Cm0LJLtB.mjs +47 -0
  43. package/dist/chunks/messages-CmymP_Ar.mjs +47 -0
  44. package/dist/chunks/messages-D0ohMB5H.mjs +47 -0
  45. package/dist/chunks/messages-D3GrDwXh.mjs +47 -0
  46. package/dist/chunks/messages-D3vTzIpL.mjs +47 -0
  47. package/dist/chunks/messages-D5WeksbV.mjs +47 -0
  48. package/dist/chunks/messages-DGaab4EP.mjs +47 -0
  49. package/dist/chunks/messages-DKha57ZU.mjs +47 -0
  50. package/dist/chunks/messages-DOaujgMW.mjs +47 -0
  51. package/dist/chunks/messages-DVbPLd_0.mjs +47 -0
  52. package/dist/chunks/messages-D_FCyfW6.mjs +47 -0
  53. package/dist/chunks/messages-Dd5iZN3c.mjs +47 -0
  54. package/dist/chunks/messages-DehM7135.mjs +47 -0
  55. package/dist/chunks/messages-Dg1OHftD.mjs +47 -0
  56. package/dist/chunks/messages-Di6Flq-b.mjs +47 -0
  57. package/dist/chunks/messages-Dqhhex6e.mjs +47 -0
  58. package/dist/chunks/messages-DueVe0F1.mjs +47 -0
  59. package/dist/chunks/messages-Dx3eFwI0.mjs +47 -0
  60. package/dist/chunks/messages-FOtiUoKl.mjs +47 -0
  61. package/dist/chunks/messages-FTOZNhRD.mjs +47 -0
  62. package/dist/chunks/messages-IQxGfQIV.mjs +47 -0
  63. package/dist/chunks/messages-JF2fzCkK.mjs +47 -0
  64. package/dist/chunks/messages-MOGl7I5v.mjs +47 -0
  65. package/dist/chunks/messages-QgYhPL-3.mjs +47 -0
  66. package/dist/chunks/messages-WYWIbQwo.mjs +47 -0
  67. package/dist/chunks/messages-a6A_LgDv.mjs +47 -0
  68. package/dist/chunks/messages-bSf31LJi.mjs +47 -0
  69. package/dist/chunks/messages-diGozhTn.mjs +47 -0
  70. package/dist/chunks/messages-er-kd-VO.mjs +47 -0
  71. package/dist/chunks/messages-ez3w5NBn.mjs +47 -0
  72. package/dist/chunks/messages-f3uXjegd.mjs +47 -0
  73. package/dist/chunks/messages-ohwI1UGv.mjs +47 -0
  74. package/dist/chunks/messages-p9BZJaFV.mjs +47 -0
  75. package/dist/chunks/messages-qIQ4L4rw.mjs +47 -0
  76. package/dist/chunks/messages-qWkXPggi.mjs +47 -0
  77. package/dist/chunks/messages-w5foGze_.mjs +47 -0
  78. package/dist/full.mjs +50 -0
  79. package/dist/locales.mjs +227 -0
  80. package/dist/messages-2434tVOK.mjs +47 -0
  81. package/dist/messages-3DcCwXMF.mjs +47 -0
  82. package/dist/messages-4kMwVAKY.mjs +47 -0
  83. package/dist/messages-57uL5htT.mjs +47 -0
  84. package/dist/messages-76-iJV9Q.mjs +47 -0
  85. package/dist/messages-8p86Eyf2.mjs +47 -0
  86. package/dist/messages-BBX0p0Pi.mjs +47 -0
  87. package/dist/messages-BCm2eudQ.mjs +47 -0
  88. package/dist/messages-BFiUomgG.mjs +47 -0
  89. package/dist/messages-BIPNHHAV.mjs +47 -0
  90. package/dist/messages-BUlwu9mo.mjs +47 -0
  91. package/dist/messages-BX-DPa-z.mjs +47 -0
  92. package/dist/messages-BextV3Qh.mjs +47 -0
  93. package/dist/messages-BiPSFlUG.mjs +47 -0
  94. package/dist/messages-BiXe9G-O.mjs +47 -0
  95. package/dist/messages-Bl5z_Igo.mjs +47 -0
  96. package/dist/messages-BnsE97ku.mjs +47 -0
  97. package/dist/messages-BoO8gsVD.mjs +47 -0
  98. package/dist/messages-BqWaOGMn.mjs +47 -0
  99. package/dist/messages-BqkL2_Ro.mjs +47 -0
  100. package/dist/messages-BvCkXKX-.mjs +47 -0
  101. package/dist/messages-C6tbPLoj.mjs +47 -0
  102. package/dist/messages-CA6T3-gQ.mjs +47 -0
  103. package/dist/messages-CFFPFdWP.mjs +47 -0
  104. package/dist/messages-CFrKE-TN.mjs +47 -0
  105. package/dist/messages-CHz8VlG-.mjs +47 -0
  106. package/dist/messages-CLixzySl.mjs +47 -0
  107. package/dist/messages-CV7OM_qk.mjs +47 -0
  108. package/dist/messages-CXHt3eCC.mjs +47 -0
  109. package/dist/messages-CbmsBrB0.mjs +47 -0
  110. package/dist/messages-Ceo1KtFx.mjs +47 -0
  111. package/dist/messages-Cm0LJLtB.mjs +47 -0
  112. package/dist/messages-CmymP_Ar.mjs +47 -0
  113. package/dist/messages-D0ohMB5H.mjs +47 -0
  114. package/dist/messages-D3GrDwXh.mjs +47 -0
  115. package/dist/messages-D3vTzIpL.mjs +47 -0
  116. package/dist/messages-D5WeksbV.mjs +47 -0
  117. package/dist/messages-DGaab4EP.mjs +47 -0
  118. package/dist/messages-DKha57ZU.mjs +47 -0
  119. package/dist/messages-DOaujgMW.mjs +47 -0
  120. package/dist/messages-DVbPLd_0.mjs +47 -0
  121. package/dist/messages-D_FCyfW6.mjs +47 -0
  122. package/dist/messages-Dd5iZN3c.mjs +47 -0
  123. package/dist/messages-DehM7135.mjs +47 -0
  124. package/dist/messages-Dg1OHftD.mjs +47 -0
  125. package/dist/messages-Di6Flq-b.mjs +47 -0
  126. package/dist/messages-Dqhhex6e.mjs +47 -0
  127. package/dist/messages-DueVe0F1.mjs +47 -0
  128. package/dist/messages-Dx3eFwI0.mjs +47 -0
  129. package/dist/messages-FOtiUoKl.mjs +47 -0
  130. package/dist/messages-FTOZNhRD.mjs +47 -0
  131. package/dist/messages-IQxGfQIV.mjs +47 -0
  132. package/dist/messages-JF2fzCkK.mjs +47 -0
  133. package/dist/messages-MOGl7I5v.mjs +47 -0
  134. package/dist/messages-QgYhPL-3.mjs +47 -0
  135. package/dist/messages-WYWIbQwo.mjs +47 -0
  136. package/dist/messages-a6A_LgDv.mjs +47 -0
  137. package/dist/messages-bSf31LJi.mjs +47 -0
  138. package/dist/messages-diGozhTn.mjs +47 -0
  139. package/dist/messages-er-kd-VO.mjs +47 -0
  140. package/dist/messages-ez3w5NBn.mjs +47 -0
  141. package/dist/messages-f3uXjegd.mjs +47 -0
  142. package/dist/messages-ohwI1UGv.mjs +47 -0
  143. package/dist/messages-p9BZJaFV.mjs +47 -0
  144. package/dist/messages-qIQ4L4rw.mjs +47 -0
  145. package/dist/messages-qWkXPggi.mjs +47 -0
  146. package/dist/messages-w5foGze_.mjs +47 -0
  147. package/dist/tools.mjs +3073 -0
  148. package/dist/vendor.LICENSE.txt +26 -225
  149. package/package.json +49 -23
  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 +1427 -0
  154. package/src/components/block-tunes/block-tune-delete.ts +51 -0
  155. package/src/components/blocks.ts +338 -0
  156. package/src/components/constants/data-attributes.ts +342 -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 +481 -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 +44 -0
  177. package/src/components/i18n/locales/ar/messages.json +44 -0
  178. package/src/components/i18n/locales/az/messages.json +44 -0
  179. package/src/components/i18n/locales/bg/messages.json +44 -0
  180. package/src/components/i18n/locales/bn/messages.json +44 -0
  181. package/src/components/i18n/locales/bs/messages.json +44 -0
  182. package/src/components/i18n/locales/cs/messages.json +44 -0
  183. package/src/components/i18n/locales/da/messages.json +44 -0
  184. package/src/components/i18n/locales/de/messages.json +44 -0
  185. package/src/components/i18n/locales/dv/messages.json +44 -0
  186. package/src/components/i18n/locales/el/messages.json +44 -0
  187. package/src/components/i18n/locales/en/messages.json +44 -0
  188. package/src/components/i18n/locales/es/messages.json +44 -0
  189. package/src/components/i18n/locales/et/messages.json +44 -0
  190. package/src/components/i18n/locales/fa/messages.json +44 -0
  191. package/src/components/i18n/locales/fi/messages.json +44 -0
  192. package/src/components/i18n/locales/fil/messages.json +44 -0
  193. package/src/components/i18n/locales/fr/messages.json +44 -0
  194. package/src/components/i18n/locales/gu/messages.json +44 -0
  195. package/src/components/i18n/locales/he/messages.json +44 -0
  196. package/src/components/i18n/locales/hi/messages.json +44 -0
  197. package/src/components/i18n/locales/hr/messages.json +44 -0
  198. package/src/components/i18n/locales/hu/messages.json +44 -0
  199. package/src/components/i18n/locales/hy/messages.json +44 -0
  200. package/src/components/i18n/locales/id/messages.json +44 -0
  201. package/src/components/i18n/locales/index.ts +225 -0
  202. package/src/components/i18n/locales/it/messages.json +44 -0
  203. package/src/components/i18n/locales/ja/messages.json +44 -0
  204. package/src/components/i18n/locales/ka/messages.json +44 -0
  205. package/src/components/i18n/locales/km/messages.json +44 -0
  206. package/src/components/i18n/locales/kn/messages.json +44 -0
  207. package/src/components/i18n/locales/ko/messages.json +44 -0
  208. package/src/components/i18n/locales/ku/messages.json +44 -0
  209. package/src/components/i18n/locales/lo/messages.json +44 -0
  210. package/src/components/i18n/locales/lt/messages.json +44 -0
  211. package/src/components/i18n/locales/lv/messages.json +44 -0
  212. package/src/components/i18n/locales/mk/messages.json +44 -0
  213. package/src/components/i18n/locales/ml/messages.json +44 -0
  214. package/src/components/i18n/locales/mn/messages.json +44 -0
  215. package/src/components/i18n/locales/mr/messages.json +44 -0
  216. package/src/components/i18n/locales/ms/messages.json +44 -0
  217. package/src/components/i18n/locales/my/messages.json +44 -0
  218. package/src/components/i18n/locales/ne/messages.json +44 -0
  219. package/src/components/i18n/locales/nl/messages.json +44 -0
  220. package/src/components/i18n/locales/no/messages.json +44 -0
  221. package/src/components/i18n/locales/pa/messages.json +44 -0
  222. package/src/components/i18n/locales/pl/messages.json +44 -0
  223. package/src/components/i18n/locales/ps/messages.json +44 -0
  224. package/src/components/i18n/locales/pt/messages.json +44 -0
  225. package/src/components/i18n/locales/ro/messages.json +44 -0
  226. package/src/components/i18n/locales/ru/messages.json +44 -0
  227. package/src/components/i18n/locales/sd/messages.json +44 -0
  228. package/src/components/i18n/locales/si/messages.json +44 -0
  229. package/src/components/i18n/locales/sk/messages.json +44 -0
  230. package/src/components/i18n/locales/sl/messages.json +44 -0
  231. package/src/components/i18n/locales/sq/messages.json +44 -0
  232. package/src/components/i18n/locales/sr/messages.json +44 -0
  233. package/src/components/i18n/locales/sv/messages.json +44 -0
  234. package/src/components/i18n/locales/sw/messages.json +44 -0
  235. package/src/components/i18n/locales/ta/messages.json +44 -0
  236. package/src/components/i18n/locales/te/messages.json +44 -0
  237. package/src/components/i18n/locales/th/messages.json +44 -0
  238. package/src/components/i18n/locales/tr/messages.json +44 -0
  239. package/src/components/i18n/locales/ug/messages.json +44 -0
  240. package/src/components/i18n/locales/uk/messages.json +44 -0
  241. package/src/components/i18n/locales/ur/messages.json +44 -0
  242. package/src/components/i18n/locales/vi/messages.json +44 -0
  243. package/src/components/i18n/locales/yi/messages.json +44 -0
  244. package/src/components/i18n/locales/zh/messages.json +44 -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 +141 -0
  248. package/src/components/inline-tools/inline-tool-italic.ts +500 -0
  249. package/src/components/inline-tools/inline-tool-link.ts +539 -0
  250. package/src/components/modules/api/blocks.ts +363 -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 +33 -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 +1375 -0
  269. package/src/components/modules/blockManager.ts +1348 -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 +1141 -0
  274. package/src/components/modules/history.ts +1098 -0
  275. package/src/components/modules/i18n.ts +325 -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 +668 -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 +776 -0
  284. package/src/components/modules/toolbar/index.ts +1311 -0
  285. package/src/components/modules/toolbar/inline.ts +956 -0
  286. package/src/components/modules/tools.ts +589 -0
  287. package/src/components/modules/ui.ts +1179 -0
  288. package/src/components/polyfills.ts +113 -0
  289. package/src/components/selection.ts +1189 -0
  290. package/src/components/tools/base.ts +274 -0
  291. package/src/components/tools/block.ts +291 -0
  292. package/src/components/tools/collection.ts +67 -0
  293. package/src/components/tools/factory.ts +85 -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 +497 -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 +666 -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 +187 -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 +181 -0
  330. package/src/components/utils/popover/components/search-input/search-input.types.ts +30 -0
  331. package/src/components/utils/popover/index.ts +13 -0
  332. package/src/components/utils/popover/popover-abstract.ts +448 -0
  333. package/src/components/utils/popover/popover-desktop.ts +643 -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 +105 -0
  344. package/src/components/utils/tooltip.ts +642 -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 +844 -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 +123 -0
  366. package/src/tools/header/index.ts +570 -0
  367. package/src/tools/index.ts +38 -0
  368. package/src/tools/list/index.ts +1803 -0
  369. package/src/tools/paragraph/index.ts +411 -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 +1 -1
  378. package/types/api/i18n.d.ts +5 -3
  379. package/types/api/selection.d.ts +6 -0
  380. package/types/api/styles.d.ts +23 -10
  381. package/types/configs/blok-config.d.ts +29 -0
  382. package/types/configs/i18n-config.d.ts +52 -2
  383. package/types/configs/i18n-dictionary.d.ts +16 -90
  384. package/types/data-attributes.d.ts +169 -0
  385. package/types/data-formats/output-data.d.ts +15 -0
  386. package/types/full.d.ts +80 -0
  387. package/types/index.d.ts +9 -12
  388. package/types/locales.d.ts +59 -0
  389. package/types/tools/adapters/inline-tool-adapter.d.ts +10 -0
  390. package/types/tools/block-tool.d.ts +9 -0
  391. package/types/tools/header.d.ts +18 -0
  392. package/types/tools/index.d.ts +1 -0
  393. package/types/tools/list.d.ts +91 -0
  394. package/types/tools/paragraph.d.ts +71 -0
  395. package/types/tools/tool-settings.d.ts +16 -2
  396. package/types/tools/tool.d.ts +6 -0
  397. package/types/tools-entry.d.ts +49 -0
  398. package/types/utils/popover/popover-item.d.ts +6 -5
  399. package/dist/blok-B870U2fw.mjs +0 -25803
  400. package/dist/blok.umd.js +0 -181
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Class allows to make a queue of async jobs and wait until they all will be finished one by one
3
+ * @example const queue = new PromiseQueue();
4
+ * queue.add(async () => { ... });
5
+ * queue.add(async () => { ... });
6
+ * await queue.completed;
7
+ */
8
+ export class PromiseQueue {
9
+ /**
10
+ * Tail promise representing the queued operations chain
11
+ */
12
+ private tail: Promise<void> = Promise.resolve();
13
+
14
+ /**
15
+ * Stored failure that should be propagated to consumers
16
+ */
17
+ private failure: unknown;
18
+
19
+ /**
20
+ * Expose completion promise that rejects if any queued task failed
21
+ */
22
+ public get completed(): Promise<void> {
23
+ return this.failure ? Promise.reject(this.failure) : this.tail;
24
+ }
25
+
26
+ /**
27
+ * Add new promise to queue
28
+ * @param operation - promise should be added to queue
29
+ */
30
+ public add(operation: () => void | PromiseLike<void>): Promise<void> {
31
+ if (this.failure) {
32
+ return Promise.reject(this.failure);
33
+ }
34
+
35
+ const task = this.tail.then(() => operation());
36
+
37
+ this.tail = task.catch((error) => {
38
+ this.failure = error;
39
+ });
40
+
41
+ return task;
42
+ }
43
+ }
@@ -0,0 +1,537 @@
1
+
2
+ /**
3
+ * Blok Sanitizer
4
+ *
5
+ * Clears HTML from taint tags
6
+ * @version 2.0.0
7
+ * @example
8
+ *
9
+ * clean(yourTaintString, yourConfig);
10
+ *
11
+ * {@link SanitizerConfig}
12
+ */
13
+
14
+ import { deepMerge, isBoolean, isEmpty, isFunction, isObject, isString } from '../utils';
15
+
16
+ /**
17
+ * @typedef {object} SanitizerConfig
18
+ * @property {object} tags - define tags restrictions
19
+ * @example
20
+ *
21
+ * tags : {
22
+ * p: true,
23
+ * a: {
24
+ * href: true,
25
+ * rel: "nofollow",
26
+ * target: "_blank"
27
+ * }
28
+ * }
29
+ */
30
+
31
+ import HTMLJanitor from 'html-janitor';
32
+ import type { BlockToolData, SanitizerConfig, SanitizerRule } from '../../../types';
33
+ import type { TagConfig } from '../../../types/configs/sanitizer-config';
34
+ import type { SavedData } from '../../../types/data-formats';
35
+
36
+ type DeepSanitizerRule = SanitizerConfig | SanitizerRule | boolean;
37
+
38
+ const UNSAFE_URL_PROTOCOL_PATTERN = /^\s*(?:javascript\s*:|data\s*:\s*text\s*\/\s*html)/i;
39
+ const UNSAFE_URL_ATTR_FALLBACK_PATTERN =
40
+ /\s*(?:href|src)\s*=\s*(?:"\s*(?:javascript\s*:|data\s*:\s*text\s*\/\s*html)[^"]*"|'\s*(?:javascript\s*:|data\s*:\s*text\s*\/\s*html)[^']*|(?:javascript\s*:|data\s*:\s*text\s*\/\s*html)[^ \t\r\n>]*)/gi;
41
+
42
+ /**
43
+ * Sanitize Blocks
44
+ *
45
+ * Enumerate blocks and clean data
46
+ * @param blocksData - blocks' data to sanitize
47
+ * @param sanitizeConfig — sanitize config to use or function to get config for Tool
48
+ * @param globalSanitizer — global sanitizer config defined on blok level
49
+ */
50
+ export const sanitizeBlocks = (
51
+ blocksData: Array<Pick<SavedData, 'data' | 'tool'>>,
52
+ sanitizeConfig: SanitizerConfig | ((toolName: string) => SanitizerConfig | undefined),
53
+ globalSanitizer: SanitizerConfig = {} as SanitizerConfig
54
+ ): Array<Pick<SavedData, 'data' | 'tool'>> => {
55
+ return blocksData.map((block) => {
56
+ const toolConfig = isFunction(sanitizeConfig) ? sanitizeConfig(block.tool) : sanitizeConfig;
57
+ const rules: DeepSanitizerRule = (toolConfig ?? {}) as SanitizerConfig;
58
+
59
+ if (isObject(rules) && isEmpty(rules) && isEmpty(globalSanitizer)) {
60
+ return block;
61
+ }
62
+
63
+ return {
64
+ ...block,
65
+ data: deepSanitize(block.data, rules, globalSanitizer) as BlockToolData,
66
+ };
67
+ });
68
+ };
69
+ /**
70
+ * Cleans string from unwanted tags
71
+ * Method allows to use default config
72
+ * @param {string} taintString - taint string
73
+ * @param {SanitizerConfig} customConfig - allowed tags
74
+ * @returns {string} clean HTML
75
+ */
76
+ export const clean = (taintString: string, customConfig: SanitizerConfig = {} as SanitizerConfig): string => {
77
+ const sanitizerConfig = {
78
+ tags: customConfig,
79
+ };
80
+
81
+ /**
82
+ * API client can use custom config to manage sanitize process
83
+ */
84
+ const sanitizerInstance = new HTMLJanitor(sanitizerConfig);
85
+
86
+ return sanitizerInstance.clean(taintString);
87
+ };
88
+
89
+ /**
90
+ * Method recursively reduces Block's data and cleans with passed rules
91
+ * @param {BlockToolData|object|*} dataToSanitize - taint string or object/array that contains taint string
92
+ * @param {SanitizerConfig} rules - object with sanitizer rules
93
+ * @param {SanitizerConfig} globalRules - global sanitizer config
94
+ */
95
+ const deepSanitize = (
96
+ dataToSanitize: object | string,
97
+ rules: DeepSanitizerRule,
98
+ globalRules: SanitizerConfig
99
+ ): object | string => {
100
+ /**
101
+ * BlockData It may contain 3 types:
102
+ * - Array
103
+ * - Object
104
+ * - Primitive
105
+ */
106
+ if (Array.isArray(dataToSanitize)) {
107
+ /**
108
+ * Array: call sanitize for each item
109
+ */
110
+ return cleanArray(dataToSanitize, rules, globalRules);
111
+ }
112
+
113
+ if (isObject(dataToSanitize)) {
114
+ /**
115
+ * Objects: just clean object deeper.
116
+ */
117
+ return cleanObject(dataToSanitize, rules, globalRules);
118
+ }
119
+
120
+ /**
121
+ * Primitives (number|string|boolean): clean this item
122
+ *
123
+ * Clean only strings
124
+ */
125
+ if (isString(dataToSanitize)) {
126
+ return cleanOneItem(dataToSanitize, rules, globalRules);
127
+ }
128
+
129
+ return dataToSanitize;
130
+ };
131
+
132
+ /**
133
+ * Clean array
134
+ * @param {Array} array - [1, 2, {}, []]
135
+ * @param {SanitizerConfig} ruleForItem - sanitizer config for array
136
+ * @param {SanitizerConfig} globalRules - global sanitizer config
137
+ */
138
+ const cleanArray = (
139
+ array: Array<object | string>,
140
+ ruleForItem: DeepSanitizerRule,
141
+ globalRules: SanitizerConfig
142
+ ): Array<object | string> => {
143
+ return array.map((arrayItem) => deepSanitize(arrayItem, ruleForItem, globalRules));
144
+ };
145
+
146
+ /**
147
+ * Clean object
148
+ * @param {object} object - {level: 0, text: 'adada', items: [1,2,3]}}
149
+ * @param {object} rules - { b: true } or true|false
150
+ * @param {SanitizerConfig} globalRules - global sanitizer config
151
+ * @returns {object}
152
+ */
153
+ const cleanObject = (
154
+ object: object,
155
+ rules: DeepSanitizerRule | Record<string, DeepSanitizerRule>,
156
+ globalRules: SanitizerConfig
157
+ ): object => {
158
+ const cleanData: Record<string, unknown> = {};
159
+ const objectRecord = object as Record<string, unknown>;
160
+
161
+ for (const fieldName in object) {
162
+ if (!Object.prototype.hasOwnProperty.call(object, fieldName)) {
163
+ continue;
164
+ }
165
+
166
+ const currentIterationItem = objectRecord[fieldName];
167
+
168
+ /**
169
+ * Get object from config by field name
170
+ * - if it is a HTML Janitor rule, call with this rule
171
+ * - otherwise, call with parent's config
172
+ */
173
+ const rulesRecord = isObject(rules) ? (rules as Record<string, DeepSanitizerRule>) : undefined;
174
+ const ruleCandidate = rulesRecord?.[fieldName];
175
+ const ruleForItem = ruleCandidate !== undefined && isRule(ruleCandidate)
176
+ ? ruleCandidate
177
+ : rules;
178
+
179
+ cleanData[fieldName] = deepSanitize(currentIterationItem as object | string, ruleForItem as DeepSanitizerRule, globalRules);
180
+ }
181
+
182
+ return cleanData;
183
+ };
184
+
185
+ /**
186
+ * Clean primitive value
187
+ * @param {string} taintString - string to clean
188
+ * @param {SanitizerConfig|boolean} rule - sanitizer rule
189
+ * @param {SanitizerConfig} globalRules - global sanitizer config
190
+ * @returns {string}
191
+ */
192
+ const cleanOneItem = (
193
+ taintString: string,
194
+ rule: DeepSanitizerRule,
195
+ globalRules: SanitizerConfig
196
+ ): string => {
197
+ const effectiveRule = getEffectiveRuleForString(rule, globalRules);
198
+
199
+ if (effectiveRule) {
200
+ const cleaned = clean(taintString, effectiveRule);
201
+
202
+ return stripUnsafeUrls(applyAttributeOverrides(cleaned, effectiveRule));
203
+ }
204
+
205
+ if (!isEmpty(globalRules)) {
206
+ const cleaned = clean(taintString, globalRules);
207
+
208
+ return stripUnsafeUrls(applyAttributeOverrides(cleaned, globalRules));
209
+ }
210
+
211
+ return stripUnsafeUrls(taintString);
212
+ };
213
+
214
+ /**
215
+ * Check if passed item is a HTML Janitor rule:
216
+ * { a : true }, {}, false, true, function(){} — correct rules
217
+ * undefined, null, 0, 1, 2 — not a rules
218
+ * @param {SanitizerConfig} config - config to check
219
+ */
220
+ const isRule = (config: DeepSanitizerRule): boolean => {
221
+ return isObject(config) || isBoolean(config) || isFunction(config);
222
+ };
223
+
224
+ /**
225
+ *
226
+ * @param {string} value - HTML string to strip unsafe URLs from
227
+ */
228
+ const hasUnsafeUrlProtocol = (value: string | null): boolean => {
229
+ if (!value) {
230
+ return false;
231
+ }
232
+
233
+ return UNSAFE_URL_PROTOCOL_PATTERN.test(value);
234
+ };
235
+
236
+ const stripUnsafeUrls = (value: string): string => {
237
+ if (!value || value.indexOf('<') === -1) {
238
+ return value;
239
+ }
240
+
241
+ if (typeof document !== 'undefined') {
242
+ const template = document.createElement('template');
243
+
244
+ template.innerHTML = value;
245
+
246
+ const elements = template.content.querySelectorAll('[href],[src]');
247
+
248
+ elements.forEach((element) => {
249
+ ['href', 'src'].forEach((attribute) => {
250
+ const attrValue = element.getAttribute(attribute);
251
+
252
+ if (hasUnsafeUrlProtocol(attrValue)) {
253
+ element.removeAttribute(attribute);
254
+ }
255
+ });
256
+ });
257
+
258
+ return template.innerHTML;
259
+ }
260
+
261
+ return value.replace(UNSAFE_URL_ATTR_FALLBACK_PATTERN, '');
262
+ };
263
+
264
+ /**
265
+ *
266
+ * @param {SanitizerConfig} config - sanitizer config to clone
267
+ */
268
+ const cloneSanitizerConfig = (config: SanitizerConfig): SanitizerConfig => {
269
+ if (isEmpty(config)) {
270
+ return {} as SanitizerConfig;
271
+ }
272
+
273
+ const cloned: SanitizerConfig = {} as SanitizerConfig;
274
+
275
+ for (const tag in config) {
276
+ if (!Object.prototype.hasOwnProperty.call(config, tag)) {
277
+ continue;
278
+ }
279
+
280
+ cloned[tag] = cloneTagConfig(config[tag]);
281
+ }
282
+
283
+ return cloned;
284
+ };
285
+
286
+ /**
287
+ *
288
+ * @param {SanitizerRule} rule - tag rule to clone
289
+ */
290
+ type SanitizerFunctionRule = (el: Element) => TagConfig;
291
+
292
+ const wrapFunctionRule = (rule: SanitizerFunctionRule): SanitizerFunctionRule => {
293
+ return function wrappedRule(this: unknown, element: Element): TagConfig {
294
+ const result = rule.call(this, element);
295
+
296
+ if (result == null) {
297
+ return {};
298
+ }
299
+
300
+ return result;
301
+ };
302
+ };
303
+
304
+ const SAFE_ATTRIBUTES = new Set(['class', 'id', 'title', 'role', 'dir', 'lang']);
305
+
306
+ const isSafeAttribute = (attribute: string): boolean => {
307
+ const lowerName = attribute.toLowerCase();
308
+
309
+ return lowerName.startsWith('data-') || lowerName.startsWith('aria-') || SAFE_ATTRIBUTES.has(lowerName);
310
+ };
311
+
312
+ const preserveExistingAttributesRule: SanitizerFunctionRule = (element) => {
313
+ const preserved: TagConfig = {};
314
+
315
+ Array.from(element.attributes).forEach((attribute) => {
316
+ if (!isSafeAttribute(attribute.name)) {
317
+ return;
318
+ }
319
+
320
+ preserved[attribute.name] = true;
321
+ });
322
+
323
+ return preserved;
324
+ };
325
+
326
+ const cloneTagConfig = (rule: SanitizerRule): SanitizerRule => {
327
+ if (rule === true) {
328
+ return wrapFunctionRule(preserveExistingAttributesRule);
329
+ }
330
+
331
+ if (rule === false) {
332
+ return false;
333
+ }
334
+
335
+ if (isFunction(rule)) {
336
+ return wrapFunctionRule(rule as SanitizerFunctionRule);
337
+ }
338
+
339
+ if (isString(rule)) {
340
+ return rule;
341
+ }
342
+
343
+ if (isObject(rule)) {
344
+ return deepMerge({}, rule as Record<string, unknown>) as SanitizerRule;
345
+ }
346
+
347
+ return rule;
348
+ };
349
+
350
+ /**
351
+ *
352
+ * @param {SanitizerConfig} globalRules - global sanitizer config
353
+ * @param {SanitizerConfig} fieldRules - field-specific sanitizer config
354
+ */
355
+ const mergeTagRules = (globalRules: SanitizerConfig, fieldRules: SanitizerConfig): SanitizerConfig => {
356
+ if (isEmpty(globalRules)) {
357
+ return cloneSanitizerConfig(fieldRules);
358
+ }
359
+
360
+ const merged: SanitizerConfig = {} as SanitizerConfig;
361
+
362
+ for (const tag in globalRules) {
363
+ if (!Object.prototype.hasOwnProperty.call(globalRules, tag)) {
364
+ continue;
365
+ }
366
+
367
+ const globalValue = globalRules[tag];
368
+ const fieldValue = fieldRules ? fieldRules[tag] : undefined;
369
+
370
+ if (isFunction(fieldValue)) {
371
+ merged[tag] = cloneTagConfig(fieldValue as SanitizerRule);
372
+
373
+ continue;
374
+ }
375
+
376
+ if (isFunction(globalValue)) {
377
+ merged[tag] = cloneTagConfig(globalValue as SanitizerRule);
378
+
379
+ continue;
380
+ }
381
+
382
+ if (isObject(globalValue) && isObject(fieldValue)) {
383
+ merged[tag] = deepMerge({}, fieldValue as SanitizerConfig, globalValue as SanitizerConfig);
384
+
385
+ continue;
386
+ }
387
+
388
+ if (fieldValue !== undefined) {
389
+ merged[tag] = cloneTagConfig(fieldValue as SanitizerRule);
390
+
391
+ continue;
392
+ }
393
+
394
+ merged[tag] = cloneTagConfig(globalValue as SanitizerRule);
395
+ }
396
+
397
+ return merged;
398
+ };
399
+
400
+ /**
401
+ *
402
+ * @param {DeepSanitizerRule} rule - sanitizer rule to evaluate
403
+ * @param {SanitizerConfig} globalRules - global sanitizer config
404
+ */
405
+ const getEffectiveRuleForString = (
406
+ rule: DeepSanitizerRule,
407
+ globalRules: SanitizerConfig
408
+ ): SanitizerConfig | null => {
409
+ if (isObject(rule) && !isFunction(rule)) {
410
+ return mergeTagRules(globalRules, rule as SanitizerConfig);
411
+ }
412
+
413
+ if (rule === false) {
414
+ return {} as SanitizerConfig;
415
+ }
416
+
417
+ if (isEmpty(globalRules)) {
418
+ return null;
419
+ }
420
+
421
+ return cloneSanitizerConfig(globalRules);
422
+ };
423
+
424
+ /**
425
+ *
426
+ * @param {SanitizerConfig} globalConfig - base global sanitizer config
427
+ * @param {...SanitizerConfig[]} configs - additional sanitizer configs to compose
428
+ */
429
+ export const composeSanitizerConfig = (
430
+ globalConfig: SanitizerConfig,
431
+ ...configs: SanitizerConfig[]
432
+ ): SanitizerConfig => {
433
+ if (isEmpty(globalConfig)) {
434
+ return Object.assign({}, ...configs) as SanitizerConfig;
435
+ }
436
+
437
+ const base = cloneSanitizerConfig(globalConfig);
438
+
439
+ configs.forEach((config) => {
440
+ if (!config) {
441
+ return;
442
+ }
443
+
444
+ for (const tag in config) {
445
+ if (!Object.prototype.hasOwnProperty.call(config, tag)) {
446
+ continue;
447
+ }
448
+
449
+ const sourceValue = config[tag];
450
+
451
+ /**
452
+ * If the tag doesn't exist in base, skip it to respect the base config
453
+ */
454
+ if (!Object.prototype.hasOwnProperty.call(base, tag)) {
455
+ continue;
456
+ }
457
+
458
+ const targetValue = base[tag];
459
+
460
+ if (isFunction(sourceValue)) {
461
+ base[tag] = sourceValue;
462
+
463
+ continue;
464
+ }
465
+
466
+ if (sourceValue === true && isFunction(targetValue)) {
467
+ continue;
468
+ }
469
+
470
+ if (sourceValue === true) {
471
+ const targetIsPlainObject = isObject(targetValue) && !isFunction(targetValue);
472
+
473
+ base[tag] = targetIsPlainObject
474
+ ? deepMerge({}, targetValue as SanitizerConfig)
475
+ : cloneTagConfig(sourceValue as SanitizerRule);
476
+
477
+ continue;
478
+ }
479
+
480
+ if (isObject(sourceValue) && isObject(targetValue)) {
481
+ base[tag] = deepMerge({}, targetValue as SanitizerConfig, sourceValue as SanitizerConfig);
482
+
483
+ continue;
484
+ }
485
+
486
+ base[tag] = cloneTagConfig(sourceValue as SanitizerRule);
487
+ }
488
+ });
489
+
490
+ return base;
491
+ };
492
+
493
+ const applyAttributeOverrides = (html: string, rules: SanitizerConfig): string => {
494
+ if (typeof document === 'undefined' || !html || html.indexOf('<') === -1) {
495
+ return html;
496
+ }
497
+
498
+ const entries = Object.entries(rules).filter(([, value]) => isFunction(value));
499
+
500
+ if (entries.length === 0) {
501
+ return html;
502
+ }
503
+
504
+ const template = document.createElement('template');
505
+
506
+ template.innerHTML = html;
507
+
508
+ entries.forEach(([tag, rule]) => {
509
+ const elements = template.content.querySelectorAll(tag);
510
+
511
+ elements.forEach((element) => {
512
+ const ruleResult = (rule as (el: Element) => SanitizerRule)(element);
513
+
514
+ if (isBoolean(ruleResult) || isFunction(ruleResult) || ruleResult == null) {
515
+ return;
516
+ }
517
+
518
+ for (const [attr, attrRule] of Object.entries(ruleResult)) {
519
+ if (attrRule === false) {
520
+ element.removeAttribute(attr);
521
+
522
+ continue;
523
+ }
524
+
525
+ if (attrRule === true) {
526
+ continue;
527
+ }
528
+
529
+ if (isString(attrRule)) {
530
+ element.setAttribute(attr, attrRule);
531
+ }
532
+ }
533
+ });
534
+ });
535
+
536
+ return template.innerHTML;
537
+ };
@@ -0,0 +1,87 @@
1
+ import { isIosDevice } from '../utils';
2
+
3
+ /**
4
+ * Utility allowing to lock body scroll on demand
5
+ */
6
+ export class ScrollLocker {
7
+ /**
8
+ * Tailwind utility classes for styling
9
+ */
10
+ private static CSS = {
11
+ overflowHidden: 'overflow-hidden',
12
+ fixed: 'fixed',
13
+ wFull: 'w-full',
14
+ };
15
+
16
+ /**
17
+ * Data attributes for state management
18
+ */
19
+ private static DATA_ATTR = {
20
+ scrollLocked: 'data-blok-scroll-locked',
21
+ scrollLockedHard: 'data-blok-scroll-locked-hard',
22
+ };
23
+
24
+ /**
25
+ * Stores scroll position, used for hard scroll lock
26
+ */
27
+ private scrollPosition: null | number = null;
28
+
29
+ /**
30
+ * Locks body element scroll
31
+ */
32
+ public lock(): void {
33
+ if (isIosDevice) {
34
+ this.lockHard();
35
+ } else {
36
+ document.body.classList.add(ScrollLocker.CSS.overflowHidden);
37
+ document.body.setAttribute(ScrollLocker.DATA_ATTR.scrollLocked, 'true');
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Unlocks body element scroll
43
+ */
44
+ public unlock(): void {
45
+ if (isIosDevice) {
46
+ this.unlockHard();
47
+ } else {
48
+ document.body.classList.remove(ScrollLocker.CSS.overflowHidden);
49
+ document.body.removeAttribute(ScrollLocker.DATA_ATTR.scrollLocked);
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Locks scroll in a hard way (via setting fixed position to body element)
55
+ */
56
+ private lockHard(): void {
57
+ this.scrollPosition = window.pageYOffset;
58
+ document.documentElement.style.setProperty(
59
+ '--window-scroll-offset',
60
+ `${this.scrollPosition}px`
61
+ );
62
+ document.body.classList.add(
63
+ ScrollLocker.CSS.overflowHidden,
64
+ ScrollLocker.CSS.fixed,
65
+ ScrollLocker.CSS.wFull
66
+ );
67
+ document.body.style.top = `calc(-1 * var(--window-scroll-offset))`;
68
+ document.body.setAttribute(ScrollLocker.DATA_ATTR.scrollLockedHard, 'true');
69
+ }
70
+
71
+ /**
72
+ * Unlocks hard scroll lock
73
+ */
74
+ private unlockHard(): void {
75
+ document.body.classList.remove(
76
+ ScrollLocker.CSS.overflowHidden,
77
+ ScrollLocker.CSS.fixed,
78
+ ScrollLocker.CSS.wFull
79
+ );
80
+ document.body.style.top = '';
81
+ document.body.removeAttribute(ScrollLocker.DATA_ATTR.scrollLockedHard);
82
+ if (this.scrollPosition !== null) {
83
+ window.scrollTo(0, this.scrollPosition);
84
+ }
85
+ this.scrollPosition = null;
86
+ }
87
+ }