@jackuait/blok 0.4.1-beta.0 → 0.4.1-beta.11

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 (402) 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-oNSQ3HA6.mjs +13217 -0
  7. package/dist/chunks/i18next-CugVlwWp.mjs +1292 -0
  8. package/dist/chunks/i18next-loader-BdNRw4n4.mjs +43 -0
  9. package/dist/{index-OwEtDFlk.mjs → chunks/index-DHgXmfki.mjs} +2 -2
  10. package/dist/chunks/inline-tool-convert-CRqgjRim.mjs +1989 -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 +3117 -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 +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 +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 +781 -0
  284. package/src/components/modules/toolbar/index.ts +1315 -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 +601 -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 +186 -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 +676 -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 +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 +646 -0
  367. package/src/tools/index.ts +45 -0
  368. package/src/tools/list/index.ts +1819 -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/data-attributes.d.ts +170 -0
  386. package/types/data-formats/output-data.d.ts +15 -0
  387. package/types/full.d.ts +80 -0
  388. package/types/index.d.ts +30 -13
  389. package/types/locales.d.ts +59 -0
  390. package/types/tools/adapters/inline-tool-adapter.d.ts +10 -0
  391. package/types/tools/block-tool.d.ts +9 -0
  392. package/types/tools/header.d.ts +18 -0
  393. package/types/tools/index.d.ts +1 -0
  394. package/types/tools/list.d.ts +91 -0
  395. package/types/tools/paragraph.d.ts +71 -0
  396. package/types/tools/tool-settings.d.ts +92 -6
  397. package/types/tools/tool.d.ts +6 -0
  398. package/types/tools-entry.d.ts +49 -0
  399. package/types/utils/popover/popover-item.d.ts +18 -5
  400. package/types/utils/popover/popover.d.ts +7 -0
  401. package/dist/blok-D_baBvTG.mjs +0 -25795
  402. package/dist/blok.umd.js +0 -181
