@quadrats/common 0.7.7 → 1.1.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.
Files changed (88) hide show
  1. package/accordion/constants.d.ts +5 -0
  2. package/accordion/constants.js +10 -0
  3. package/accordion/createAccordion.d.ts +6 -0
  4. package/accordion/createAccordion.js +62 -0
  5. package/accordion/index.cjs.js +76 -0
  6. package/accordion/index.d.ts +3 -0
  7. package/accordion/index.js +2 -0
  8. package/accordion/package.json +7 -0
  9. package/accordion/typings.d.ts +18 -0
  10. package/align/constants.d.ts +2 -0
  11. package/align/constants.js +7 -0
  12. package/align/createAlign.d.ts +9 -0
  13. package/align/createAlign.js +39 -0
  14. package/align/index.cjs.js +46 -0
  15. package/align/index.d.ts +3 -0
  16. package/align/index.js +2 -0
  17. package/align/package.json +7 -0
  18. package/align/typings.d.ts +1 -0
  19. package/blockquote/createBlockquote.js +27 -10
  20. package/blockquote/index.cjs.js +26 -9
  21. package/card/constants.d.ts +6 -0
  22. package/card/constants.js +11 -0
  23. package/card/createCard.d.ts +15 -0
  24. package/card/createCard.js +147 -0
  25. package/card/getFilesFromInput.d.ts +4 -0
  26. package/card/index.cjs.js +163 -0
  27. package/card/index.d.ts +3 -0
  28. package/card/index.js +2 -0
  29. package/card/package.json +7 -0
  30. package/card/typings.d.ts +73 -0
  31. package/carousel/_virtual/_tslib.js +33 -0
  32. package/carousel/constants.d.ts +6 -0
  33. package/carousel/constants.js +11 -0
  34. package/carousel/createCarousel.d.ts +16 -0
  35. package/carousel/createCarousel.js +127 -0
  36. package/carousel/getFilesFromInput.d.ts +4 -0
  37. package/carousel/getFilesFromInput.js +30 -0
  38. package/carousel/index.cjs.js +202 -0
  39. package/carousel/index.d.ts +3 -0
  40. package/carousel/index.js +2 -0
  41. package/carousel/package.json +7 -0
  42. package/carousel/typings.d.ts +58 -0
  43. package/embed/constants.d.ts +1 -0
  44. package/embed/constants.js +2 -1
  45. package/embed/createEmbed.js +21 -4
  46. package/embed/index.cjs.js +26 -9
  47. package/embed/index.js +1 -1
  48. package/embed/serializeEmbedCode.d.ts +1 -1
  49. package/embed/serializeEmbedCode.js +5 -7
  50. package/embed/strategies/podcast-apple/index.cjs.js +1 -1
  51. package/embed/strategies/podcast-apple/index.js +1 -1
  52. package/embed/typings.d.ts +16 -1
  53. package/file-uploader/constants.d.ts +1 -0
  54. package/file-uploader/constants.js +2 -1
  55. package/file-uploader/createFileUploader.js +70 -7
  56. package/file-uploader/getFilesFromInput.js +3 -0
  57. package/file-uploader/index.cjs.js +73 -5
  58. package/file-uploader/index.js +1 -1
  59. package/file-uploader/typings.d.ts +8 -2
  60. package/heading/typings.d.ts +1 -0
  61. package/image/createImage.js +12 -11
  62. package/image/getImageFigureElementCommonProps.d.ts +2 -0
  63. package/image/getImageFigureElementCommonProps.js +28 -2
  64. package/image/index.cjs.js +40 -13
  65. package/image/typings.d.ts +2 -0
  66. package/list/createList.d.ts +1 -0
  67. package/list/createList.js +3 -0
  68. package/list/index.cjs.js +3 -0
  69. package/list/typings.d.ts +1 -0
  70. package/package.json +4 -4
  71. package/paragraph/createParagraph.d.ts +2 -0
  72. package/paragraph/createParagraph.js +24 -0
  73. package/paragraph/index.cjs.js +26 -0
  74. package/paragraph/index.d.ts +2 -0
  75. package/paragraph/index.js +1 -0
  76. package/paragraph/package.json +7 -0
  77. package/paragraph/typings.d.ts +9 -0
  78. package/table/constants.d.ts +14 -0
  79. package/table/constants.js +25 -0
  80. package/table/createTable.d.ts +6 -0
  81. package/table/createTable.js +429 -0
  82. package/table/index.cjs.js +714 -0
  83. package/table/index.d.ts +4 -0
  84. package/table/index.js +3 -0
  85. package/table/package.json +7 -0
  86. package/table/typings.d.ts +70 -0
  87. package/table/utils.d.ts +68 -0
  88. package/table/utils.js +243 -0
