@jackuait/blok 0.7.0-beta.4 → 0.7.0
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/dist/blok.mjs +3 -7
- package/dist/chunks/blok-Ufr5cPq-.mjs +12435 -0
- package/dist/chunks/constants-DT17zmu_.mjs +2934 -0
- package/dist/chunks/i18next-DymC16cN.mjs +1146 -0
- package/dist/chunks/i18next-loader-qjweOJ-t.mjs +35 -0
- package/dist/chunks/lightweight-i18n-vbtPx5C4.mjs +105 -0
- package/dist/chunks/messages-3bOAVT3X2.mjs +80 -0
- package/dist/chunks/messages-43N0Vfg42.mjs +80 -0
- package/dist/chunks/messages-B0cg-ThO2.mjs +80 -0
- package/dist/chunks/messages-B3StvafX.mjs +80 -0
- package/dist/chunks/messages-B7LU-b6n2.mjs +80 -0
- package/dist/chunks/messages-B87-89os.mjs +80 -0
- package/dist/chunks/messages-BFiMCfDX2.mjs +80 -0
- package/dist/chunks/messages-BLxyso1L.mjs +80 -0
- package/dist/chunks/messages-BQZtOYxr2.mjs +80 -0
- package/dist/chunks/messages-BRrtoRdw2.mjs +80 -0
- package/dist/chunks/messages-BU_YdaAf.mjs +80 -0
- package/dist/chunks/messages-BWbZYIs12.mjs +80 -0
- package/dist/chunks/messages-B_Qcy8kr2.mjs +80 -0
- package/dist/chunks/messages-B_uTiuQ-.mjs +80 -0
- package/dist/chunks/messages-BdWTM73p.mjs +80 -0
- package/dist/chunks/messages-BhZcNoIQ.mjs +80 -0
- package/dist/chunks/messages-Bn6LwI4B.mjs +80 -0
- package/dist/chunks/messages-BoTtYEct2.mjs +80 -0
- package/dist/chunks/messages-BrvAiuWT.mjs +80 -0
- package/dist/chunks/messages-Byp0YFMg.mjs +80 -0
- package/dist/chunks/messages-C0ZWDShx2.mjs +80 -0
- package/dist/chunks/messages-CA-jms9R.mjs +80 -0
- package/dist/chunks/messages-CFr0Ha6p2.mjs +80 -0
- package/dist/chunks/messages-CG2xl0IV.mjs +80 -0
- package/dist/chunks/messages-CIGX0FfW.mjs +80 -0
- package/dist/chunks/messages-CRMdL0jG.mjs +80 -0
- package/dist/chunks/messages-CRdl14uE.mjs +80 -0
- package/dist/chunks/messages-Cimsel4e.mjs +80 -0
- package/dist/chunks/messages-CjcSWeud.mjs +80 -0
- package/dist/chunks/messages-ClDJuy8K2.mjs +80 -0
- package/dist/chunks/messages-Cn1AC0Qk.mjs +80 -0
- package/dist/chunks/messages-CpnXbVOK2.mjs +80 -0
- package/dist/chunks/messages-CqsES1wk2.mjs +80 -0
- package/dist/chunks/messages-Csq7JatN.mjs +80 -0
- package/dist/chunks/messages-CtufKbaD.mjs +80 -0
- package/dist/chunks/messages-Cuk0QaLM.mjs +80 -0
- package/dist/chunks/messages-CvamFN6x.mjs +80 -0
- package/dist/chunks/messages-CwRhVVui.mjs +80 -0
- package/dist/chunks/messages-CzCezryo.mjs +80 -0
- package/dist/chunks/messages-D0v0Xa_i2.mjs +80 -0
- package/dist/chunks/messages-D3JVx_CH2.mjs +80 -0
- package/dist/chunks/messages-D4jR5Oc-.mjs +80 -0
- package/dist/chunks/messages-D7fI9Pj52.mjs +80 -0
- package/dist/chunks/messages-DGodJU2R.mjs +80 -0
- package/dist/chunks/messages-DLrmLkco2.mjs +80 -0
- package/dist/chunks/messages-DPe7kW6J.mjs +80 -0
- package/dist/chunks/messages-DRYKKPk8.mjs +80 -0
- package/dist/chunks/messages-DV5c_ZRQ.mjs +80 -0
- package/dist/chunks/messages-Dg6kSnxq.mjs +80 -0
- package/dist/chunks/messages-Dgfbmyf-.mjs +80 -0
- package/dist/chunks/messages-DihczS7L.mjs +80 -0
- package/dist/chunks/messages-DkSwQvmi2.mjs +80 -0
- package/dist/chunks/messages-Doxcj7Qy.mjs +80 -0
- package/dist/chunks/messages-DqGQvcXv2.mjs +80 -0
- package/dist/chunks/messages-Dr7yA3xM.mjs +80 -0
- package/dist/chunks/messages-DriB5lEF.mjs +80 -0
- package/dist/chunks/messages-FB_MePlt.mjs +80 -0
- package/dist/chunks/messages-JyZvGvrN.mjs +80 -0
- package/dist/chunks/messages-KdvbGwLH.mjs +80 -0
- package/dist/chunks/messages-M0HT-kBW.mjs +80 -0
- package/dist/chunks/messages-M8noQ6Kp2.mjs +80 -0
- package/dist/chunks/messages-elZUbCrN.mjs +80 -0
- package/dist/chunks/messages-iWMOMK822.mjs +80 -0
- package/dist/chunks/messages-kC92TJI72.mjs +80 -0
- package/dist/chunks/messages-tfyq1JIh2.mjs +80 -0
- package/dist/chunks/messages-v1HkA3kF2.mjs +80 -0
- package/dist/chunks/messages-yuqArCc6.mjs +80 -0
- package/dist/chunks/notifier-BqYxvxnV.mjs +96 -0
- package/dist/chunks/objectSpread2-CyPxu8-u.mjs +62 -0
- package/dist/chunks/tools-CJIETS-H.mjs +6004 -0
- package/dist/chunks/tw-DmW6-pCY.mjs +237 -0
- package/dist/cli.mjs +36 -49
- package/dist/full.mjs +26 -52
- package/dist/locales.mjs +181 -254
- package/dist/messages-2iHnlF0U.mjs +80 -0
- package/dist/messages-49ZJ_ISf.mjs +80 -0
- package/dist/messages-B8jjwMLK.mjs +80 -0
- package/dist/messages-BEDVb3ZX.mjs +80 -0
- package/dist/messages-BEEr6Vh82.mjs +80 -0
- package/dist/messages-BFT0F9pw.mjs +80 -0
- package/dist/messages-BHOI7R4K.mjs +80 -0
- package/dist/messages-BRPH_a6a.mjs +80 -0
- package/dist/messages-BSlQrYwp.mjs +80 -0
- package/dist/messages-BTNuOkhL.mjs +80 -0
- package/dist/messages-BX2KVzJp2.mjs +80 -0
- package/dist/messages-BaGwIHPb2.mjs +80 -0
- package/dist/messages-BdA_xvxj.mjs +80 -0
- package/dist/messages-BeJaje7e2.mjs +80 -0
- package/dist/messages-BfgHOkAy.mjs +80 -0
- package/dist/messages-BflWzIcP2.mjs +80 -0
- package/dist/messages-BigRnQS92.mjs +80 -0
- package/dist/messages-BjnJajTO2.mjs +80 -0
- package/dist/messages-BpA30dPf.mjs +80 -0
- package/dist/messages-BrPEPj382.mjs +80 -0
- package/dist/messages-Bt_9ptDu.mjs +80 -0
- package/dist/messages-C0cXOCHN2.mjs +80 -0
- package/dist/messages-C3tLCwJp2.mjs +80 -0
- package/dist/messages-C45IBZtA2.mjs +80 -0
- package/dist/messages-CA0hwajz.mjs +80 -0
- package/dist/messages-CCKZS2f4.mjs +80 -0
- package/dist/messages-CCm71gq3.mjs +80 -0
- package/dist/messages-CERs9LC9.mjs +80 -0
- package/dist/messages-CLQvtc_8.mjs +80 -0
- package/dist/messages-CPx1R-PH.mjs +80 -0
- package/dist/messages-CYFdbooL2.mjs +80 -0
- package/dist/messages-CYLYnOV82.mjs +80 -0
- package/dist/messages-CYZVFnaF.mjs +80 -0
- package/dist/messages-CaAdEXoh2.mjs +80 -0
- package/dist/messages-CicggErN2.mjs +80 -0
- package/dist/messages-CkAWTSc4.mjs +80 -0
- package/dist/messages-CkVfziK_2.mjs +80 -0
- package/dist/messages-CsM2iz1H2.mjs +80 -0
- package/dist/messages-D-12TeCM2.mjs +80 -0
- package/dist/messages-D0i5Vdyy2.mjs +80 -0
- package/dist/messages-D5KmRsUV2.mjs +80 -0
- package/dist/messages-DBwaWI0X.mjs +80 -0
- package/dist/messages-DDGzypb4.mjs +80 -0
- package/dist/messages-DQGzw4IC.mjs +80 -0
- package/dist/messages-DWZyaZNA.mjs +80 -0
- package/dist/messages-DYlxQEIv.mjs +80 -0
- package/dist/messages-DZo0x7Bd.mjs +80 -0
- package/dist/messages-Dc1yFFBM.mjs +80 -0
- package/dist/messages-DdUpYaJ1.mjs +80 -0
- package/dist/messages-DgstU8GH.mjs +80 -0
- package/dist/messages-DhdWq5oQ2.mjs +80 -0
- package/dist/messages-DmX52AQr.mjs +80 -0
- package/dist/messages-Dr-YJYIK2.mjs +80 -0
- package/dist/messages-DuubRyFf.mjs +80 -0
- package/dist/messages-DvTVsLOK2.mjs +80 -0
- package/dist/messages-DwPfgL_u.mjs +80 -0
- package/dist/messages-DxKIxLKw.mjs +80 -0
- package/dist/messages-DzhR8Klk.mjs +80 -0
- package/dist/messages-MBBSKGjJ2.mjs +80 -0
- package/dist/messages-RNusm48G2.mjs +80 -0
- package/dist/messages-XwPD18Kk.mjs +80 -0
- package/dist/messages-YfjdnhUF.mjs +80 -0
- package/dist/messages-aNMLsF8T2.mjs +80 -0
- package/dist/messages-cOqXp22e.mjs +80 -0
- package/dist/messages-g58itYPI.mjs +80 -0
- package/dist/messages-vfkwiKQo.mjs +80 -0
- package/dist/messages-vssmW7KO.mjs +80 -0
- package/dist/react.mjs +108 -0
- package/dist/tools.mjs +3 -7485
- package/dist/vendor.LICENSE.txt +86 -86
- package/package.json +56 -29
- package/src/blok.ts +52 -2
- package/src/components/block/api.ts +8 -0
- package/src/components/block/mutation-handler.ts +29 -4
- package/src/components/block/style-manager.ts +1 -1
- package/src/components/block-tunes/block-tune-width.ts +39 -0
- package/src/components/blocks.ts +56 -2
- package/src/components/core.ts +1 -0
- package/src/components/i18n/locales/am/messages.json +6 -1
- package/src/components/i18n/locales/ar/messages.json +6 -1
- package/src/components/i18n/locales/az/messages.json +6 -1
- package/src/components/i18n/locales/bg/messages.json +8 -3
- package/src/components/i18n/locales/bn/messages.json +6 -1
- package/src/components/i18n/locales/bs/messages.json +6 -1
- package/src/components/i18n/locales/cs/messages.json +6 -1
- package/src/components/i18n/locales/da/messages.json +6 -1
- package/src/components/i18n/locales/de/messages.json +8 -3
- package/src/components/i18n/locales/dv/messages.json +6 -1
- package/src/components/i18n/locales/el/messages.json +8 -3
- package/src/components/i18n/locales/en/messages.json +5 -0
- package/src/components/i18n/locales/es/messages.json +6 -1
- package/src/components/i18n/locales/et/messages.json +6 -1
- package/src/components/i18n/locales/fa/messages.json +8 -3
- package/src/components/i18n/locales/fi/messages.json +6 -1
- package/src/components/i18n/locales/fil/messages.json +21 -16
- package/src/components/i18n/locales/fr/messages.json +6 -1
- package/src/components/i18n/locales/gu/messages.json +6 -1
- package/src/components/i18n/locales/he/messages.json +6 -1
- package/src/components/i18n/locales/hi/messages.json +6 -1
- package/src/components/i18n/locales/hr/messages.json +6 -1
- package/src/components/i18n/locales/hu/messages.json +6 -1
- package/src/components/i18n/locales/hy/messages.json +8 -3
- package/src/components/i18n/locales/id/messages.json +12 -7
- package/src/components/i18n/locales/it/messages.json +6 -1
- package/src/components/i18n/locales/ja/messages.json +6 -1
- package/src/components/i18n/locales/ka/messages.json +6 -1
- package/src/components/i18n/locales/km/messages.json +6 -1
- package/src/components/i18n/locales/kn/messages.json +6 -1
- package/src/components/i18n/locales/ko/messages.json +6 -1
- package/src/components/i18n/locales/ku/messages.json +7 -2
- package/src/components/i18n/locales/lo/messages.json +7 -2
- package/src/components/i18n/locales/lt/messages.json +6 -1
- package/src/components/i18n/locales/lv/messages.json +6 -1
- package/src/components/i18n/locales/mk/messages.json +6 -1
- package/src/components/i18n/locales/ml/messages.json +6 -1
- package/src/components/i18n/locales/mn/messages.json +6 -1
- package/src/components/i18n/locales/mr/messages.json +6 -1
- package/src/components/i18n/locales/ms/messages.json +6 -1
- package/src/components/i18n/locales/my/messages.json +6 -1
- package/src/components/i18n/locales/ne/messages.json +9 -4
- package/src/components/i18n/locales/nl/messages.json +6 -1
- package/src/components/i18n/locales/no/messages.json +6 -1
- package/src/components/i18n/locales/pa/messages.json +6 -1
- package/src/components/i18n/locales/pl/messages.json +6 -1
- package/src/components/i18n/locales/ps/messages.json +8 -3
- package/src/components/i18n/locales/pt/messages.json +6 -1
- package/src/components/i18n/locales/ro/messages.json +6 -1
- package/src/components/i18n/locales/ru/messages.json +10 -5
- package/src/components/i18n/locales/sd/messages.json +6 -1
- package/src/components/i18n/locales/si/messages.json +6 -1
- package/src/components/i18n/locales/sk/messages.json +6 -1
- package/src/components/i18n/locales/sl/messages.json +6 -1
- package/src/components/i18n/locales/sq/messages.json +6 -1
- package/src/components/i18n/locales/sr/messages.json +6 -1
- package/src/components/i18n/locales/sv/messages.json +6 -1
- package/src/components/i18n/locales/sw/messages.json +6 -1
- package/src/components/i18n/locales/ta/messages.json +6 -1
- package/src/components/i18n/locales/te/messages.json +9 -4
- package/src/components/i18n/locales/th/messages.json +6 -1
- package/src/components/i18n/locales/tr/messages.json +6 -1
- package/src/components/i18n/locales/ug/messages.json +7 -2
- package/src/components/i18n/locales/uk/messages.json +6 -1
- package/src/components/i18n/locales/ur/messages.json +6 -1
- package/src/components/i18n/locales/vi/messages.json +6 -1
- package/src/components/i18n/locales/yi/messages.json +7 -2
- package/src/components/i18n/locales/zh/messages.json +6 -1
- package/src/components/icons/index.ts +16 -0
- package/src/components/inline-tools/inline-tool-link.ts +1 -1
- package/src/components/modules/api/blocks.ts +45 -2
- package/src/components/modules/api/index.ts +1 -0
- package/src/components/modules/api/width.ts +17 -0
- package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +99 -0
- package/src/components/modules/blockEvents/composers/markdownShortcuts.ts +109 -2
- package/src/components/modules/blockEvents/constants.ts +7 -0
- package/src/components/modules/blockManager/blockManager.ts +113 -9
- package/src/components/modules/blockManager/hierarchy.ts +61 -0
- package/src/components/modules/blockManager/operations.ts +133 -15
- package/src/components/modules/blockManager/yjs-sync.ts +112 -4
- package/src/components/modules/blockSelection.ts +36 -2
- package/src/components/modules/crossBlockSelection.ts +22 -2
- package/src/components/modules/drag/DragController.ts +178 -4
- package/src/components/modules/drag/operations/DragOperations.ts +48 -9
- package/src/components/modules/drag/preview/DragPreview.ts +21 -1
- package/src/components/modules/drag/state/DragStateMachine.ts +6 -1
- package/src/components/modules/drag/target/DropTargetDetector.ts +80 -4
- package/src/components/modules/drag/utils/ToggleSpringLoader.ts +71 -0
- package/src/components/modules/index.ts +7 -1
- package/src/components/modules/modificationsObserver.ts +19 -0
- package/src/components/modules/paste/constants.ts +2 -0
- package/src/components/modules/paste/handlers/base.ts +33 -1
- package/src/components/modules/paste/handlers/html-handler.ts +121 -54
- package/src/components/modules/paste/index.ts +5 -0
- package/src/components/modules/paste/types.ts +5 -0
- package/src/components/modules/rectangleSelection.ts +74 -81
- package/src/components/modules/toolbar/blockSettings.ts +25 -7
- package/src/components/modules/toolbar/index.ts +9 -7
- package/src/components/modules/toolbar/inline/index.ts +6 -1
- package/src/components/modules/toolbar/plus-button.ts +2 -6
- package/src/components/modules/toolbar/positioning.ts +10 -1
- package/src/components/modules/toolbar/settings-toggler.ts +1 -1
- package/src/components/modules/toolbar/styles.ts +3 -7
- package/src/components/modules/ui.ts +59 -5
- package/src/components/modules/uiControllers/handlers/click.ts +3 -2
- package/src/components/modules/widthManager.ts +69 -0
- package/src/components/modules/yjs/document-store.ts +11 -0
- package/src/components/modules/yjs/index.ts +11 -0
- package/src/components/shared/color-picker.ts +3 -3
- package/src/components/tools/block.ts +1 -11
- package/src/components/ui/toolbox.ts +52 -8
- package/src/components/utils/blocks.ts +37 -7
- package/src/components/utils/mutations.ts +2 -2
- package/src/components/utils/notifier/draw.ts +1 -1
- package/src/components/utils/placeholder.ts +5 -6
- package/src/components/utils/popover/components/popover-header/popover-header.const.ts +1 -1
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.const.ts +4 -4
- package/src/components/utils/popover/components/popover-item/popover-item-default/popover-item-default.ts +6 -6
- package/src/components/utils/popover/components/popover-item/popover-item-separator/popover-item-separator.const.ts +2 -2
- package/src/components/utils/popover/components/search-input/search-input.const.ts +2 -2
- package/src/components/utils/popover/components/search-input/search-input.ts +7 -11
- package/src/components/utils/popover/components/search-input/search-input.types.ts +149 -10
- package/src/components/utils/popover/popover-abstract.ts +3 -2
- package/src/components/utils/popover/popover-desktop.ts +133 -11
- package/src/components/utils/popover/popover-inline.ts +1 -1
- package/src/components/utils/popover/popover.const.ts +3 -3
- package/src/components/utils/shortcut.ts +2 -0
- package/src/components/utils/tooltip.ts +11 -1
- package/src/react/BlokContent.tsx +46 -0
- package/src/react/holder-map.ts +17 -0
- package/src/react/index.ts +3 -0
- package/src/react/types.ts +16 -0
- package/src/react/useBlok.ts +173 -0
- package/src/stories/Placeholder.stories.ts +0 -59
- package/src/styles/main.css +663 -52
- package/src/tools/header/header-toggle-keyboard.ts +115 -0
- package/src/tools/header/index.ts +382 -187
- package/src/tools/list/block-operations.ts +1 -1
- package/src/tools/list/caret-manager.ts +9 -12
- package/src/tools/list/index.ts +2 -6
- package/src/tools/list/list-keyboard.ts +2 -2
- package/src/tools/paragraph/index.ts +1 -1
- package/src/tools/table/index.ts +37 -3
- package/src/tools/table/table-add-controls.ts +97 -8
- package/src/tools/table/table-cell-blocks.ts +17 -8
- package/src/tools/table/table-cell-clipboard.ts +1 -1
- package/src/tools/table/table-cell-selection.ts +27 -2
- package/src/tools/table/table-operations.ts +3 -2
- package/src/tools/toggle/block-operations.ts +4 -2
- package/src/tools/toggle/constants.ts +26 -2
- package/src/tools/toggle/dom-builder.ts +90 -25
- package/src/tools/toggle/index.ts +112 -9
- package/src/tools/toggle/toggle-keyboard.ts +5 -3
- package/src/tools/toggle/toggle-lifecycle.ts +79 -7
- package/src/tools/toggle/toggle-shortcuts.ts +214 -20
- package/src/tools/toggle/types.ts +2 -0
- package/src/types-internal/blok-modules.d.ts +4 -0
- package/types/api/block.d.ts +5 -0
- package/types/api/blocks.d.ts +29 -0
- package/types/api/index.d.ts +1 -0
- package/types/api/width.d.ts +19 -0
- package/types/configs/blok-config.d.ts +33 -0
- package/types/index.d.ts +4 -0
- package/types/react.d.ts +58 -0
- package/types/utils/popover/popover.d.ts +7 -0
- package/dist/chunks/blok-B0pAWdVk.mjs +0 -20102
- package/dist/chunks/constants-DmDwNSTM.mjs +0 -5123
- package/dist/chunks/i18next-B47TKgbU.mjs +0 -1303
- package/dist/chunks/i18next-loader-v9SlYZ0i.mjs +0 -43
- package/dist/chunks/index-DHLWzZaA.mjs +0 -130
- package/dist/chunks/messages-0Pxnqd4N.mjs +0 -75
- package/dist/chunks/messages-0ZXYUq7S.mjs +0 -75
- package/dist/chunks/messages-2OD2uUDS.mjs +0 -75
- package/dist/chunks/messages-7cEMfYzh.mjs +0 -75
- package/dist/chunks/messages-8mwfda1Q.mjs +0 -75
- package/dist/chunks/messages-B-FqWsBM.mjs +0 -75
- package/dist/chunks/messages-B1jzqWiQ.mjs +0 -75
- package/dist/chunks/messages-B5wk4Ezz.mjs +0 -75
- package/dist/chunks/messages-BAZ5Ld8x.mjs +0 -75
- package/dist/chunks/messages-BBhGp198.mjs +0 -75
- package/dist/chunks/messages-BC9IjIb7.mjs +0 -75
- package/dist/chunks/messages-BFEmpeV-.mjs +0 -75
- package/dist/chunks/messages-BGqzTZy0.mjs +0 -75
- package/dist/chunks/messages-BICs1abK.mjs +0 -75
- package/dist/chunks/messages-BJX6rOnd.mjs +0 -75
- package/dist/chunks/messages-BL2bXRhN.mjs +0 -75
- package/dist/chunks/messages-BMs5qdlH.mjs +0 -75
- package/dist/chunks/messages-BRsjUNwB.mjs +0 -75
- package/dist/chunks/messages-BSqV8OUR.mjs +0 -75
- package/dist/chunks/messages-BTqu3DfG.mjs +0 -75
- package/dist/chunks/messages-BXnDEsur.mjs +0 -75
- package/dist/chunks/messages-BYcre4-6.mjs +0 -75
- package/dist/chunks/messages-BZ9LRJf-.mjs +0 -75
- package/dist/chunks/messages-BgypBy7y.mjs +0 -75
- package/dist/chunks/messages-BsuGf70G.mjs +0 -75
- package/dist/chunks/messages-BwaoF4lQ.mjs +0 -75
- package/dist/chunks/messages-C1l8_7-y.mjs +0 -75
- package/dist/chunks/messages-C5NA_r9v.mjs +0 -75
- package/dist/chunks/messages-C6zgZ5pA.mjs +0 -75
- package/dist/chunks/messages-CAo5ghFI.mjs +0 -75
- package/dist/chunks/messages-CH9qlJ9I.mjs +0 -75
- package/dist/chunks/messages-CI0HqAeS.mjs +0 -75
- package/dist/chunks/messages-CJJtms9k.mjs +0 -75
- package/dist/chunks/messages-CM2hJqk6.mjs +0 -75
- package/dist/chunks/messages-CRMiDPIQ.mjs +0 -75
- package/dist/chunks/messages-CWsZuBj1.mjs +0 -75
- package/dist/chunks/messages-C_gLHo6A.mjs +0 -75
- package/dist/chunks/messages-Cbu-NUDn.mjs +0 -75
- package/dist/chunks/messages-Cjb_MCeh.mjs +0 -75
- package/dist/chunks/messages-ClXYO9Wn.mjs +0 -75
- package/dist/chunks/messages-CsH20vhP.mjs +0 -75
- package/dist/chunks/messages-CsjAGhzA.mjs +0 -75
- package/dist/chunks/messages-Cx7VKFOE.mjs +0 -75
- package/dist/chunks/messages-D3JeBwxo.mjs +0 -75
- package/dist/chunks/messages-D541fieJ.mjs +0 -75
- package/dist/chunks/messages-D7XPdglc.mjs +0 -75
- package/dist/chunks/messages-DBhylfvt.mjs +0 -75
- package/dist/chunks/messages-DCA120lW.mjs +0 -75
- package/dist/chunks/messages-DCf_xZMN.mjs +0 -75
- package/dist/chunks/messages-DDwXKCpe.mjs +0 -75
- package/dist/chunks/messages-DNKDlxcy.mjs +0 -75
- package/dist/chunks/messages-DPvEjrGK.mjs +0 -75
- package/dist/chunks/messages-DQ-AkNxA.mjs +0 -75
- package/dist/chunks/messages-DVuvkNap.mjs +0 -75
- package/dist/chunks/messages-DaglyqUT.mjs +0 -75
- package/dist/chunks/messages-Di0bAfwA.mjs +0 -75
- package/dist/chunks/messages-DuLct0Yr.mjs +0 -75
- package/dist/chunks/messages-DzEYYhZh.mjs +0 -75
- package/dist/chunks/messages-DznNGAB2.mjs +0 -75
- package/dist/chunks/messages-DzoIzyu8.mjs +0 -75
- package/dist/chunks/messages-QYOGmket.mjs +0 -75
- package/dist/chunks/messages-cEjGDAgI.mjs +0 -75
- package/dist/chunks/messages-ddhvrdpE.mjs +0 -75
- package/dist/chunks/messages-mwfNK5nZ.mjs +0 -75
- package/dist/chunks/messages-nG_vNDte.mjs +0 -75
- package/dist/chunks/messages-tDq3Owh7.mjs +0 -75
- package/dist/chunks/messages-x6VJVZKx.mjs +0 -75
- package/dist/messages-0Pxnqd4N.mjs +0 -75
- package/dist/messages-0ZXYUq7S.mjs +0 -75
- package/dist/messages-2OD2uUDS.mjs +0 -75
- package/dist/messages-7cEMfYzh.mjs +0 -75
- package/dist/messages-8mwfda1Q.mjs +0 -75
- package/dist/messages-B-FqWsBM.mjs +0 -75
- package/dist/messages-B1jzqWiQ.mjs +0 -75
- package/dist/messages-B5wk4Ezz.mjs +0 -75
- package/dist/messages-BAZ5Ld8x.mjs +0 -75
- package/dist/messages-BBhGp198.mjs +0 -75
- package/dist/messages-BC9IjIb7.mjs +0 -75
- package/dist/messages-BFEmpeV-.mjs +0 -75
- package/dist/messages-BGqzTZy0.mjs +0 -75
- package/dist/messages-BICs1abK.mjs +0 -75
- package/dist/messages-BJX6rOnd.mjs +0 -75
- package/dist/messages-BL2bXRhN.mjs +0 -75
- package/dist/messages-BMs5qdlH.mjs +0 -75
- package/dist/messages-BRsjUNwB.mjs +0 -75
- package/dist/messages-BSqV8OUR.mjs +0 -75
- package/dist/messages-BTqu3DfG.mjs +0 -75
- package/dist/messages-BXnDEsur.mjs +0 -75
- package/dist/messages-BYcre4-6.mjs +0 -75
- package/dist/messages-BZ9LRJf-.mjs +0 -75
- package/dist/messages-BgypBy7y.mjs +0 -75
- package/dist/messages-BsuGf70G.mjs +0 -75
- package/dist/messages-BwaoF4lQ.mjs +0 -75
- package/dist/messages-C1l8_7-y.mjs +0 -75
- package/dist/messages-C5NA_r9v.mjs +0 -75
- package/dist/messages-C6zgZ5pA.mjs +0 -75
- package/dist/messages-CAo5ghFI.mjs +0 -75
- package/dist/messages-CH9qlJ9I.mjs +0 -75
- package/dist/messages-CI0HqAeS.mjs +0 -75
- package/dist/messages-CJJtms9k.mjs +0 -75
- package/dist/messages-CM2hJqk6.mjs +0 -75
- package/dist/messages-CRMiDPIQ.mjs +0 -75
- package/dist/messages-CWsZuBj1.mjs +0 -75
- package/dist/messages-C_gLHo6A.mjs +0 -75
- package/dist/messages-Cbu-NUDn.mjs +0 -75
- package/dist/messages-Cjb_MCeh.mjs +0 -75
- package/dist/messages-ClXYO9Wn.mjs +0 -75
- package/dist/messages-CsH20vhP.mjs +0 -75
- package/dist/messages-CsjAGhzA.mjs +0 -75
- package/dist/messages-Cx7VKFOE.mjs +0 -75
- package/dist/messages-D3JeBwxo.mjs +0 -75
- package/dist/messages-D541fieJ.mjs +0 -75
- package/dist/messages-D7XPdglc.mjs +0 -75
- package/dist/messages-DBhylfvt.mjs +0 -75
- package/dist/messages-DCA120lW.mjs +0 -75
- package/dist/messages-DCf_xZMN.mjs +0 -75
- package/dist/messages-DDwXKCpe.mjs +0 -75
- package/dist/messages-DNKDlxcy.mjs +0 -75
- package/dist/messages-DPvEjrGK.mjs +0 -75
- package/dist/messages-DQ-AkNxA.mjs +0 -75
- package/dist/messages-DVuvkNap.mjs +0 -75
- package/dist/messages-DaglyqUT.mjs +0 -75
- package/dist/messages-Di0bAfwA.mjs +0 -75
- package/dist/messages-DuLct0Yr.mjs +0 -75
- package/dist/messages-DzEYYhZh.mjs +0 -75
- package/dist/messages-DznNGAB2.mjs +0 -75
- package/dist/messages-DzoIzyu8.mjs +0 -75
- package/dist/messages-QYOGmket.mjs +0 -75
- package/dist/messages-cEjGDAgI.mjs +0 -75
- package/dist/messages-ddhvrdpE.mjs +0 -75
- package/dist/messages-mwfNK5nZ.mjs +0 -75
- package/dist/messages-nG_vNDte.mjs +0 -75
- package/dist/messages-tDq3Owh7.mjs +0 -75
- package/dist/messages-x6VJVZKx.mjs +0 -75
|
@@ -6,14 +6,17 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { DATA_ATTR } from '../../components/constants';
|
|
9
|
+
import { PLACEHOLDER_ACTIVE_CLASSES, PLACEHOLDER_EMPTY_EDITOR_CLASSES } from '../../components/utils/placeholder';
|
|
9
10
|
import { twMerge } from '../../components/utils/tw';
|
|
10
11
|
|
|
11
12
|
import {
|
|
12
13
|
ARROW_ICON,
|
|
13
14
|
ARROW_STYLES,
|
|
14
15
|
BASE_STYLES,
|
|
16
|
+
BODY_PLACEHOLDER_STYLES,
|
|
15
17
|
CONTENT_STYLES,
|
|
16
18
|
TOGGLE_ATTR,
|
|
19
|
+
TOGGLE_CHILDREN_STYLES,
|
|
17
20
|
TOGGLE_WRAPPER_STYLES,
|
|
18
21
|
TOOL_NAME,
|
|
19
22
|
} from './constants';
|
|
@@ -31,8 +34,14 @@ export interface ToggleDOMBuilderContext {
|
|
|
31
34
|
isOpen: boolean;
|
|
32
35
|
/** Optional keydown event handler */
|
|
33
36
|
keydownHandler: ((event: KeyboardEvent) => void) | null;
|
|
34
|
-
/** Callback when the arrow is clicked */
|
|
35
|
-
onArrowClick: () => void;
|
|
37
|
+
/** Callback when the arrow is clicked. Null/undefined disables interaction (read-only mode). */
|
|
38
|
+
onArrowClick: (() => void) | null | undefined;
|
|
39
|
+
/** Callback when the body placeholder is clicked */
|
|
40
|
+
onBodyPlaceholderClick: (() => void) | null;
|
|
41
|
+
/** Translated text for the body placeholder */
|
|
42
|
+
bodyPlaceholderText: string;
|
|
43
|
+
/** Translated aria labels for the toggle arrow */
|
|
44
|
+
ariaLabels: { collapse: string; expand: string };
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
/**
|
|
@@ -45,6 +54,10 @@ export interface ToggleBuildResult {
|
|
|
45
54
|
arrowElement: HTMLElement;
|
|
46
55
|
/** The content element for text input */
|
|
47
56
|
contentElement: HTMLElement;
|
|
57
|
+
/** The body placeholder element */
|
|
58
|
+
bodyPlaceholderElement: HTMLElement;
|
|
59
|
+
/** The child container element */
|
|
60
|
+
childContainerElement: HTMLElement;
|
|
48
61
|
}
|
|
49
62
|
|
|
50
63
|
/**
|
|
@@ -54,20 +67,40 @@ export interface ToggleBuildResult {
|
|
|
54
67
|
* @returns Object containing the created elements
|
|
55
68
|
*/
|
|
56
69
|
export const buildToggleItem = (context: ToggleDOMBuilderContext): ToggleBuildResult => {
|
|
57
|
-
const { data, readOnly, isOpen, keydownHandler, onArrowClick } = context;
|
|
70
|
+
const { data, readOnly, isOpen, keydownHandler, onArrowClick, onBodyPlaceholderClick } = context;
|
|
58
71
|
|
|
59
72
|
const wrapper = document.createElement('div');
|
|
60
|
-
wrapper.className =
|
|
73
|
+
wrapper.className = BASE_STYLES;
|
|
61
74
|
wrapper.setAttribute(DATA_ATTR.tool, TOOL_NAME);
|
|
62
75
|
wrapper.setAttribute(TOGGLE_ATTR.toggleOpen, String(isOpen));
|
|
63
76
|
|
|
64
|
-
const
|
|
77
|
+
const headerRow = document.createElement('div');
|
|
78
|
+
headerRow.className = TOGGLE_WRAPPER_STYLES;
|
|
79
|
+
|
|
80
|
+
const arrowElement = buildArrow(isOpen, onArrowClick, {}, context.ariaLabels);
|
|
65
81
|
const contentElement = buildContent(data, readOnly, keydownHandler);
|
|
66
82
|
|
|
67
|
-
|
|
68
|
-
|
|
83
|
+
headerRow.appendChild(arrowElement);
|
|
84
|
+
headerRow.appendChild(contentElement);
|
|
85
|
+
|
|
86
|
+
const bodyPlaceholderElement = buildBodyPlaceholder(onBodyPlaceholderClick, context.bodyPlaceholderText);
|
|
87
|
+
|
|
88
|
+
const childContainerElement = document.createElement('div');
|
|
89
|
+
childContainerElement.className = TOGGLE_CHILDREN_STYLES;
|
|
90
|
+
childContainerElement.setAttribute(TOGGLE_ATTR.toggleChildren, '');
|
|
91
|
+
// Block DOM mutations inside the children container from triggering the toggle tool's
|
|
92
|
+
// didMutated → syncBlockDataToYjs path. Child block insertions/removals are tracked
|
|
93
|
+
// via the block hierarchy (parentId / contentIds) and must not create spurious Yjs
|
|
94
|
+
// undo entries that split "insert child" into two CMD+Z steps.
|
|
95
|
+
childContainerElement.setAttribute('data-blok-mutation-free', 'true');
|
|
96
|
+
childContainerElement.id = `toggle-children-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
97
|
+
arrowElement.setAttribute('aria-controls', childContainerElement.id);
|
|
69
98
|
|
|
70
|
-
|
|
99
|
+
wrapper.appendChild(headerRow);
|
|
100
|
+
wrapper.appendChild(bodyPlaceholderElement);
|
|
101
|
+
wrapper.appendChild(childContainerElement);
|
|
102
|
+
|
|
103
|
+
return { wrapper, arrowElement, contentElement, bodyPlaceholderElement, childContainerElement };
|
|
71
104
|
};
|
|
72
105
|
|
|
73
106
|
/**
|
|
@@ -82,14 +115,15 @@ export interface BuildArrowOptions {
|
|
|
82
115
|
* Build the arrow element for toggling open/closed state.
|
|
83
116
|
*
|
|
84
117
|
* @param isOpen - Whether the toggle is currently open
|
|
85
|
-
* @param onArrowClick - Callback when arrow is clicked
|
|
118
|
+
* @param onArrowClick - Callback when arrow is clicked. Pass null/undefined to disable click interaction (e.g. read-only mode).
|
|
86
119
|
* @param options - Optional configuration
|
|
87
120
|
* @returns The arrow element
|
|
88
121
|
*/
|
|
89
122
|
export const buildArrow = (
|
|
90
123
|
isOpen: boolean,
|
|
91
|
-
onArrowClick: () => void,
|
|
92
|
-
options: BuildArrowOptions = {}
|
|
124
|
+
onArrowClick: (() => void) | null | undefined,
|
|
125
|
+
options: BuildArrowOptions = {},
|
|
126
|
+
ariaLabels: { collapse: string; expand: string } = { collapse: 'Collapse', expand: 'Expand' }
|
|
93
127
|
): HTMLElement => {
|
|
94
128
|
const arrow = document.createElement('span');
|
|
95
129
|
arrow.className = ARROW_STYLES;
|
|
@@ -97,7 +131,7 @@ export const buildArrow = (
|
|
|
97
131
|
arrow.setAttribute(DATA_ATTR.mutationFree, 'true');
|
|
98
132
|
arrow.setAttribute('role', 'button');
|
|
99
133
|
arrow.setAttribute('tabindex', '0');
|
|
100
|
-
arrow.setAttribute('aria-label', isOpen ?
|
|
134
|
+
arrow.setAttribute('aria-label', isOpen ? ariaLabels.collapse : ariaLabels.expand);
|
|
101
135
|
arrow.setAttribute('aria-expanded', String(isOpen));
|
|
102
136
|
|
|
103
137
|
if (options.contentEditableFalse === true) {
|
|
@@ -106,26 +140,57 @@ export const buildArrow = (
|
|
|
106
140
|
|
|
107
141
|
arrow.innerHTML = ARROW_ICON;
|
|
108
142
|
|
|
109
|
-
|
|
110
|
-
arrow.style.transform = 'rotate(90deg)';
|
|
111
|
-
}
|
|
143
|
+
const svg = arrow.querySelector('svg');
|
|
112
144
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
onArrowClick();
|
|
116
|
-
});
|
|
145
|
+
if (svg) {
|
|
146
|
+
svg.style.transition = 'transform 200ms ease-in-out';
|
|
117
147
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
148
|
+
if (isOpen) {
|
|
149
|
+
svg.style.transform = 'rotate(90deg)';
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (onArrowClick) {
|
|
154
|
+
arrow.addEventListener('click', (event: MouseEvent) => {
|
|
121
155
|
event.stopPropagation();
|
|
122
156
|
onArrowClick();
|
|
123
|
-
}
|
|
124
|
-
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
arrow.addEventListener('keydown', (event: KeyboardEvent) => {
|
|
160
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
event.stopPropagation();
|
|
163
|
+
onArrowClick();
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
125
167
|
|
|
126
168
|
return arrow;
|
|
127
169
|
};
|
|
128
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Build the body placeholder element shown when the toggle has no children.
|
|
173
|
+
*
|
|
174
|
+
* @param onClick - Optional click handler (creates a child block)
|
|
175
|
+
* @returns The body placeholder element
|
|
176
|
+
*/
|
|
177
|
+
const buildBodyPlaceholder = (onClick: (() => void) | null, text: string): HTMLElement => {
|
|
178
|
+
const placeholder = document.createElement('div');
|
|
179
|
+
placeholder.className = BODY_PLACEHOLDER_STYLES;
|
|
180
|
+
placeholder.setAttribute(TOGGLE_ATTR.toggleBodyPlaceholder, '');
|
|
181
|
+
// Class changes on the body placeholder (show/hide) must not trigger didMutated →
|
|
182
|
+
// syncBlockDataToYjs, which would create a spurious Yjs undo entry when a child
|
|
183
|
+
// block is inserted via Enter. The placeholder holds no user-editable content.
|
|
184
|
+
placeholder.setAttribute('data-blok-mutation-free', 'true');
|
|
185
|
+
placeholder.textContent = text;
|
|
186
|
+
|
|
187
|
+
if (onClick) {
|
|
188
|
+
placeholder.addEventListener('click', onClick);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return placeholder;
|
|
192
|
+
};
|
|
193
|
+
|
|
129
194
|
/**
|
|
130
195
|
* Build the content element for text input.
|
|
131
196
|
*
|
|
@@ -140,7 +205,7 @@ const buildContent = (
|
|
|
140
205
|
keydownHandler: ((event: KeyboardEvent) => void) | null
|
|
141
206
|
): HTMLElement => {
|
|
142
207
|
const content = document.createElement('div');
|
|
143
|
-
content.className = CONTENT_STYLES;
|
|
208
|
+
content.className = twMerge(CONTENT_STYLES, PLACEHOLDER_ACTIVE_CLASSES, PLACEHOLDER_EMPTY_EDITOR_CLASSES);
|
|
144
209
|
content.setAttribute(TOGGLE_ATTR.toggleContent, '');
|
|
145
210
|
content.contentEditable = readOnly ? 'false' : 'true';
|
|
146
211
|
content.innerHTML = data.text;
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
BlockToolConstructorOptions,
|
|
12
12
|
ToolboxConfig,
|
|
13
13
|
ConversionConfig,
|
|
14
|
+
SanitizerConfig,
|
|
14
15
|
ToolSanitizerConfig,
|
|
15
16
|
PasteConfig,
|
|
16
17
|
PasteEvent,
|
|
@@ -23,9 +24,10 @@ import {
|
|
|
23
24
|
setToggleItemData,
|
|
24
25
|
parseHTML,
|
|
25
26
|
} from './block-operations';
|
|
26
|
-
import {
|
|
27
|
+
import { clean } from '../../components/utils/sanitizer';
|
|
28
|
+
import { ARIA_LABEL_COLLAPSE_KEY, ARIA_LABEL_EXPAND_KEY, BODY_PLACEHOLDER_KEY, PLACEHOLDER_KEY, TOOL_NAME } from './constants';
|
|
27
29
|
import { IconToggleList } from '../../components/icons';
|
|
28
|
-
import { renderToggleItem, updateArrowState, updateChildrenVisibility } from './toggle-lifecycle';
|
|
30
|
+
import { renderToggleItem, updateArrowState, updateChildrenVisibility, updateBodyPlaceholderVisibility } from './toggle-lifecycle';
|
|
29
31
|
import { handleToggleEnter, handleToggleBackspace } from './toggle-keyboard';
|
|
30
32
|
import type { ToggleItemData, ToggleItemConfig } from './types';
|
|
31
33
|
|
|
@@ -37,7 +39,9 @@ export class ToggleItem implements BlockTool {
|
|
|
37
39
|
private _element: HTMLElement | null = null;
|
|
38
40
|
private _contentElement: HTMLElement | null = null;
|
|
39
41
|
private _arrowElement: HTMLElement | null = null;
|
|
40
|
-
private
|
|
42
|
+
private _bodyPlaceholderElement: HTMLElement | null = null;
|
|
43
|
+
private _childContainerElement: HTMLElement | null = null;
|
|
44
|
+
private _isOpen: boolean;
|
|
41
45
|
|
|
42
46
|
private blockId?: string;
|
|
43
47
|
|
|
@@ -46,17 +50,28 @@ export class ToggleItem implements BlockTool {
|
|
|
46
50
|
this.readOnly = readOnly;
|
|
47
51
|
this._settings = config || {};
|
|
48
52
|
this._data = this.normalizeData(data);
|
|
53
|
+
this._isOpen = this._data.isOpen ?? !readOnly;
|
|
49
54
|
|
|
50
55
|
if (block) {
|
|
51
56
|
this.blockId = block.id;
|
|
52
57
|
}
|
|
58
|
+
|
|
59
|
+
if (!readOnly) {
|
|
60
|
+
this.api.events.on('block changed', this.handleBlockChanged);
|
|
61
|
+
}
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
private normalizeData(data: ToggleItemData | Record<string, never>): ToggleItemData {
|
|
56
65
|
if (typeof data === 'object' && data !== null && 'text' in data) {
|
|
57
|
-
|
|
66
|
+
const normalized: ToggleItemData = {
|
|
58
67
|
text: typeof data.text === 'string' ? data.text : '',
|
|
59
68
|
};
|
|
69
|
+
|
|
70
|
+
if (typeof (data as ToggleItemData).isOpen === 'boolean') {
|
|
71
|
+
normalized.isOpen = (data as ToggleItemData).isOpen;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return normalized;
|
|
60
75
|
}
|
|
61
76
|
|
|
62
77
|
return { text: '' };
|
|
@@ -83,22 +98,31 @@ export class ToggleItem implements BlockTool {
|
|
|
83
98
|
isOpen: this._isOpen,
|
|
84
99
|
placeholder: this.placeholder,
|
|
85
100
|
keydownHandler: this.readOnly ? null : this.handleKeyDown.bind(this),
|
|
86
|
-
onArrowClick: () => this.toggleOpen(),
|
|
101
|
+
onArrowClick: this.readOnly ? null : () => this.toggleOpen(),
|
|
102
|
+
onBodyPlaceholderClick: this.readOnly ? null : () => this.handleBodyPlaceholderClick(),
|
|
103
|
+
bodyPlaceholderText: this.api.i18n.t(BODY_PLACEHOLDER_KEY),
|
|
104
|
+
ariaLabels: {
|
|
105
|
+
collapse: this.api.i18n.t(ARIA_LABEL_COLLAPSE_KEY),
|
|
106
|
+
expand: this.api.i18n.t(ARIA_LABEL_EXPAND_KEY),
|
|
107
|
+
},
|
|
87
108
|
});
|
|
88
109
|
|
|
89
110
|
this._element = result.wrapper;
|
|
90
111
|
this._contentElement = result.contentElement;
|
|
91
112
|
this._arrowElement = result.arrowElement;
|
|
113
|
+
this._bodyPlaceholderElement = result.bodyPlaceholderElement;
|
|
114
|
+
this._childContainerElement = result.childContainerElement;
|
|
92
115
|
|
|
93
116
|
return this._element;
|
|
94
117
|
}
|
|
95
118
|
|
|
96
119
|
public rendered(): void {
|
|
97
120
|
this.updateChildrenVisibility();
|
|
121
|
+
this.updateBodyPlaceholderVisibility();
|
|
98
122
|
}
|
|
99
123
|
|
|
100
124
|
public save(): ToggleItemData {
|
|
101
|
-
return saveToggleItem(this._data, this._element, this.getContentElement.bind(this));
|
|
125
|
+
return saveToggleItem(this._data, this._element, this.getContentElement.bind(this), this._isOpen);
|
|
102
126
|
}
|
|
103
127
|
|
|
104
128
|
public validate(_blockData: ToggleItemData): boolean {
|
|
@@ -125,7 +149,8 @@ export class ToggleItem implements BlockTool {
|
|
|
125
149
|
|
|
126
150
|
const content = detail.data as HTMLElement;
|
|
127
151
|
const summary = content.querySelector('summary');
|
|
128
|
-
const
|
|
152
|
+
const rawText = summary !== null ? summary.innerHTML : content.innerHTML;
|
|
153
|
+
const text = clean(rawText, ToggleItem.sanitize.text as SanitizerConfig);
|
|
129
154
|
|
|
130
155
|
this._data = { text };
|
|
131
156
|
|
|
@@ -145,7 +170,19 @@ export class ToggleItem implements BlockTool {
|
|
|
145
170
|
|
|
146
171
|
this._data = result.newData;
|
|
147
172
|
|
|
173
|
+
if (typeof this._data.isOpen === 'boolean') {
|
|
174
|
+
this._isOpen = this._data.isOpen;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (this._arrowElement && this._element) {
|
|
178
|
+
updateArrowState(this._arrowElement, this._element, this._isOpen, {
|
|
179
|
+
collapse: this.api.i18n.t(ARIA_LABEL_COLLAPSE_KEY),
|
|
180
|
+
expand: this.api.i18n.t(ARIA_LABEL_EXPAND_KEY),
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
148
184
|
this.updateChildrenVisibility();
|
|
185
|
+
this.updateBodyPlaceholderVisibility();
|
|
149
186
|
|
|
150
187
|
return result.inPlace;
|
|
151
188
|
}
|
|
@@ -178,6 +215,32 @@ export class ToggleItem implements BlockTool {
|
|
|
178
215
|
this.setOpenState(false);
|
|
179
216
|
}
|
|
180
217
|
|
|
218
|
+
public removed(): void {
|
|
219
|
+
this.api.events.off('block changed', this.handleBlockChanged);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private handleBlockChanged = (data: unknown): void => {
|
|
223
|
+
if (!this.isBlockChangedPayload(data)) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (data.event.type === 'block-removed' || data.event.type === 'block-added') {
|
|
228
|
+
this.updateBodyPlaceholderVisibility();
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
private isBlockChangedPayload(data: unknown): data is { event: { type: string } } {
|
|
233
|
+
return (
|
|
234
|
+
typeof data === 'object' &&
|
|
235
|
+
data !== null &&
|
|
236
|
+
'event' in data &&
|
|
237
|
+
typeof (data as { event: unknown }).event === 'object' &&
|
|
238
|
+
(data as { event: unknown }).event !== null &&
|
|
239
|
+
'type' in (data as { event: { type: unknown } }).event &&
|
|
240
|
+
typeof (data as { event: { type: unknown } }).event.type === 'string'
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
181
244
|
private getContentElement(): HTMLElement | null {
|
|
182
245
|
return this._contentElement;
|
|
183
246
|
}
|
|
@@ -186,10 +249,14 @@ export class ToggleItem implements BlockTool {
|
|
|
186
249
|
this._isOpen = open;
|
|
187
250
|
|
|
188
251
|
if (this._arrowElement && this._element) {
|
|
189
|
-
updateArrowState(this._arrowElement, this._element, this._isOpen
|
|
252
|
+
updateArrowState(this._arrowElement, this._element, this._isOpen, {
|
|
253
|
+
collapse: this.api.i18n.t(ARIA_LABEL_COLLAPSE_KEY),
|
|
254
|
+
expand: this.api.i18n.t(ARIA_LABEL_EXPAND_KEY),
|
|
255
|
+
});
|
|
190
256
|
}
|
|
191
257
|
|
|
192
258
|
this.updateChildrenVisibility();
|
|
259
|
+
this.updateBodyPlaceholderVisibility();
|
|
193
260
|
}
|
|
194
261
|
|
|
195
262
|
private toggleOpen(): void {
|
|
@@ -201,7 +268,40 @@ export class ToggleItem implements BlockTool {
|
|
|
201
268
|
return;
|
|
202
269
|
}
|
|
203
270
|
|
|
204
|
-
updateChildrenVisibility(this.api, this.blockId, this._isOpen);
|
|
271
|
+
updateChildrenVisibility(this.api, this.blockId, this._isOpen, this._childContainerElement, this._arrowElement);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private updateBodyPlaceholderVisibility(): void {
|
|
275
|
+
if (this.blockId === undefined) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
updateBodyPlaceholderVisibility(
|
|
280
|
+
this._bodyPlaceholderElement,
|
|
281
|
+
this.api,
|
|
282
|
+
this.blockId,
|
|
283
|
+
this._isOpen,
|
|
284
|
+
this.readOnly
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private handleBodyPlaceholderClick(): void {
|
|
289
|
+
if (this.blockId === undefined) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const blockIndex = this.api.blocks.getBlockIndex(this.blockId);
|
|
294
|
+
|
|
295
|
+
if (blockIndex === undefined) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const newBlock = this.api.blocks.insertInsideParent(this.blockId, blockIndex + 1);
|
|
300
|
+
|
|
301
|
+
this.api.caret.setToBlock(newBlock.id, 'start');
|
|
302
|
+
|
|
303
|
+
// Hide the body placeholder now that a child exists
|
|
304
|
+
this._bodyPlaceholderElement?.classList.add('hidden');
|
|
205
305
|
}
|
|
206
306
|
|
|
207
307
|
private handleKeyDown(event: KeyboardEvent): void {
|
|
@@ -236,6 +336,9 @@ export class ToggleItem implements BlockTool {
|
|
|
236
336
|
|
|
237
337
|
private async handleEnter(): Promise<void> {
|
|
238
338
|
await handleToggleEnter(this.createKeyboardContext());
|
|
339
|
+
|
|
340
|
+
// After Enter may create a child, update body placeholder visibility
|
|
341
|
+
this.updateBodyPlaceholderVisibility();
|
|
239
342
|
}
|
|
240
343
|
|
|
241
344
|
private async handleBackspace(event: KeyboardEvent): Promise<void> {
|
|
@@ -57,11 +57,13 @@ export const handleToggleEnter = async (context: ToggleKeyboardContext): Promise
|
|
|
57
57
|
/**
|
|
58
58
|
* When toggle is open and caret is at the end (no content after caret),
|
|
59
59
|
* create a child paragraph inside the toggle rather than a sibling toggle.
|
|
60
|
+
* insertInsideParent() groups both block creation and parent assignment into
|
|
61
|
+
* a single Yjs undo entry, so one CMD+Z removes the new block completely.
|
|
60
62
|
*/
|
|
61
63
|
if (isOpen && afterContent === '') {
|
|
62
|
-
const newBlock = api.blocks.
|
|
64
|
+
const newBlock = api.blocks.insertInsideParent(blockId, currentBlockIndex + 1);
|
|
63
65
|
|
|
64
|
-
api.
|
|
66
|
+
api.caret.setToBlock(newBlock.id, 'start');
|
|
65
67
|
|
|
66
68
|
return;
|
|
67
69
|
}
|
|
@@ -127,7 +129,7 @@ export const handleToggleBackspace = async (
|
|
|
127
129
|
* @param range - The current selection range
|
|
128
130
|
* @returns Object with before/after HTML content
|
|
129
131
|
*/
|
|
130
|
-
const splitContentAtRange = (
|
|
132
|
+
export const splitContentAtRange = (
|
|
131
133
|
contentEl: HTMLElement,
|
|
132
134
|
range: Range
|
|
133
135
|
): { beforeContent: string; afterContent: string } => {
|
|
@@ -26,19 +26,21 @@ export interface ToggleRenderResult {
|
|
|
26
26
|
wrapper: HTMLElement;
|
|
27
27
|
contentElement: HTMLElement;
|
|
28
28
|
arrowElement: HTMLElement;
|
|
29
|
+
bodyPlaceholderElement: HTMLElement;
|
|
30
|
+
childContainerElement: HTMLElement;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* Render a toggle item with placeholder support.
|
|
33
35
|
*
|
|
34
36
|
* @param context - The render context
|
|
35
|
-
* @returns Object containing the wrapper, content, and
|
|
37
|
+
* @returns Object containing the wrapper, content, arrow, and body placeholder elements
|
|
36
38
|
*/
|
|
37
39
|
export const renderToggleItem = (context: ToggleRenderContext): ToggleRenderResult => {
|
|
38
40
|
const result = buildToggleItem(context);
|
|
39
41
|
|
|
40
42
|
if (result.contentElement) {
|
|
41
|
-
setupPlaceholder(result.contentElement, context.placeholder);
|
|
43
|
+
setupPlaceholder(result.contentElement, context.placeholder, 'data-blok-placeholder-active');
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
return result;
|
|
@@ -51,11 +53,19 @@ export const renderToggleItem = (context: ToggleRenderContext): ToggleRenderResu
|
|
|
51
53
|
* @param wrapper - The wrapper element to update the open attribute on
|
|
52
54
|
* @param isOpen - Whether the toggle is open
|
|
53
55
|
*/
|
|
54
|
-
export const updateArrowState = (
|
|
55
|
-
|
|
56
|
+
export const updateArrowState = (
|
|
57
|
+
arrowEl: HTMLElement,
|
|
58
|
+
wrapper: HTMLElement,
|
|
59
|
+
isOpen: boolean,
|
|
60
|
+
ariaLabels: { collapse: string; expand: string } = { collapse: 'Collapse', expand: 'Expand' }
|
|
61
|
+
): void => {
|
|
62
|
+
const svg = arrowEl.querySelector('svg');
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
if (svg) {
|
|
65
|
+
svg.style.transform = isOpen ? 'rotate(90deg)' : '';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
arrowEl.setAttribute('aria-label', isOpen ? ariaLabels.collapse : ariaLabels.expand);
|
|
59
69
|
arrowEl.setAttribute('aria-expanded', String(isOpen));
|
|
60
70
|
wrapper.setAttribute(TOGGLE_ATTR.toggleOpen, String(isOpen));
|
|
61
71
|
};
|
|
@@ -67,15 +77,77 @@ export const updateArrowState = (arrowEl: HTMLElement, wrapper: HTMLElement, isO
|
|
|
67
77
|
* @param api - Blok API instance
|
|
68
78
|
* @param blockId - The toggle block's id
|
|
69
79
|
* @param isOpen - Whether the toggle is currently open (expanded)
|
|
80
|
+
* @param childContainer - Optional child container element for aria-hidden management
|
|
81
|
+
* @param arrowElement - Optional arrow element to receive focus when collapsing with focus inside children
|
|
70
82
|
*/
|
|
71
|
-
export const updateChildrenVisibility = (
|
|
83
|
+
export const updateChildrenVisibility = (
|
|
84
|
+
api: API,
|
|
85
|
+
blockId: string,
|
|
86
|
+
isOpen: boolean,
|
|
87
|
+
childContainer?: HTMLElement | null,
|
|
88
|
+
arrowElement?: HTMLElement | null
|
|
89
|
+
): void => {
|
|
72
90
|
const children = api.blocks.getChildren(blockId);
|
|
73
91
|
|
|
92
|
+
// Before hiding, check if focus is inside the child container and move it to arrow
|
|
93
|
+
if (!isOpen && childContainer && arrowElement && childContainer.contains(document.activeElement)) {
|
|
94
|
+
arrowElement.focus();
|
|
95
|
+
}
|
|
96
|
+
|
|
74
97
|
for (const child of children) {
|
|
98
|
+
if (childContainer && child.holder.parentElement !== childContainer) {
|
|
99
|
+
childContainer.appendChild(child.holder);
|
|
100
|
+
}
|
|
101
|
+
|
|
75
102
|
if (isOpen) {
|
|
76
103
|
child.holder.classList.remove('hidden');
|
|
77
104
|
} else {
|
|
78
105
|
child.holder.classList.add('hidden');
|
|
79
106
|
}
|
|
80
107
|
}
|
|
108
|
+
|
|
109
|
+
if (childContainer) {
|
|
110
|
+
if (isOpen) {
|
|
111
|
+
childContainer.removeAttribute('aria-hidden');
|
|
112
|
+
} else {
|
|
113
|
+
childContainer.setAttribute('aria-hidden', 'true');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Update visibility of the body placeholder based on toggle state and children.
|
|
120
|
+
* The placeholder is shown only when the toggle is open, has no children, and is not read-only.
|
|
121
|
+
*
|
|
122
|
+
* @param bodyPlaceholder - The body placeholder element
|
|
123
|
+
* @param api - Blok API instance
|
|
124
|
+
* @param blockId - The toggle block's id
|
|
125
|
+
* @param isOpen - Whether the toggle is currently open
|
|
126
|
+
* @param readOnly - Whether the editor is in read-only mode
|
|
127
|
+
*/
|
|
128
|
+
export const updateBodyPlaceholderVisibility = (
|
|
129
|
+
bodyPlaceholder: HTMLElement | null,
|
|
130
|
+
api: API,
|
|
131
|
+
blockId: string,
|
|
132
|
+
isOpen: boolean,
|
|
133
|
+
readOnly: boolean
|
|
134
|
+
): void => {
|
|
135
|
+
if (bodyPlaceholder === null) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (readOnly) {
|
|
140
|
+
bodyPlaceholder.classList.add('hidden');
|
|
141
|
+
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const children = api.blocks.getChildren(blockId);
|
|
146
|
+
const shouldShow = isOpen && children.length === 0;
|
|
147
|
+
|
|
148
|
+
if (shouldShow) {
|
|
149
|
+
bodyPlaceholder.classList.remove('hidden');
|
|
150
|
+
} else {
|
|
151
|
+
bodyPlaceholder.classList.add('hidden');
|
|
152
|
+
}
|
|
81
153
|
};
|