@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.
- package/README.md +138 -17
- package/codemod/README.md +45 -7
- package/codemod/migrate-editorjs-to-blok.js +960 -92
- package/codemod/test.js +780 -77
- package/dist/blok.mjs +5 -2
- package/dist/chunks/blok-oNSQ3HA6.mjs +13217 -0
- package/dist/chunks/i18next-CugVlwWp.mjs +1292 -0
- package/dist/chunks/i18next-loader-BdNRw4n4.mjs +43 -0
- package/dist/{index-OwEtDFlk.mjs → chunks/index-DHgXmfki.mjs} +2 -2
- package/dist/chunks/inline-tool-convert-CRqgjRim.mjs +1989 -0
- package/dist/chunks/messages-0tDXLuyH.mjs +48 -0
- package/dist/chunks/messages-2_xedlYw.mjs +48 -0
- package/dist/chunks/messages-AHESHJm_.mjs +48 -0
- package/dist/chunks/messages-B5hdXZwA.mjs +48 -0
- package/dist/chunks/messages-B5jGUnOy.mjs +48 -0
- package/dist/chunks/messages-B5puUm7R.mjs +48 -0
- package/dist/chunks/messages-B66ZSDCJ.mjs +48 -0
- package/dist/chunks/messages-B9Oba7sq.mjs +48 -0
- package/dist/chunks/messages-BA0rcTCY.mjs +48 -0
- package/dist/chunks/messages-BBJgd5jG.mjs +48 -0
- package/dist/chunks/messages-BPqWKx5Z.mjs +48 -0
- package/dist/chunks/messages-Bdv-IkfG.mjs +48 -0
- package/dist/chunks/messages-BeUhMpsr.mjs +48 -0
- package/dist/chunks/messages-Bf6Y3_GI.mjs +48 -0
- package/dist/chunks/messages-BiExzWJv.mjs +48 -0
- package/dist/chunks/messages-BlpqL8vG.mjs +48 -0
- package/dist/chunks/messages-BmKCChWZ.mjs +48 -0
- package/dist/chunks/messages-Bn253WWC.mjs +48 -0
- package/dist/chunks/messages-BrJHUxQL.mjs +48 -0
- package/dist/chunks/messages-C5b7hr_E.mjs +48 -0
- package/dist/chunks/messages-C7I_AVH2.mjs +48 -0
- package/dist/chunks/messages-CJoBtXU6.mjs +48 -0
- package/dist/chunks/messages-CQj2JU2j.mjs +48 -0
- package/dist/chunks/messages-CUZ1x1QD.mjs +48 -0
- package/dist/chunks/messages-CUy1vn-b.mjs +48 -0
- package/dist/chunks/messages-CVeWVKsV.mjs +48 -0
- package/dist/chunks/messages-CXHd9SUK.mjs +48 -0
- package/dist/chunks/messages-CbMyJSzS.mjs +48 -0
- package/dist/chunks/messages-CbhuIWRJ.mjs +48 -0
- package/dist/chunks/messages-CeCjVKMW.mjs +48 -0
- package/dist/chunks/messages-Cj-t1bdy.mjs +48 -0
- package/dist/chunks/messages-CkFT2gle.mjs +48 -0
- package/dist/chunks/messages-Cm9aLHeX.mjs +48 -0
- package/dist/chunks/messages-CnvW8Slp.mjs +48 -0
- package/dist/chunks/messages-Cr-RJ7YB.mjs +48 -0
- package/dist/chunks/messages-CrsJ1TEJ.mjs +48 -0
- package/dist/chunks/messages-Cu08aLS3.mjs +48 -0
- package/dist/chunks/messages-CvaqJFN-.mjs +48 -0
- package/dist/chunks/messages-CyDU5lz9.mjs +48 -0
- package/dist/chunks/messages-CySyfkMU.mjs +48 -0
- package/dist/chunks/messages-Cyi2AMmz.mjs +48 -0
- package/dist/chunks/messages-D00OjS2n.mjs +48 -0
- package/dist/chunks/messages-DDLgIPDF.mjs +48 -0
- package/dist/chunks/messages-DMQIHGRj.mjs +48 -0
- package/dist/chunks/messages-DOlC_Tty.mjs +48 -0
- package/dist/chunks/messages-DV6shA9b.mjs +48 -0
- package/dist/chunks/messages-DY94ykcE.mjs +48 -0
- package/dist/chunks/messages-DbVquYKN.mjs +48 -0
- package/dist/chunks/messages-DcKOuncK.mjs +48 -0
- package/dist/chunks/messages-Dg92dXZ5.mjs +48 -0
- package/dist/chunks/messages-DnbbyJT3.mjs +48 -0
- package/dist/chunks/messages-DteYq0rv.mjs +48 -0
- package/dist/chunks/messages-GC2PhgV3.mjs +48 -0
- package/dist/chunks/messages-JGsXAReJ.mjs +48 -0
- package/dist/chunks/messages-JZUhXTuV.mjs +48 -0
- package/dist/chunks/messages-LvFKBBPa.mjs +48 -0
- package/dist/chunks/messages-NP1myMGI.mjs +48 -0
- package/dist/chunks/messages-Q4kc_ZtL.mjs +48 -0
- package/dist/chunks/messages-RvMHb2Ht.mjs +48 -0
- package/dist/chunks/messages-ftMcCEuO.mjs +48 -0
- package/dist/chunks/messages-o24dK6CU.mjs +48 -0
- package/dist/chunks/messages-pA5TvcAj.mjs +48 -0
- package/dist/chunks/messages-rRSHQDCX.mjs +48 -0
- package/dist/chunks/messages-srxrv8Yh.mjs +48 -0
- package/dist/chunks/messages-wdqp4610.mjs +48 -0
- package/dist/chunks/messages-zS1AXZ0y.mjs +48 -0
- package/dist/chunks/messages-zSzDzXej.mjs +48 -0
- package/dist/full.mjs +50 -0
- package/dist/locales.mjs +228 -0
- package/dist/messages-0tDXLuyH.mjs +48 -0
- package/dist/messages-2_xedlYw.mjs +48 -0
- package/dist/messages-AHESHJm_.mjs +48 -0
- package/dist/messages-B5hdXZwA.mjs +48 -0
- package/dist/messages-B5jGUnOy.mjs +48 -0
- package/dist/messages-B5puUm7R.mjs +48 -0
- package/dist/messages-B66ZSDCJ.mjs +48 -0
- package/dist/messages-B9Oba7sq.mjs +48 -0
- package/dist/messages-BA0rcTCY.mjs +48 -0
- package/dist/messages-BBJgd5jG.mjs +48 -0
- package/dist/messages-BPqWKx5Z.mjs +48 -0
- package/dist/messages-Bdv-IkfG.mjs +48 -0
- package/dist/messages-BeUhMpsr.mjs +48 -0
- package/dist/messages-Bf6Y3_GI.mjs +48 -0
- package/dist/messages-BiExzWJv.mjs +48 -0
- package/dist/messages-BlpqL8vG.mjs +48 -0
- package/dist/messages-BmKCChWZ.mjs +48 -0
- package/dist/messages-Bn253WWC.mjs +48 -0
- package/dist/messages-BrJHUxQL.mjs +48 -0
- package/dist/messages-C5b7hr_E.mjs +48 -0
- package/dist/messages-C7I_AVH2.mjs +48 -0
- package/dist/messages-CJoBtXU6.mjs +48 -0
- package/dist/messages-CQj2JU2j.mjs +48 -0
- package/dist/messages-CUZ1x1QD.mjs +48 -0
- package/dist/messages-CUy1vn-b.mjs +48 -0
- package/dist/messages-CVeWVKsV.mjs +48 -0
- package/dist/messages-CXHd9SUK.mjs +48 -0
- package/dist/messages-CbMyJSzS.mjs +48 -0
- package/dist/messages-CbhuIWRJ.mjs +48 -0
- package/dist/messages-CeCjVKMW.mjs +48 -0
- package/dist/messages-Cj-t1bdy.mjs +48 -0
- package/dist/messages-CkFT2gle.mjs +48 -0
- package/dist/messages-Cm9aLHeX.mjs +48 -0
- package/dist/messages-CnvW8Slp.mjs +48 -0
- package/dist/messages-Cr-RJ7YB.mjs +48 -0
- package/dist/messages-CrsJ1TEJ.mjs +48 -0
- package/dist/messages-Cu08aLS3.mjs +48 -0
- package/dist/messages-CvaqJFN-.mjs +48 -0
- package/dist/messages-CyDU5lz9.mjs +48 -0
- package/dist/messages-CySyfkMU.mjs +48 -0
- package/dist/messages-Cyi2AMmz.mjs +48 -0
- package/dist/messages-D00OjS2n.mjs +48 -0
- package/dist/messages-DDLgIPDF.mjs +48 -0
- package/dist/messages-DMQIHGRj.mjs +48 -0
- package/dist/messages-DOlC_Tty.mjs +48 -0
- package/dist/messages-DV6shA9b.mjs +48 -0
- package/dist/messages-DY94ykcE.mjs +48 -0
- package/dist/messages-DbVquYKN.mjs +48 -0
- package/dist/messages-DcKOuncK.mjs +48 -0
- package/dist/messages-Dg92dXZ5.mjs +48 -0
- package/dist/messages-DnbbyJT3.mjs +48 -0
- package/dist/messages-DteYq0rv.mjs +48 -0
- package/dist/messages-GC2PhgV3.mjs +48 -0
- package/dist/messages-JGsXAReJ.mjs +48 -0
- package/dist/messages-JZUhXTuV.mjs +48 -0
- package/dist/messages-LvFKBBPa.mjs +48 -0
- package/dist/messages-NP1myMGI.mjs +48 -0
- package/dist/messages-Q4kc_ZtL.mjs +48 -0
- package/dist/messages-RvMHb2Ht.mjs +48 -0
- package/dist/messages-ftMcCEuO.mjs +48 -0
- package/dist/messages-o24dK6CU.mjs +48 -0
- package/dist/messages-pA5TvcAj.mjs +48 -0
- package/dist/messages-rRSHQDCX.mjs +48 -0
- package/dist/messages-srxrv8Yh.mjs +48 -0
- package/dist/messages-wdqp4610.mjs +48 -0
- package/dist/messages-zS1AXZ0y.mjs +48 -0
- package/dist/messages-zSzDzXej.mjs +48 -0
- package/dist/tools.mjs +3117 -0
- package/dist/vendor.LICENSE.txt +26 -225
- package/package.json +63 -24
- package/src/blok.ts +267 -0
- package/src/components/__module.ts +139 -0
- package/src/components/block/api.ts +155 -0
- package/src/components/block/index.ts +1428 -0
- package/src/components/block-tunes/block-tune-delete.ts +51 -0
- package/src/components/blocks.ts +352 -0
- package/src/components/constants/data-attributes.ts +344 -0
- package/src/components/constants.ts +76 -0
- package/src/components/core.ts +392 -0
- package/src/components/dom.ts +773 -0
- package/src/components/domIterator.ts +189 -0
- package/src/components/errors/critical.ts +5 -0
- package/src/components/events/BlockChanged.ts +16 -0
- package/src/components/events/BlockHovered.ts +21 -0
- package/src/components/events/BlockSettingsClosed.ts +12 -0
- package/src/components/events/BlockSettingsOpened.ts +12 -0
- package/src/components/events/BlokMobileLayoutToggled.ts +15 -0
- package/src/components/events/FakeCursorAboutToBeToggled.ts +17 -0
- package/src/components/events/FakeCursorHaveBeenSet.ts +17 -0
- package/src/components/events/HistoryStateChanged.ts +19 -0
- package/src/components/events/RedactorDomChanged.ts +14 -0
- package/src/components/events/index.ts +46 -0
- package/src/components/flipper.ts +497 -0
- package/src/components/i18n/i18next-loader.ts +84 -0
- package/src/components/i18n/lightweight-i18n.ts +86 -0
- package/src/components/i18n/locales/TRANSLATION_GUIDELINES.md +113 -0
- package/src/components/i18n/locales/am/messages.json +45 -0
- package/src/components/i18n/locales/ar/messages.json +45 -0
- package/src/components/i18n/locales/az/messages.json +45 -0
- package/src/components/i18n/locales/bg/messages.json +45 -0
- package/src/components/i18n/locales/bn/messages.json +45 -0
- package/src/components/i18n/locales/bs/messages.json +45 -0
- package/src/components/i18n/locales/cs/messages.json +45 -0
- package/src/components/i18n/locales/da/messages.json +45 -0
- package/src/components/i18n/locales/de/messages.json +45 -0
- package/src/components/i18n/locales/dv/messages.json +45 -0
- package/src/components/i18n/locales/el/messages.json +45 -0
- package/src/components/i18n/locales/en/messages.json +45 -0
- package/src/components/i18n/locales/es/messages.json +45 -0
- package/src/components/i18n/locales/et/messages.json +45 -0
- package/src/components/i18n/locales/fa/messages.json +45 -0
- package/src/components/i18n/locales/fi/messages.json +45 -0
- package/src/components/i18n/locales/fil/messages.json +45 -0
- package/src/components/i18n/locales/fr/messages.json +45 -0
- package/src/components/i18n/locales/gu/messages.json +45 -0
- package/src/components/i18n/locales/he/messages.json +45 -0
- package/src/components/i18n/locales/hi/messages.json +45 -0
- package/src/components/i18n/locales/hr/messages.json +45 -0
- package/src/components/i18n/locales/hu/messages.json +45 -0
- package/src/components/i18n/locales/hy/messages.json +45 -0
- package/src/components/i18n/locales/id/messages.json +45 -0
- package/src/components/i18n/locales/index.ts +231 -0
- package/src/components/i18n/locales/it/messages.json +45 -0
- package/src/components/i18n/locales/ja/messages.json +45 -0
- package/src/components/i18n/locales/ka/messages.json +45 -0
- package/src/components/i18n/locales/km/messages.json +45 -0
- package/src/components/i18n/locales/kn/messages.json +45 -0
- package/src/components/i18n/locales/ko/messages.json +45 -0
- package/src/components/i18n/locales/ku/messages.json +45 -0
- package/src/components/i18n/locales/lo/messages.json +45 -0
- package/src/components/i18n/locales/lt/messages.json +45 -0
- package/src/components/i18n/locales/lv/messages.json +45 -0
- package/src/components/i18n/locales/mk/messages.json +45 -0
- package/src/components/i18n/locales/ml/messages.json +45 -0
- package/src/components/i18n/locales/mn/messages.json +45 -0
- package/src/components/i18n/locales/mr/messages.json +45 -0
- package/src/components/i18n/locales/ms/messages.json +45 -0
- package/src/components/i18n/locales/my/messages.json +45 -0
- package/src/components/i18n/locales/ne/messages.json +45 -0
- package/src/components/i18n/locales/nl/messages.json +45 -0
- package/src/components/i18n/locales/no/messages.json +45 -0
- package/src/components/i18n/locales/pa/messages.json +45 -0
- package/src/components/i18n/locales/pl/messages.json +45 -0
- package/src/components/i18n/locales/ps/messages.json +45 -0
- package/src/components/i18n/locales/pt/messages.json +45 -0
- package/src/components/i18n/locales/ro/messages.json +45 -0
- package/src/components/i18n/locales/ru/messages.json +45 -0
- package/src/components/i18n/locales/sd/messages.json +45 -0
- package/src/components/i18n/locales/si/messages.json +45 -0
- package/src/components/i18n/locales/sk/messages.json +45 -0
- package/src/components/i18n/locales/sl/messages.json +45 -0
- package/src/components/i18n/locales/sq/messages.json +45 -0
- package/src/components/i18n/locales/sr/messages.json +45 -0
- package/src/components/i18n/locales/sv/messages.json +45 -0
- package/src/components/i18n/locales/sw/messages.json +45 -0
- package/src/components/i18n/locales/ta/messages.json +45 -0
- package/src/components/i18n/locales/te/messages.json +45 -0
- package/src/components/i18n/locales/th/messages.json +45 -0
- package/src/components/i18n/locales/tr/messages.json +45 -0
- package/src/components/i18n/locales/ug/messages.json +45 -0
- package/src/components/i18n/locales/uk/messages.json +45 -0
- package/src/components/i18n/locales/ur/messages.json +45 -0
- package/src/components/i18n/locales/vi/messages.json +45 -0
- package/src/components/i18n/locales/yi/messages.json +45 -0
- package/src/components/i18n/locales/zh/messages.json +45 -0
- package/src/components/icons/index.ts +242 -0
- package/src/components/inline-tools/inline-tool-bold.ts +2213 -0
- package/src/components/inline-tools/inline-tool-convert.ts +141 -0
- package/src/components/inline-tools/inline-tool-italic.ts +500 -0
- package/src/components/inline-tools/inline-tool-link.ts +539 -0
- package/src/components/modules/api/blocks.ts +377 -0
- package/src/components/modules/api/caret.ts +125 -0
- package/src/components/modules/api/events.ts +51 -0
- package/src/components/modules/api/history.ts +73 -0
- package/src/components/modules/api/i18n.ts +35 -0
- package/src/components/modules/api/index.ts +39 -0
- package/src/components/modules/api/inlineToolbar.ts +33 -0
- package/src/components/modules/api/listeners.ts +56 -0
- package/src/components/modules/api/notifier.ts +46 -0
- package/src/components/modules/api/readonly.ts +39 -0
- package/src/components/modules/api/sanitizer.ts +30 -0
- package/src/components/modules/api/saver.ts +52 -0
- package/src/components/modules/api/selection.ts +48 -0
- package/src/components/modules/api/styles.ts +72 -0
- package/src/components/modules/api/toolbar.ts +79 -0
- package/src/components/modules/api/tools.ts +16 -0
- package/src/components/modules/api/tooltip.ts +67 -0
- package/src/components/modules/api/ui.ts +36 -0
- package/src/components/modules/blockEvents.ts +1591 -0
- package/src/components/modules/blockManager.ts +1356 -0
- package/src/components/modules/blockSelection.ts +708 -0
- package/src/components/modules/caret.ts +853 -0
- package/src/components/modules/crossBlockSelection.ts +329 -0
- package/src/components/modules/dragManager.ts +1204 -0
- package/src/components/modules/history.ts +1098 -0
- package/src/components/modules/i18n.ts +332 -0
- package/src/components/modules/index.ts +139 -0
- package/src/components/modules/modificationsObserver.ts +147 -0
- package/src/components/modules/paste.ts +1092 -0
- package/src/components/modules/readonly.ts +136 -0
- package/src/components/modules/rectangleSelection.ts +711 -0
- package/src/components/modules/renderer.ts +155 -0
- package/src/components/modules/saver.ts +283 -0
- package/src/components/modules/toolbar/blockSettings.ts +781 -0
- package/src/components/modules/toolbar/index.ts +1315 -0
- package/src/components/modules/toolbar/inline.ts +956 -0
- package/src/components/modules/tools.ts +625 -0
- package/src/components/modules/ui.ts +1283 -0
- package/src/components/polyfills.ts +113 -0
- package/src/components/selection.ts +1179 -0
- package/src/components/tools/base.ts +301 -0
- package/src/components/tools/block.ts +339 -0
- package/src/components/tools/collection.ts +67 -0
- package/src/components/tools/factory.ts +138 -0
- package/src/components/tools/inline.ts +71 -0
- package/src/components/tools/tune.ts +33 -0
- package/src/components/ui/toolbox.ts +601 -0
- package/src/components/utils/announcer.ts +205 -0
- package/src/components/utils/api.ts +20 -0
- package/src/components/utils/bem.ts +26 -0
- package/src/components/utils/blocks.ts +284 -0
- package/src/components/utils/caret.ts +1067 -0
- package/src/components/utils/data-model-transform.ts +382 -0
- package/src/components/utils/events.ts +117 -0
- package/src/components/utils/keyboard.ts +60 -0
- package/src/components/utils/listeners.ts +296 -0
- package/src/components/utils/mutations.ts +39 -0
- package/src/components/utils/notifier/draw.ts +190 -0
- package/src/components/utils/notifier/index.ts +66 -0
- package/src/components/utils/notifier/types.ts +1 -0
- package/src/components/utils/notifier.ts +77 -0
- package/src/components/utils/placeholder.ts +140 -0
- package/src/components/utils/popover/components/hint/hint.const.ts +10 -0
- package/src/components/utils/popover/components/hint/hint.ts +46 -0
- package/src/components/utils/popover/components/hint/index.ts +6 -0
- package/src/components/utils/popover/components/popover-header/index.ts +2 -0
- package/src/components/utils/popover/components/popover-header/popover-header.const.ts +8 -0
- package/src/components/utils/popover/components/popover-header/popover-header.ts +80 -0
- package/src/components/utils/popover/components/popover-header/popover-header.types.ts +14 -0
- package/src/components/utils/popover/components/popover-item/index.ts +13 -0
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +50 -0
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +680 -0
- package/src/components/utils/popover/components/popover-item/popover-item-html/popover-item-html.const.ts +14 -0
- package/src/components/utils/popover/components/popover-item/popover-item-html/popover-item-html.ts +136 -0
- package/src/components/utils/popover/components/popover-item/popover-item-separator/popover-item-separator.const.ts +20 -0
- package/src/components/utils/popover/components/popover-item/popover-item-separator/popover-item-separator.ts +117 -0
- package/src/components/utils/popover/components/popover-item/popover-item.ts +186 -0
- package/src/components/utils/popover/components/search-input/index.ts +2 -0
- package/src/components/utils/popover/components/search-input/search-input.const.ts +8 -0
- package/src/components/utils/popover/components/search-input/search-input.ts +178 -0
- package/src/components/utils/popover/components/search-input/search-input.types.ts +59 -0
- package/src/components/utils/popover/index.ts +13 -0
- package/src/components/utils/popover/popover-abstract.ts +457 -0
- package/src/components/utils/popover/popover-desktop.ts +676 -0
- package/src/components/utils/popover/popover-inline.ts +338 -0
- package/src/components/utils/popover/popover-mobile.ts +201 -0
- package/src/components/utils/popover/popover.const.ts +81 -0
- package/src/components/utils/popover/utils/popover-states-history.ts +72 -0
- package/src/components/utils/promise-queue.ts +43 -0
- package/src/components/utils/sanitizer.ts +537 -0
- package/src/components/utils/scroll-locker.ts +87 -0
- package/src/components/utils/shortcut.ts +231 -0
- package/src/components/utils/shortcuts.ts +113 -0
- package/src/components/utils/tools.ts +110 -0
- package/src/components/utils/tooltip.ts +591 -0
- package/src/components/utils/tw.ts +241 -0
- package/src/components/utils.ts +1081 -0
- package/src/env.d.ts +13 -0
- package/src/full.ts +69 -0
- package/src/locales.ts +51 -0
- package/src/stories/Block.stories.ts +498 -0
- package/src/stories/EditorModes.stories.ts +505 -0
- package/src/stories/Header.stories.ts +137 -0
- package/src/stories/InlineToolbar.stories.ts +498 -0
- package/src/stories/List.stories.ts +259 -0
- package/src/stories/Notifier.stories.ts +340 -0
- package/src/stories/Paragraph.stories.ts +112 -0
- package/src/stories/Placeholder.stories.ts +319 -0
- package/src/stories/Popover.stories.ts +844 -0
- package/src/stories/Selection.stories.ts +250 -0
- package/src/stories/StubBlock.stories.ts +156 -0
- package/src/stories/Toolbar.stories.ts +223 -0
- package/src/stories/Toolbox.stories.ts +166 -0
- package/src/stories/Tooltip.stories.ts +198 -0
- package/src/stories/helpers.ts +463 -0
- package/src/styles/main.css +123 -0
- package/src/tools/header/index.ts +646 -0
- package/src/tools/index.ts +45 -0
- package/src/tools/list/index.ts +1819 -0
- package/src/tools/paragraph/index.ts +412 -0
- package/src/tools/stub/index.ts +107 -0
- package/src/types-internal/blok-modules.d.ts +87 -0
- package/src/types-internal/html-janitor.d.ts +28 -0
- package/src/types-internal/module-config.d.ts +11 -0
- package/src/variants/all-locales.ts +155 -0
- package/src/variants/blok-maximum.ts +20 -0
- package/src/variants/blok-minimum.ts +243 -0
- package/types/api/blocks.d.ts +9 -1
- package/types/api/history.d.ts +7 -0
- package/types/api/i18n.d.ts +22 -3
- package/types/api/selection.d.ts +6 -0
- package/types/api/styles.d.ts +23 -10
- package/types/configs/blok-config.d.ts +29 -0
- package/types/configs/i18n-config.d.ts +52 -2
- package/types/configs/i18n-dictionary.d.ts +16 -90
- package/types/data-attributes.d.ts +170 -0
- package/types/data-formats/output-data.d.ts +15 -0
- package/types/full.d.ts +80 -0
- package/types/index.d.ts +30 -13
- package/types/locales.d.ts +59 -0
- package/types/tools/adapters/inline-tool-adapter.d.ts +10 -0
- package/types/tools/block-tool.d.ts +9 -0
- package/types/tools/header.d.ts +18 -0
- package/types/tools/index.d.ts +1 -0
- package/types/tools/list.d.ts +91 -0
- package/types/tools/paragraph.d.ts +71 -0
- package/types/tools/tool-settings.d.ts +92 -6
- package/types/tools/tool.d.ts +6 -0
- package/types/tools-entry.d.ts +49 -0
- package/types/utils/popover/popover-item.d.ts +18 -5
- package/types/utils/popover/popover.d.ts +7 -0
- package/dist/blok-D_baBvTG.mjs +0 -25795
- package/dist/blok.umd.js +0 -181
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
import { beautifyShortcut, capitalize, isMobileScreen } from '../utils';
|
|
2
|
+
import { Shortcuts } from '../utils/shortcuts';
|
|
3
|
+
import type { BlockToolAdapter } from '../tools/block';
|
|
4
|
+
import type { ToolsCollection } from '../tools/collection';
|
|
5
|
+
import type { API, BlockToolData, ToolboxConfigEntry, PopoverItemParams, BlockAPI } from '@/types';
|
|
6
|
+
import { EventsDispatcher } from '../utils/events';
|
|
7
|
+
import { translateToolTitle, type I18nInstance } from '../utils/tools';
|
|
8
|
+
import { PopoverEvent } from '@/types/utils/popover/popover-event';
|
|
9
|
+
import { Listeners } from '../utils/listeners';
|
|
10
|
+
import { Dom } from '../dom';
|
|
11
|
+
import type { Popover } from '../utils/popover';
|
|
12
|
+
import { PopoverDesktop, PopoverMobile } from '../utils/popover';
|
|
13
|
+
import { BlokMobileLayoutToggled } from '../events';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @todo the first Tab on the Block — focus Plus Button, the second — focus Block Tunes Toggler, the third — focus next Block
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Event that can be triggered by the Toolbox
|
|
21
|
+
*/
|
|
22
|
+
export enum ToolboxEvent {
|
|
23
|
+
/**
|
|
24
|
+
* When the Toolbox is opened
|
|
25
|
+
*/
|
|
26
|
+
Opened = 'toolbox-opened',
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* When the Toolbox is closed
|
|
30
|
+
*/
|
|
31
|
+
Closed = 'toolbox-closed',
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* When the new Block added by Toolbox
|
|
35
|
+
*/
|
|
36
|
+
BlockAdded = 'toolbox-block-added',
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Events fired by the Toolbox
|
|
41
|
+
*
|
|
42
|
+
* Event name -> payload
|
|
43
|
+
*/
|
|
44
|
+
export interface ToolboxEventMap {
|
|
45
|
+
[ToolboxEvent.Opened]: undefined;
|
|
46
|
+
[ToolboxEvent.Closed]: undefined;
|
|
47
|
+
[ToolboxEvent.BlockAdded]: {
|
|
48
|
+
block: BlockAPI
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Available i18n dict keys that should be passed to the constructor
|
|
54
|
+
*/
|
|
55
|
+
type ToolboxTextLabelsKeys = 'filter' | 'nothingFound';
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Toolbox
|
|
59
|
+
* This UI element contains list of Block Tools available to be inserted
|
|
60
|
+
* It appears after click on the Plus Button
|
|
61
|
+
* @implements {EventsDispatcher} with some events, see {@link ToolboxEvent}
|
|
62
|
+
*/
|
|
63
|
+
export class Toolbox extends EventsDispatcher<ToolboxEventMap> {
|
|
64
|
+
/**
|
|
65
|
+
* Returns True if Toolbox is Empty and nothing to show
|
|
66
|
+
* @returns {boolean}
|
|
67
|
+
*/
|
|
68
|
+
public get isEmpty(): boolean {
|
|
69
|
+
return this.toolsToBeDisplayed.length === 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Opening state
|
|
74
|
+
* @type {boolean}
|
|
75
|
+
*/
|
|
76
|
+
public opened = false;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Listeners util instance
|
|
80
|
+
*/
|
|
81
|
+
protected listeners: Listeners = new Listeners();
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Blok API
|
|
85
|
+
*/
|
|
86
|
+
private api: API;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Popover instance. There is a util for vertical lists.
|
|
90
|
+
* Null until initialized
|
|
91
|
+
*/
|
|
92
|
+
private popover: Popover | null = null;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* List of Tools available. Some of them will be shown in the Toolbox
|
|
96
|
+
*/
|
|
97
|
+
private tools: ToolsCollection<BlockToolAdapter>;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Cache for tools to be displayed
|
|
101
|
+
*/
|
|
102
|
+
private _toolsToBeDisplayed: BlockToolAdapter[] | undefined;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Cache for toolbox items to be displayed
|
|
106
|
+
*/
|
|
107
|
+
private _toolboxItemsToBeDisplayed: PopoverItemParams[] | undefined;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Text labels used in the Toolbox. Should be passed from the i18n module
|
|
111
|
+
*/
|
|
112
|
+
private i18nLabels: Record<ToolboxTextLabelsKeys, string>;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* I18n instance for translations
|
|
116
|
+
*/
|
|
117
|
+
private i18n: I18nInstance;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Current module HTML Elements
|
|
121
|
+
*/
|
|
122
|
+
private nodes: {
|
|
123
|
+
toolbox: HTMLElement;
|
|
124
|
+
} ;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* CSS styles
|
|
128
|
+
* @deprecated Use data attributes for identification instead
|
|
129
|
+
*/
|
|
130
|
+
private static get CSS(): {
|
|
131
|
+
toolbox: string;
|
|
132
|
+
} {
|
|
133
|
+
return {
|
|
134
|
+
toolbox: '',
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Element relative to which the popover should be positioned
|
|
140
|
+
*/
|
|
141
|
+
private triggerElement?: HTMLElement;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The block element currently being listened to for inline slash search
|
|
145
|
+
*/
|
|
146
|
+
private currentBlockForSearch: HTMLElement | null = null;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Toolbox constructor
|
|
150
|
+
* @param options - available parameters
|
|
151
|
+
* @param options.api - Blok API methods
|
|
152
|
+
* @param options.tools - Tools available to check whether some of them should be displayed at the Toolbox or not
|
|
153
|
+
* @param options.i18n - I18n instance for translations
|
|
154
|
+
* @param options.triggerElement - Element relative to which the popover should be positioned
|
|
155
|
+
*/
|
|
156
|
+
constructor({ api, tools, i18nLabels, i18n, triggerElement }: {
|
|
157
|
+
api: API;
|
|
158
|
+
tools: ToolsCollection<BlockToolAdapter>;
|
|
159
|
+
i18nLabels: Record<ToolboxTextLabelsKeys, string>;
|
|
160
|
+
i18n: I18nInstance;
|
|
161
|
+
triggerElement?: HTMLElement;
|
|
162
|
+
}) {
|
|
163
|
+
super();
|
|
164
|
+
|
|
165
|
+
this.api = api;
|
|
166
|
+
this.tools = tools;
|
|
167
|
+
this.i18nLabels = i18nLabels;
|
|
168
|
+
this.i18n = i18n;
|
|
169
|
+
this.triggerElement = triggerElement;
|
|
170
|
+
|
|
171
|
+
this.enableShortcuts();
|
|
172
|
+
|
|
173
|
+
this.nodes = {
|
|
174
|
+
toolbox: Dom.make('div'),
|
|
175
|
+
};
|
|
176
|
+
this.nodes.toolbox.setAttribute('data-blok-testid', 'toolbox');
|
|
177
|
+
|
|
178
|
+
this.initPopover();
|
|
179
|
+
|
|
180
|
+
this.api.events.on(BlokMobileLayoutToggled, this.handleMobileLayoutToggle);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Returns root block settings element
|
|
185
|
+
*/
|
|
186
|
+
public getElement(): HTMLElement | null {
|
|
187
|
+
return this.nodes.toolbox;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Checks if the element is contained in the Toolbox or its Popover
|
|
192
|
+
* @param element - element to check
|
|
193
|
+
*/
|
|
194
|
+
public contains(element: HTMLElement): boolean {
|
|
195
|
+
if (this.nodes.toolbox.contains(element)) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (this.popover?.getElement().contains(element)) {
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Returns true if the Toolbox has the Flipper activated and the Flipper has selected button
|
|
208
|
+
*/
|
|
209
|
+
public hasFocus(): boolean | undefined {
|
|
210
|
+
if (this.popover === null) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return 'hasFocus' in this.popover ? this.popover.hasFocus() : undefined;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Destroy Module
|
|
219
|
+
*/
|
|
220
|
+
public destroy(): void {
|
|
221
|
+
super.destroy();
|
|
222
|
+
|
|
223
|
+
if (this.nodes && this.nodes.toolbox) {
|
|
224
|
+
this.nodes.toolbox.remove();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
this.removeAllShortcuts();
|
|
228
|
+
this.popover?.off(PopoverEvent.Closed, this.onPopoverClose);
|
|
229
|
+
this.listeners.destroy();
|
|
230
|
+
this.api.events.off(BlokMobileLayoutToggled, this.handleMobileLayoutToggle);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Toolbox Tool's button click handler
|
|
235
|
+
* @param toolName - tool type to be activated
|
|
236
|
+
* @param blockDataOverrides - Block data predefined by the activated Toolbox item
|
|
237
|
+
*/
|
|
238
|
+
public async toolButtonActivated(toolName: string, blockDataOverrides?: BlockToolData): Promise<void> {
|
|
239
|
+
await this.insertNewBlock(toolName, blockDataOverrides);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Open Toolbox with Tools
|
|
244
|
+
*/
|
|
245
|
+
public open(): void {
|
|
246
|
+
if (this.isEmpty) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Stop mutation watching on the current block when toolbox opens.
|
|
252
|
+
* This prevents spurious block-changed events from DOM manipulations
|
|
253
|
+
* that may occur during toolbox interactions (focus changes, etc).
|
|
254
|
+
*/
|
|
255
|
+
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
|
256
|
+
|
|
257
|
+
this.api.blocks.stopBlockMutationWatching(currentBlockIndex);
|
|
258
|
+
|
|
259
|
+
this.popover?.show();
|
|
260
|
+
this.opened = true;
|
|
261
|
+
this.emit(ToolboxEvent.Opened);
|
|
262
|
+
this.startListeningToBlockInput();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Close Toolbox
|
|
267
|
+
*/
|
|
268
|
+
public close(): void {
|
|
269
|
+
this.popover?.hide();
|
|
270
|
+
this.opened = false;
|
|
271
|
+
this.emit(ToolboxEvent.Closed);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Close Toolbox
|
|
276
|
+
*/
|
|
277
|
+
public toggle(): void {
|
|
278
|
+
if (!this.opened) {
|
|
279
|
+
this.open();
|
|
280
|
+
} else {
|
|
281
|
+
this.close();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Destroys existing popover instance and contructs the new one.
|
|
287
|
+
*/
|
|
288
|
+
public handleMobileLayoutToggle = (): void => {
|
|
289
|
+
this.destroyPopover();
|
|
290
|
+
this.initPopover();
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Creates toolbox popover and appends it inside wrapper element
|
|
295
|
+
*/
|
|
296
|
+
private initPopover(): void {
|
|
297
|
+
const PopoverClass = isMobileScreen() ? PopoverMobile : PopoverDesktop;
|
|
298
|
+
|
|
299
|
+
this.popover = new PopoverClass({
|
|
300
|
+
scopeElement: this.api.ui.nodes.redactor,
|
|
301
|
+
trigger: this.triggerElement || this.nodes.toolbox,
|
|
302
|
+
messages: {
|
|
303
|
+
nothingFound: this.i18nLabels.nothingFound,
|
|
304
|
+
search: this.i18nLabels.filter,
|
|
305
|
+
},
|
|
306
|
+
items: this.toolboxItemsToBeDisplayed,
|
|
307
|
+
handleContentEditableNavigation: true,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
this.popover.on(PopoverEvent.Closed, this.onPopoverClose);
|
|
311
|
+
this.popover.getElement().setAttribute('data-blok-testid', 'toolbox-popover');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Destroys popover instance and removes it from DOM
|
|
316
|
+
*/
|
|
317
|
+
private destroyPopover(): void {
|
|
318
|
+
if (this.popover !== null) {
|
|
319
|
+
this.popover.hide();
|
|
320
|
+
this.popover.off(PopoverEvent.Closed, this.onPopoverClose);
|
|
321
|
+
this.popover.destroy();
|
|
322
|
+
this.popover = null;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (this.nodes.toolbox !== null) {
|
|
326
|
+
this.nodes.toolbox.innerHTML = '';
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Handles popover close event
|
|
332
|
+
*/
|
|
333
|
+
private onPopoverClose = (): void => {
|
|
334
|
+
this.stopListeningToBlockInput();
|
|
335
|
+
this.opened = false;
|
|
336
|
+
this.emit(ToolboxEvent.Closed);
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Returns list of tools that enables the Toolbox (by specifying the 'toolbox' getter)
|
|
341
|
+
*/
|
|
342
|
+
private get toolsToBeDisplayed(): BlockToolAdapter[] {
|
|
343
|
+
if (this._toolsToBeDisplayed) {
|
|
344
|
+
return this._toolsToBeDisplayed;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const result: BlockToolAdapter[] = [];
|
|
348
|
+
|
|
349
|
+
this.tools.forEach((tool) => {
|
|
350
|
+
const toolToolboxSettings = tool.toolbox;
|
|
351
|
+
|
|
352
|
+
if (toolToolboxSettings) {
|
|
353
|
+
result.push(tool);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
this._toolsToBeDisplayed = result;
|
|
358
|
+
|
|
359
|
+
return result;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Returns list of items that will be displayed in toolbox
|
|
364
|
+
*/
|
|
365
|
+
private get toolboxItemsToBeDisplayed(): PopoverItemParams[] {
|
|
366
|
+
if (this._toolboxItemsToBeDisplayed) {
|
|
367
|
+
return this._toolboxItemsToBeDisplayed;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Maps tool data to popover item structure
|
|
372
|
+
*/
|
|
373
|
+
const toPopoverItem = (toolboxItem: ToolboxConfigEntry, tool: BlockToolAdapter, displaySecondaryLabel = true): PopoverItemParams => {
|
|
374
|
+
// Get English title for search fallback
|
|
375
|
+
const titleKey = toolboxItem.titleKey;
|
|
376
|
+
const englishTitleKey = titleKey ? `toolNames.${titleKey}` : undefined;
|
|
377
|
+
const englishTitle = englishTitleKey
|
|
378
|
+
? this.api.i18n.getEnglishTranslation(englishTitleKey)
|
|
379
|
+
: toolboxItem.title;
|
|
380
|
+
|
|
381
|
+
// Merge library searchTerms with user-provided searchTerms
|
|
382
|
+
const librarySearchTerms = toolboxItem.searchTerms ?? [];
|
|
383
|
+
const userSearchTerms = tool.searchTerms ?? [];
|
|
384
|
+
const mergedSearchTerms = [...new Set([...librarySearchTerms, ...userSearchTerms])];
|
|
385
|
+
|
|
386
|
+
return {
|
|
387
|
+
icon: toolboxItem.icon,
|
|
388
|
+
title: translateToolTitle(this.i18n, toolboxItem, capitalize(tool.name)),
|
|
389
|
+
name: toolboxItem.name ?? tool.name,
|
|
390
|
+
onActivate: (): void => {
|
|
391
|
+
void this.toolButtonActivated(tool.name, toolboxItem.data);
|
|
392
|
+
},
|
|
393
|
+
secondaryLabel: (tool.shortcut && displaySecondaryLabel) ? beautifyShortcut(tool.shortcut) : '',
|
|
394
|
+
englishTitle,
|
|
395
|
+
searchTerms: mergedSearchTerms,
|
|
396
|
+
};
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
const result = this.toolsToBeDisplayed
|
|
400
|
+
.reduce<PopoverItemParams[]>((acc, tool) => {
|
|
401
|
+
const { toolbox } = tool;
|
|
402
|
+
|
|
403
|
+
if (toolbox === undefined) {
|
|
404
|
+
return acc;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const items = Array.isArray(toolbox) ? toolbox : [ toolbox ];
|
|
408
|
+
|
|
409
|
+
items.forEach((item, index) => {
|
|
410
|
+
acc.push(toPopoverItem(item, tool, index === 0));
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
return acc;
|
|
414
|
+
}, []);
|
|
415
|
+
|
|
416
|
+
this._toolboxItemsToBeDisplayed = result;
|
|
417
|
+
|
|
418
|
+
return result;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Iterate all tools and enable theirs shortcuts if specified
|
|
423
|
+
*/
|
|
424
|
+
private enableShortcuts(): void {
|
|
425
|
+
this.toolsToBeDisplayed.forEach((tool: BlockToolAdapter) => {
|
|
426
|
+
const shortcut = tool.shortcut;
|
|
427
|
+
|
|
428
|
+
if (shortcut) {
|
|
429
|
+
this.enableShortcutForTool(tool.name, shortcut);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Enable shortcut Block Tool implemented shortcut
|
|
436
|
+
* @param {string} toolName - Tool name
|
|
437
|
+
* @param {string} shortcut - shortcut according to the ShortcutData Module format
|
|
438
|
+
*/
|
|
439
|
+
private enableShortcutForTool(toolName: string, shortcut: string): void {
|
|
440
|
+
Shortcuts.add({
|
|
441
|
+
name: shortcut,
|
|
442
|
+
on: this.api.ui.nodes.redactor,
|
|
443
|
+
handler: async (event: KeyboardEvent) => {
|
|
444
|
+
event.preventDefault();
|
|
445
|
+
|
|
446
|
+
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
|
447
|
+
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Try to convert current Block to shortcut's tool
|
|
451
|
+
* If conversion is not possible, insert a new Block below
|
|
452
|
+
*/
|
|
453
|
+
if (currentBlock) {
|
|
454
|
+
try {
|
|
455
|
+
const newBlock = await this.api.blocks.convert(currentBlock.id, toolName);
|
|
456
|
+
|
|
457
|
+
this.api.caret.setToBlock(newBlock, 'end');
|
|
458
|
+
|
|
459
|
+
return;
|
|
460
|
+
} catch (_error) {}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
await this.insertNewBlock(toolName);
|
|
464
|
+
},
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Removes all added shortcuts
|
|
470
|
+
* Fired when the Read-Only mode is activated
|
|
471
|
+
*/
|
|
472
|
+
private removeAllShortcuts(): void {
|
|
473
|
+
this.toolsToBeDisplayed.forEach((tool: BlockToolAdapter) => {
|
|
474
|
+
const shortcut = tool.shortcut;
|
|
475
|
+
|
|
476
|
+
if (shortcut) {
|
|
477
|
+
Shortcuts.remove(this.api.ui.nodes.redactor, shortcut);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Inserts new block
|
|
484
|
+
* Can be called when button clicked on Toolbox or by ShortcutData
|
|
485
|
+
* @param {string} toolName - Tool name
|
|
486
|
+
* @param blockDataOverrides - predefined Block data
|
|
487
|
+
*/
|
|
488
|
+
private async insertNewBlock(toolName: string, blockDataOverrides?: BlockToolData): Promise<void> {
|
|
489
|
+
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
|
490
|
+
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
|
491
|
+
|
|
492
|
+
if (!currentBlock) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Check if the block contains only slash search text (e.g., "/head").
|
|
498
|
+
* If so, treat it as empty and replace it with the new block.
|
|
499
|
+
*/
|
|
500
|
+
const shouldReplaceBlock = currentBlock.isEmpty || this.isBlockSlashSearchOnly(currentBlock.holder);
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* On mobile version, we see the Plus Button even near non-empty blocks,
|
|
504
|
+
* so if current block is not empty, add the new block below the current
|
|
505
|
+
*/
|
|
506
|
+
const index = shouldReplaceBlock ? currentBlockIndex : currentBlockIndex + 1;
|
|
507
|
+
|
|
508
|
+
const hasBlockDataOverrides = blockDataOverrides !== undefined && Object.keys(blockDataOverrides as Record<string, unknown>).length > 0;
|
|
509
|
+
|
|
510
|
+
const blockData: BlockToolData | undefined = hasBlockDataOverrides
|
|
511
|
+
? Object.assign(await this.api.blocks.composeBlockData(toolName), blockDataOverrides)
|
|
512
|
+
: undefined;
|
|
513
|
+
|
|
514
|
+
const newBlock = this.api.blocks.insert(
|
|
515
|
+
toolName,
|
|
516
|
+
blockData,
|
|
517
|
+
undefined,
|
|
518
|
+
index,
|
|
519
|
+
undefined,
|
|
520
|
+
shouldReplaceBlock
|
|
521
|
+
);
|
|
522
|
+
|
|
523
|
+
this.api.caret.setToBlock(index);
|
|
524
|
+
|
|
525
|
+
this.emit(ToolboxEvent.BlockAdded, {
|
|
526
|
+
block: newBlock,
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* close toolbar when node is changed
|
|
531
|
+
*/
|
|
532
|
+
this.api.toolbar.close();
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Starts listening to input events on the current block for inline slash search.
|
|
537
|
+
* When the user types after "/", the toolbox filters based on the typed text.
|
|
538
|
+
*/
|
|
539
|
+
private startListeningToBlockInput(): void {
|
|
540
|
+
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
|
|
541
|
+
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
|
|
542
|
+
|
|
543
|
+
if (!currentBlock) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
this.currentBlockForSearch = currentBlock.holder;
|
|
548
|
+
this.listeners.on(this.currentBlockForSearch, 'input', this.handleBlockInput);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Stops listening to block input events and resets the filter.
|
|
553
|
+
*/
|
|
554
|
+
private stopListeningToBlockInput(): void {
|
|
555
|
+
if (this.currentBlockForSearch !== null) {
|
|
556
|
+
this.listeners.off(this.currentBlockForSearch, 'input', this.handleBlockInput);
|
|
557
|
+
this.currentBlockForSearch = null;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
this.popover?.filterItems('');
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Handles input events on the block to filter the toolbox.
|
|
565
|
+
* Extracts text after "/" and applies it as a filter query.
|
|
566
|
+
*/
|
|
567
|
+
private handleBlockInput = (): void => {
|
|
568
|
+
if (this.currentBlockForSearch === null) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Get text from the contenteditable element inside the block
|
|
573
|
+
const contentEditable = this.currentBlockForSearch.querySelector('[contenteditable="true"]');
|
|
574
|
+
const text = contentEditable?.textContent || '';
|
|
575
|
+
const slashIndex = text.lastIndexOf('/');
|
|
576
|
+
|
|
577
|
+
if (slashIndex === -1) {
|
|
578
|
+
this.close();
|
|
579
|
+
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const query = text.slice(slashIndex + 1);
|
|
584
|
+
|
|
585
|
+
this.popover?.filterItems(query);
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Checks if a block contains only slash search text (e.g., "/head").
|
|
590
|
+
* A block is considered "slash search only" if its text starts with "/" and contains no other content before it.
|
|
591
|
+
* @param blockHolder - the block's holder element
|
|
592
|
+
* @returns true if the block only contains slash search text
|
|
593
|
+
*/
|
|
594
|
+
private isBlockSlashSearchOnly(blockHolder: HTMLElement): boolean {
|
|
595
|
+
const contentEditable = blockHolder.querySelector('[contenteditable="true"]');
|
|
596
|
+
const text = contentEditable?.textContent?.trim() || '';
|
|
597
|
+
|
|
598
|
+
// Block must start with "/" to be considered slash search only
|
|
599
|
+
return text.startsWith('/');
|
|
600
|
+
}
|
|
601
|
+
}
|