@jackuait/blok 0.6.0-beta.5 → 0.6.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +16 -169
  2. package/bin/blok.mjs +10 -0
  3. package/dist/blok.mjs +2 -2
  4. package/dist/chunks/{blok-XA2L0_-K.mjs → blok-BOtlKwVO.mjs} +877 -783
  5. package/dist/chunks/{i18next-loader-Ci2zhA-n.mjs → i18next-loader-CJNShSyT.mjs} +1 -1
  6. package/dist/chunks/{index-R38OiQ_d.mjs → index-BUAPAChM.mjs} +1 -1
  7. package/dist/chunks/{inline-tool-convert-e3PyuxB6.mjs → inline-tool-convert-UoYdJJic.mjs} +1 -1
  8. package/dist/{messages-BGxiFoZf.mjs → chunks/messages-7QoX8DkW.mjs} +14 -14
  9. package/dist/{messages-UX4gkere.mjs → chunks/messages-BMXCuEKO.mjs} +5 -5
  10. package/dist/{messages-wp_1b1hD.mjs → chunks/messages-BSbjsyHY.mjs} +16 -16
  11. package/dist/chunks/{messages-DChXyvh2.mjs → messages-BdeLo0N9.mjs} +14 -14
  12. package/dist/chunks/{messages-B9fe4dQJ.mjs → messages-C2htQ_3F.mjs} +12 -12
  13. package/dist/{messages-BNe6LuHW.mjs → chunks/messages-C9eaarcK.mjs} +7 -7
  14. package/dist/chunks/messages-CKI54h6O.mjs +62 -0
  15. package/dist/{messages-DjvaFRqx.mjs → chunks/messages-CQwpzUFp.mjs} +6 -6
  16. package/dist/{messages-EL5ARzmK.mjs → chunks/messages-CVw84KdI.mjs} +7 -7
  17. package/dist/chunks/{messages-49thXXGz.mjs → messages-Diu6jAaR.mjs} +6 -6
  18. package/dist/{messages-Bfiw5w_W.mjs → chunks/messages-DvFLX36Q.mjs} +10 -10
  19. package/dist/chunks/{messages-QtoE8uEv.mjs → messages-Dzwxv9v1.mjs} +8 -8
  20. package/dist/cli.mjs +50 -0
  21. package/dist/full.mjs +15 -15
  22. package/dist/locales.mjs +12 -12
  23. package/dist/{chunks/messages-BGxiFoZf.mjs → messages-7QoX8DkW.mjs} +14 -14
  24. package/dist/{chunks/messages-UX4gkere.mjs → messages-BMXCuEKO.mjs} +5 -5
  25. package/dist/{chunks/messages-wp_1b1hD.mjs → messages-BSbjsyHY.mjs} +16 -16
  26. package/dist/{messages-DChXyvh2.mjs → messages-BdeLo0N9.mjs} +14 -14
  27. package/dist/{messages-B9fe4dQJ.mjs → messages-C2htQ_3F.mjs} +12 -12
  28. package/dist/{chunks/messages-BNe6LuHW.mjs → messages-C9eaarcK.mjs} +7 -7
  29. package/dist/messages-CKI54h6O.mjs +62 -0
  30. package/dist/{chunks/messages-DjvaFRqx.mjs → messages-CQwpzUFp.mjs} +6 -6
  31. package/dist/{chunks/messages-EL5ARzmK.mjs → messages-CVw84KdI.mjs} +7 -7
  32. package/dist/{messages-49thXXGz.mjs → messages-Diu6jAaR.mjs} +6 -6
  33. package/dist/{chunks/messages-Bfiw5w_W.mjs → messages-DvFLX36Q.mjs} +10 -10
  34. package/dist/{messages-QtoE8uEv.mjs → messages-Dzwxv9v1.mjs} +8 -8
  35. package/dist/tools.mjs +222 -207
  36. package/dist/vendor.LICENSE.txt +1 -1
  37. package/package.json +13 -8
  38. package/src/cli/commands/migration.ts +16 -0
  39. package/src/cli/commands/migrationContent.ts +6 -0
  40. package/src/cli/index.ts +47 -0
  41. package/src/cli/utils/output.ts +10 -0
  42. package/src/components/i18n/locales/bn/messages.json +16 -16
  43. package/src/components/i18n/locales/fil/messages.json +7 -7
  44. package/src/components/i18n/locales/hi/messages.json +14 -14
  45. package/src/components/i18n/locales/id/messages.json +6 -6
  46. package/src/components/i18n/locales/mr/messages.json +14 -14
  47. package/src/components/i18n/locales/ms/messages.json +6 -6
  48. package/src/components/i18n/locales/ne/messages.json +12 -12
  49. package/src/components/i18n/locales/si/messages.json +8 -8
  50. package/src/components/i18n/locales/ta/messages.json +7 -7
  51. package/src/components/i18n/locales/te/messages.json +35 -35
  52. package/src/components/i18n/locales/th/messages.json +5 -5
  53. package/src/components/i18n/locales/vi/messages.json +10 -10
  54. package/src/components/modules/api/history.ts +64 -0
  55. package/src/components/modules/api/index.ts +1 -0
  56. package/src/components/modules/api/readonly.ts +11 -1
  57. package/src/components/modules/blockManager/blockManager.ts +7 -0
  58. package/src/components/modules/blockManager/yjs-sync.ts +12 -2
  59. package/src/components/modules/index.ts +3 -0
  60. package/src/components/modules/readonly.ts +11 -0
  61. package/src/components/modules/yjs/index.ts +23 -0
  62. package/src/tools/table/index.ts +20 -0
  63. package/src/tools/table/table-add-controls.ts +8 -0
  64. package/src/tools/table/table-cell-blocks.ts +15 -5
  65. package/src/types-internal/blok-modules.d.ts +2 -0
  66. package/types/api/history.d.ts +33 -0
  67. package/types/api/index.d.ts +1 -0
  68. package/types/api/readonly.d.ts +12 -2
  69. package/types/index.d.ts +3 -0
  70. package/dist/chunks/messages-DsVNtdgM.mjs +0 -62
  71. 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": "బ్లాక్ {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": "ఏదైనా రాయండి లేదా ఎంచుకోడానికి / నొక్కండి",
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": "คัดลอกบล็อกไปตำแหน่ง {position} จาก {total}",
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": "Thêm khối",
5
- "toolbox.optionAddAbove": "⌥ Thêm trên",
6
- "toolbox.ctrlAddAbove": "Ctrl Thêm trên",
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 đổi",
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} trên {total}",
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} trên {total}",
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} trên {total}",
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, vị trí {position} trên {total}",
56
- "a11y.movedDown": "Khối đã di chuyển xuống, vị trí {position} trên {total}",
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
  */
