@atlaskit/editor-tables 2.2.3 → 2.2.5

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 (160) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/cell-bookmark.js +0 -10
  3. package/dist/cjs/cell-selection.js +37 -102
  4. package/dist/cjs/index.js +0 -4
  5. package/dist/cjs/pm-plugins/input.js +24 -75
  6. package/dist/cjs/pm-plugins/plugin-key.js +0 -2
  7. package/dist/cjs/pm-plugins/table-editing.js +17 -18
  8. package/dist/cjs/pm-plugins.js +0 -2
  9. package/dist/cjs/table-map.js +63 -134
  10. package/dist/cjs/utils/add-column-at.js +0 -9
  11. package/dist/cjs/utils/add-column.js +8 -24
  12. package/dist/cjs/utils/add-row-at.js +8 -37
  13. package/dist/cjs/utils/add-row.js +2 -23
  14. package/dist/cjs/utils/analytics-helpers.js +4 -15
  15. package/dist/cjs/utils/cells.js +0 -12
  16. package/dist/cjs/utils/clone-tr.js +0 -2
  17. package/dist/cjs/utils/colspan.js +2 -18
  18. package/dist/cjs/utils/copy-paste.js +94 -120
  19. package/dist/cjs/utils/create-table.js +14 -28
  20. package/dist/cjs/utils/draw-cell-selection.js +0 -4
  21. package/dist/cjs/utils/empty-cells.js +0 -6
  22. package/dist/cjs/utils/find.js +6 -18
  23. package/dist/cjs/utils/fix-tables.js +13 -56
  24. package/dist/cjs/utils/for-each-cell.js +3 -17
  25. package/dist/cjs/utils/get-cell-selection-ranges.js +2 -9
  26. package/dist/cjs/utils/get-cells-in-column.js +0 -7
  27. package/dist/cjs/utils/get-cells-in-row.js +0 -7
  28. package/dist/cjs/utils/get-cells-in-table.js +0 -8
  29. package/dist/cjs/utils/get-selection-range-in-column.js +6 -27
  30. package/dist/cjs/utils/get-selection-range-in-row.js +6 -27
  31. package/dist/cjs/utils/get-selection-rect.js +0 -7
  32. package/dist/cjs/utils/go-to-next-cell.js +3 -22
  33. package/dist/cjs/utils/handle-paste.js +4 -33
  34. package/dist/cjs/utils/is-selected.js +6 -23
  35. package/dist/cjs/utils/is-selection-type.js +0 -2
  36. package/dist/cjs/utils/move-column.js +0 -12
  37. package/dist/cjs/utils/move-row.js +0 -11
  38. package/dist/cjs/utils/normalize-selection.js +3 -27
  39. package/dist/cjs/utils/remove-column.js +10 -46
  40. package/dist/cjs/utils/remove-row.js +8 -49
  41. package/dist/cjs/utils/remove-table.js +0 -6
  42. package/dist/cjs/utils/reorder-utils.js +13 -37
  43. package/dist/cjs/utils/replace-table.js +0 -8
  44. package/dist/cjs/utils/select-nodes.js +11 -31
  45. package/dist/cjs/utils/selection-cell.js +0 -5
  46. package/dist/cjs/utils/selection-rect.js +0 -10
  47. package/dist/cjs/utils/set-cell-attrs.js +0 -4
  48. package/dist/cjs/utils/split-cell-with-type.js +2 -35
  49. package/dist/cjs/utils/split-cell.js +0 -4
  50. package/dist/cjs/utils/table-node-types.js +4 -8
  51. package/dist/cjs/utils/tables.js +0 -4
  52. package/dist/cjs/utils/test-utils.js +9 -26
  53. package/dist/cjs/utils/toggle-header.js +4 -16
  54. package/dist/cjs/utils/uuid.js +0 -3
  55. package/dist/cjs/utils.js +0 -42
  56. package/dist/cjs/version.json +1 -1
  57. package/dist/es2019/cell-bookmark.js +0 -5
  58. package/dist/es2019/cell-selection.js +37 -81
  59. package/dist/es2019/index.js +1 -0
  60. package/dist/es2019/pm-plugins/input.js +27 -63
  61. package/dist/es2019/pm-plugins/table-editing.js +3 -12
  62. package/dist/es2019/table-map.js +54 -124
  63. package/dist/es2019/utils/add-column-at.js +2 -4
  64. package/dist/es2019/utils/add-column.js +6 -16
  65. package/dist/es2019/utils/add-row-at.js +8 -22
  66. package/dist/es2019/utils/add-row.js +2 -17
  67. package/dist/es2019/utils/analytics-helpers.js +0 -5
  68. package/dist/es2019/utils/cells.js +4 -9
  69. package/dist/es2019/utils/colspan.js +6 -11
  70. package/dist/es2019/utils/copy-paste.js +85 -99
  71. package/dist/es2019/utils/create-table.js +3 -12
  72. package/dist/es2019/utils/draw-cell-selection.js +0 -1
  73. package/dist/es2019/utils/empty-cells.js +2 -3
  74. package/dist/es2019/utils/find.js +8 -8
  75. package/dist/es2019/utils/fix-tables.js +17 -47
  76. package/dist/es2019/utils/for-each-cell.js +6 -11
  77. package/dist/es2019/utils/get-cell-selection-ranges.js +2 -4
  78. package/dist/es2019/utils/get-cells-in-column.js +2 -3
  79. package/dist/es2019/utils/get-cells-in-row.js +2 -3
  80. package/dist/es2019/utils/get-cells-in-table.js +2 -4
  81. package/dist/es2019/utils/get-selection-range-in-column.js +8 -22
  82. package/dist/es2019/utils/get-selection-range-in-row.js +8 -22
  83. package/dist/es2019/utils/get-selection-rect.js +2 -2
  84. package/dist/es2019/utils/go-to-next-cell.js +3 -19
  85. package/dist/es2019/utils/handle-paste.js +3 -14
  86. package/dist/es2019/utils/is-selected.js +8 -10
  87. package/dist/es2019/utils/is-selection-type.js +0 -1
  88. package/dist/es2019/utils/move-column.js +3 -8
  89. package/dist/es2019/utils/move-row.js +3 -7
  90. package/dist/es2019/utils/normalize-selection.js +0 -16
  91. package/dist/es2019/utils/remove-column.js +10 -27
  92. package/dist/es2019/utils/remove-row.js +12 -32
  93. package/dist/es2019/utils/remove-table.js +2 -4
  94. package/dist/es2019/utils/reorder-utils.js +11 -26
  95. package/dist/es2019/utils/replace-table.js +0 -2
  96. package/dist/es2019/utils/select-nodes.js +9 -20
  97. package/dist/es2019/utils/selection-cell.js +0 -2
  98. package/dist/es2019/utils/selection-rect.js +0 -4
  99. package/dist/es2019/utils/set-cell-attrs.js +2 -2
  100. package/dist/es2019/utils/split-cell-with-type.js +8 -28
  101. package/dist/es2019/utils/split-cell.js +3 -2
  102. package/dist/es2019/utils/table-node-types.js +4 -7
  103. package/dist/es2019/utils/tables.js +0 -2
  104. package/dist/es2019/utils/test-utils.js +12 -16
  105. package/dist/es2019/utils/toggle-header.js +4 -13
  106. package/dist/es2019/utils/uuid.js +0 -2
  107. package/dist/es2019/version.json +1 -1
  108. package/dist/esm/cell-bookmark.js +0 -5
  109. package/dist/esm/cell-selection.js +37 -79
  110. package/dist/esm/index.js +1 -0
  111. package/dist/esm/pm-plugins/input.js +24 -63
  112. package/dist/esm/pm-plugins/table-editing.js +8 -13
  113. package/dist/esm/table-map.js +65 -130
  114. package/dist/esm/utils/add-column-at.js +2 -4
  115. package/dist/esm/utils/add-column.js +8 -20
  116. package/dist/esm/utils/add-row-at.js +8 -23
  117. package/dist/esm/utils/add-row.js +2 -21
  118. package/dist/esm/utils/analytics-helpers.js +4 -10
  119. package/dist/esm/utils/cells.js +0 -5
  120. package/dist/esm/utils/colspan.js +2 -14
  121. package/dist/esm/utils/copy-paste.js +88 -109
  122. package/dist/esm/utils/create-table.js +14 -25
  123. package/dist/esm/utils/draw-cell-selection.js +0 -1
  124. package/dist/esm/utils/empty-cells.js +2 -3
  125. package/dist/esm/utils/find.js +8 -8
  126. package/dist/esm/utils/fix-tables.js +13 -49
  127. package/dist/esm/utils/for-each-cell.js +6 -11
  128. package/dist/esm/utils/get-cell-selection-ranges.js +2 -4
  129. package/dist/esm/utils/get-cells-in-column.js +2 -3
  130. package/dist/esm/utils/get-cells-in-row.js +2 -3
  131. package/dist/esm/utils/get-cells-in-table.js +2 -4
  132. package/dist/esm/utils/get-selection-range-in-column.js +8 -24
  133. package/dist/esm/utils/get-selection-range-in-row.js +8 -24
  134. package/dist/esm/utils/get-selection-rect.js +2 -2
  135. package/dist/esm/utils/go-to-next-cell.js +3 -19
  136. package/dist/esm/utils/handle-paste.js +4 -22
  137. package/dist/esm/utils/is-selected.js +8 -10
  138. package/dist/esm/utils/is-selection-type.js +0 -1
  139. package/dist/esm/utils/move-column.js +3 -8
  140. package/dist/esm/utils/move-row.js +3 -7
  141. package/dist/esm/utils/normalize-selection.js +3 -22
  142. package/dist/esm/utils/remove-column.js +10 -31
  143. package/dist/esm/utils/remove-row.js +8 -35
  144. package/dist/esm/utils/remove-table.js +2 -4
  145. package/dist/esm/utils/reorder-utils.js +11 -26
  146. package/dist/esm/utils/replace-table.js +0 -2
  147. package/dist/esm/utils/select-nodes.js +11 -22
  148. package/dist/esm/utils/selection-cell.js +0 -2
  149. package/dist/esm/utils/selection-rect.js +0 -4
  150. package/dist/esm/utils/set-cell-attrs.js +2 -2
  151. package/dist/esm/utils/split-cell-with-type.js +2 -28
  152. package/dist/esm/utils/split-cell.js +3 -2
  153. package/dist/esm/utils/table-node-types.js +4 -7
  154. package/dist/esm/utils/tables.js +0 -2
  155. package/dist/esm/utils/test-utils.js +12 -16
  156. package/dist/esm/utils/toggle-header.js +4 -13
  157. package/dist/esm/version.json +1 -1
  158. package/dist/types/utils/toggle-header.d.ts +3 -0
  159. package/package.json +7 -5
  160. package/report.api.md +11 -0
