@jackuait/blok 0.4.1-beta.1 → 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-CEXLTV6f.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 +29 -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-C8XbyLHh.mjs +0 -25795
- package/dist/blok.umd.js +0 -181
package/src/env.d.ts
ADDED
package/src/full.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Blok/Full
|
|
3
|
+
* Full bundle with Blok core + all built-in tools.
|
|
4
|
+
* Use this for batteries-included setup (same as pre-modularization behavior).
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* import { Blok, defaultTools, defaultInlineTools } from '@jackuait/blok/full';
|
|
8
|
+
*
|
|
9
|
+
* new Blok({
|
|
10
|
+
* holder: 'editor',
|
|
11
|
+
* tools: defaultTools,
|
|
12
|
+
* inlineTools: defaultInlineTools,
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// Re-export everything from core
|
|
17
|
+
export { Blok, version, DATA_ATTR } from './blok';
|
|
18
|
+
|
|
19
|
+
// Re-export all tools
|
|
20
|
+
export {
|
|
21
|
+
Paragraph,
|
|
22
|
+
Header,
|
|
23
|
+
List,
|
|
24
|
+
Bold,
|
|
25
|
+
Italic,
|
|
26
|
+
Link,
|
|
27
|
+
defaultBlockTools,
|
|
28
|
+
defaultInlineTools,
|
|
29
|
+
} from './tools';
|
|
30
|
+
|
|
31
|
+
// Import tools for defaultTools object
|
|
32
|
+
import { Paragraph } from './tools/paragraph';
|
|
33
|
+
import { Header } from './tools/header';
|
|
34
|
+
import { ListItem as List } from './tools/list';
|
|
35
|
+
import { BoldInlineTool as Bold } from './components/inline-tools/inline-tool-bold';
|
|
36
|
+
import { ItalicInlineTool as Italic } from './components/inline-tools/inline-tool-italic';
|
|
37
|
+
import { LinkInlineTool as Link } from './components/inline-tools/inline-tool-link';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Default tools configuration matching pre-modularization behavior.
|
|
41
|
+
* Includes Paragraph, Header, and List with inline toolbar enabled.
|
|
42
|
+
*/
|
|
43
|
+
export const defaultTools = {
|
|
44
|
+
paragraph: {
|
|
45
|
+
class: Paragraph,
|
|
46
|
+
inlineToolbar: true,
|
|
47
|
+
config: { preserveBlank: true },
|
|
48
|
+
},
|
|
49
|
+
header: {
|
|
50
|
+
class: Header,
|
|
51
|
+
inlineToolbar: true,
|
|
52
|
+
},
|
|
53
|
+
list: {
|
|
54
|
+
class: List,
|
|
55
|
+
inlineToolbar: true,
|
|
56
|
+
},
|
|
57
|
+
} as const;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* All built-in tools including inline tools.
|
|
61
|
+
* For users who want every tool available.
|
|
62
|
+
* Note: Convert and Delete are internal tools and don't need to be configured.
|
|
63
|
+
*/
|
|
64
|
+
export const allTools = {
|
|
65
|
+
...defaultTools,
|
|
66
|
+
bold: { class: Bold },
|
|
67
|
+
italic: { class: Italic },
|
|
68
|
+
link: { class: Link },
|
|
69
|
+
} as const;
|
package/src/locales.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry point for locale imports.
|
|
3
|
+
*
|
|
4
|
+
* Lazy Loading:
|
|
5
|
+
* Only English is bundled by default. All 68 supported locales are available
|
|
6
|
+
* for on-demand loading, reducing initial bundle size while providing full
|
|
7
|
+
* language support.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // Load a single locale on-demand
|
|
11
|
+
* import { loadLocale } from '@aspect/blok/locales';
|
|
12
|
+
* const frConfig = await loadLocale('fr');
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Get all supported locale codes
|
|
16
|
+
* import { ALL_LOCALE_CODES } from '@aspect/blok/locales';
|
|
17
|
+
* console.log(ALL_LOCALE_CODES); // Array of all 68 locale codes
|
|
18
|
+
*
|
|
19
|
+
* @see README.md#localization for usage examples
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Constants and utilities
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
// Constants
|
|
28
|
+
DEFAULT_LOCALE,
|
|
29
|
+
ALL_LOCALE_CODES,
|
|
30
|
+
|
|
31
|
+
// English locale (always bundled)
|
|
32
|
+
enLocale,
|
|
33
|
+
|
|
34
|
+
// Lazy loading functions
|
|
35
|
+
loadLocale,
|
|
36
|
+
preloadLocales,
|
|
37
|
+
buildRegistry,
|
|
38
|
+
getLocaleSync,
|
|
39
|
+
|
|
40
|
+
// Direction utilities
|
|
41
|
+
getDirection,
|
|
42
|
+
|
|
43
|
+
// Testing utilities
|
|
44
|
+
clearLocaleCache,
|
|
45
|
+
} from './components/i18n/locales';
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Re-export types
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
export type { LocaleConfig, LocaleRegistry, SupportedLocale } from '../types/configs/i18n-config';
|
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/html-vite';
|
|
2
|
+
import { userEvent, waitFor, expect } from 'storybook/test';
|
|
3
|
+
import type { OutputData } from '@/types';
|
|
4
|
+
import { createEditorContainer, simulateClick, waitForToolbar, TOOLBAR_TESTID, triggerSelectAll } from './helpers';
|
|
5
|
+
import type { EditorFactoryOptions } from './helpers';
|
|
6
|
+
|
|
7
|
+
interface BlockArgs extends EditorFactoryOptions {
|
|
8
|
+
minHeight: number;
|
|
9
|
+
data: OutputData | undefined;
|
|
10
|
+
readOnly: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Constants
|
|
14
|
+
const BLOCK_TESTID = '[data-blok-testid="block-wrapper"]';
|
|
15
|
+
const CONTENTEDITABLE_SELECTOR = '[contenteditable="true"]';
|
|
16
|
+
const BLOCK_SELECTED_SELECTOR = '[data-blok-selected="true"]';
|
|
17
|
+
|
|
18
|
+
const TIMEOUT_INIT = { timeout: 5000 };
|
|
19
|
+
const TIMEOUT_ACTION = { timeout: 5000 };
|
|
20
|
+
|
|
21
|
+
const sampleData: OutputData = {
|
|
22
|
+
time: Date.now(),
|
|
23
|
+
version: '1.0.0',
|
|
24
|
+
blocks: [
|
|
25
|
+
{
|
|
26
|
+
id: 'block-state-1',
|
|
27
|
+
type: 'paragraph',
|
|
28
|
+
data: { text: 'First block for testing block states.' },
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'block-state-2',
|
|
32
|
+
type: 'paragraph',
|
|
33
|
+
data: { text: 'Second block with different content.' },
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'block-state-3',
|
|
37
|
+
type: 'paragraph',
|
|
38
|
+
data: { text: 'Third block for multi-select testing.' },
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const createEditor = (args: BlockArgs): HTMLElement => createEditorContainer(args);
|
|
44
|
+
|
|
45
|
+
const meta: Meta<BlockArgs> = {
|
|
46
|
+
title: 'Components/Block',
|
|
47
|
+
tags: ['autodocs'],
|
|
48
|
+
args: {
|
|
49
|
+
minHeight: 300,
|
|
50
|
+
data: sampleData,
|
|
51
|
+
readOnly: false,
|
|
52
|
+
},
|
|
53
|
+
render: createEditor,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default meta;
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
type Story = StoryObj<BlockArgs>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Default state: Blocks displayed without selection.
|
|
63
|
+
*/
|
|
64
|
+
export const Default: Story = {
|
|
65
|
+
args: {
|
|
66
|
+
data: sampleData,
|
|
67
|
+
readOnly: false,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Block focused state with cursor inside.
|
|
73
|
+
*/
|
|
74
|
+
export const Focused: Story = {
|
|
75
|
+
args: {
|
|
76
|
+
data: sampleData,
|
|
77
|
+
readOnly: false,
|
|
78
|
+
},
|
|
79
|
+
play: async ({ canvasElement, step }) => {
|
|
80
|
+
await step('Wait for editor and toolbar to initialize', async () => {
|
|
81
|
+
await waitFor(
|
|
82
|
+
() => {
|
|
83
|
+
const block = canvasElement.querySelector(BLOCK_TESTID);
|
|
84
|
+
|
|
85
|
+
expect(block).toBeInTheDocument();
|
|
86
|
+
},
|
|
87
|
+
TIMEOUT_INIT
|
|
88
|
+
);
|
|
89
|
+
// Wait for toolbar to be created (happens in requestIdleCallback)
|
|
90
|
+
await waitForToolbar(canvasElement);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await step('Click block to focus', async () => {
|
|
94
|
+
const block = canvasElement.querySelector(BLOCK_TESTID);
|
|
95
|
+
const contentEditable = block?.querySelector(CONTENTEDITABLE_SELECTOR);
|
|
96
|
+
|
|
97
|
+
if (contentEditable) {
|
|
98
|
+
simulateClick(contentEditable);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
await waitFor(
|
|
102
|
+
() => {
|
|
103
|
+
const toolbar = canvasElement.querySelector(TOOLBAR_TESTID);
|
|
104
|
+
|
|
105
|
+
expect(toolbar).toHaveAttribute('data-blok-opened', 'true');
|
|
106
|
+
},
|
|
107
|
+
TIMEOUT_ACTION
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Block selected state (cross-block selection visual).
|
|
115
|
+
*/
|
|
116
|
+
export const SelectedByShortcut: Story = {
|
|
117
|
+
args: {
|
|
118
|
+
data: sampleData,
|
|
119
|
+
readOnly: false,
|
|
120
|
+
},
|
|
121
|
+
play: async ({ canvasElement, step }) => {
|
|
122
|
+
await step('Wait for editor and toolbar to initialize', async () => {
|
|
123
|
+
await waitFor(
|
|
124
|
+
() => {
|
|
125
|
+
const blocks = canvasElement.querySelectorAll(BLOCK_TESTID);
|
|
126
|
+
|
|
127
|
+
expect(blocks.length).toBeGreaterThan(0);
|
|
128
|
+
},
|
|
129
|
+
TIMEOUT_INIT
|
|
130
|
+
);
|
|
131
|
+
// Wait for toolbar to be created (happens in requestIdleCallback)
|
|
132
|
+
await waitForToolbar(canvasElement);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
await step('Click block to focus', async () => {
|
|
136
|
+
const block = canvasElement.querySelector(BLOCK_TESTID);
|
|
137
|
+
const contentEditable = block?.querySelector(CONTENTEDITABLE_SELECTOR);
|
|
138
|
+
|
|
139
|
+
if (contentEditable) {
|
|
140
|
+
simulateClick(contentEditable);
|
|
141
|
+
// Wait a bit for focus to be established
|
|
142
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
await step('Select all blocks with keyboard shortcut', async () => {
|
|
147
|
+
const block = canvasElement.querySelector(BLOCK_TESTID);
|
|
148
|
+
const contentEditable = block?.querySelector(CONTENTEDITABLE_SELECTOR);
|
|
149
|
+
|
|
150
|
+
if (contentEditable) {
|
|
151
|
+
// First select-all selects text within the block
|
|
152
|
+
triggerSelectAll(contentEditable);
|
|
153
|
+
// Short delay to let the first selection happen
|
|
154
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
155
|
+
// Second select-all selects all blocks (cross-block selection)
|
|
156
|
+
triggerSelectAll(contentEditable);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await waitFor(
|
|
160
|
+
() => {
|
|
161
|
+
const selectedBlocks = canvasElement.querySelectorAll(BLOCK_SELECTED_SELECTOR);
|
|
162
|
+
|
|
163
|
+
expect(selectedBlocks.length).toBeGreaterThan(0);
|
|
164
|
+
},
|
|
165
|
+
TIMEOUT_ACTION
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Multiple blocks selected.
|
|
173
|
+
*/
|
|
174
|
+
export const MultipleSelected: Story = {
|
|
175
|
+
args: {
|
|
176
|
+
data: sampleData,
|
|
177
|
+
readOnly: false,
|
|
178
|
+
},
|
|
179
|
+
play: async ({ canvasElement, step }) => {
|
|
180
|
+
await step('Wait for editor and toolbar to initialize', async () => {
|
|
181
|
+
await waitFor(
|
|
182
|
+
() => {
|
|
183
|
+
const blocks = canvasElement.querySelectorAll(BLOCK_TESTID);
|
|
184
|
+
|
|
185
|
+
expect(blocks.length).toBeGreaterThan(2);
|
|
186
|
+
},
|
|
187
|
+
TIMEOUT_INIT
|
|
188
|
+
);
|
|
189
|
+
// Wait for toolbar to be created (happens in requestIdleCallback)
|
|
190
|
+
await waitForToolbar(canvasElement);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
await step('Focus first block', async () => {
|
|
194
|
+
const firstBlock = canvasElement.querySelector(BLOCK_TESTID);
|
|
195
|
+
const contentEditable = firstBlock?.querySelector(CONTENTEDITABLE_SELECTOR);
|
|
196
|
+
|
|
197
|
+
if (contentEditable) {
|
|
198
|
+
simulateClick(contentEditable);
|
|
199
|
+
// Wait a bit for focus to be established
|
|
200
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
await step('Select all to trigger multi-block selection', async () => {
|
|
205
|
+
const firstBlock = canvasElement.querySelector(BLOCK_TESTID);
|
|
206
|
+
const contentEditable = firstBlock?.querySelector(CONTENTEDITABLE_SELECTOR);
|
|
207
|
+
|
|
208
|
+
if (contentEditable) {
|
|
209
|
+
// First select-all selects text within the block
|
|
210
|
+
triggerSelectAll(contentEditable);
|
|
211
|
+
// Short delay to let the first selection happen
|
|
212
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
213
|
+
// Second select-all selects all blocks (cross-block selection)
|
|
214
|
+
triggerSelectAll(contentEditable);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
await waitFor(
|
|
218
|
+
() => {
|
|
219
|
+
const selectedBlocks = canvasElement.querySelectorAll(BLOCK_SELECTED_SELECTOR);
|
|
220
|
+
|
|
221
|
+
expect(selectedBlocks.length).toBeGreaterThanOrEqual(3);
|
|
222
|
+
},
|
|
223
|
+
TIMEOUT_ACTION
|
|
224
|
+
);
|
|
225
|
+
});
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Block with selection highlight (text selection within block).
|
|
231
|
+
*/
|
|
232
|
+
export const WithTextSelection: Story = {
|
|
233
|
+
args: {
|
|
234
|
+
data: sampleData,
|
|
235
|
+
readOnly: false,
|
|
236
|
+
},
|
|
237
|
+
play: async ({ canvasElement, step }) => {
|
|
238
|
+
await step('Wait for editor to initialize', async () => {
|
|
239
|
+
await waitFor(
|
|
240
|
+
() => {
|
|
241
|
+
const block = canvasElement.querySelector(BLOCK_TESTID);
|
|
242
|
+
|
|
243
|
+
expect(block).toBeInTheDocument();
|
|
244
|
+
},
|
|
245
|
+
TIMEOUT_INIT
|
|
246
|
+
);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
await step('Select text within block', async () => {
|
|
250
|
+
const block = canvasElement.querySelector(BLOCK_TESTID);
|
|
251
|
+
const contentEditable = block?.querySelector(CONTENTEDITABLE_SELECTOR);
|
|
252
|
+
|
|
253
|
+
if (contentEditable) {
|
|
254
|
+
await userEvent.click(contentEditable);
|
|
255
|
+
await userEvent.tripleClick(contentEditable);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const selection = window.getSelection();
|
|
259
|
+
|
|
260
|
+
expect(selection?.toString().length).toBeGreaterThan(0);
|
|
261
|
+
});
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Block in read-only mode.
|
|
267
|
+
*/
|
|
268
|
+
export const ReadOnly: Story = {
|
|
269
|
+
args: {
|
|
270
|
+
data: sampleData,
|
|
271
|
+
readOnly: true,
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Block link hover state.
|
|
277
|
+
*/
|
|
278
|
+
export const LinkInBlock: Story = {
|
|
279
|
+
args: {
|
|
280
|
+
data: {
|
|
281
|
+
time: Date.now(),
|
|
282
|
+
version: '1.0.0',
|
|
283
|
+
blocks: [
|
|
284
|
+
{
|
|
285
|
+
id: 'link-block-1',
|
|
286
|
+
type: 'paragraph',
|
|
287
|
+
data: { text: 'This block contains a <a href="https://example.com">clickable link</a> to test hover states.' },
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
},
|
|
291
|
+
readOnly: false,
|
|
292
|
+
},
|
|
293
|
+
play: async ({ canvasElement, step }) => {
|
|
294
|
+
await step('Wait for editor to initialize', async () => {
|
|
295
|
+
await waitFor(
|
|
296
|
+
() => {
|
|
297
|
+
const link = canvasElement.querySelector('a');
|
|
298
|
+
|
|
299
|
+
expect(link).toBeInTheDocument();
|
|
300
|
+
},
|
|
301
|
+
TIMEOUT_INIT
|
|
302
|
+
);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
await step('Hover over link', async () => {
|
|
306
|
+
const link = canvasElement.querySelector('a');
|
|
307
|
+
|
|
308
|
+
if (link) {
|
|
309
|
+
await userEvent.hover(link);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Block with bold and italic text.
|
|
317
|
+
*/
|
|
318
|
+
export const WithFormattedText: Story = {
|
|
319
|
+
args: {
|
|
320
|
+
data: {
|
|
321
|
+
time: Date.now(),
|
|
322
|
+
version: '1.0.0',
|
|
323
|
+
blocks: [
|
|
324
|
+
{
|
|
325
|
+
id: 'formatted-block-1',
|
|
326
|
+
type: 'paragraph',
|
|
327
|
+
data: { text: 'This text has <b>bold</b>, <i>italic</i>, and <b><i>bold italic</i></b> formatting.' },
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
},
|
|
331
|
+
readOnly: false,
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Block fade-in animation on creation.
|
|
337
|
+
*/
|
|
338
|
+
export const NewBlockAnimation: Story = {
|
|
339
|
+
args: {
|
|
340
|
+
data: sampleData,
|
|
341
|
+
readOnly: false,
|
|
342
|
+
},
|
|
343
|
+
play: async ({ canvasElement, step }) => {
|
|
344
|
+
await step('Wait for editor and toolbar to initialize', async () => {
|
|
345
|
+
await waitFor(
|
|
346
|
+
() => {
|
|
347
|
+
const block = canvasElement.querySelector(BLOCK_TESTID);
|
|
348
|
+
|
|
349
|
+
expect(block).toBeInTheDocument();
|
|
350
|
+
},
|
|
351
|
+
TIMEOUT_INIT
|
|
352
|
+
);
|
|
353
|
+
// Wait for toolbar to be created (happens in requestIdleCallback)
|
|
354
|
+
await waitForToolbar(canvasElement);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
await step('Focus last block and press Enter to create new block', async () => {
|
|
358
|
+
const blocks = canvasElement.querySelectorAll(BLOCK_TESTID);
|
|
359
|
+
const initialBlockCount = blocks.length;
|
|
360
|
+
const lastBlock = blocks[blocks.length - 1];
|
|
361
|
+
const contentEditable = lastBlock?.querySelector(CONTENTEDITABLE_SELECTOR);
|
|
362
|
+
|
|
363
|
+
if (contentEditable) {
|
|
364
|
+
simulateClick(contentEditable);
|
|
365
|
+
// Wait a bit for focus to be established
|
|
366
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
367
|
+
|
|
368
|
+
const selection = window.getSelection();
|
|
369
|
+
const range = document.createRange();
|
|
370
|
+
|
|
371
|
+
range.selectNodeContents(contentEditable);
|
|
372
|
+
range.collapse(false);
|
|
373
|
+
selection?.removeAllRanges();
|
|
374
|
+
selection?.addRange(range);
|
|
375
|
+
|
|
376
|
+
await userEvent.keyboard('{Enter}');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
await waitFor(
|
|
380
|
+
() => {
|
|
381
|
+
const newBlocks = canvasElement.querySelectorAll(BLOCK_TESTID);
|
|
382
|
+
|
|
383
|
+
expect(newBlocks.length).toBeGreaterThan(initialBlockCount);
|
|
384
|
+
},
|
|
385
|
+
TIMEOUT_ACTION
|
|
386
|
+
);
|
|
387
|
+
});
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Stretched block - full-width block layout.
|
|
393
|
+
* This state is shown when a block is configured to stretch to full width.
|
|
394
|
+
*/
|
|
395
|
+
export const StretchedBlock: Story = {
|
|
396
|
+
args: {
|
|
397
|
+
data: {
|
|
398
|
+
time: Date.now(),
|
|
399
|
+
version: '1.0.0',
|
|
400
|
+
blocks: [
|
|
401
|
+
{
|
|
402
|
+
id: 'normal-block-1',
|
|
403
|
+
type: 'paragraph',
|
|
404
|
+
data: { text: 'This is a normal width paragraph block.' },
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
id: 'stretched-block-1',
|
|
408
|
+
type: 'paragraph',
|
|
409
|
+
data: { text: 'This block has the stretched class applied to demonstrate full-width layout.' },
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
id: 'normal-block-2',
|
|
413
|
+
type: 'paragraph',
|
|
414
|
+
data: { text: 'Another normal width paragraph for comparison.' },
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
},
|
|
418
|
+
readOnly: false,
|
|
419
|
+
},
|
|
420
|
+
play: async ({ canvasElement, step }) => {
|
|
421
|
+
await step('Wait for editor to initialize', async () => {
|
|
422
|
+
await waitFor(
|
|
423
|
+
() => {
|
|
424
|
+
const blocks = canvasElement.querySelectorAll(BLOCK_TESTID);
|
|
425
|
+
|
|
426
|
+
expect(blocks.length).toBe(3);
|
|
427
|
+
},
|
|
428
|
+
TIMEOUT_INIT
|
|
429
|
+
);
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
await step('Apply stretched state to middle block', async () => {
|
|
433
|
+
const blocks = canvasElement.querySelectorAll(BLOCK_TESTID);
|
|
434
|
+
const middleBlock = blocks[1];
|
|
435
|
+
|
|
436
|
+
if (middleBlock) {
|
|
437
|
+
middleBlock.setAttribute('data-blok-stretched', 'true');
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
await waitFor(
|
|
441
|
+
() => {
|
|
442
|
+
const stretchedBlock = canvasElement.querySelector('[data-blok-stretched="true"]');
|
|
443
|
+
|
|
444
|
+
expect(stretchedBlock).toBeInTheDocument();
|
|
445
|
+
},
|
|
446
|
+
TIMEOUT_ACTION
|
|
447
|
+
);
|
|
448
|
+
});
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Block in navigation mode - keyboard-based block navigation.
|
|
454
|
+
* Activated by pressing Escape when focus is in the editor.
|
|
455
|
+
* Use arrow keys to navigate between blocks, Enter to edit.
|
|
456
|
+
*/
|
|
457
|
+
export const NavigationMode: Story = {
|
|
458
|
+
args: {
|
|
459
|
+
data: sampleData,
|
|
460
|
+
readOnly: false,
|
|
461
|
+
},
|
|
462
|
+
play: async ({ canvasElement, step }) => {
|
|
463
|
+
await step('Wait for editor and toolbar to initialize', async () => {
|
|
464
|
+
await waitFor(
|
|
465
|
+
() => {
|
|
466
|
+
const blocks = canvasElement.querySelectorAll(BLOCK_TESTID);
|
|
467
|
+
|
|
468
|
+
expect(blocks.length).toBeGreaterThan(0);
|
|
469
|
+
},
|
|
470
|
+
TIMEOUT_INIT
|
|
471
|
+
);
|
|
472
|
+
await waitForToolbar(canvasElement);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
await step('Focus first block', async () => {
|
|
476
|
+
const block = canvasElement.querySelector(BLOCK_TESTID);
|
|
477
|
+
const contentEditable = block?.querySelector(CONTENTEDITABLE_SELECTOR);
|
|
478
|
+
|
|
479
|
+
if (contentEditable) {
|
|
480
|
+
simulateClick(contentEditable);
|
|
481
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
await step('Enable navigation mode by pressing Escape', async () => {
|
|
486
|
+
await userEvent.keyboard('{Escape}');
|
|
487
|
+
|
|
488
|
+
await waitFor(
|
|
489
|
+
() => {
|
|
490
|
+
const navigationFocusedBlock = canvasElement.querySelector('[data-blok-navigation-focused="true"]');
|
|
491
|
+
|
|
492
|
+
expect(navigationFocusedBlock).toBeInTheDocument();
|
|
493
|
+
},
|
|
494
|
+
TIMEOUT_ACTION
|
|
495
|
+
);
|
|
496
|
+
});
|
|
497
|
+
},
|
|
498
|
+
};
|