@@ -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.
@@ -72,6 +72,7 @@ export class Table implements BlockTool {
72
72
  private element: HTMLDivElement | null = null;
73
73
  private blockId: string | undefined;
74
74
  private pendingHighlight: PendingHighlight | null = null;
75
+ private isNewTable = false;
75
76
 
76
77
  constructor({ data, config, api, readOnly, block }: BlockToolConstructorOptions<TableData, TableConfig>) {
77
78
  this.api = api;
@@ -127,6 +128,8 @@ export class Table implements BlockTool {
127
128
  wrapper.setAttribute('data-blok-table-readonly', '');
128
129
  }
129
130
 
131
+ this.isNewTable = this.data.content.length === 0;
132
+
130
133
  const rows = this.data.content.length || this.config.rows || DEFAULT_ROWS;
131
134
  const cols = this.data.content[0]?.length || this.config.cols || DEFAULT_COLS;
132
135
 
@@ -178,6 +181,10 @@ export class Table implements BlockTool {
178
181
 
179
182
  this.data.content = this.cellBlocks?.initializeCells(this.data.content) ?? this.data.content;
180
183
 
184
+ if (this.isNewTable) {
185
+ populateNewCells(gridEl, this.cellBlocks);
186
+ }
187
+
181
188
  if (this.data.initialColWidth === undefined) {
182
189
  const widths = this.data.colWidths ?? readPixelWidths(gridEl);
183
190
 
@@ -190,6 +197,12 @@ export class Table implements BlockTool {
190
197
  this.initAddControls(gridEl);
191
198
  this.initRowColControls(gridEl);
192
199
  this.initCellSelection(gridEl);
200
+
201
+ if (this.isNewTable) {
202
+ const firstEditable = gridEl.querySelector<HTMLElement>('[contenteditable="true"]');
203
+
204
+ firstEditable?.focus();
205
+ }
193
206
  }
194
207
 
195
208
  public save(blockContent: HTMLElement): TableData {
@@ -313,6 +326,13 @@ export class Table implements BlockTool {
313
326
  wrapper: this.element,
314
327
  grid: gridEl,
315
328
  i18n: this.api.i18n,
329
+ getNewColumnWidth: () => {
330
+ const colWidths = this.data.colWidths ?? readPixelWidths(gridEl);
331
+
332
+ return this.data.initialColWidth !== undefined
333
+ ? Math.round((this.data.initialColWidth / 2) * 100) / 100
334
+ : computeHalfAvgWidth(colWidths);
335
+ },
316
336
  onAddRow: () => {
317
337
  this.grid.addRow(gridEl);
318
338
  populateNewCells(gridEl, this.cellBlocks);
@@ -56,6 +56,8 @@ interface TableAddControlsOptions {
56
56
  onDragAddCol: () => void;
57
57
  onDragRemoveCol: () => void;
58
58
  onDragEnd: () => void;
59
+ /** Returns the pixel width of a newly added column, used as the drag unit size. */
60
+ getNewColumnWidth?: () => number;
59
61
  }
60
62
 
61
63
  /**
@@ -89,6 +91,7 @@ export class TableAddControls {
89
91
  private boundPointerUp: (e: PointerEvent) => void;
90
92
  private boundRowPointerDown: (e: PointerEvent) => void;
91
93
  private boundColPointerDown: (e: PointerEvent) => void;
94
+ private getNewColumnWidth: (() => number) | undefined;
92
95
 
93
96
  constructor(options: TableAddControlsOptions) {
94
97
  this.wrapper = options.wrapper;
@@ -103,6 +106,7 @@ export class TableAddControls {
103
106
  this.onDragAddCol = options.onDragAddCol;
104
107
  this.onDragRemoveCol = options.onDragRemoveCol;
105
108
  this.onDragEnd = options.onDragEnd;
109
+ this.getNewColumnWidth = options.getNewColumnWidth;
106
110
  this.boundMouseMove = this.handleMouseMove.bind(this);
107
111
  this.boundMouseLeave = this.handleMouseLeave.bind(this);
108
112
  this.boundPointerMove = this.handlePointerMove.bind(this);
@@ -283,6 +287,10 @@ export class TableAddControls {
283
287
  return lastRow?.offsetHeight || 30;
284
288
  }
285
289
 
290
+ if (this.getNewColumnWidth) {
291
+ return this.getNewColumnWidth();
292
+ }
293
+
286
294
  const firstRow = this.grid.querySelector('[data-blok-table-row]');
287
295
 
288
296
  if (!firstRow) {
@@ -229,6 +229,7 @@ export class TableCellBlocks {
229
229
  * Initialize all cells with blocks.
230
230
  * - Empty cells or legacy string cells get a new paragraph block.
231
231
  * - Cells that already have block references get those blocks mounted.
232
+ * - If referenced blocks are missing from BlockManager, a fallback paragraph is created.
232
233
  */
233
234
  public initializeCells(content: LegacyCellContent[][]): CellContent[][] {
234
235
  const rowElements = this.gridElement.querySelectorAll(`[${ROW_ATTR}]`);
@@ -257,9 +258,12 @@ export class TableCellBlocks {
257
258
  return;
258
259
  }
259
260
 
260
- if (isCellWithBlocks(cellContent)) {
261
- this.mountBlocksInCell(container, cellContent.blocks);
262
- normalizedRow.push(cellContent);
261
+ const mountedIds = isCellWithBlocks(cellContent)
262
+ ? this.mountBlocksInCell(container, cellContent.blocks)
263
+ : [];
264
+
265
+ if (mountedIds.length > 0) {
266
+ normalizedRow.push({ blocks: mountedIds });
263
267
  } else {
264
268
  const text = typeof cellContent === 'string' ? cellContent : '';
265
269
  const block = this.api.blocks.insert('paragraph', { text }, {}, this.api.blocks.getBlocksCount(), false);
@@ -291,9 +295,12 @@ export class TableCellBlocks {
291
295
  }
292
296
 
293
297
  /**
294
- * Mount existing blocks into a cell container by their IDs
298
+ * Mount existing blocks into a cell container by their IDs.
299
+ * Returns the IDs of blocks that were successfully mounted.
295
300
  */
296
- private mountBlocksInCell(container: HTMLElement, blockIds: string[]): void {
301
+ private mountBlocksInCell(container: HTMLElement, blockIds: string[]): string[] {
302
+ const mountedIds: string[] = [];
303
+
297
304
  for (const blockId of blockIds) {
298
305
  const index = this.api.blocks.getBlockIndex(blockId);
299
306
 
@@ -308,7 +315,10 @@ export class TableCellBlocks {
308
315
  }
309
316
 
310
317
  container.appendChild(block.holder);
318
+ mountedIds.push(blockId);
311
319
  }
320
+
321
+ return mountedIds;
312
322
  }
313
323
 
314
324
  /**
@@ -2,6 +2,7 @@
2
2
  import { BlocksAPI } from '../components/modules/api/blocks';
3
3
  import { CaretAPI } from '../components/modules/api/caret';
4
4
  import { EventsAPI } from '../components/modules/api/events';
5
+ import { HistoryAPI } from '../components/modules/api/history';
5
6
  import { I18nAPI } from '../components/modules/api/i18n';
6
7
  import { API } from '../components/modules/api/index';
7
8
  import { InlineToolbarAPI } from '../components/modules/api/inlineToolbar';
@@ -45,6 +46,7 @@ export interface BlokModules {
45
46
  CaretAPI: CaretAPI,
46
47
  ToolsAPI: ToolsAPI,
47
48
  EventsAPI: EventsAPI,
49
+ HistoryAPI: HistoryAPI,
48
50
  I18nAPI: I18nAPI,
49
51
  API: API,
50
52
  InlineToolbarAPI: InlineToolbarAPI,
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Describes Blok's history API
3
+ */
4
+ export interface History {
5
+ /**
6
+ * Undo the last operation
7
+ */
8
+ undo(): void;
9
+
10
+ /**
11
+ * Redo the last undone operation
12
+ */
13
+ redo(): void;
14
+
15
+ /**
16
+ * Check if undo is available
17
+ *
18
+ * @returns {boolean} true if undo is available
19
+ */
20
+ canUndo(): boolean;
21
+
22
+ /**
23
+ * Check if redo is available
24
+ *
25
+ * @returns {boolean} true if redo is available
26
+ */
27
+ canRedo(): boolean;
28
+
29
+ /**
30
+ * Clear all history
31
+ */
32
+ clear(): void;
33
+ }
@@ -1,5 +1,6 @@
1
1
  export * from './blocks';
2
2
  export * from './events';
3
+ export * from './history';
3
4
  export * from './listeners';
4
5
  export * from './sanitizer';
5
6
  export * from './saver';
@@ -3,10 +3,20 @@
3
3
  */
4
4
  export interface ReadOnly {
5
5
  /**
6
- * Set or toggle read-only state
6
+ * Set read-only mode to the specified boolean state
7
7
  *
8
- * @param {Boolean|undefined} state - set or toggle state
8
+ * @param {Boolean} state - read-only state to set
9
+ * @returns {Promise<boolean>} the new read-only state
10
+ */
11
+ set: (state: boolean) => Promise<boolean>;
12
+
13
+ /**
14
+ * Toggle read-only state (deprecated - use set() instead)
15
+ * Without parameter, toggles current state. With parameter, sets to specified state.
16
+ *
17
+ * @param {Boolean|undefined} state - optional state to set (if omitted, toggles)
9
18
  * @returns {Promise<boolean>} current value
19
+ * @deprecated Use `set()` method for clearer intent
10
20
  */
11
21
  toggle: (state?: boolean) => Promise<boolean>;
12
22
 
package/types/index.d.ts CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  Blocks,
17
17
  Caret,
18
18
  Events,
19
+ History,
19
20
  InlineToolbar,
20
21
  Listeners,
21
22
  Notifier,
@@ -90,6 +91,7 @@ export {
90
91
  Blocks,
91
92
  Caret,
92
93
  Events,
94
+ History,
93
95
  InlineToolbar,
94
96
  Listeners,
95
97
  Notifier,
@@ -127,6 +129,7 @@ export interface API {
127
129
  caret: Caret;
128
130
  tools: Tools;
129
131
  events: Events;
132
+ history: History;
130
133
  listeners: Listeners;
131
134
  notifier: Notifier;
132
135
  sanitizer: Sanitizer;