@@ -9,58 +9,74 @@
9
9
  // cell selection is different, here the cells in the selection are
10
10
  // clipped to the selection's rectangle, optionally repeating the
11
11
  // pasted cells when they are smaller than the selection.
12
+
12
13
  import { Fragment, Slice } from 'prosemirror-model';
13
14
  import { Transform } from 'prosemirror-transform';
14
15
  import { CellSelection } from '../cell-selection';
15
16
  import { TableMap } from '../table-map';
16
17
  import { removeColSpan } from './colspan';
17
- import { tableNodeTypes } from './table-node-types'; // Utilities to help with copying and pasting table cells
18
+ import { selectedRect } from './selection-rect';
19
+ import { tableNodeTypes } from './table-node-types';
20
+ import { isHeaderEnabledByType } from './toggle-header';
21
+
22
+ // Utilities to help with copying and pasting table cells
23
+
24
+ /**
25
+ * Replace any header cells with table cells.
26
+ *
27
+ * @param schema
28
+ * @param cells
29
+ * @returns Fragment with header cells converted to table cells
30
+ */
31
+ function stripHeaderType(schema, cells) {
32
+ const newCells = [];
33
+ cells.forEach(cell => {
34
+ var _cellNodeType$createA;
35
+ // Convert to cell type if not already
36
+ const cellNodeType = tableNodeTypes(schema).cell;
37
+ const tableCell = cell.type === cellNodeType ? cell : (_cellNodeType$createA = cellNodeType.createAndFill(cell.attrs, cell.content, cell.marks)) !== null && _cellNodeType$createA !== void 0 ? _cellNodeType$createA : cell;
38
+ newCells.push(tableCell);
39
+ });
40
+ return Fragment.from(newCells);
41
+ }
42
+
18
43
  // : (Slice) → ?{width: number, height: number, rows: [Fragment]}
