@jackuait/blok 0.6.0-beta.5 → 0.6.0-beta.7
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 +16 -169
- package/bin/blok.mjs +10 -0
- package/dist/blok.mjs +2 -2
- package/dist/chunks/{blok-XA2L0_-K.mjs → blok-Bjkxis7j.mjs} +1029 -934
- package/dist/chunks/{i18next-loader-Ci2zhA-n.mjs → i18next-loader-D-sjerXt.mjs} +1 -1
- package/dist/chunks/{index-R38OiQ_d.mjs → index-CJfN4Vuv.mjs} +1 -1
- package/dist/chunks/{inline-tool-convert-e3PyuxB6.mjs → inline-tool-convert-5DE7c2fi.mjs} +1 -1
- package/dist/{messages-BGxiFoZf.mjs → chunks/messages-7QoX8DkW.mjs} +14 -14
- package/dist/{messages-UX4gkere.mjs → chunks/messages-BMXCuEKO.mjs} +5 -5
- package/dist/{messages-wp_1b1hD.mjs → chunks/messages-BSbjsyHY.mjs} +16 -16
- package/dist/chunks/{messages-DChXyvh2.mjs → messages-BdeLo0N9.mjs} +14 -14
- package/dist/chunks/{messages-B9fe4dQJ.mjs → messages-C2htQ_3F.mjs} +12 -12
- package/dist/{messages-BNe6LuHW.mjs → chunks/messages-C9eaarcK.mjs} +7 -7
- package/dist/chunks/messages-CKI54h6O.mjs +62 -0
- package/dist/{messages-DjvaFRqx.mjs → chunks/messages-CQwpzUFp.mjs} +6 -6
- package/dist/{messages-EL5ARzmK.mjs → chunks/messages-CVw84KdI.mjs} +7 -7
- package/dist/chunks/{messages-49thXXGz.mjs → messages-Diu6jAaR.mjs} +6 -6
- package/dist/{messages-Bfiw5w_W.mjs → chunks/messages-DvFLX36Q.mjs} +10 -10
- package/dist/chunks/{messages-QtoE8uEv.mjs → messages-Dzwxv9v1.mjs} +8 -8
- package/dist/cli.mjs +50 -0
- package/dist/full.mjs +15 -15
- package/dist/locales.mjs +12 -12
- package/dist/{chunks/messages-BGxiFoZf.mjs → messages-7QoX8DkW.mjs} +14 -14
- package/dist/{chunks/messages-UX4gkere.mjs → messages-BMXCuEKO.mjs} +5 -5
- package/dist/{chunks/messages-wp_1b1hD.mjs → messages-BSbjsyHY.mjs} +16 -16
- package/dist/{messages-DChXyvh2.mjs → messages-BdeLo0N9.mjs} +14 -14
- package/dist/{messages-B9fe4dQJ.mjs → messages-C2htQ_3F.mjs} +12 -12
- package/dist/{chunks/messages-BNe6LuHW.mjs → messages-C9eaarcK.mjs} +7 -7
- package/dist/messages-CKI54h6O.mjs +62 -0
- package/dist/{chunks/messages-DjvaFRqx.mjs → messages-CQwpzUFp.mjs} +6 -6
- package/dist/{chunks/messages-EL5ARzmK.mjs → messages-CVw84KdI.mjs} +7 -7
- package/dist/{messages-49thXXGz.mjs → messages-Diu6jAaR.mjs} +6 -6
- package/dist/{chunks/messages-Bfiw5w_W.mjs → messages-DvFLX36Q.mjs} +10 -10
- package/dist/{messages-QtoE8uEv.mjs → messages-Dzwxv9v1.mjs} +8 -8
- package/dist/tools.mjs +222 -207
- package/dist/vendor.LICENSE.txt +1 -1
- package/package.json +13 -8
- package/src/cli/commands/migration.ts +16 -0
- package/src/cli/commands/migrationContent.ts +6 -0
- package/src/cli/index.ts +47 -0
- package/src/cli/utils/output.ts +10 -0
- package/src/components/i18n/locales/bn/messages.json +16 -16
- package/src/components/i18n/locales/fil/messages.json +7 -7
- package/src/components/i18n/locales/hi/messages.json +14 -14
- package/src/components/i18n/locales/id/messages.json +6 -6
- package/src/components/i18n/locales/mr/messages.json +14 -14
- package/src/components/i18n/locales/ms/messages.json +6 -6
- package/src/components/i18n/locales/ne/messages.json +12 -12
- package/src/components/i18n/locales/si/messages.json +8 -8
- package/src/components/i18n/locales/ta/messages.json +7 -7
- package/src/components/i18n/locales/te/messages.json +35 -35
- package/src/components/i18n/locales/th/messages.json +5 -5
- package/src/components/i18n/locales/vi/messages.json +10 -10
- package/src/components/modules/api/history.ts +64 -0
- package/src/components/modules/api/index.ts +1 -0
- package/src/components/modules/api/readonly.ts +11 -1
- package/src/components/modules/blockManager/blockManager.ts +7 -0
- package/src/components/modules/blockManager/yjs-sync.ts +12 -2
- package/src/components/modules/index.ts +3 -0
- package/src/components/modules/readonly.ts +11 -0
- package/src/components/modules/rectangleSelection.ts +7 -3
- package/src/components/modules/saver.ts +3 -2
- package/src/components/modules/toolbar/index.ts +46 -11
- package/src/components/modules/toolbar/plus-button.ts +22 -1
- package/src/components/modules/yjs/index.ts +23 -0
- package/src/tools/table/index.ts +20 -0
- package/src/tools/table/table-add-controls.ts +8 -0
- package/src/tools/table/table-cell-blocks.ts +15 -5
- package/src/types-internal/blok-modules.d.ts +2 -0
- package/types/api/history.d.ts +33 -0
- package/types/api/index.d.ts +1 -0
- package/types/api/readonly.d.ts +12 -2
- package/types/index.d.ts +3 -0
- package/dist/chunks/messages-DsVNtdgM.mjs +0 -62
- package/dist/messages-DsVNtdgM.mjs +0 -62
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
{
|
|
2
|
-
"blockSettings.dragToMove": "తరలించడానికి
|
|
3
|
-
"blockSettings.clickToOpenMenu": "
|
|
4
|
-
"toolbox.addBelow": "క్రింద జోడించడానికి
|
|
5
|
-
"toolbox.optionAddAbove": "పైన జోడించడానికి Option
|
|
6
|
-
"toolbox.ctrlAddAbove": "పైన జోడించడానికి Ctrl
|
|
2
|
+
"blockSettings.dragToMove": "తరలించడానికి లాగండి",
|
|
3
|
+
"blockSettings.clickToOpenMenu": "జాబితా తెరవడానికి నొక్కండి",
|
|
4
|
+
"toolbox.addBelow": "క్రింద జోడించడానికి నొక్కండి",
|
|
5
|
+
"toolbox.optionAddAbove": "పైన జోడించడానికి Option-నొక్కండి",
|
|
6
|
+
"toolbox.ctrlAddAbove": "పైన జోడించడానికి Ctrl-నొక్కండి",
|
|
7
7
|
"popover.search": "వెతకండి",
|
|
8
8
|
"popover.nothingFound": "ఏమీ కనుగొనబడలేదు",
|
|
9
9
|
"popover.convertTo": "మార్చు",
|
|
10
|
-
"toolNames.text": "
|
|
10
|
+
"toolNames.text": "వచనం",
|
|
11
11
|
"toolNames.heading": "శీర్షిక",
|
|
12
12
|
"toolNames.link": "లింక్",
|
|
13
|
-
"toolNames.bold": "
|
|
14
|
-
"toolNames.italic": "
|
|
15
|
-
"toolNames.bulletedList": "
|
|
16
|
-
"toolNames.numberedList": "
|
|
13
|
+
"toolNames.bold": "గాఢం",
|
|
14
|
+
"toolNames.italic": "వాలు",
|
|
15
|
+
"toolNames.bulletedList": "చుక్కల జాబితా",
|
|
16
|
+
"toolNames.numberedList": "అంకెల జాబితా",
|
|
17
17
|
"toolNames.todoList": "చేయవలసిన పనుల జాబితా",
|
|
18
18
|
"tools.link.addLink": "లింక్ జోడించండి",
|
|
19
19
|
"tools.link.invalidLink": "చెల్లని లింక్",
|
|
20
20
|
"tools.stub.error": "లోపం",
|
|
21
|
-
"tools.stub.blockCannotBeDisplayed": "ఈ
|
|
21
|
+
"tools.stub.blockCannotBeDisplayed": "ఈ విభాగాన్ని ప్రదర్శించలేము",
|
|
22
22
|
"tools.header.heading1": "శీర్షిక 1",
|
|
23
23
|
"tools.header.heading2": "శీర్షిక 2",
|
|
24
24
|
"tools.header.heading3": "శీర్షిక 3",
|
|
@@ -27,33 +27,33 @@
|
|
|
27
27
|
"tools.header.heading6": "శీర్షిక 6",
|
|
28
28
|
"tools.list.placeholder": "జాబితా",
|
|
29
29
|
"blockSettings.delete": "తొలగించు",
|
|
30
|
-
"a11y.dragHandle": "
|
|
31
|
-
"a11y.dragHandleRole": "
|
|
32
|
-
"a11y.dragStarted": "
|
|
33
|
-
"a11y.dragStartedMultiple": "{count}
|
|
34
|
-
"a11y.dropPosition": "{total} లో {position} స్థానంలో
|
|
35
|
-
"a11y.dropCancelled": "
|
|
36
|
-
"a11y.blockMoved": "
|
|
37
|
-
"a11y.blocksMoved": "{count}
|
|
38
|
-
"a11y.blockDuplicated": "
|
|
39
|
-
"a11y.blocksDuplicated": "{count}
|
|
40
|
-
"a11y.movedUp": "
|
|
41
|
-
"a11y.movedDown": "
|
|
42
|
-
"a11y.atTop": "
|
|
43
|
-
"a11y.atBottom": "
|
|
44
|
-
"tools.paragraph.placeholder": "ఏదైనా రాయండి లేదా ఎంచుకోడానికి / నొక్కండి",
|
|
30
|
+
"a11y.dragHandle": "విభాగం తరలించడానికి లాగండి లేదా జాబితా కోసం నొక్కండి",
|
|
31
|
+
"a11y.dragHandleRole": "లాగు పట్టిక",
|
|
32
|
+
"a11y.dragStarted": "విభాగం తరలుతోంది",
|
|
33
|
+
"a11y.dragStartedMultiple": "{count} విభాగాలు తరలుతున్నాయి",
|
|
34
|
+
"a11y.dropPosition": "{total} లో {position} స్థానంలో వదులుతుంది",
|
|
35
|
+
"a11y.dropCancelled": "లాగడం రద్దు చేయబడింది",
|
|
36
|
+
"a11y.blockMoved": "విభాగం {total} లో {position} స్థానానికి తరలించబడింది",
|
|
37
|
+
"a11y.blocksMoved": "{count} విభాగాలు {position} స్థానానికి తరలించబడ్డాయి",
|
|
38
|
+
"a11y.blockDuplicated": "విభాగం {total} లో {position} స్థానంలో నకలు చేయబడింది",
|
|
39
|
+
"a11y.blocksDuplicated": "{count} విభాగాలు {position} స్థానం నుండి నకలు చేయబడ్డాయి",
|
|
40
|
+
"a11y.movedUp": "విభాగం {total} లో {position} స్థానానికి పైకి తరలించబడింది",
|
|
41
|
+
"a11y.movedDown": "విభాగం {total} లో {position} స్థానానికి క్రిందికి తరలించబడింది",
|
|
42
|
+
"a11y.atTop": "విభాగం పైన ఉంది, పైకి తరలించలేము",
|
|
43
|
+
"a11y.atBottom": "విభాగం క్రింద ఉంది, క్రిందికి తరలించలేము",
|
|
44
|
+
"tools.paragraph.placeholder": "ఏదైనా రాయండి లేదా సాధనం ఎంచుకోడానికి / నొక్కండి",
|
|
45
45
|
"tools.table.title": "పట్టిక",
|
|
46
|
-
"tools.table.clearSelection": "
|
|
47
|
-
"tools.table.headerColumn": "
|
|
48
|
-
"tools.table.insertColumnLeft": "ఎడమవైపు
|
|
49
|
-
"tools.table.insertColumnRight": "కుడివైపు
|
|
46
|
+
"tools.table.clearSelection": "తుడుచు",
|
|
47
|
+
"tools.table.headerColumn": "శీర్ష స్తంభం",
|
|
48
|
+
"tools.table.insertColumnLeft": "ఎడమవైపు స్తంభం చొప్పించు",
|
|
49
|
+
"tools.table.insertColumnRight": "కుడివైపు స్తంభం చొప్పించు",
|
|
50
50
|
"tools.table.deleteColumn": "తొలగించు",
|
|
51
|
-
"tools.table.headerRow": "
|
|
51
|
+
"tools.table.headerRow": "శీర్ష వరుస",
|
|
52
52
|
"tools.table.insertRowAbove": "పైన వరుస చొప్పించు",
|
|
53
53
|
"tools.table.insertRowBelow": "క్రింద వరుస చొప్పించు",
|
|
54
54
|
"tools.table.deleteRow": "తొలగించు",
|
|
55
|
-
"tools.table.clickToAddRow": "కొత్త వరుస జోడించడానికి
|
|
56
|
-
"tools.table.dragToAddRemoveRows": "వరుసలు జోడించడానికి లేదా తొలగించడానికి
|
|
57
|
-
"tools.table.clickToAddColumn": "కొత్త
|
|
58
|
-
"tools.table.dragToAddRemoveColumns": "
|
|
55
|
+
"tools.table.clickToAddRow": "కొత్త వరుస జోడించడానికి నొక్కండి",
|
|
56
|
+
"tools.table.dragToAddRemoveRows": "వరుసలు జోడించడానికి లేదా తొలగించడానికి లాగండి",
|
|
57
|
+
"tools.table.clickToAddColumn": "కొత్త స్తంభం జోడించడానికి నొక్కండి",
|
|
58
|
+
"tools.table.dragToAddRemoveColumns": "స్తంభాలు జోడించడానికి లేదా తొలగించడానికి లాగండి"
|
|
59
59
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"blockSettings.dragToMove": "ลากเพื่อย้าย",
|
|
3
3
|
"blockSettings.clickToOpenMenu": "คลิกเพื่อเปิดเมนู",
|
|
4
|
-
"toolbox.addBelow": "
|
|
5
|
-
"toolbox.optionAddAbove": "⌥
|
|
6
|
-
"toolbox.ctrlAddAbove": "Ctrl
|
|
4
|
+
"toolbox.addBelow": "คลิกเพื่อเพิ่มด้านล่าง",
|
|
5
|
+
"toolbox.optionAddAbove": "⌥ คลิกเพื่อเพิ่มด้านบน",
|
|
6
|
+
"toolbox.ctrlAddAbove": "Ctrl คลิกเพื่อเพิ่มด้านบน",
|
|
7
7
|
"popover.search": "ค้นหา",
|
|
8
8
|
"popover.nothingFound": "ไม่พบผลลัพธ์",
|
|
9
9
|
"popover.convertTo": "แปลงเป็น",
|
|
@@ -35,13 +35,13 @@
|
|
|
35
35
|
"a11y.dropCancelled": "ยกเลิกการลาก",
|
|
36
36
|
"a11y.blockMoved": "ย้ายบล็อกไปตำแหน่ง {position} จาก {total}",
|
|
37
37
|
"a11y.blocksMoved": "ย้าย {count} บล็อกไปตำแหน่ง {position}",
|
|
38
|
-
"a11y.blockDuplicated": "
|
|
38
|
+
"a11y.blockDuplicated": "คัดลอกบล็อกที่ตำแหน่ง {position} จาก {total}",
|
|
39
39
|
"a11y.blocksDuplicated": "คัดลอก {count} บล็อก เริ่มจากตำแหน่ง {position}",
|
|
40
40
|
"a11y.movedUp": "ย้ายบล็อกขึ้น ตำแหน่ง {position} จาก {total}",
|
|
41
41
|
"a11y.movedDown": "ย้ายบล็อกลง ตำแหน่ง {position} จาก {total}",
|
|
42
42
|
"a11y.atTop": "บล็อกอยู่บนสุดแล้ว ไม่สามารถย้ายขึ้นได้",
|
|
43
43
|
"a11y.atBottom": "บล็อกอยู่ล่างสุดแล้ว ไม่สามารถย้ายลงได้",
|
|
44
|
-
"tools.paragraph.placeholder": "เขียนอะไรสักอย่าง หรือกด /
|
|
44
|
+
"tools.paragraph.placeholder": "เขียนอะไรสักอย่าง หรือกด / เพื่อเลือกเครื่องมือ",
|
|
45
45
|
"tools.table.title": "ตาราง",
|
|
46
46
|
"tools.table.clearSelection": "ล้าง",
|
|
47
47
|
"tools.table.headerColumn": "คอลัมน์หัวข้อ",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"blockSettings.dragToMove": "Kéo để di chuyển",
|
|
3
3
|
"blockSettings.clickToOpenMenu": "Nhấp để mở menu",
|
|
4
|
-
"toolbox.addBelow": "
|
|
5
|
-
"toolbox.optionAddAbove": "⌥
|
|
6
|
-
"toolbox.ctrlAddAbove": "Ctrl
|
|
4
|
+
"toolbox.addBelow": "Nhấp để thêm bên dưới",
|
|
5
|
+
"toolbox.optionAddAbove": "⌥ Nhấp để thêm bên trên",
|
|
6
|
+
"toolbox.ctrlAddAbove": "Ctrl+Nhấp để thêm bên trên",
|
|
7
7
|
"popover.search": "Tìm kiếm",
|
|
8
8
|
"popover.nothingFound": "Không tìm thấy",
|
|
9
|
-
"popover.convertTo": "Chuyển
|
|
9
|
+
"popover.convertTo": "Chuyển sang",
|
|
10
10
|
"toolNames.text": "Văn bản",
|
|
11
11
|
"toolNames.heading": "Tiêu đề",
|
|
12
12
|
"toolNames.link": "Liên kết",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"tools.header.heading5": "Tiêu đề 5",
|
|
27
27
|
"tools.header.heading6": "Tiêu đề 6",
|
|
28
28
|
"tools.list.placeholder": "Danh sách",
|
|
29
|
-
"tools.paragraph.placeholder": "Viết gì đó hoặc nhấn / để chọn",
|
|
29
|
+
"tools.paragraph.placeholder": "Viết gì đó hoặc nhấn / để chọn công cụ",
|
|
30
30
|
"tools.table.title": "Bảng",
|
|
31
31
|
"tools.table.clearSelection": "Xóa",
|
|
32
32
|
"tools.table.headerColumn": "Cột tiêu đề",
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
"a11y.dragHandleRole": "tay nắm kéo",
|
|
47
47
|
"a11y.dragStarted": "Đang kéo khối",
|
|
48
48
|
"a11y.dragStartedMultiple": "Đang kéo {count} khối",
|
|
49
|
-
"a11y.dropPosition": "Sẽ thả vào vị trí {position}
|
|
49
|
+
"a11y.dropPosition": "Sẽ thả vào vị trí {position} trong {total}",
|
|
50
50
|
"a11y.dropCancelled": "Đã hủy kéo",
|
|
51
|
-
"a11y.blockMoved": "Khối đã được di chuyển đến vị trí {position}
|
|
51
|
+
"a11y.blockMoved": "Khối đã được di chuyển đến vị trí {position} trong {total}",
|
|
52
52
|
"a11y.blocksMoved": "{count} khối đã được di chuyển đến vị trí {position}",
|
|
53
|
-
"a11y.blockDuplicated": "Khối đã được sao chép tại vị trí {position}
|
|
53
|
+
"a11y.blockDuplicated": "Khối đã được sao chép tại vị trí {position} trong {total}",
|
|
54
54
|
"a11y.blocksDuplicated": "{count} khối đã được sao chép từ vị trí {position}",
|
|
55
|
-
"a11y.movedUp": "Khối đã di chuyển lên
|
|
56
|
-
"a11y.movedDown": "Khối đã di chuyển xuống
|
|
55
|
+
"a11y.movedUp": "Khối đã di chuyển lên đến vị trí {position} trong {total}",
|
|
56
|
+
"a11y.movedDown": "Khối đã di chuyển xuống đến vị trí {position} trong {total}",
|
|
57
57
|
"a11y.atTop": "Khối đang ở trên cùng, không thể di chuyển lên",
|
|
58
58
|
"a11y.atBottom": "Khối đang ở dưới cùng, không thể di chuyển xuống"
|
|
59
59
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module HistoryAPI
|
|
3
|
+
* @copyright <CodeX> 2018
|
|
4
|
+
*
|
|
5
|
+
* Provides public methods for undo/redo operations
|
|
6
|
+
*/
|
|
7
|
+
import type { History } from '../../../../types/api';
|
|
8
|
+
import { Module } from '../../__module';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @class HistoryAPI
|
|
12
|
+
*/
|
|
13
|
+
export class HistoryAPI extends Module {
|
|
14
|
+
/**
|
|
15
|
+
* Available methods
|
|
16
|
+
* @returns {History}
|
|
17
|
+
*/
|
|
18
|
+
public get methods(): History {
|
|
19
|
+
return {
|
|
20
|
+
undo: (): void => this.undo(),
|
|
21
|
+
redo: (): void => this.redo(),
|
|
22
|
+
canUndo: (): boolean => this.canUndo(),
|
|
23
|
+
canRedo: (): boolean => this.canRedo(),
|
|
24
|
+
clear: (): void => this.clear(),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Undo the last operation
|
|
30
|
+
*/
|
|
31
|
+
public undo(): void {
|
|
32
|
+
this.Blok.YjsManager.undo();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Redo the last undone operation
|
|
37
|
+
*/
|
|
38
|
+
public redo(): void {
|
|
39
|
+
this.Blok.YjsManager.redo();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check if undo is available
|
|
44
|
+
* @returns {boolean} true if undo is available
|
|
45
|
+
*/
|
|
46
|
+
public canUndo(): boolean {
|
|
47
|
+
return this.Blok.YjsManager.canUndo();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Check if redo is available
|
|
52
|
+
* @returns {boolean} true if redo is available
|
|
53
|
+
*/
|
|
54
|
+
public canRedo(): boolean {
|
|
55
|
+
return this.Blok.YjsManager.canRedo();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Clear all history
|
|
60
|
+
*/
|
|
61
|
+
public clear(): void {
|
|
62
|
+
this.Blok.YjsManager.clear();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -21,6 +21,7 @@ export class API extends Module {
|
|
|
21
21
|
caret: this.Blok.CaretAPI.methods,
|
|
22
22
|
tools: this.Blok.ToolsAPI.methods,
|
|
23
23
|
events: this.Blok.EventsAPI.methods,
|
|
24
|
+
history: this.Blok.HistoryAPI.methods,
|
|
24
25
|
listeners: this.Blok.ListenersAPI.methods,
|
|
25
26
|
notifier: this.Blok.NotifierAPI.methods,
|
|
26
27
|
sanitizer: this.Blok.SanitizerAPI.methods,
|
|
@@ -12,9 +12,10 @@ export class ReadOnlyAPI extends Module {
|
|
|
12
12
|
public get methods(): ReadOnly {
|
|
13
13
|
const getIsEnabled = (): boolean => this.isEnabled;
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
return {
|
|
17
17
|
toggle: (state): Promise<boolean> => this.toggle(state),
|
|
18
|
+
set: (state): Promise<boolean> => this.set(state),
|
|
18
19
|
get isEnabled(): boolean {
|
|
19
20
|
return getIsEnabled();
|
|
20
21
|
},
|
|
@@ -30,6 +31,15 @@ export class ReadOnlyAPI extends Module {
|
|
|
30
31
|
return this.Blok.ReadOnly.toggle(state);
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Set read-only mode to the specified boolean state
|
|
36
|
+
* @param {boolean} state - read-only state to set
|
|
37
|
+
* @returns {Promise<boolean>} the new read-only state
|
|
38
|
+
*/
|
|
39
|
+
public set(state: boolean): Promise<boolean> {
|
|
40
|
+
return this.Blok.ReadOnly.set(state);
|
|
41
|
+
}
|
|
42
|
+
|
|
33
43
|
/**
|
|
34
44
|
* Returns current read-only state
|
|
35
45
|
*/
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import type { BlockToolData, OutputBlockData, PasteEvent } from '../../../../types';
|
|
8
8
|
import type { BlockTuneData } from '../../../../types/block-tunes/block-tune-data';
|
|
9
9
|
import type { BlockMutationEventMap, BlockMutationType } from '../../../../types/events/block';
|
|
10
|
+
import { BlockAddedMutationType } from '../../../../types/events/block/BlockAdded';
|
|
10
11
|
import { BlockChangedMutationType } from '../../../../types/events/block/BlockChanged';
|
|
11
12
|
import { BlockRemovedMutationType } from '../../../../types/events/block/BlockRemoved';
|
|
12
13
|
import { Module } from '../../__module';
|
|
@@ -307,6 +308,12 @@ export class BlockManager extends Module {
|
|
|
307
308
|
replaceBlock: (index, newBlock) => {
|
|
308
309
|
this.blocksStore.replace(index, newBlock);
|
|
309
310
|
},
|
|
311
|
+
onBlockRemoved: (block, index) => {
|
|
312
|
+
this.blockDidMutated(BlockRemovedMutationType, block, { index });
|
|
313
|
+
},
|
|
314
|
+
onBlockAdded: (block, index) => {
|
|
315
|
+
this.blockDidMutated(BlockAddedMutationType, block, { index });
|
|
316
|
+
},
|
|
310
317
|
},
|
|
311
318
|
this.blocksStore
|
|
312
319
|
);
|
|
@@ -43,6 +43,10 @@ export interface SyncHandlers {
|
|
|
43
43
|
updateIndentation: (block: Block) => void;
|
|
44
44
|
/** Called to replace a block at a specific index with a new block instance */
|
|
45
45
|
replaceBlock: (index: number, newBlock: Block) => void;
|
|
46
|
+
/** Called when a block is removed during undo/redo (before DOM removal) */
|
|
47
|
+
onBlockRemoved: (block: Block, index: number) => void;
|
|
48
|
+
/** Called when a block is added during undo/redo (after insertion) */
|
|
49
|
+
onBlockAdded: (block: Block, index: number) => void;
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
/**
|
|
@@ -273,10 +277,12 @@ export class BlockYjsSync {
|
|
|
273
277
|
bindEventsImmediately: true,
|
|
274
278
|
});
|
|
275
279
|
|
|
276
|
-
// Insert into blocks store at correct position - caller must handle this
|
|
277
|
-
// This is a limitation - we need the blocksStore.insert method
|
|
278
280
|
this.blocksStore.insert(targetIndex, block);
|
|
279
281
|
|
|
282
|
+
// Emit block-added event so listeners (e.g., TableCellBlocks) can
|
|
283
|
+
// claim the block for the correct cell during undo/redo
|
|
284
|
+
this.handlers.onBlockAdded(block, targetIndex);
|
|
285
|
+
|
|
280
286
|
// Apply indentation if needed
|
|
281
287
|
if (parentId !== undefined) {
|
|
282
288
|
this.handlers.updateIndentation(block);
|
|
@@ -300,6 +306,10 @@ export class BlockYjsSync {
|
|
|
300
306
|
return;
|
|
301
307
|
}
|
|
302
308
|
|
|
309
|
+
// Emit block-removed event BEFORE removal so listeners can inspect
|
|
310
|
+
// the block's DOM position (e.g., which table cell it's in)
|
|
311
|
+
this.handlers.onBlockRemoved(block, index);
|
|
312
|
+
|
|
303
313
|
// Remove from DOM
|
|
304
314
|
this.blocksStore.remove(index);
|
|
305
315
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BlocksAPI } from './api/blocks';
|
|
2
2
|
import { CaretAPI } from './api/caret';
|
|
3
3
|
import { EventsAPI } from './api/events';
|
|
4
|
+
import { HistoryAPI } from './api/history';
|
|
4
5
|
import { I18nAPI } from './api/i18n';
|
|
5
6
|
import { API } from './api/index';
|
|
6
7
|
import { InlineToolbarAPI } from './api/inlineToolbar';
|
|
@@ -44,6 +45,7 @@ export {
|
|
|
44
45
|
BlocksAPI,
|
|
45
46
|
CaretAPI,
|
|
46
47
|
EventsAPI,
|
|
48
|
+
HistoryAPI,
|
|
47
49
|
I18nAPI,
|
|
48
50
|
API,
|
|
49
51
|
InlineToolbarAPI,
|
|
@@ -91,6 +93,7 @@ export const Modules = {
|
|
|
91
93
|
BlocksAPI,
|
|
92
94
|
CaretAPI,
|
|
93
95
|
EventsAPI,
|
|
96
|
+
HistoryAPI,
|
|
94
97
|
I18nAPI,
|
|
95
98
|
API,
|
|
96
99
|
InlineToolbarAPI,
|
|
@@ -125,6 +125,17 @@ export class ReadOnly extends Module {
|
|
|
125
125
|
return this.readOnlyEnabled;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Set read-only mode to the specified boolean state
|
|
130
|
+
* Unlike toggle(), this method requires a parameter and does not have default toggle behavior
|
|
131
|
+
* Call all Modules `toggleReadOnly` method and re-render Blok
|
|
132
|
+
* @param state - read-only state to set (required)
|
|
133
|
+
* @returns the new read-only state
|
|
134
|
+
*/
|
|
135
|
+
public async set(state: boolean): Promise<boolean> {
|
|
136
|
+
return this.toggle(state);
|
|
137
|
+
}
|
|
138
|
+
|
|
128
139
|
/**
|
|
129
140
|
* Throws an error about tools which don't support read-only mode
|
|
130
141
|
*/
|
|
@@ -140,11 +140,15 @@ export class RectangleSelection extends Module {
|
|
|
140
140
|
const pointerX = pageX - scrollLeft;
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
|
-
* Check if pointer is within
|
|
143
|
+
* Check if pointer is within the content area's horizontal bounds.
|
|
144
144
|
* This determines whether we should close the toolbar when starting selection.
|
|
145
|
-
* Clicks outside the
|
|
145
|
+
* Clicks outside the content area (to the left or right, in the margin/toolbar zone)
|
|
146
|
+
* should NOT close the toolbar. Use the first block's content element for bounds,
|
|
147
|
+
* falling back to the redactor bounds if no content element exists.
|
|
146
148
|
*/
|
|
147
|
-
const
|
|
149
|
+
const contentElement = redactor.querySelector('[data-blok-testid="block-content"]');
|
|
150
|
+
const contentRect = contentElement ? contentElement.getBoundingClientRect() : editorRect;
|
|
151
|
+
const withinEditorHorizontally = pointerX >= contentRect.left && pointerX <= contentRect.right;
|
|
148
152
|
|
|
149
153
|
const elemWhereSelectionStart = document.elementFromPoint(pageX - scrollLeft, pointerY);
|
|
150
154
|
|
|
@@ -125,7 +125,9 @@ export class Saver extends Module {
|
|
|
125
125
|
const extractedBlocks: OutputData['blocks'] = [];
|
|
126
126
|
|
|
127
127
|
allExtractedData.forEach(({ id, tool, data, tunes, isValid, parentId, contentIds }) => {
|
|
128
|
-
|
|
128
|
+
const hasParent = parentId !== undefined && parentId !== null;
|
|
129
|
+
|
|
130
|
+
if (!isValid && !hasParent) {
|
|
129
131
|
log(`Block «${tool}» skipped because saved data is invalid`);
|
|
130
132
|
|
|
131
133
|
return;
|
|
@@ -151,7 +153,6 @@ export class Saver extends Module {
|
|
|
151
153
|
}
|
|
152
154
|
|
|
153
155
|
const isTunesEmpty = tunes === undefined || isEmpty(tunes);
|
|
154
|
-
const hasParent = parentId !== undefined && parentId !== null;
|
|
155
156
|
const hasContent = contentIds !== undefined && contentIds.length > 0;
|
|
156
157
|
|
|
157
158
|
const output: OutputData['blocks'][number] = {
|
|
@@ -85,6 +85,13 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
85
85
|
*/
|
|
86
86
|
private explicitlyClosed: boolean = false;
|
|
87
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Flag to track if the current hovered block was resolved from a table cell block.
|
|
90
|
+
* When true, the toolbar suppresses plus button, settings toggler, and
|
|
91
|
+
* prevents overriding the current block when the toolbox opens.
|
|
92
|
+
*/
|
|
93
|
+
private hoveredBlockIsFromTableCell: boolean = false;
|
|
94
|
+
|
|
88
95
|
/**
|
|
89
96
|
* Toolbox class instance
|
|
90
97
|
* It will be created in requestIdleCallback so it can be null in some period of time
|
|
@@ -215,8 +222,10 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
215
222
|
|
|
216
223
|
/**
|
|
217
224
|
* Set current block to cover the case when the Toolbar showed near hovered Block but caret is set to another Block.
|
|
225
|
+
* Skip this when the hovered block was resolved from a table cell, so the toolbox
|
|
226
|
+
* can detect the original cell block and hide restricted tools (e.g., table, header).
|
|
218
227
|
*/
|
|
219
|
-
if (this.hoveredBlock) {
|
|
228
|
+
if (this.hoveredBlock && !this.hoveredBlockIsFromTableCell) {
|
|
220
229
|
this.Blok.BlockManager.currentBlock = this.hoveredBlock;
|
|
221
230
|
}
|
|
222
231
|
|
|
@@ -328,11 +337,12 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
328
337
|
|
|
329
338
|
const targetBlock = this.resolveTableCellBlock(unresolvedBlock);
|
|
330
339
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
340
|
+
/**
|
|
341
|
+
* Track whether the original block was inside a table cell.
|
|
342
|
+
* When true, the toolbar suppresses plus button and settings toggler,
|
|
343
|
+
* and the toolbox uses the original current block for cell detection.
|
|
344
|
+
*/
|
|
345
|
+
this.hoveredBlockIsFromTableCell = targetBlock !== unresolvedBlock;
|
|
336
346
|
|
|
337
347
|
/** Clean up draggable on previous block if any */
|
|
338
348
|
if (this.hoveredBlock && this.hoveredBlock !== targetBlock) {
|
|
@@ -351,6 +361,25 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
351
361
|
return;
|
|
352
362
|
}
|
|
353
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Suppress toolbar buttons when the block is inside a table cell.
|
|
366
|
+
* The toolbar still positions itself for toolbox/slash-search purposes,
|
|
367
|
+
* but plus button and settings toggler remain hidden.
|
|
368
|
+
*/
|
|
369
|
+
if (this.hoveredBlockIsFromTableCell) {
|
|
370
|
+
plusButton.style.display = 'none';
|
|
371
|
+
|
|
372
|
+
if (settingsToggler) {
|
|
373
|
+
settingsToggler.style.display = 'none';
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
plusButton.style.display = '';
|
|
377
|
+
|
|
378
|
+
if (settingsToggler) {
|
|
379
|
+
settingsToggler.style.display = '';
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
354
383
|
const targetBlockHolder = targetBlock.holder;
|
|
355
384
|
const { isMobile } = this.Blok.UI;
|
|
356
385
|
|
|
@@ -521,18 +550,24 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
521
550
|
* to prevent toolbar from reopening on subsequent block-hovered events
|
|
522
551
|
*/
|
|
523
552
|
this.hoveredBlock = null;
|
|
553
|
+
this.hoveredBlockIsFromTableCell = false;
|
|
524
554
|
// Only set explicitlyClosed if not explicitly disabled (e.g., when called from toolbox after block insertion)
|
|
525
555
|
if (options?.setExplicitlyClosed !== false) {
|
|
526
556
|
this.explicitlyClosed = true;
|
|
527
557
|
}
|
|
528
558
|
|
|
529
559
|
/**
|
|
530
|
-
* Restore plus button
|
|
560
|
+
* Restore plus button and settings toggler visibility
|
|
561
|
+
* in case they were hidden for table cell blocks
|
|
531
562
|
*/
|
|
532
563
|
if (this.nodes.plusButton) {
|
|
533
564
|
this.nodes.plusButton.style.display = '';
|
|
534
565
|
}
|
|
535
566
|
|
|
567
|
+
if (this.nodes.settingsToggler) {
|
|
568
|
+
this.nodes.settingsToggler.style.display = '';
|
|
569
|
+
}
|
|
570
|
+
|
|
536
571
|
/**
|
|
537
572
|
* Reset the content offset transform
|
|
538
573
|
*/
|
|
@@ -566,9 +601,9 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
566
601
|
* Uses the DOM attribute directly to avoid cross-module dependency on the table tool.
|
|
567
602
|
*
|
|
568
603
|
* @param block - the block to resolve
|
|
569
|
-
* @returns the parent table block if inside a cell, the original block otherwise
|
|
604
|
+
* @returns the parent table block if inside a cell, the original block otherwise
|
|
570
605
|
*/
|
|
571
|
-
private resolveTableCellBlock(block: Block): Block
|
|
606
|
+
private resolveTableCellBlock(block: Block): Block {
|
|
572
607
|
const cellBlocksContainer = block.holder.closest('[data-blok-table-cell-blocks]');
|
|
573
608
|
|
|
574
609
|
if (!cellBlocksContainer) {
|
|
@@ -578,10 +613,10 @@ export class Toolbar extends Module<ToolbarNodes> {
|
|
|
578
613
|
const tableBlockHolder = cellBlocksContainer.closest('[data-blok-testid="block-wrapper"]');
|
|
579
614
|
|
|
580
615
|
if (!tableBlockHolder) {
|
|
581
|
-
return
|
|
616
|
+
return block;
|
|
582
617
|
}
|
|
583
618
|
|
|
584
|
-
return this.Blok.BlockManager.getBlockByChildNode(tableBlockHolder) ??
|
|
619
|
+
return this.Blok.BlockManager.getBlockByChildNode(tableBlockHolder) ?? block;
|
|
585
620
|
}
|
|
586
621
|
|
|
587
622
|
/**
|
|
@@ -173,12 +173,33 @@ export class PlusButtonHandler {
|
|
|
173
173
|
const hoveredBlockIndex = hoveredBlock !== null
|
|
174
174
|
? BlockManager.getBlockIndex(hoveredBlock)
|
|
175
175
|
: BlockManager.currentBlockIndex;
|
|
176
|
-
const
|
|
176
|
+
const baseInsertIndex = insertAbove ? hoveredBlockIndex : hoveredBlockIndex + 1;
|
|
177
|
+
|
|
178
|
+
// When inserting below, skip past any blocks nested inside another block's
|
|
179
|
+
// DOM (e.g. paragraph blocks inside table cells). The block array may
|
|
180
|
+
// interleave nested blocks from multiple parents, so check whether each
|
|
181
|
+
// block's holder lives inside any block-wrapper ancestor rather than only
|
|
182
|
+
// the hovered block's holder.
|
|
183
|
+
const blocksAfterInsert = BlockManager.blocks.slice(baseInsertIndex);
|
|
184
|
+
const isNested = (block: Block): boolean =>
|
|
185
|
+
block.holder.parentElement?.closest('[data-blok-testid="block-wrapper"]') !== null;
|
|
186
|
+
const firstNonNestedOffset = !insertAbove && hoveredBlock && blocksAfterInsert.length > 0
|
|
187
|
+
? blocksAfterInsert.findIndex((block) => !isNested(block))
|
|
188
|
+
: 0;
|
|
189
|
+
const insertIndex = baseInsertIndex + (firstNonNestedOffset === -1 ? blocksAfterInsert.length : firstNonNestedOffset);
|
|
177
190
|
|
|
178
191
|
const targetBlock = isEmptyParagraph || startsWithSlash
|
|
179
192
|
? hoveredBlock
|
|
180
193
|
: BlockManager.insertDefaultBlockAtIndex(insertIndex, true);
|
|
181
194
|
|
|
195
|
+
// The DOM insertion may place the new block's holder inside a nested
|
|
196
|
+
// container (e.g. a table cell) because the previous block in the array
|
|
197
|
+
// is inside another block's DOM. Move the holder to be a sibling after
|
|
198
|
+
// the hovered block so it becomes a top-level block.
|
|
199
|
+
if (targetBlock !== hoveredBlock && isNested(targetBlock)) {
|
|
200
|
+
hoveredBlock?.holder.after(targetBlock.holder);
|
|
201
|
+
}
|
|
202
|
+
|
|
182
203
|
// Insert "/" or position caret after existing one
|
|
183
204
|
if (startsWithSlash) {
|
|
184
205
|
Caret.setToBlock(targetBlock, Caret.positions.DEFAULT, 1);
|
|
@@ -189,6 +189,29 @@ export class YjsManager extends Module {
|
|
|
189
189
|
this.undoHistory.redo();
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Check if undo is available.
|
|
194
|
+
* @returns true if undo is available
|
|
195
|
+
*/
|
|
196
|
+
public canUndo(): boolean {
|
|
197
|
+
return this.undoHistory.canUndo();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Check if redo is available.
|
|
202
|
+
* @returns true if redo is available
|
|
203
|
+
*/
|
|
204
|
+
public canRedo(): boolean {
|
|
205
|
+
return this.undoHistory.canRedo();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Clear all history.
|
|
210
|
+
*/
|
|
211
|
+
public clear(): void {
|
|
212
|
+
this.undoHistory.clear();
|
|
213
|
+
}
|
|
214
|
+
|
|
192
215
|
/**
|
|
193
216
|
* Stop capturing changes into current undo group.
|
|
194
217
|
* Call this to force next change into a new undo entry.
|