@@ -0,0 +1,4 @@
1
+ export * from './typings';
2
+ export * from './constants';
3
+ export * from './utils';
4
+ export { CreateTableOptions, createTable } from './createTable';
package/table/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { MAX_PINNED_COLUMNS_WIDTH_PERCENTAGE, MIN_COLUMN_WIDTH_PERCENTAGE, MIN_COLUMN_WIDTH_PIXEL, TABLE_BODY_TYPE, TABLE_CELL_TYPE, TABLE_DEFAULT_MAX_COLUMNS, TABLE_DEFAULT_MAX_ROWS, TABLE_HEADER_TYPE, TABLE_MAIN_TYPE, TABLE_ROW_TYPE, TABLE_TITLE_TYPE, TABLE_TYPE, TABLE_TYPES } from './constants.js';
2
+ export { calculateTableMinWidth, columnWidthToCSS, getCellLocation, getTableContainers, tryCrossBoundaryMove, tryExtendSelectionHorizontal, tryMoveToAdjacentRow, tryMoveToNextCell } from './utils.js';
3
+ export { createTable } from './createTable.js';
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@quadrats/common/table",
3
+ "sideEffects": false,
4
+ "main": "./index.cjs.js",
5
+ "module": "./index.js",
6
+ "typings": "./index.d.ts"
7
+ }
@@ -0,0 +1,70 @@
1
+ import { Ancestor, Editor, QuadratsElement, Text, Withable, WithElementType } from '@quadrats/core';
2
+ export type TableTypeKey = 'table';
3
+ export type TableTitleTypeKey = 'table_title';
4
+ export type TableMainTypeKey = 'table_main';
5
+ export type TableHeaderTypeKey = 'table_header';
6
+ export type TableBodyTypeKey = 'table_body';
7
+ export type TableRowTypeKey = 'table_row';
8
+ export type TableCellTypeKey = 'table_cell';
9
+ export type TableTypes = Record<TableTypeKey | TableTitleTypeKey | TableMainTypeKey | TableHeaderTypeKey | TableBodyTypeKey | TableRowTypeKey | TableCellTypeKey, string>;
10
+ export type ColumnWidth = {
11
+ type: 'percentage';
12
+ value: number;
13
+ } | {
14
+ type: 'pixel';
15
+ value: number;
16
+ };
17
+ export interface TableElement extends QuadratsElement, WithElementType {
18
+ treatAsTitle?: boolean;
19
+ pinned?: boolean;
20
+ align?: 'left' | 'center' | 'right';
21
+ columnWidths?: ColumnWidth[];
22
+ scrollPosition?: {
23
+ scrollLeft: number;
24
+ scrollTop: number;
25
+ };
26
+ children: {
27
+ type: string;
28
+ treatAsTitle?: boolean;
29
+ pinned?: boolean;
30
+ align?: 'left' | 'center' | 'right';
31
+ children: TableElement['children'] | Text[];
32
+ }[];
33
+ }
34
+ export interface Table<T extends Editor = Editor> extends Withable {
35
+ types: TableTypes;
36
+ createTableElement(rows: number, cols: number): QuadratsElement[];
37
+ insertTable(editor: T, rows: number, cols: number): void;
38
+ moveToNextCell(editor: Editor, types: TableTypes): void;
39
+ moveToRowAbove(editor: Editor, types: TableTypes): void;
40
+ moveToRowBelow(editor: Editor, types: TableTypes): void;
41
+ extendSelectionLeft(editor: Editor, types: TableTypes): void;
42
+ extendSelectionRight(editor: Editor, types: TableTypes): void;
43
+ extendSelectionUp(editor: Editor, types: TableTypes): void;
44
+ extendSelectionDown(editor: Editor, types: TableTypes): void;
45
+ isSelectionInTableMain(editor: T): boolean;
46
+ isSelectionInTableCell(editor: T): boolean;
47
+ isSelectionInTableRow(editor: T): boolean;
48
+ isSelectionInTableHeader(editor: T): boolean;
49
+ isSelectionInTableBody(editor: T): boolean;
50
+ isSelectionInTableList(editor: T): boolean;
51
+ }
52
+ export interface CellLocation {
53
+ cellPath: number[];
54
+ columnIndex: number;
55
+ row: Ancestor;
56
+ rowPath: number[];
57
+ rowIndex: number;
58
+ container: Ancestor;
59
+ containerPath: number[];
60
+ isHeader: boolean;
61
+ isBody: boolean;
62
+ }
63
+ export interface TableContainers {
64
+ tableMain: Ancestor;
65
+ tableMainPath: number[];
66
+ tableHeader: TableElement | null;
67
+ tableBody: TableElement | null;
68
+ tableHeaderIndex: number;
69
+ tableBodyIndex: number;
70
+ }
@@ -0,0 +1,68 @@
1
+ import { Editor } from '@quadrats/core';
2
+ import { CellLocation, ColumnWidth, TableContainers, TableTypes } from './typings';
3
+ /**
4
+ * 將 ColumnWidth 轉換為 CSS 可用的字串
5
+ * @param width - 行寬定義(column width)
6
+ * @returns CSS 寬度字串(例如 "30%" 或 "200px")
7
+ */
8
+ export declare function columnWidthToCSS(width: ColumnWidth): string;
9
+ /**
10
+ * 計算 table 的總寬度(用於設定 min-width 以支援 overflow)
11
+ * 此函數會將所有 columnWidths 的百分比和 pixel 值加總:
12
+ * - percentage: 保留為百分比
13
+ * - pixel: 直接累加
14
+ *
15
+ * @param columnWidths - 行寬陣列(column widths)
16
+ * @returns 總寬度的 CSS 字串(例如 "calc(50% + 400px)" 或 "100%" 或 "800px")
17
+ */
18
+ export declare function calculateTableMinWidth(columnWidths: ColumnWidth[]): string;
19
+ /**
20
+ * 獲取 cell 的位置資訊
21
+ * @param editor - Slate editor
22
+ * @param types - Table types
23
+ * @param at - 可選的位置,預設使用 editor.selection
24
+ * @returns cell 的位置資訊,如果找不到則返回 null
25
+ */
26
+ export declare function getCellLocation(editor: Editor, types: TableTypes, at?: any): CellLocation | null;
27
+ /**
28
+ * 獲取 table main 和相關容器資訊
29
+ * @param editor - Slate editor
30
+ * @param types - Table types
31
+ * @param containerPath - 當前容器的路徑
32
+ * @returns table 容器資訊,如果找不到則返回 null
33
+ */
34
+ export declare function getTableContainers(editor: Editor, types: TableTypes, containerPath: number[]): TableContainers | null;
35
+ /**
36
+ * 嘗試移動到相鄰列的相同行
37
+ * @param location - 當前 cell 位置資訊
38
+ * @param direction - 移動方向('up' 或 'down')
39
+ * @param selectFn - 選擇函數(用於 move 或 extend 模式)
40
+ * @returns 是否成功移動
41
+ */
42
+ export declare function tryMoveToAdjacentRow(location: CellLocation, direction: 'up' | 'down', selectFn: (cellPath: number[], position: 'start' | 'end') => void): boolean;
43
+ /**
44
+ * 嘗試跨容器移動(header <-> body)
45
+ * @param containers - Table 容器資訊
46
+ * @param location - 當前 cell 位置資訊
47
+ * @param direction - 移動方向('up' 或 'down')
48
+ * @param selectFn - 選擇函數(用於 move 或 extend 模式)
49
+ * @param targetColumn - 目標行索引,預設為保持當前行,設為 0 可強制移動到第一行
50
+ * @returns 是否成功移動
51
+ */
52
+ export declare function tryCrossBoundaryMove(containers: TableContainers, location: CellLocation, direction: 'up' | 'down', selectFn: (cellPath: number[], position: 'start' | 'end') => void, targetColumn?: number): boolean;
53
+ /**
54
+ * 嘗試移動到下一個 cell
55
+ * @param location - 當前 cell 位置資訊
56
+ * @param selectFn - 選擇函數
57
+ * @returns 是否成功移動
58
+ */
59
+ export declare function tryMoveToNextCell(location: CellLocation, selectFn: (cellPath: number[], position: 'start' | 'end') => void): boolean;
60
+ /**
61
+ * 嘗試在水平方向擴展選擇(左右移動)
62
+ * @param editor - Slate editor
63
+ * @param location - 當前 cell 位置資訊
64
+ * @param direction - 移動方向('left' 或 'right')
65
+ * @param anchor - 選擇的起點
66
+ * @returns 是否成功擴展
67
+ */
68
+ export declare function tryExtendSelectionHorizontal(editor: Editor, location: CellLocation, direction: 'left' | 'right', anchor: any): boolean;
package/table/utils.js ADDED
@@ -0,0 +1,243 @@
1
+ import { Editor, Element, Transforms } from '@quadrats/core';
2
+
3
+ /**
4
+ * 將 ColumnWidth 轉換為 CSS 可用的字串
5
+ * @param width - 行寬定義(column width)
6
+ * @returns CSS 寬度字串(例如 "30%" 或 "200px")
7
+ */
8
+ function columnWidthToCSS(width) {
9
+ if (width.type === 'percentage') {
10
+ return `${width.value.toFixed(1)}%`;
11
+ }
12
+ return `${width.value}px`;
13
+ }
14
+ /**
15
+ * 計算 table 的總寬度(用於設定 min-width 以支援 overflow)
16
+ * 此函數會將所有 columnWidths 的百分比和 pixel 值加總:
17
+ * - percentage: 保留為百分比
18
+ * - pixel: 直接累加
19
+ *
20
+ * @param columnWidths - 行寬陣列(column widths)
21
+ * @returns 總寬度的 CSS 字串(例如 "calc(50% + 400px)" 或 "100%" 或 "800px")
22
+ */
23
+ function calculateTableMinWidth(columnWidths) {
24
+ if (columnWidths.length === 0) {
25
+ return '100%';
26
+ }
27
+ let totalPercentage = 0;
28
+ let totalPixels = 0;
29
+ columnWidths.forEach((width) => {
30
+ if (width.type === 'percentage') {
31
+ totalPercentage += width.value;
32
+ }
33
+ else {
34
+ totalPixels += width.value;
35
+ }
36
+ });
37
+ // 只有 percentage,沒有 pixel
38
+ if (totalPixels === 0) {
39
+ return `${totalPercentage.toFixed(1)}%`;
40
+ }
41
+ // 只有 pixel,沒有 percentage
42
+ if (totalPercentage === 0) {
43
+ return `${totalPixels}px`;
44
+ }
45
+ // 有 percentage 也有 pixel
46
+ // 使用 calc() 來結合兩者
47
+ return `calc(${totalPercentage.toFixed(1)}% + ${totalPixels}px)`;
48
+ }
49
+ /**
50
+ * 獲取 cell 的位置資訊
51
+ * @param editor - Slate editor
52
+ * @param types - Table types
53
+ * @param at - 可選的位置,預設使用 editor.selection
54
+ * @returns cell 的位置資訊,如果找不到則返回 null
55
+ */
56
+ function getCellLocation(editor, types, at) {
57
+ const cellEntry = Editor.above(editor, {
58
+ at,
59
+ match: (n) => Element.isElement(n) && n.type === types.table_cell,
60
+ });
61
+ if (!cellEntry)
62
+ return null;
63
+ const [, cellPath] = cellEntry;
64
+ const columnIndex = cellPath[cellPath.length - 1];
65
+ const rowEntry = Editor.above(editor, {
66
+ at: cellPath,
67
+ match: (n) => Element.isElement(n) && n.type === types.table_row,
68
+ });
69
+ if (!rowEntry)
70
+ return null;
71
+ const [row, rowPath] = rowEntry;
72
+ const rowIndex = rowPath[rowPath.length - 1];
73
+ const containerEntry = Editor.above(editor, {
74
+ at: rowPath,
75
+ match: (n) => Element.isElement(n) && [types.table_header, types.table_body].includes(n.type),
76
+ });
77
+ if (!containerEntry)
78
+ return null;
79
+ const [container, containerPath] = containerEntry;
80
+ return {
81
+ cellPath,
82
+ columnIndex,
83
+ row,
84
+ rowPath,
85
+ rowIndex,
86
+ container,
87
+ containerPath,
88
+ isHeader: Element.isElement(container) && container.type === types.table_header,
89
+ isBody: Element.isElement(container) && container.type === types.table_body,
90
+ };
91
+ }
92
+ /**
93
+ * 獲取 table main 和相關容器資訊
94
+ * @param editor - Slate editor
95
+ * @param types - Table types
96
+ * @param containerPath - 當前容器的路徑
97
+ * @returns table 容器資訊,如果找不到則返回 null
98
+ */
99
+ function getTableContainers(editor, types, containerPath) {
100
+ const tableMainEntry = Editor.above(editor, {
101
+ at: containerPath,
102
+ match: (n) => Element.isElement(n) && n.type === types.table_main,
103
+ });
104
+ if (!tableMainEntry)
105
+ return null;
106
+ const [tableMain, tableMainPath] = tableMainEntry;
107
+ const tableHeader = tableMain.children.find((child) => Element.isElement(child) && child.type === types.table_header);
108
+ const tableBody = tableMain.children.find((child) => Element.isElement(child) && child.type === types.table_body);
109
+ const tableHeaderIndex = tableHeader ? tableMain.children.findIndex((child) => child === tableHeader) : -1;
110
+ const tableBodyIndex = tableBody ? tableMain.children.findIndex((child) => child === tableBody) : -1;
111
+ return {
112
+ tableMain,
113
+ tableMainPath,
114
+ tableHeader,
115
+ tableBody,
116
+ tableHeaderIndex,
117
+ tableBodyIndex,
118
+ };
119
+ }
120
+ /**
121
+ * 嘗試移動到相鄰列的相同行
122
+ * @param location - 當前 cell 位置資訊
123
+ * @param direction - 移動方向('up' 或 'down')
124
+ * @param selectFn - 選擇函數(用於 move 或 extend 模式)
125
+ * @returns 是否成功移動
126
+ */
127
+ function tryMoveToAdjacentRow(location, direction, selectFn) {
128
+ const { container, containerPath, rowIndex, columnIndex } = location;
129
+ const targetRowIndex = direction === 'up' ? rowIndex - 1 : rowIndex + 1;
130
+ // 嘗試在當前容器中移動
131
+ if (targetRowIndex >= 0 && targetRowIndex < container.children.length) {
132
+ const targetRow = container.children[targetRowIndex];
133
+ if (Element.isElement(targetRow)) {
134
+ const targetColumnIndex = Math.min(columnIndex, targetRow.children.length - 1);
135
+ const targetCellPath = [...containerPath, targetRowIndex, targetColumnIndex];
136
+ selectFn(targetCellPath, direction === 'up' ? 'start' : 'end');
137
+ return true;
138
+ }
139
+ }
140
+ return false;
141
+ }
142
+ /**
143
+ * 嘗試跨容器移動(header <-> body)
144
+ * @param containers - Table 容器資訊
145
+ * @param location - 當前 cell 位置資訊
146
+ * @param direction - 移動方向('up' 或 'down')
147
+ * @param selectFn - 選擇函數(用於 move 或 extend 模式)
148
+ * @param targetColumn - 目標行索引,預設為保持當前行,設為 0 可強制移動到第一行
149
+ * @returns 是否成功移動
150
+ */
151
+ function tryCrossBoundaryMove(containers, location, direction, selectFn, targetColumn) {
152
+ const { columnIndex, isHeader, isBody } = location;
153
+ const { tableMainPath, tableHeader, tableBody, tableHeaderIndex, tableBodyIndex } = containers;
154
+ // 從 body 向上移動到 header
155
+ if (direction === 'up' && isBody && tableHeader && Element.isElement(tableHeader)) {
156
+ const lastRowIndex = tableHeader.children.length - 1;
157
+ const lastRow = tableHeader.children[lastRowIndex];
158
+ if (Element.isElement(lastRow)) {
159
+ const targetColumnIndex = targetColumn !== undefined ? targetColumn : Math.min(columnIndex, lastRow.children.length - 1);
160
+ const targetCellPath = [...tableMainPath, tableHeaderIndex, lastRowIndex, targetColumnIndex];
161
+ selectFn(targetCellPath, 'start');
162
+ return true;
163
+ }
164
+ }
165
+ // 從 header 向下移動到 body
166
+ if (direction === 'down' && isHeader && tableBody && Element.isElement(tableBody)) {
167
+ const firstRow = tableBody.children[0];
168
+ if (Element.isElement(firstRow)) {
169
+ const targetColumnIndex = targetColumn !== undefined ? targetColumn : Math.min(columnIndex, firstRow.children.length - 1);
170
+ const targetCellPath = [...tableMainPath, tableBodyIndex, 0, targetColumnIndex];
171
+ // Tab 導航時使用 'start',上下鍵導航時使用 'end'
172
+ const position = targetColumn === 0 ? 'start' : 'end';
173
+ selectFn(targetCellPath, position);
174
+ return true;
175
+ }
176
+ }
177
+ return false;
178
+ }
179
+ /**
180
+ * 嘗試移動到下一個 cell
181
+ * @param location - 當前 cell 位置資訊
182
+ * @param selectFn - 選擇函數
183
+ * @returns 是否成功移動
184
+ */
185
+ function tryMoveToNextCell(location, selectFn) {
186
+ const { cellPath, row, rowPath, container, containerPath, rowIndex } = location;
187
+ const currentColumnIndex = cellPath[cellPath.length - 1];
188
+ const nextColumnIndex = currentColumnIndex + 1;
189
+ if (nextColumnIndex < row.children.length) {
190
+ const targetCellPath = [...rowPath, nextColumnIndex];
191
+ selectFn(targetCellPath, 'start');
192
+ return true;
193
+ }
194
+ const nextRowIndex = rowIndex + 1;
195
+ if (nextRowIndex < container.children.length) {
196
+ const nextRow = container.children[nextRowIndex];
197
+ if (Element.isElement(nextRow) && nextRow.children.length > 0) {
198
+ const targetCellPath = [...containerPath, nextRowIndex, 0];
199
+ selectFn(targetCellPath, 'start');
200
+ return true;
201
+ }
202
+ }
203
+ return false;
204
+ }
205
+ /**
206
+ * 嘗試在水平方向擴展選擇(左右移動)
207
+ * @param editor - Slate editor
208
+ * @param location - 當前 cell 位置資訊
209
+ * @param direction - 移動方向('left' 或 'right')
210
+ * @param anchor - 選擇的起點
211
+ * @returns 是否成功擴展
212
+ */
213
+ function tryExtendSelectionHorizontal(editor, location, direction, anchor) {
214
+ var _a;
215
+ const { cellPath, columnIndex, row, rowPath } = location;
216
+ const focus = (_a = editor.selection) === null || _a === void 0 ? void 0 : _a.focus;
217
+ if (!focus)
218
+ return false;
219
+ const isLeftDirection = direction === 'left';
220
+ const isAtBoundary = isLeftDirection ? columnIndex === 0 : columnIndex >= row.children.length - 1;
221
+ // 如果已經在邊界,嘗試擴展到該 cell 的開頭或結尾
222
+ if (isAtBoundary) {
223
+ const boundaryPoint = isLeftDirection ? Editor.start(editor, cellPath) : Editor.end(editor, cellPath);
224
+ // 只有當 focus 還沒到邊界時才移動
225
+ const shouldMove = isLeftDirection
226
+ ? focus.offset > boundaryPoint.offset || focus.path.length !== boundaryPoint.path.length
227
+ : focus.offset < boundaryPoint.offset || focus.path.length !== boundaryPoint.path.length;
228
+ if (shouldMove) {
229
+ Transforms.select(editor, { anchor, focus: boundaryPoint });
230
+ }
231
+ return true;
232
+ }
233
+ // 找到目標 cell
234
+ const targetColumnIndex = isLeftDirection ? columnIndex - 1 : columnIndex + 1;
235
+ const targetCellPath = [...rowPath, targetColumnIndex];
236
+ // 根據方向選擇目標點(左邊用 end,右邊用 start)
237
+ const targetPoint = isLeftDirection ? Editor.end(editor, targetCellPath) : Editor.start(editor, targetCellPath);
238
+ // 保持 anchor 不變,移動 focus
239
+ Transforms.select(editor, { anchor, focus: targetPoint });
240
+ return true;
241
+ }
242
+
243
+ export { calculateTableMinWidth, columnWidthToCSS, getCellLocation, getTableContainers, tryCrossBoundaryMove, tryExtendSelectionHorizontal, tryMoveToAdjacentRow, tryMoveToNextCell };