19
44
  // Get a rectangular area of cells from a slice, or null if the outer
20
45
  // nodes of the slice aren't table cells or rows.
21
-
22
46
  export function pastedCells(slice) {
23
47
  if (!slice.size) {
24
48
  return null;
25
49
  }
26
-
27
50
  let {
28
51
  content,
29
52
  openStart,
30
53
  openEnd
31
54
  } = slice;
32
-
33
55
  if (!content.firstChild) {
34
56
  throw new Error('pastedCells: no firstChild defined for content');
35
57
  }
36
-
37
58
  while (content.childCount === 1 && (openStart > 0 && openEnd > 0 || content.firstChild.type.spec.tableRole === 'table')) {
38
59
  openStart--;
39
60
  openEnd--;
40
61
  content = content.firstChild.content;
41
-
42
62
  if (!content.firstChild) {
43
63
  throw new Error('pastedCells: no firstChild defined for content');
44
64
  }
45
65
  }
46
-
47
66
  const first = content.firstChild;
48
67
  const role = first.type.spec.tableRole;
49
68
  const {
50
69
  schema
51
70
  } = first.type;
52
71
  const rows = [];
53
-
54
72
  if (role === 'row') {
55
73
  for (let i = 0; i < content.childCount; i++) {
56
74
  let cells = content.child(i).content;
57
75
  const left = i ? 0 : Math.max(0, openStart - 1);
58
76
  const right = i < content.childCount - 1 ? 0 : Math.max(0, openEnd - 1);
59
-
60
77
  if (left || right) {
61
78
  cells = fitSlice(tableNodeTypes(schema).row, new Slice(cells, left, right)).content;
62
79
  }
63
-
64
80
  rows.push(cells);
65
81
  }
66
82
  } else if (role === 'cell' || role === 'header_cell') {
@@ -68,75 +84,64 @@ export function pastedCells(slice) {
68
84
  } else {
69
85
  return null;
70
86
  }
87
+ const rowsWithoutHeaders = rows.map(row => stripHeaderType(schema, row));
88
+ return ensureRectangular(schema, rowsWithoutHeaders);
89
+ }
71
90
 
72
- return ensureRectangular(schema, rows);
73
- } // : (Schema, [Fragment]) → {width: number, height: number, rows: [Fragment]}
91
+ // : (Schema, [Fragment]) → {width: number, height: number, rows: [Fragment]}
74
92
  // Compute the width and height of a set of cells, and make sure each