@@ -0,0 +1,296 @@
1
+ import { generateId } from '../utils';
2
+
3
+ /**
4
+ * Event listener information
5
+ * @interface ListenerData
6
+ */
7
+ export interface ListenerData {
8
+ /**
9
+ * Listener unique identifier
10
+ */
11
+ id: string;
12
+
13
+ /**
14
+ * Element where to listen to dispatched events
15
+ */
16
+ element: EventTarget;
17
+
18
+ /**
19
+ * Event to listen
20
+ */
21
+ eventType: string;
22
+
23
+ /**
24
+ * Event handler
25
+ * @param {Event} event - event object
26
+ */
27
+ handler: (event: Event) => void;
28
+
29
+ /**
30
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
31
+ */
32
+ options: boolean | AddEventListenerOptions;
33
+ }
34
+
35
+ interface NormalizedListenerOptions {
36
+ capture: boolean;
37
+ once: boolean;
38
+ passive: boolean;
39
+ signal?: AbortSignal | null;
40
+ }
41
+
42
+ /**
43
+ * Blok Listeners helper
44
+ *
45
+ * Decorator for event listeners assignment
46
+ * @author Blok Team
47
+ * @version 2.0.0
48
+ */
49
+
50
+ /**
51
+ * @typedef {Listeners} Listeners
52
+ * @property {ListenerData[]} allListeners - listeners store
53
+ */
54
+ export class Listeners {
55
+ /**
56
+ * Stores all listeners data to find/remove/process it
57
+ * @type {ListenerData[]}
58
+ */
59
+ private allListeners: ListenerData[] = [];
60
+
61
+ /**
62
+ * Assigns event listener on element and returns unique identifier
63
+ * @param {EventTarget} element - DOM element that needs to be listened
64
+ * @param {string} eventType - event type
65
+ * @param {Function} handler - method that will be fired on event
66
+ * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once}
67
+ */
68
+ public on(
69
+ element: EventTarget,
70
+ eventType: string,
71
+ handler: (event: Event) => void,
72
+ options: boolean | AddEventListenerOptions = false
73
+ ): string | undefined {
74
+ const alreadyExist = this.findOne(element, eventType, handler, options);
75
+
76
+ if (alreadyExist) {
77
+ return undefined;
78
+ }
79
+
80
+ const id = generateId('l');
81
+ const assignedEventData: ListenerData = {
82
+ id,
83
+ element,
84
+ eventType,
85
+ handler,
86
+ options,
87
+ };
88
+
89
+ this.allListeners.push(assignedEventData);
90
+ element.addEventListener(eventType, handler, options);
91
+
92
+ return id;
93
+ }
94
+
95
+ /**
96
+ * Removes event listener from element
97
+ * @param {EventTarget} element - DOM element that we removing listener
98
+ * @param {string} eventType - event type
99
+ * @param {Function} handler - remove handler, if element listens several handlers on the same event type
100
+ * @param {boolean|AddEventListenerOptions} options - useCapture or {capture, passive, once}
101
+ */
102
+ public off(
103
+ element: EventTarget,
104
+ eventType: string,
105
+ handler?: (event: Event) => void,
106
+ options?: boolean | AddEventListenerOptions
107
+ ): void {
108
+ const existingListeners = this.findAll(element, eventType, handler, options);
109
+
110
+ existingListeners.forEach((listener, i) => {
111
+ const index = this.allListeners.indexOf(existingListeners[i]);
112
+
113
+ if (index > -1) {
114
+ this.allListeners.splice(index, 1);
115
+
116
+ listener.element.removeEventListener(listener.eventType, listener.handler, listener.options);
117
+ }
118
+ });
119
+ }
120
+
121
+ /**
122
+ * Removes listener by id
123
+ * @param {string} id - listener identifier
124
+ */
125
+ public offById(id: string): void {
126
+ const listener = this.findById(id);
127
+
128
+ if (!listener) {
129
+ return;
130
+ }
131
+
132
+ listener.element.removeEventListener(listener.eventType, listener.handler, listener.options);
133
+ const index = this.allListeners.indexOf(listener);
134
+
135
+ if (index > -1) {
136
+ this.allListeners.splice(index, 1);
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Finds and returns first listener by passed params
142
+ * @param {EventTarget} element - event target
143
+ * @param {string} [eventType] - event type
144
+ * @param {Function} [handler] - event handler
145
+ * @param {boolean|AddEventListenerOptions} [options] - event options
146
+ * @returns {ListenerData|null}
147
+ */
148
+ public findOne(
149
+ element: EventTarget,
150
+ eventType?: string,
151
+ handler?: (event: Event) => void,
152
+ options?: boolean | AddEventListenerOptions
153
+ ): ListenerData | null {
154
+ const foundListeners = this.findAll(element, eventType, handler, options);
155
+
156
+ return foundListeners[0] ?? null;
157
+ }
158
+
159
+ /**
160
+ * Return all stored listeners by passed params
161
+ * @param {EventTarget} element - event target
162
+ * @param {string} eventType - event type
163
+ * @param {Function} handler - event handler
164
+ * @param {boolean|AddEventListenerOptions} [options] - event options
165
+ * @returns {ListenerData[]}
166
+ */
167
+ public findAll(
168
+ element: EventTarget,
169
+ eventType?: string,
170
+ handler?: (event: Event) => void,
171
+ options?: boolean | AddEventListenerOptions
172
+ ): ListenerData[] {
173
+ if (!element) {
174
+ return [];
175
+ }
176
+
177
+ const foundByEventTargets = this.findByEventTarget(element);
178
+
179
+ return foundByEventTargets.filter((listener) => {
180
+ const matchesEventType = eventType === undefined || listener.eventType === eventType;
181
+ const matchesHandler = handler === undefined || listener.handler === handler;
182
+ const matchesOptions = this.areOptionsEqual(listener.options, options);
183
+
184
+ return matchesEventType && matchesHandler && matchesOptions;
185
+ });
186
+ }
187
+
188
+ /**
189
+ * Removes all listeners
190
+ */
191
+ public removeAll(): void {
192
+ this.allListeners.forEach((current) => {
193
+ current.element.removeEventListener(current.eventType, current.handler, current.options);
194
+ });
195
+
196
+ this.allListeners = [];
197
+ }
198
+
199
+ /**
200
+ * Module cleanup on destruction
201
+ */
202
+ public destroy(): void {
203
+ this.removeAll();
204
+ }
205
+
206
+ /**
207
+ * Search method: looks for listener by passed element
208
+ * @param {EventTarget} element - searching element
209
+ * @returns {Array} listeners that found on element
210
+ */
211
+ private findByEventTarget(element: EventTarget): ListenerData[] {
212
+ return this.allListeners.filter((listener) => listener.element === element);
213
+ }
214
+
215
+ /**
216
+ * Search method: looks for listener by passed event type
217
+ * @param {string} eventType - event type
218
+ * @returns {ListenerData[]} listeners that found on element
219
+ */
220
+ private findByType(eventType: string): ListenerData[] {
221
+ return this.allListeners.filter((listener) => listener.eventType === eventType);
222
+ }
223
+
224
+ /**
225
+ * Search method: looks for listener by passed handler
226
+ * @param {Function} handler - event handler
227
+ * @returns {ListenerData[]} listeners that found on element
228
+ */
229
+ private findByHandler(handler: (event: Event) => void): ListenerData[] {
230
+ return this.allListeners.filter((listener) => listener.handler === handler);
231
+ }
232
+
233
+ /**
234
+ * Returns listener data found by id
235
+ * @param {string} id - listener identifier
236
+ * @returns {ListenerData}
237
+ */
238
+ private findById(id: string): ListenerData | undefined {
239
+ return this.allListeners.find((listener) => listener.id === id);
240
+ }
241
+
242
+ /**
243
+ * Normalizes listener options to a comparable shape
244
+ * @param {boolean|AddEventListenerOptions} [options] - event options
245
+ * @returns {NormalizedListenerOptions}
246
+ */
247
+ private normalizeListenerOptions(options?: boolean | AddEventListenerOptions): NormalizedListenerOptions {
248
+ if (typeof options === 'boolean') {
249
+ return {
250
+ capture: options,
251
+ once: false,
252
+ passive: false,
253
+ };
254
+ }
255
+
256
+ if (!options) {
257
+ return {
258
+ capture: false,
259
+ once: false,
260
+ passive: false,
261
+ };
262
+ }
263
+
264
+ return {
265
+ capture: options.capture ?? false,
266
+ once: options.once ?? false,
267
+ passive: options.passive ?? false,
268
+ signal: options.signal,
269
+ };
270
+ }
271
+
272
+ /**
273
+ * Compares stored listener options with provided ones
274
+ * @param {boolean|AddEventListenerOptions} storedOptions - stored event options
275
+ * @param {boolean|AddEventListenerOptions} [providedOptions] - provided event options
276
+ * @returns {boolean}
277
+ */
278
+ private areOptionsEqual(
279
+ storedOptions: boolean | AddEventListenerOptions,
280
+ providedOptions?: boolean | AddEventListenerOptions
281
+ ): boolean {
282
+ if (providedOptions === undefined) {
283
+ return true;
284
+ }
285
+
286
+ const storedNormalized = this.normalizeListenerOptions(storedOptions);
287
+ const providedNormalized = this.normalizeListenerOptions(providedOptions);
288
+
289
+ return (
290
+ storedNormalized.capture === providedNormalized.capture &&
291
+ storedNormalized.once === providedNormalized.once &&
292
+ storedNormalized.passive === providedNormalized.passive &&
293
+ storedNormalized.signal === providedNormalized.signal
294
+ );
295
+ }
296
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Check if passed mutation belongs to a passed element
3
+ * @param mutationRecord - mutation to check
4
+ * @param element - element that is expected to contain mutation
5
+ */
6
+ export const isMutationBelongsToElement = (mutationRecord: MutationRecord, element: Element): boolean => {
7
+ const { type, target, addedNodes, removedNodes } = mutationRecord;
8
+
9
+ /**
10
+ * Skip own technical mutations, for example, data-blok-empty attribute changes
11
+ */
12
+ if (mutationRecord.type === 'attributes' && mutationRecord.attributeName === 'data-blok-empty') {
13
+ return false;
14
+ }
15
+
16
+ /**
17
+ * Covers all types of mutations happened to the element or it's descendants with the only one exception - removing/adding the element itself;
18
+ */
19
+ if (element.contains(target)) {
20
+ return true;
21
+ }
22
+
23
+ /**
24
+ * In case of removing/adding the element itself, mutation type will be 'childList' and 'removedNodes'/'addedNodes' will contain the element.
25
+ */
26
+ if (type !== 'childList') {
27
+ return false;
28
+ }
29
+
30
+ const elementAddedItself = Array.from(addedNodes).some(node => node === element);
31
+
32
+ if (elementAddedItself) {
33
+ return true;
34
+ }
35
+
36
+ const elementRemovedItself = Array.from(removedNodes).some(node => node === element);
37
+
38
+ return elementRemovedItself;
39
+ };
@@ -0,0 +1,190 @@
1
+ import { twMerge, twJoin } from '../tw';
2
+ import type { NotifierOptions, ConfirmNotifierOptions, PromptNotifierOptions } from './types';
3
+
4
+ export const CSS = {
5
+ wrapper: twJoin(
6
+ 'fixed z-[2] bottom-5 left-5',
7
+ 'font-[-apple-system,BlinkMacSystemFont,"Segoe_UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira_Sans","Droid_Sans","Helvetica_Neue",sans-serif]'
8
+ ),
9
+ notification: twJoin(
10
+ 'relative w-[230px] mt-[15px] py-[13px] px-4',
11
+ 'bg-white shadow-[0_11px_17px_0_rgba(23,32,61,0.13)] rounded-[5px]',
12
+ 'text-sm leading-[1.4em] break-words',
13
+ 'before:content-[""] before:absolute before:block before:top-0 before:left-0',
14
+ 'before:w-[3px] before:h-[calc(100%-6px)] before:m-[3px] before:rounded-[5px] before:bg-transparent'
15
+ ),
16
+ crossBtn: twJoin(
17
+ 'absolute top-[7px] right-[15px] w-2.5 h-2.5 p-[5px] opacity-55 cursor-pointer',
18
+ 'before:content-[""] before:absolute before:left-[9px] before:top-[5px] before:h-3 before:w-0.5 before:bg-[#575d67] before:rotate-[-45deg]',
19
+ 'after:content-[""] after:absolute after:left-[9px] after:top-[5px] after:h-3 after:w-0.5 after:bg-[#575d67] after:rotate-45',
20
+ 'hover:opacity-100'
21
+ ),
22
+ btnsWrapper: 'flex flex-row flex-nowrap mt-[5px]',
23
+ btn: 'border-none rounded-[3px] text-[13px] py-[5px] px-2.5 cursor-pointer last:ml-2.5',
24
+ okBtn: 'bg-[#34c992] shadow-[0_1px_1px_0_rgba(18,49,35,0.05)] text-white hover:bg-[#2db583]',
25
+ cancelBtn: 'bg-[#f2f5f7] shadow-[0_2px_1px_0_rgba(16,19,29,0)] text-[#656b7c] hover:bg-[#e9ecee]',
26
+ input: twJoin(
27
+ 'max-w-[130px] py-[5px] px-2.5 bg-[#f7f7f7] border-0 rounded-[3px]',
28
+ 'text-[13px] text-[#656b7c] outline-none',
29
+ 'placeholder:text-[#656b7c] focus:placeholder:text-[rgba(101,107,124,0.3)]'
30
+ ),
31
+ successNotification: twJoin(
32
+ '!bg-[#fafffe]',
33
+ 'before:!bg-[#41ffb1]'
34
+ ),
35
+ errorNotification: twJoin(
36
+ '!bg-[#fffbfb]',
37
+ 'before:!bg-[#fb5d5d]'
38
+ ),
39
+ };
40
+
41
+ /**
42
+ * @param {NotifierOptions} options - options for the notification
43
+ * @returns {HTMLElement} - the notification element
44
+ */
45
+ export const alert = (options: NotifierOptions): HTMLElement => {
46
+ const notify = document.createElement('DIV');
47
+ const cross = document.createElement('DIV');
48
+ const message = options.message;
49
+ const style = options.style;
50
+
51
+ const getStyleClasses = (): string => {
52
+ if (style === 'success') {
53
+ return CSS.successNotification;
54
+ }
55
+
56
+ if (style === 'error') {
57
+ return CSS.errorNotification;
58
+ }
59
+
60
+ return '';
61
+ };
62
+
63
+ notify.className = twMerge(CSS.notification, getStyleClasses());
64
+
65
+ if (style) {
66
+ notify.setAttribute('data-blok-testid', `notification-${style}`);
67
+ } else {
68
+ notify.setAttribute('data-blok-testid', 'notification');
69
+ }
70
+
71
+ notify.innerHTML = message;
72
+
73
+ cross.className = CSS.crossBtn;
74
+ cross.setAttribute('data-blok-testid', 'notification-cross');
75
+ cross.addEventListener('click', () => notify.remove());
76
+
77
+ notify.appendChild(cross);
78
+
79
+ return notify;
80
+ };
81
+
82
+ /**
83
+ * @param {ConfirmNotifierOptions} options - options for the confirmation notification
84
+ * @returns {HTMLElement} - the notification element
85
+ */
86
+ export const confirm = (options: ConfirmNotifierOptions): HTMLElement => {
87
+ const notify = alert(options);
88
+ const btnsWrapper = document.createElement('div');
89
+ const okBtn = document.createElement('button');
90
+ const cancelBtn = document.createElement('button');
91
+ const crossBtn = notify.querySelector('[data-blok-testid="notification-cross"]');
92
+ const cancelHandler = options.cancelHandler;
93
+ const okHandler = options.okHandler;
94
+
95
+ btnsWrapper.className = CSS.btnsWrapper;
96
+ btnsWrapper.setAttribute('data-blok-testid', 'notification-buttons-wrapper');
97
+
98
+ okBtn.innerHTML = options.okText || 'Confirm';
99
+ cancelBtn.innerHTML = options.cancelText || 'Cancel';
100
+
101
+ okBtn.className = twJoin(CSS.btn, CSS.okBtn);
102
+ cancelBtn.className = twJoin(CSS.btn, CSS.cancelBtn);
103
+
104
+ okBtn.setAttribute('data-blok-testid', 'notification-confirm-button');
105
+ cancelBtn.setAttribute('data-blok-testid', 'notification-cancel-button');
106
+
107
+ if (cancelHandler && typeof cancelHandler === 'function') {
108
+ cancelBtn.addEventListener('click', cancelHandler);
109
+ }
110
+
111
+ if (cancelHandler && typeof cancelHandler === 'function' && crossBtn) {
112
+ crossBtn.addEventListener('click', cancelHandler);
113
+ }
114
+
115
+ if (okHandler && typeof okHandler === 'function') {
116
+ okBtn.addEventListener('click', okHandler);
117
+ }
118
+
119
+ okBtn.addEventListener('click', () => notify.remove());
120
+ cancelBtn.addEventListener('click', () => notify.remove());
121
+
122
+ btnsWrapper.appendChild(okBtn);
123
+ btnsWrapper.appendChild(cancelBtn);
124
+
125
+ notify.appendChild(btnsWrapper);
126
+
127
+ return notify;
128
+ };
129
+
130
+ /**
131
+ * @param {PromptNotifierOptions} options - options for the prompt notification
132
+ * @returns {HTMLElement} - the notification element
133
+ */
134
+ export const prompt = (options: PromptNotifierOptions): HTMLElement => {
135
+ const notify = alert(options);
136
+ const btnsWrapper = document.createElement('div');
137
+ const okBtn = document.createElement('button');
138
+ const input = document.createElement('input');
139
+ const crossBtn = notify.querySelector('[data-blok-testid="notification-cross"]');
140
+ const cancelHandler = options.cancelHandler;
141
+ const okHandler = options.okHandler;
142
+
143
+ btnsWrapper.className = CSS.btnsWrapper;
144
+
145
+ okBtn.innerHTML = options.okText || 'Ok';
146
+ okBtn.className = twJoin(CSS.btn, CSS.okBtn);
147
+
148
+ input.className = CSS.input;
149
+ input.setAttribute('data-blok-testid', 'notification-input');
150
+
151
+ if (options.placeholder) {
152
+ input.setAttribute('placeholder', options.placeholder);
153
+ }
154
+
155
+ if (options.default) {
156
+ input.value = options.default;
157
+ }
158
+
159
+ if (options.inputType) {
160
+ input.type = options.inputType;
161
+ }
162
+
163
+ if (cancelHandler && typeof cancelHandler === 'function' && crossBtn) {
164
+ crossBtn.addEventListener('click', cancelHandler);
165
+ }
166
+
167
+ if (okHandler && typeof okHandler === 'function') {
168
+ okBtn.addEventListener('click', () => {
169
+ okHandler(input.value);
170
+ });
171
+ }
172
+
173
+ okBtn.addEventListener('click', () => notify.remove());
174
+
175
+ btnsWrapper.appendChild(input);
176
+ btnsWrapper.appendChild(okBtn);
177
+
178
+ notify.appendChild(btnsWrapper);
179
+
180
+ return notify;
181
+ };
182
+
183
+ export const getWrapper = (): HTMLElement => {
184
+ const wrapper = document.createElement('DIV');
185
+
186
+ wrapper.className = CSS.wrapper;
187
+ wrapper.setAttribute('data-blok-testid', 'notifier-container');
188
+
189
+ return wrapper;
190
+ };
@@ -0,0 +1,66 @@
1
+ import { alert, confirm, getWrapper, prompt } from './draw';
2
+ import type { NotifierOptions, ConfirmNotifierOptions, PromptNotifierOptions } from './types';
3
+
4
+ const DEFAULT_TIME = 8000;
5
+
6
+ /**
7
+ * Prepare wrapper for notifications
8
+ * @returns {HTMLElement}
9
+ */
10
+ const prepare_ = (): HTMLElement => {
11
+ const existingWrapper = document.querySelector('[data-blok-testid="notifier-container"]') as HTMLElement;
12
+
13
+ if (existingWrapper) {
14
+ return existingWrapper;
15
+ }
16
+
17
+ const wrapper = getWrapper();
18
+
19
+ document.body.appendChild(wrapper);
20
+
21
+ return wrapper;
22
+ };
23
+
24
+ /**
25
+ * Show new notification
26
+ * @param {NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions} options - notification options
27
+ */
28
+ export const show = (options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions): void => {
29
+ if (!options.message) {
30
+ return;
31
+ }
32
+
33
+ const wrapper = prepare_();
34
+
35
+ const time = options.time || DEFAULT_TIME;
36
+
37
+ const notify: HTMLElement = (() => {
38
+ switch (options.type) {
39
+ case 'confirm':
40
+ return confirm(options as ConfirmNotifierOptions);
41
+
42
+ case 'prompt':
43
+ return prompt(options as PromptNotifierOptions);
44
+
45
+ default: {
46
+ const alertElement = alert(options);
47
+
48
+ window.setTimeout(() => {
49
+ alertElement.remove();
50
+ }, time);
51
+
52
+ return alertElement;
53
+ }
54
+ }
55
+ })();
56
+
57
+ if (wrapper && notify) {
58
+ wrapper.appendChild(notify);
59
+ notify.className = `${notify.className} animate-notify-bounce-in`;
60
+ notify.setAttribute('data-blok-bounce-in', 'true');
61
+ }
62
+ };
63
+
64
+ export const Notifier = {
65
+ show,
66
+ };
@@ -0,0 +1 @@
1
+ export type * from '@/types/configs/notifier';
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Use local module for notifications
3
+ */
4
+ import type { ConfirmNotifierOptions, NotifierOptions, PromptNotifierOptions } from './notifier/types';
5
+
6
+ type NotifierModule = {
7
+ show: (options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions) => void;
8
+ };
9
+
10
+ /**
11
+ * Util for showing notifications
12
+ */
13
+ export class Notifier {
14
+ /**
15
+ * Cached notifier module instance
16
+ */
17
+ private notifierModule: NotifierModule | null = null;
18
+
19
+ /**
20
+ * Promise used to avoid multiple parallel loads of the notifier module
21
+ */
22
+ private loadingPromise: Promise<NotifierModule> | null = null;
23
+
24
+ /**
25
+ * Lazily load notifier only when necessary.
26
+ * @returns {Promise<NotifierModule>} loaded notifier module
27
+ */
28
+ private loadNotifierModule(): Promise<NotifierModule> {
29
+ if (this.notifierModule !== null) {
30
+ return Promise.resolve(this.notifierModule);
31
+ }
32
+
33
+ if (this.loadingPromise === null) {
34
+ this.loadingPromise = import('./notifier/index')
35
+ .then((module) => {
36
+ const resolvedModule = module as unknown;
37
+
38
+ if (!this.isNotifierModule(resolvedModule)) {
39
+ throw new Error('notifier module does not expose a "show" method.');
40
+ }
41
+
42
+ this.notifierModule = resolvedModule;
43
+
44
+ return resolvedModule;
45
+ })
46
+ .catch((error) => {
47
+ this.loadingPromise = null;
48
+
49
+ throw error;
50
+ });
51
+ }
52
+
53
+ return this.loadingPromise;
54
+ }
55
+
56
+ /**
57
+ * Show web notification
58
+ * @param {NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions} options - notification options
59
+ */
60
+ public show(options: NotifierOptions | ConfirmNotifierOptions | PromptNotifierOptions): void {
61
+ void this.loadNotifierModule()
62
+ .then((notifier) => {
63
+ notifier.show(options);
64
+ })
65
+ .catch((error) => {
66
+ console.error('[Blok] Failed to display notification. Reason:', error);
67
+ });
68
+ }
69
+
70
+ /**
71
+ * Narrow unknown module to notifier module shape
72
+ * @param {unknown} candidate - module to verify
73
+ */
74
+ private isNotifierModule(candidate: unknown): candidate is NotifierModule {
75
+ return typeof candidate === 'object' && candidate !== null && 'show' in candidate && typeof (candidate as { show?: unknown }).show === 'function';
76
+ }
77
+ }