75
93
  // row has the same number of cells.
76
-
77
94
  function ensureRectangular(schema, rowsFragment) {
78
95
  const rows = rowsFragment;
79
96
  const widths = [];
80
-
81
97
  for (let i = 0; i < rows.length; i++) {
82
98
  const row = rows[i];
83
-
84
99
  for (let j = row.childCount - 1; j >= 0; j--) {
85
100
  const {
86
101
  rowspan,
87
102
  colspan
88
103
  } = row.child(j).attrs;
89
-
90
104
  for (let r = i; r < i + rowspan; r++) {
91
105
  widths[r] = (widths[r] || 0) + colspan;
92
106
  }
93
107
  }
94
108
  }
95
-
96
109
  let width = 0;
97
-
98
110
  for (let r = 0; r < widths.length; r++) {
99
111
  width = Math.max(width, widths[r]);
100
112
  }
101
-
102
113
  for (let r = 0; r < widths.length; r++) {
103
114
  if (r >= rows.length) {
104
115
  rows.push(Fragment.empty);
105
116
  }
106
-
107
117
  if (widths[r] < width) {
108
118
  const empty = tableNodeTypes(schema).cell.createAndFill();
109
119
  const cells = [];
110
-
111
120
  for (let i = widths[r]; i < width; i++) {
112
121
  cells.push(empty);
113
122
  }
114
-
115
123
  rows[r] = rows[r].append(Fragment.from(cells));
116
124
  }
117
125
  }
118
-
119
126
  return {
120
127
  height: rows.length,
121
128
  width,
122
129
  rows
123
130
  };
124
131
  }
125
-
126
132
  export function fitSlice(nodeType, slice) {
127
133
  const node = nodeType.createAndFill();
128
-
129
134
  if (!node) {
130
135
  throw new Error(`fitSlice: unable to create node`);
131
136
  }
132
-
133
137
  const tr = new Transform(node).replace(0, node.content.size, slice);
134
138
  return tr.doc;
135
- } // : ({width: number, height: number, rows: [Fragment]}, number, number) → {width: number, height: number, rows: [Fragment]}
139
+ }
140
+
141
+ // : ({width: number, height: number, rows: [Fragment]}, number, number) → {width: number, height: number, rows: [Fragment]}
136
142
  // Clip or extend (repeat) the given set of cells to cover the given
137
143
  // width and height. Will clip rowspan/colspan cells at the edges when
138
144
  // they stick out.
139
-
140
145
  export function clipCells({
141
146
  width: currentWidth,
142
147
  height: currentHeight,
@@ -145,71 +150,57 @@ export function clipCells({
145
150
  let rows = currentRows;
146
151
  let width = currentWidth;
147
152
  let height = currentHeight;
148
-
149
153
  if (width !== newWidth) {
150
154
  const added = [];
151
155
  const newRows = [];
152
-
153
156
  for (let row = 0; row < rows.length; row++) {
154
157
  const frag = rows[row];
155
158
  const cells = [];
156
-
157
159
  for (let col = added[row] || 0, i = 0; col < newWidth; i++) {
158
160
  let cell = frag.child(i % frag.childCount);
159
-
160
161
  if (col + cell.attrs.colspan > newWidth) {
161
162
  cell = cell.type.create(removeColSpan(cell.attrs, cell.attrs.colspan, col + cell.attrs.colspan - newWidth), cell.content);
162
163
  }
163
-
164
164
  cells.push(cell);
165
165
  col += cell.attrs.colspan;
166
-
167
166
  for (let j = 1; j < cell.attrs.rowspan; j++) {
168
167
  added[row + j] = (added[row + j] || 0) + cell.attrs.colspan;
169
168
  }
170
169
  }
171
-
172
170
  newRows.push(Fragment.from(cells));
173
171
  }
174
-
175
172
  rows = newRows;
176
173
  width = newWidth;
177
174
  }
178
-
179
175
  if (height !== newHeight) {
180
176
  const newRows = [];
181
-
182
177
  for (let row = 0, i = 0; row < newHeight; row++, i++) {
183
178
  const cells = [];
184
179
  const source = rows[i % height];
185
-
186
180
  for (let j = 0; j < source.childCount; j++) {
187
181
  let cell = source.child(j);
188
-
189
182
  if (row + cell.attrs.rowspan > newHeight) {
190
- cell = cell.type.create({ ...cell.attrs,
183
+ cell = cell.type.create({
184
+ ...cell.attrs,
191
185
  rowspan: Math.max(1, newHeight - cell.attrs.rowspan)
192
186
  }, cell.content);
193
187
  }
194
-
195
188
  cells.push(cell);
196
189
  }
197
-
198
190
  newRows.push(Fragment.from(cells));
199
191
  }
200
-
201
192
  rows = newRows;
202
193
  height = newHeight;
203
194
  }
204
-
205
195
  return {
206
196
  width,
207
197
  height,
208
198
  rows
209
199
  };
210
- } // Make sure a table has at least the given width and height. Return
211
- // true if something was changed.
200
+ }
212
201
 
202
+ // Make sure a table has at least the given width and height. Return
203
+ // true if something was changed.
213
204
  function growTable(tr, map, table, start, width, height, mapFrom) {
214
205
  const {
215
206
  schema
@@ -217,160 +208,162 @@ function growTable(tr, map, table, start, width, height, mapFrom) {
217
208
  const types = tableNodeTypes(schema);
218
209
  let empty;
219
210
  let emptyHead;
220
-
221
211
  if (width > map.width) {
222
212
  for (let row = 0, rowEnd = 0; row < map.height; row++) {
223
213
  const rowNode = table.child(row);
224
214
  rowEnd += rowNode.nodeSize;
225
215
  const cells = [];
226
216
  let add;
227
-
228
217
  if (rowNode.lastChild == null || rowNode.lastChild.type === types.cell) {
229
218
  add = empty || (empty = types.cell.createAndFill());
230
219
  } else {
231
220
  add = emptyHead || (emptyHead = types.header_cell.createAndFill());
232
221
  }
233
-
234
222
  for (let i = map.width; i < width; i++) {
235
223
  cells.push(add);
236
224
  }
237
-
238
225
  tr.insert(tr.mapping.slice(mapFrom).map(rowEnd - 1 + start), cells);
239
226
  }
240
227
  }
241
-
242
228
  if (height > map.height) {
243
229
  const cells = [];
244
-
245
230
  for (let i = 0, k = (map.height - 1) * map.width; i < Math.max(map.width, width); i++) {
246
231
  let header;
247
-
248
232
  if (i >= map.width) {
249
233
  header = false;
250
234
  } else {
251
235
  const mappedPos = map.map[k + i];
252
236
  const node = table.nodeAt(mappedPos);
253
-
254
237
  if (!node) {
255
238
  throw new Error(`growTable: no node found at pos ${mappedPos}`);
256
239
  }
257
-
258
240
  header = node.type === types.header_cell;
259
241
  }
260
-
261
242
  cells.push(header ? emptyHead || (emptyHead = types.header_cell.createAndFill()) : empty || (empty = types.cell.createAndFill()));
262
243
  }
263
-
264
244
  const emptyRow = types.row.create(null, Fragment.from(cells));
265
245
  const rows = [];
266
-
267
246
  for (let i = map.height; i < height; i++) {
268
247
  rows.push(emptyRow);
269
248
  }
270
-
271
249
  tr.insert(tr.mapping.slice(mapFrom).map(start + table.nodeSize - 2), rows);
272
250
  }
273
-
274
251
  return !!(empty || emptyHead);
275
- } // Make sure the given line (left, top) to (right, top) doesn't cross
252
+ }
253
+
254
+ // Make sure the given line (left, top) to (right, top) doesn't cross
276
255
  // any rowspan cells by splitting cells that cross it. Return true if
277
256
  // something changed.
278
-
279
-
280
257
  function isolateHorizontal(tr, map, table, start, left, right, top, mapFrom) {
281
258
  if (top === 0 || top === map.height) {
282
259
  return false;
283
260
  }
284
-
285
261
  let found = false;
286
-
287
262
  for (let col = left; col < right; col++) {
288
263
  const index = top * map.width + col;
289
264
  const pos = map.map[index];
290
-
291
265
  if (map.map[index - map.width] === pos) {
292
266
  found = true;
293
267
  const cell = table.nodeAt(pos);
294
-
295
268
  if (!cell) {
296
269
  throw new Error(`isolateHorizontal: no cell found at pos ${pos}`);
297
270
  }
298
-
299
271
  const {
300
272
  top: cellTop,
301
273
  left: cellLeft
302
274
  } = map.findCell(pos);
303
- tr.setNodeMarkup(tr.mapping.slice(mapFrom).map(pos + start), undefined, { ...cell.attrs,
275
+ tr.setNodeMarkup(tr.mapping.slice(mapFrom).map(pos + start), undefined, {
276
+ ...cell.attrs,
304
277
  rowspan: top - cellTop
305
278
  });
306
- const newCell = cell.type.createAndFill({ ...cell.attrs,
279
+ const newCell = cell.type.createAndFill({
280
+ ...cell.attrs,
307
281
  rowspan: cellTop + cell.attrs.rowspan - top
308
282
  });
309
-
310
283
  if (!newCell) {
311
284
  throw new Error('isolateHorizontal: failed to create cell');
312
285
  }
313
-
314
286
  tr.insert(tr.mapping.slice(mapFrom).map(map.positionAt(top, cellLeft, table)), newCell);
315
287
  col += cell.attrs.colspan - 1;
316
288
  }
317
289
  }
318
-
319
290
  return found;
320
- } // Make sure the given line (left, top) to (left, bottom) doesn't
291
+ }
292
+
293
+ // Make sure the given line (left, top) to (left, bottom) doesn't
321
294
  // cross any colspan cells by splitting cells that cross it. Return
322
295
  // true if something changed.
323
-
324
-
325
296
  function isolateVertical(tr, map, table, start, top, bottom, left, mapFrom) {
326
297
  if (left === 0 || left === map.width) {
327
298
  return false;
328
299
  }
329
-
330
300
  let found = false;
331
-
332
301
  for (let row = top; row < bottom; row++) {
333
302
  const index = row * map.width + left;
334
303
  const pos = map.map[index];
335
-
336
304
  if (map.map[index - 1] === pos) {
337
305
  found = true;
338
306
  const cell = table.nodeAt(pos);
339
-
340
307
  if (!cell) {
341
308
  throw new Error(`isolateVertical: could not find cell at pos ${pos}`);
342
309
  }
343
-
344
310
  const cellLeft = map.colCount(pos);
345
311
  const updatePos = tr.mapping.slice(mapFrom).map(pos + start);
346
312
  tr.setNodeMarkup(updatePos, undefined, removeColSpan(cell.attrs, left - cellLeft, cell.attrs.colspan - (left - cellLeft)));
347
313
  const newCell = cell.type.createAndFill(removeColSpan(cell.attrs, 0, left - cellLeft));
348
-
349
314
  if (!newCell) {
350
315
  throw new Error('isolateVertical: failed to create cell');
351
316
  }
352
-
353
317
  tr.insert(updatePos + cell.nodeSize, newCell);
354
318
  row += cell.attrs.rowspan - 1;
355
319
  }
356
320
  }
357
-
358
321
  return found;
359
- } // Insert the given set of cells (as returned by `pastedCells`) into a
360
- // table, at the position pointed at by rect.
322
+ }
323
+ function applyHeaderCells(tr, tableMap, state, tableStart, table, headerRowEnabled, headerColumnEnabled) {
324
+ const {
325
+ schema
326
+ } = state;
327
+ const setMarkup = (tr, row, col, headerEnabled) => {
328
+ const cellPos = tableStart + tableMap.positionAt(row, col, table);
329
+ const cell = tr.doc.nodeAt(cellPos);
330
+ const newType = headerEnabled ? schema.nodes.tableHeader : schema.nodes.tableCell;
331
+ const isCellTypeChanged = newType !== (cell === null || cell === void 0 ? void 0 : cell.type);
332
+ const isCellTypeValid = [schema.nodes.tableCell, schema.nodes.tableHeader].includes(cell === null || cell === void 0 ? void 0 : cell.type);
333
+ if (isCellTypeChanged && isCellTypeValid) {
334
+ tr.setNodeMarkup(cellPos, newType, cell === null || cell === void 0 ? void 0 : cell.attrs, cell === null || cell === void 0 ? void 0 : cell.marks);
335
+ }
336
+ };
337
+
338
+ // For row === 0 && col === 0 it is enabled if either are enabled
339
+ setMarkup(tr, 0, 0, headerColumnEnabled || headerRowEnabled);
361
340
 
341
+ // Header Column
342
+ for (let col = 1; col < tableMap.width; col++) {
343
+ setMarkup(tr, 0, col, headerRowEnabled);
344
+ }
345
+ // Header Row
346
+ for (let row = 1; row < tableMap.height; row++) {
347
+ setMarkup(tr, row, 0, headerColumnEnabled);
348
+ }
349
+ }
362
350
 
351
+ // Insert the given set of cells (as returned by `pastedCells`) into a
352
+ // table, at the position pointed at by rect.
363
353
  export function insertCells(state, dispatch, tableStart, rect, cells) {
364
354
  let table = state.doc;
355
+ const newRect = selectedRect(state);
356
+ const types = tableNodeTypes(state.schema);
365
357
 
358
+ // Get if the header row and column are enabled on the original table
359
+ const headerRowEnabled = isHeaderEnabledByType('row', newRect, types);
360
+ const headerColumnEnabled = isHeaderEnabledByType('column', newRect, types);
366
361
  if (tableStart) {
367
362
  table = state.doc.nodeAt(tableStart - 1);
368
-
369
363
  if (!table) {
370
364
  throw new Error(`insertCells: could not find table at pos ${tableStart - 1}`);
371
365
  }
372
366
  }
373
-
374
367
  let map = TableMap.get(table);
375
368
  const {
376
369
  top,
@@ -382,44 +375,37 @@ export function insertCells(state, dispatch, tableStart, rect, cells) {
382
375
  tr
383
376
  } = state;
384
377
  let mapFrom = 0;
385
-
386
378
  function recomp() {
387
379
  table = tableStart ? tr.doc.nodeAt(tableStart - 1) : tr.doc;
388
380
  map = TableMap.get(table);
389
381
  mapFrom = tr.mapping.maps.length;
390
- } // Prepare the table to be large enough and not have any cells
382
+ }
383
+ // Prepare the table to be large enough and not have any cells
391
384
  // crossing the boundaries of the rectangle that we want to
392
385
  // insert into. If anything about it changes, recompute the table
393
386
  // map so that subsequent operations can see the current shape.
394
-
395
-
396
387
  if (growTable(tr, map, table, tableStart, right, bottom, mapFrom)) {
397
388
  recomp();
398
389
  }
399
-
400
390
  if (isolateHorizontal(tr, map, table, tableStart, left, right, top, mapFrom)) {
401
391
  recomp();
402
392
  }
403
-
404
393
  if (isolateHorizontal(tr, map, table, tableStart, left, right, bottom, mapFrom)) {
405
394
  recomp();
406
395
  }
407
-
408
396
  if (isolateVertical(tr, map, table, tableStart, top, bottom, left, mapFrom)) {
409
397
  recomp();
410
398
  }
411
-
412
399
  if (isolateVertical(tr, map, table, tableStart, top, bottom, right, mapFrom)) {
413
400
  recomp();
414
401
  }
415
-
416
402
  for (let row = top; row < bottom; row++) {
417
403
  const from = map.positionAt(row, left, table);
418
404
  const to = map.positionAt(row, right, table);
419
405
  tr.replace(tr.mapping.slice(mapFrom).map(from + tableStart), tr.mapping.slice(mapFrom).map(to + tableStart), new Slice(cells.rows[row - top], 0, 0));
420
406
  }
421
-
422
407
  recomp();
408
+ applyHeaderCells(tr, map, state, tableStart, table, headerRowEnabled, headerColumnEnabled);
423
409
  tr.setSelection(new CellSelection(tr.doc.resolve(tableStart + map.positionAt(top, left, table)), tr.doc.resolve(tableStart + map.positionAt(bottom - 1, right - 1, table))));
424
410
  dispatch(tr);
425
411
  }
@@ -1,17 +1,15 @@
1
1
  import { tableNodeTypes } from './table-node-types';
2
2
  import { uuid } from './uuid';
3
-
4
3
  const createCell = (cellType, cellContent) => {
5
4
  if (cellContent) {
6
5
  return cellType.createChecked(null, cellContent);
7
6
  }
8
-
9
7
  return cellType.createAndFill();
10
- }; // Returns a table node of a given size.
8
+ };
9
+
10
+ // Returns a table node of a given size.
11
11
  // `withHeaderRow` defines whether the first row of the table will be a header row.
12
12
  // `cellContent` defines the content of each cell.
13
-
14
-
15
13
  export const createTable = ({
16
14
  schema,
17
15
  rowsCount = 3,
@@ -27,29 +25,22 @@ export const createTable = ({
27
25
  } = tableNodeTypes(schema);
28
26
  const cells = [];
29
27
  const headerCells = [];
30
-
31
28
  for (let i = 0; i < colsCount; i++) {
32
29
  const cell = createCell(tableCell, cellContent);
33
-
34
30
  if (cell) {
35
31
  cells.push(cell);
36
32
  }
37
-
38
33
  if (withHeaderRow) {
39
34
  const headerCell = createCell(tableHeader, cellContent);
40
-
41
35
  if (headerCell) {
42
36
  headerCells.push(headerCell);
43
37
  }
44
38
  }
45
39
  }
46
-
47
40
  const rows = [];
48
-
49
41
  for (let i = 0; i < rowsCount; i++) {
50
42
  rows.push(tableRow.createChecked(null, withHeaderRow && i === 0 ? headerCells : cells));
51
43
  }
52
-
53
44
  return table.createChecked({
54
45
  localId: uuid.generate()
55
46
  }, rows);
@@ -4,7 +4,6 @@ export function drawCellSelection(state) {
4
4
  if (!(state.selection instanceof CellSelection)) {
5
5
  return null;
6
6
  }
7
-
8
7
  const cells = [];
9
8
  state.selection.forEachCell((node, pos) => {
10
9
  cells.push(Decoration.node(pos, pos + node.nodeSize, {
@@ -1,15 +1,14 @@
1
1
  import { cloneTr } from './clone-tr';
2
- import { tableNodeTypes } from './table-node-types'; // Returns a new transaction that clears the content of a given `cell`.
2
+ import { tableNodeTypes } from './table-node-types';
3
3
 
4
+ // Returns a new transaction that clears the content of a given `cell`.
4
5
  export const emptyCell = (cell, schema) => tr => {
5
6
  if (cell) {
6
7
  const node = tableNodeTypes(schema).cell.createAndFill();
7
-
8
8
  if (node && !cell.node.content.eq(node.content)) {
9
9
  tr.replaceWith(cell.pos + 1, cell.pos + cell.node.nodeSize, node.content);
10
10
  return cloneTr(tr);
11
11
  }
12
12
  }
13
-
14
13
  return tr;
15
14
  };
@@ -1,26 +1,26 @@
1
1
  import { findParentNode, findParentNodeClosestToPos } from 'prosemirror-utils';
2
- import { TableMap } from '../table-map'; // Iterates over parent nodes, returning the closest table node.
2
+ import { TableMap } from '../table-map';
3
3
 
4
- export const findTable = selection => findParentNode(node => node.type.spec.tableRole && node.type.spec.tableRole === 'table')(selection); // Iterates over parent nodes, returning a table node closest to a given `$pos`.
4
+ // Iterates over parent nodes, returning the closest table node.
5
+ export const findTable = selection => findParentNode(node => node.type.spec.tableRole && node.type.spec.tableRole === 'table')(selection);
5
6
 
7
+ // Iterates over parent nodes, returning a table node closest to a given `$pos`.
6
8
  export const findTableClosestToPos = $pos => {
7
9
  const predicate = node => node.type.spec.tableRole && node.type.spec.tableRole === 'table';
8
-
9
10
  return findParentNodeClosestToPos($pos, predicate);
10
- }; // Iterates over parent nodes, returning a table cell or a table header node closest to a given `$pos`.
11
+ };
11
12
 
13
+ // Iterates over parent nodes, returning a table cell or a table header node closest to a given `$pos`.
12
14
  export const findCellClosestToPos = $pos => {
13
15
  const predicate = node => node.type.spec.tableRole && /cell/i.test(node.type.spec.tableRole);
14
-
15
16
  return findParentNodeClosestToPos($pos, predicate);
16
- }; // Returns the rectangle spanning a cell closest to a given `$pos`.
17
+ };
17
18
 
19
+ // Returns the rectangle spanning a cell closest to a given `$pos`.
18
20
  export const findCellRectClosestToPos = $pos => {
19
21
  const cell = findCellClosestToPos($pos);
20
-
21
22
  if (cell) {
22
23
  const table = findTableClosestToPos($pos);
23
-
24
24
  if (table) {
25
25
  const map = TableMap.get(table.node);
26
26
  const cellPos = cell.pos - table.start;