@atlaskit/editor-plugin-tasks-and-decisions 8.4.9 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/cjs/pm-plugins/keymaps.js +124 -28
- package/dist/es2019/pm-plugins/keymaps.js +127 -29
- package/dist/esm/pm-plugins/keymaps.js +124 -28
- package/package.json +16 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-tasks-and-decisions
|
|
2
2
|
|
|
3
|
+
## 9.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`133f7636e3a6c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/133f7636e3a6c) -
|
|
8
|
+
[ux] EDITOR-1750 Refactoring and improving delete key behaviours for block task item
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
11
|
+
## 8.5.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [`687c1b8fa7801`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/687c1b8fa7801) -
|
|
16
|
+
EDITOR-1566 bump adf-schema + update validator
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 8.4.9
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -225,6 +225,7 @@ var backspaceFrom = function backspaceFrom(editorAnalyticsAPI) {
|
|
|
225
225
|
var _slice;
|
|
226
226
|
try {
|
|
227
227
|
_slice = _taskContent.size ? paragraph.createChecked(undefined, _taskContent) : paragraph.createChecked();
|
|
228
|
+
|
|
228
229
|
// might be end of document after
|
|
229
230
|
var _tr2 = splitListItemWith(state.tr, _slice, $from, true);
|
|
230
231
|
dispatch(_tr2);
|
|
@@ -260,40 +261,131 @@ var unindentTaskOrUnwrapTaskDecisionFollowing = function unindentTaskOrUnwrapTas
|
|
|
260
261
|
taskList = _state$schema$nodes4.taskList,
|
|
261
262
|
doc = _state$schema$nodes4.doc,
|
|
262
263
|
paragraph = _state$schema$nodes4.paragraph,
|
|
264
|
+
blockTaskItem = _state$schema$nodes4.blockTaskItem,
|
|
265
|
+
taskItem = _state$schema$nodes4.taskItem,
|
|
263
266
|
tr = state.tr;
|
|
267
|
+
if ((0, _platformFeatureFlags.fg)('platform_editor_blocktaskitem_patch_3')) {
|
|
268
|
+
var _$next$node, _$from$node, _$next$node2, _$from$node2, _$next$node3;
|
|
269
|
+
// only run if cursor is at the end of the node
|
|
270
|
+
if (!(0, _utils.isEmptySelectionAtEnd)(state) || !dispatch) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
264
273
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
return false;
|
|
268
|
-
}
|
|
274
|
+
// look for the node after this current one
|
|
275
|
+
var $next = (0, _helpers.walkOut)($from);
|
|
269
276
|
|
|
270
|
-
|
|
271
|
-
|
|
277
|
+
// this is a top-level node it wont have $next.before()
|
|
278
|
+
if (!$next.parent || $next.parent.type === doc) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
272
281
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
282
|
+
// get resolved position of parent
|
|
283
|
+
var $parentPos = $from.doc.resolve($from.start($from.depth - 1));
|
|
284
|
+
var currentNode = $from.node();
|
|
285
|
+
var parentNode = $parentPos.node();
|
|
277
286
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
(0,
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
287
|
+
// if current position isn't an action or decision item, return false
|
|
288
|
+
if (!(0, _helpers.isActionOrDecisionItem)(currentNode) && !(0, _helpers.isActionOrDecisionItem)(parentNode)) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
var resultOfCurrentFindBlockTaskItem = (0, _utils3.findBlockTaskItem)($next);
|
|
292
|
+
var isCurrentEmptyBlockTaskItem = false;
|
|
293
|
+
if (resultOfCurrentFindBlockTaskItem) {
|
|
294
|
+
var _blockTaskItemNode$fi;
|
|
295
|
+
var blockTaskItemNode = resultOfCurrentFindBlockTaskItem.blockTaskItemNode;
|
|
296
|
+
isCurrentEmptyBlockTaskItem = blockTaskItem && blockTaskItemNode && blockTaskItemNode.childCount === 1 && ((_blockTaskItemNode$fi = blockTaskItemNode.firstChild) === null || _blockTaskItemNode$fi === void 0 ? void 0 : _blockTaskItemNode$fi.type) === paragraph && blockTaskItemNode.firstChild.childCount === 0;
|
|
297
|
+
}
|
|
298
|
+
var isEmptyActionOrDecisionItem = currentNode && (0, _helpers.isActionOrDecisionItem)(currentNode) && currentNode.childCount === 0;
|
|
299
|
+
|
|
300
|
+
// If empty item, use default handler
|
|
301
|
+
if (isEmptyActionOrDecisionItem || isCurrentEmptyBlockTaskItem) {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
286
304
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
$next.node().type.name === $from.node().type.name) {
|
|
291
|
-
var taskContent = state.doc.slice($next.start(), $next.end()).content;
|
|
305
|
+
// Check if next node is a blockTaskItem paragraph
|
|
306
|
+
var resultOfNextFindBlockTaskItem = (0, _utils3.findBlockTaskItem)($next);
|
|
307
|
+
var isNextInBlockTaskItemParagraph = resultOfNextFindBlockTaskItem && (resultOfNextFindBlockTaskItem === null || resultOfNextFindBlockTaskItem === void 0 ? void 0 : resultOfNextFindBlockTaskItem.hasParagraph);
|
|
292
308
|
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
309
|
+
// if nested, just unindent
|
|
310
|
+
if ($next.node($next.depth - 2).type === taskList ||
|
|
311
|
+
// this is for the case when we are on a non-nested item and next one is nested
|
|
312
|
+
$next.node($next.depth - 1).type === taskList && $next.parent.type === taskList) {
|
|
313
|
+
(0, _helpers.liftBlock)(tr, $next, $next);
|
|
314
|
+
dispatch(tr);
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
var isNextCompatibleWithBlockTaskItem = blockTaskItem && (($next === null || $next === void 0 || (_$next$node = $next.node()) === null || _$next$node === void 0 ? void 0 : _$next$node.type) === taskItem && ($from === null || $from === void 0 || (_$from$node = $from.node()) === null || _$from$node === void 0 ? void 0 : _$from$node.type) === blockTaskItem || ($next === null || $next === void 0 || (_$next$node2 = $next.node()) === null || _$next$node2 === void 0 ? void 0 : _$next$node2.type) === blockTaskItem && ($from === null || $from === void 0 || (_$from$node2 = $from.node()) === null || _$from$node2 === void 0 ? void 0 : _$from$node2.type) === taskItem || [taskItem, blockTaskItem].includes($next === null || $next === void 0 || (_$next$node3 = $next.node()) === null || _$next$node3 === void 0 ? void 0 : _$next$node3.type) && resultOfCurrentFindBlockTaskItem && resultOfCurrentFindBlockTaskItem.blockTaskItemNode);
|
|
318
|
+
|
|
319
|
+
// if next node is of same type or compatible type, remove the node wrapping and create paragraph
|
|
320
|
+
if (!(0, _helpers.isTable)($next.nodeAfter) && (0, _helpers.isActionOrDecisionItem)($from.parent) || resultOfCurrentFindBlockTaskItem && resultOfCurrentFindBlockTaskItem.blockTaskItemNode && actionDecisionFollowsOrNothing($from) && (
|
|
321
|
+
// only forward delete if the node is same type or compatible
|
|
322
|
+
$next.node().type.name === $from.node().type.name || isNextCompatibleWithBlockTaskItem)) {
|
|
323
|
+
if (dispatch) {
|
|
324
|
+
// If next node is in a blockTaskItem paragraph, we need to get the content of the whole blockTaskItem
|
|
325
|
+
// So we reduce the depth by 1 to get to the blockTaskItem node content
|
|
326
|
+
var taskContent = isNextInBlockTaskItemParagraph ? state.doc.slice($next.start($next.depth - 1), $next.end($next.depth - 1)).content : state.doc.slice($next.start(), $next.end()).content;
|
|
327
|
+
var slice;
|
|
328
|
+
try {
|
|
329
|
+
slice = taskContent.size ? paragraph.createChecked(undefined, taskContent) : paragraph.createChecked();
|
|
330
|
+
|
|
331
|
+
// might be end of document after
|
|
332
|
+
var _tr4 = splitListItemWith(state.tr, slice, $next, false);
|
|
333
|
+
dispatch(_tr4);
|
|
334
|
+
return true;
|
|
335
|
+
} catch (error) {
|
|
336
|
+
// If there's an error creating a paragraph, check if we are in a blockTaskItem
|
|
337
|
+
// Block task item's can have non-text content that cannot be wrapped in a paragraph
|
|
338
|
+
// So if the selection is in a blockTaskItem, just pass the content as is
|
|
339
|
+
if (resultOfNextFindBlockTaskItem && resultOfNextFindBlockTaskItem.blockTaskItemNode) {
|
|
340
|
+
var _$next$node$firstChil;
|
|
341
|
+
// Create an array from the fragment to pass into splitListItemWith, as the `content` property is readonly
|
|
342
|
+
slice = Array.from(taskContent.content);
|
|
343
|
+
var $splitPos = $next;
|
|
344
|
+
if ((_$next$node$firstChil = $next.node().firstChild) !== null && _$next$node$firstChil !== void 0 && _$next$node$firstChil.isTextblock) {
|
|
345
|
+
// set $next to the resolved position of inside the textblock
|
|
346
|
+
$splitPos = $next.doc.resolve($next.pos + 1);
|
|
347
|
+
}
|
|
348
|
+
var _tr5 = splitListItemWith(state.tr, slice, $splitPos, false);
|
|
349
|
+
dispatch(_tr5);
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
} else {
|
|
356
|
+
// only run if cursor is at the end of the node
|
|
357
|
+
if (!(0, _utils.isEmptySelectionAtEnd)(state) || !dispatch) {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// look for the node after this current one
|
|
362
|
+
var _$next = (0, _helpers.walkOut)($from);
|
|
363
|
+
|
|
364
|
+
// this is a top-level node it wont have $next.before()
|
|
365
|
+
if (!_$next.parent || _$next.parent.type === doc) {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// if nested, just unindent
|
|
370
|
+
if (_$next.node(_$next.depth - 2).type === taskList ||
|
|
371
|
+
// this is for the case when we are on a non-nested item and next one is nested
|
|
372
|
+
_$next.node(_$next.depth - 1).type === taskList && _$next.parent.type === taskList) {
|
|
373
|
+
(0, _helpers.liftBlock)(tr, _$next, _$next);
|
|
374
|
+
dispatch(tr);
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// if next node is of same type, remove the node wrapping and create paragraph
|
|
379
|
+
if (!(0, _helpers.isTable)(_$next.nodeAfter) && (0, _helpers.isActionOrDecisionItem)($from.parent) && actionDecisionFollowsOrNothing($from) &&
|
|
380
|
+
// only forward delete if the node is same type
|
|
381
|
+
_$next.node().type.name === $from.node().type.name) {
|
|
382
|
+
var _taskContent2 = state.doc.slice(_$next.start(), _$next.end()).content;
|
|
383
|
+
|
|
384
|
+
// might be end of document after
|
|
385
|
+
var _slice2 = _taskContent2.size ? paragraph.createChecked(undefined, _taskContent2) : [];
|
|
386
|
+
dispatch(splitListItemWith(tr, _slice2, _$next, false));
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
297
389
|
}
|
|
298
390
|
return false;
|
|
299
391
|
};
|
|
@@ -341,11 +433,13 @@ var splitListItemWith = function splitListItemWith(tr, content, $from, setSelect
|
|
|
341
433
|
var deleteBlockModifier = 0;
|
|
342
434
|
var shouldSplitBlockTaskItem = true;
|
|
343
435
|
var isGapCursorSelection = false;
|
|
436
|
+
var hasBlockTaskItem = false;
|
|
344
437
|
if (blockTaskItem) {
|
|
345
438
|
var result = (0, _utils3.findBlockTaskItem)($from);
|
|
346
439
|
if (result) {
|
|
347
440
|
var blockTaskItemNode = result.blockTaskItemNode,
|
|
348
441
|
hasParagraph = result.hasParagraph;
|
|
442
|
+
hasBlockTaskItem = (0, _platformFeatureFlags.fg)('platform_editor_blocktaskitem_patch_3') && !!blockTaskItemNode;
|
|
349
443
|
if (blockTaskItemNode) {
|
|
350
444
|
var _$oldAfter$nodeAfter, _$posPreviousSibling$;
|
|
351
445
|
// If the case there is a paragraph in the block task item we need to
|
|
@@ -391,7 +485,9 @@ var splitListItemWith = function splitListItemWith(tr, content, $from, setSelect
|
|
|
391
485
|
if (shouldSplit && !isNestedActionInsideLists) {
|
|
392
486
|
// this only splits a node to delete it, so we probably don't need a random uuid
|
|
393
487
|
// but generate one anyway for correctness
|
|
394
|
-
tr = tr.split($from.pos,
|
|
488
|
+
tr = tr.split($from.pos,
|
|
489
|
+
// eslint-disable-next-line @atlaskit/platform/no-preconditioning
|
|
490
|
+
(0, _platformFeatureFlags.fg)('platform_editor_blocktaskitem_patch_3') && hasBlockTaskItem ? 0 : 1, [{
|
|
395
491
|
type: $from.parent.type,
|
|
396
492
|
attrs: {
|
|
397
493
|
localId: _adfSchema.uuid.generate()
|
|
@@ -201,6 +201,7 @@ const backspaceFrom = editorAnalyticsAPI => $from => (state, dispatch) => {
|
|
|
201
201
|
let slice;
|
|
202
202
|
try {
|
|
203
203
|
slice = taskContent.size ? paragraph.createChecked(undefined, taskContent) : paragraph.createChecked();
|
|
204
|
+
|
|
204
205
|
// might be end of document after
|
|
205
206
|
const tr = splitListItemWith(state.tr, slice, $from, true);
|
|
206
207
|
dispatch(tr);
|
|
@@ -231,44 +232,137 @@ const unindentTaskOrUnwrapTaskDecisionFollowing = (state, dispatch) => {
|
|
|
231
232
|
nodes: {
|
|
232
233
|
taskList,
|
|
233
234
|
doc,
|
|
234
|
-
paragraph
|
|
235
|
+
paragraph,
|
|
236
|
+
blockTaskItem,
|
|
237
|
+
taskItem
|
|
235
238
|
}
|
|
236
239
|
},
|
|
237
240
|
tr
|
|
238
241
|
} = state;
|
|
242
|
+
if (fg('platform_editor_blocktaskitem_patch_3')) {
|
|
243
|
+
var _$next$node, _$from$node, _$next$node2, _$from$node2, _$next$node3;
|
|
244
|
+
// only run if cursor is at the end of the node
|
|
245
|
+
if (!isEmptySelectionAtEnd(state) || !dispatch) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
239
248
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
249
|
+
// look for the node after this current one
|
|
250
|
+
const $next = walkOut($from);
|
|
244
251
|
|
|
245
|
-
|
|
246
|
-
|
|
252
|
+
// this is a top-level node it wont have $next.before()
|
|
253
|
+
if (!$next.parent || $next.parent.type === doc) {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
247
256
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
257
|
+
// get resolved position of parent
|
|
258
|
+
const $parentPos = $from.doc.resolve($from.start($from.depth - 1));
|
|
259
|
+
const currentNode = $from.node();
|
|
260
|
+
const parentNode = $parentPos.node();
|
|
252
261
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
262
|
+
// if current position isn't an action or decision item, return false
|
|
263
|
+
if (!isActionOrDecisionItem(currentNode) && !isActionOrDecisionItem(parentNode)) {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
const resultOfCurrentFindBlockTaskItem = findBlockTaskItem($next);
|
|
267
|
+
let isCurrentEmptyBlockTaskItem = false;
|
|
268
|
+
if (resultOfCurrentFindBlockTaskItem) {
|
|
269
|
+
var _blockTaskItemNode$fi;
|
|
270
|
+
const {
|
|
271
|
+
blockTaskItemNode
|
|
272
|
+
} = resultOfCurrentFindBlockTaskItem;
|
|
273
|
+
isCurrentEmptyBlockTaskItem = blockTaskItem && blockTaskItemNode && blockTaskItemNode.childCount === 1 && ((_blockTaskItemNode$fi = blockTaskItemNode.firstChild) === null || _blockTaskItemNode$fi === void 0 ? void 0 : _blockTaskItemNode$fi.type) === paragraph && blockTaskItemNode.firstChild.childCount === 0;
|
|
274
|
+
}
|
|
275
|
+
const isEmptyActionOrDecisionItem = currentNode && isActionOrDecisionItem(currentNode) && currentNode.childCount === 0;
|
|
261
276
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const taskContent = state.doc.slice($next.start(), $next.end()).content;
|
|
277
|
+
// If empty item, use default handler
|
|
278
|
+
if (isEmptyActionOrDecisionItem || isCurrentEmptyBlockTaskItem) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
267
281
|
|
|
268
|
-
//
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
282
|
+
// Check if next node is a blockTaskItem paragraph
|
|
283
|
+
const resultOfNextFindBlockTaskItem = findBlockTaskItem($next);
|
|
284
|
+
const isNextInBlockTaskItemParagraph = resultOfNextFindBlockTaskItem && (resultOfNextFindBlockTaskItem === null || resultOfNextFindBlockTaskItem === void 0 ? void 0 : resultOfNextFindBlockTaskItem.hasParagraph);
|
|
285
|
+
|
|
286
|
+
// if nested, just unindent
|
|
287
|
+
if ($next.node($next.depth - 2).type === taskList ||
|
|
288
|
+
// this is for the case when we are on a non-nested item and next one is nested
|
|
289
|
+
$next.node($next.depth - 1).type === taskList && $next.parent.type === taskList) {
|
|
290
|
+
liftBlock(tr, $next, $next);
|
|
291
|
+
dispatch(tr);
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
const isNextCompatibleWithBlockTaskItem = blockTaskItem && (($next === null || $next === void 0 ? void 0 : (_$next$node = $next.node()) === null || _$next$node === void 0 ? void 0 : _$next$node.type) === taskItem && ($from === null || $from === void 0 ? void 0 : (_$from$node = $from.node()) === null || _$from$node === void 0 ? void 0 : _$from$node.type) === blockTaskItem || ($next === null || $next === void 0 ? void 0 : (_$next$node2 = $next.node()) === null || _$next$node2 === void 0 ? void 0 : _$next$node2.type) === blockTaskItem && ($from === null || $from === void 0 ? void 0 : (_$from$node2 = $from.node()) === null || _$from$node2 === void 0 ? void 0 : _$from$node2.type) === taskItem || [taskItem, blockTaskItem].includes($next === null || $next === void 0 ? void 0 : (_$next$node3 = $next.node()) === null || _$next$node3 === void 0 ? void 0 : _$next$node3.type) && resultOfCurrentFindBlockTaskItem && resultOfCurrentFindBlockTaskItem.blockTaskItemNode);
|
|
295
|
+
|
|
296
|
+
// if next node is of same type or compatible type, remove the node wrapping and create paragraph
|
|
297
|
+
if (!isTable($next.nodeAfter) && isActionOrDecisionItem($from.parent) || resultOfCurrentFindBlockTaskItem && resultOfCurrentFindBlockTaskItem.blockTaskItemNode && actionDecisionFollowsOrNothing($from) && (
|
|
298
|
+
// only forward delete if the node is same type or compatible
|
|
299
|
+
$next.node().type.name === $from.node().type.name || isNextCompatibleWithBlockTaskItem)) {
|
|
300
|
+
if (dispatch) {
|
|
301
|
+
// If next node is in a blockTaskItem paragraph, we need to get the content of the whole blockTaskItem
|
|
302
|
+
// So we reduce the depth by 1 to get to the blockTaskItem node content
|
|
303
|
+
const taskContent = isNextInBlockTaskItemParagraph ? state.doc.slice($next.start($next.depth - 1), $next.end($next.depth - 1)).content : state.doc.slice($next.start(), $next.end()).content;
|
|
304
|
+
let slice;
|
|
305
|
+
try {
|
|
306
|
+
slice = taskContent.size ? paragraph.createChecked(undefined, taskContent) : paragraph.createChecked();
|
|
307
|
+
|
|
308
|
+
// might be end of document after
|
|
309
|
+
const tr = splitListItemWith(state.tr, slice, $next, false);
|
|
310
|
+
dispatch(tr);
|
|
311
|
+
return true;
|
|
312
|
+
} catch (error) {
|
|
313
|
+
// If there's an error creating a paragraph, check if we are in a blockTaskItem
|
|
314
|
+
// Block task item's can have non-text content that cannot be wrapped in a paragraph
|
|
315
|
+
// So if the selection is in a blockTaskItem, just pass the content as is
|
|
316
|
+
if (resultOfNextFindBlockTaskItem && resultOfNextFindBlockTaskItem.blockTaskItemNode) {
|
|
317
|
+
var _$next$node$firstChil;
|
|
318
|
+
// Create an array from the fragment to pass into splitListItemWith, as the `content` property is readonly
|
|
319
|
+
slice = Array.from(taskContent.content);
|
|
320
|
+
let $splitPos = $next;
|
|
321
|
+
if ((_$next$node$firstChil = $next.node().firstChild) !== null && _$next$node$firstChil !== void 0 && _$next$node$firstChil.isTextblock) {
|
|
322
|
+
// set $next to the resolved position of inside the textblock
|
|
323
|
+
$splitPos = $next.doc.resolve($next.pos + 1);
|
|
324
|
+
}
|
|
325
|
+
const tr = splitListItemWith(state.tr, slice, $splitPos, false);
|
|
326
|
+
dispatch(tr);
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
} else {
|
|
333
|
+
// only run if cursor is at the end of the node
|
|
334
|
+
if (!isEmptySelectionAtEnd(state) || !dispatch) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// look for the node after this current one
|
|
339
|
+
const $next = walkOut($from);
|
|
340
|
+
|
|
341
|
+
// this is a top-level node it wont have $next.before()
|
|
342
|
+
if (!$next.parent || $next.parent.type === doc) {
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// if nested, just unindent
|
|
347
|
+
if ($next.node($next.depth - 2).type === taskList ||
|
|
348
|
+
// this is for the case when we are on a non-nested item and next one is nested
|
|
349
|
+
$next.node($next.depth - 1).type === taskList && $next.parent.type === taskList) {
|
|
350
|
+
liftBlock(tr, $next, $next);
|
|
351
|
+
dispatch(tr);
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// if next node is of same type, remove the node wrapping and create paragraph
|
|
356
|
+
if (!isTable($next.nodeAfter) && isActionOrDecisionItem($from.parent) && actionDecisionFollowsOrNothing($from) &&
|
|
357
|
+
// only forward delete if the node is same type
|
|
358
|
+
$next.node().type.name === $from.node().type.name) {
|
|
359
|
+
const taskContent = state.doc.slice($next.start(), $next.end()).content;
|
|
360
|
+
|
|
361
|
+
// might be end of document after
|
|
362
|
+
const slice = taskContent.size ? paragraph.createChecked(undefined, taskContent) : [];
|
|
363
|
+
dispatch(splitListItemWith(tr, slice, $next, false));
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
272
366
|
}
|
|
273
367
|
return false;
|
|
274
368
|
};
|
|
@@ -317,6 +411,7 @@ const splitListItemWith = (tr, content, $from, setSelection) => {
|
|
|
317
411
|
let deleteBlockModifier = 0;
|
|
318
412
|
let shouldSplitBlockTaskItem = true;
|
|
319
413
|
let isGapCursorSelection = false;
|
|
414
|
+
let hasBlockTaskItem = false;
|
|
320
415
|
if (blockTaskItem) {
|
|
321
416
|
const result = findBlockTaskItem($from);
|
|
322
417
|
if (result) {
|
|
@@ -324,6 +419,7 @@ const splitListItemWith = (tr, content, $from, setSelection) => {
|
|
|
324
419
|
blockTaskItemNode,
|
|
325
420
|
hasParagraph
|
|
326
421
|
} = result;
|
|
422
|
+
hasBlockTaskItem = fg('platform_editor_blocktaskitem_patch_3') && !!blockTaskItemNode;
|
|
327
423
|
if (blockTaskItemNode) {
|
|
328
424
|
var _$oldAfter$nodeAfter, _$posPreviousSibling$;
|
|
329
425
|
// If the case there is a paragraph in the block task item we need to
|
|
@@ -369,7 +465,9 @@ const splitListItemWith = (tr, content, $from, setSelection) => {
|
|
|
369
465
|
if (shouldSplit && !isNestedActionInsideLists) {
|
|
370
466
|
// this only splits a node to delete it, so we probably don't need a random uuid
|
|
371
467
|
// but generate one anyway for correctness
|
|
372
|
-
tr = tr.split($from.pos,
|
|
468
|
+
tr = tr.split($from.pos,
|
|
469
|
+
// eslint-disable-next-line @atlaskit/platform/no-preconditioning
|
|
470
|
+
fg('platform_editor_blocktaskitem_patch_3') && hasBlockTaskItem ? 0 : 1, [{
|
|
373
471
|
type: $from.parent.type,
|
|
374
472
|
attrs: {
|
|
375
473
|
localId: uuid.generate()
|
|
@@ -217,6 +217,7 @@ var backspaceFrom = function backspaceFrom(editorAnalyticsAPI) {
|
|
|
217
217
|
var _slice;
|
|
218
218
|
try {
|
|
219
219
|
_slice = _taskContent.size ? paragraph.createChecked(undefined, _taskContent) : paragraph.createChecked();
|
|
220
|
+
|
|
220
221
|
// might be end of document after
|
|
221
222
|
var _tr2 = splitListItemWith(state.tr, _slice, $from, true);
|
|
222
223
|
dispatch(_tr2);
|
|
@@ -252,40 +253,131 @@ var unindentTaskOrUnwrapTaskDecisionFollowing = function unindentTaskOrUnwrapTas
|
|
|
252
253
|
taskList = _state$schema$nodes4.taskList,
|
|
253
254
|
doc = _state$schema$nodes4.doc,
|
|
254
255
|
paragraph = _state$schema$nodes4.paragraph,
|
|
256
|
+
blockTaskItem = _state$schema$nodes4.blockTaskItem,
|
|
257
|
+
taskItem = _state$schema$nodes4.taskItem,
|
|
255
258
|
tr = state.tr;
|
|
259
|
+
if (fg('platform_editor_blocktaskitem_patch_3')) {
|
|
260
|
+
var _$next$node, _$from$node, _$next$node2, _$from$node2, _$next$node3;
|
|
261
|
+
// only run if cursor is at the end of the node
|
|
262
|
+
if (!isEmptySelectionAtEnd(state) || !dispatch) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
256
265
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
266
|
+
// look for the node after this current one
|
|
267
|
+
var $next = walkOut($from);
|
|
261
268
|
|
|
262
|
-
|
|
263
|
-
|
|
269
|
+
// this is a top-level node it wont have $next.before()
|
|
270
|
+
if (!$next.parent || $next.parent.type === doc) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
264
273
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
274
|
+
// get resolved position of parent
|
|
275
|
+
var $parentPos = $from.doc.resolve($from.start($from.depth - 1));
|
|
276
|
+
var currentNode = $from.node();
|
|
277
|
+
var parentNode = $parentPos.node();
|
|
269
278
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
279
|
+
// if current position isn't an action or decision item, return false
|
|
280
|
+
if (!isActionOrDecisionItem(currentNode) && !isActionOrDecisionItem(parentNode)) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
var resultOfCurrentFindBlockTaskItem = findBlockTaskItem($next);
|
|
284
|
+
var isCurrentEmptyBlockTaskItem = false;
|
|
285
|
+
if (resultOfCurrentFindBlockTaskItem) {
|
|
286
|
+
var _blockTaskItemNode$fi;
|
|
287
|
+
var blockTaskItemNode = resultOfCurrentFindBlockTaskItem.blockTaskItemNode;
|
|
288
|
+
isCurrentEmptyBlockTaskItem = blockTaskItem && blockTaskItemNode && blockTaskItemNode.childCount === 1 && ((_blockTaskItemNode$fi = blockTaskItemNode.firstChild) === null || _blockTaskItemNode$fi === void 0 ? void 0 : _blockTaskItemNode$fi.type) === paragraph && blockTaskItemNode.firstChild.childCount === 0;
|
|
289
|
+
}
|
|
290
|
+
var isEmptyActionOrDecisionItem = currentNode && isActionOrDecisionItem(currentNode) && currentNode.childCount === 0;
|
|
291
|
+
|
|
292
|
+
// If empty item, use default handler
|
|
293
|
+
if (isEmptyActionOrDecisionItem || isCurrentEmptyBlockTaskItem) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
278
296
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
$next.node().type.name === $from.node().type.name) {
|
|
283
|
-
var taskContent = state.doc.slice($next.start(), $next.end()).content;
|
|
297
|
+
// Check if next node is a blockTaskItem paragraph
|
|
298
|
+
var resultOfNextFindBlockTaskItem = findBlockTaskItem($next);
|
|
299
|
+
var isNextInBlockTaskItemParagraph = resultOfNextFindBlockTaskItem && (resultOfNextFindBlockTaskItem === null || resultOfNextFindBlockTaskItem === void 0 ? void 0 : resultOfNextFindBlockTaskItem.hasParagraph);
|
|
284
300
|
|
|
285
|
-
//
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
301
|
+
// if nested, just unindent
|
|
302
|
+
if ($next.node($next.depth - 2).type === taskList ||
|
|
303
|
+
// this is for the case when we are on a non-nested item and next one is nested
|
|
304
|
+
$next.node($next.depth - 1).type === taskList && $next.parent.type === taskList) {
|
|
305
|
+
liftBlock(tr, $next, $next);
|
|
306
|
+
dispatch(tr);
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
var isNextCompatibleWithBlockTaskItem = blockTaskItem && (($next === null || $next === void 0 || (_$next$node = $next.node()) === null || _$next$node === void 0 ? void 0 : _$next$node.type) === taskItem && ($from === null || $from === void 0 || (_$from$node = $from.node()) === null || _$from$node === void 0 ? void 0 : _$from$node.type) === blockTaskItem || ($next === null || $next === void 0 || (_$next$node2 = $next.node()) === null || _$next$node2 === void 0 ? void 0 : _$next$node2.type) === blockTaskItem && ($from === null || $from === void 0 || (_$from$node2 = $from.node()) === null || _$from$node2 === void 0 ? void 0 : _$from$node2.type) === taskItem || [taskItem, blockTaskItem].includes($next === null || $next === void 0 || (_$next$node3 = $next.node()) === null || _$next$node3 === void 0 ? void 0 : _$next$node3.type) && resultOfCurrentFindBlockTaskItem && resultOfCurrentFindBlockTaskItem.blockTaskItemNode);
|
|
310
|
+
|
|
311
|
+
// if next node is of same type or compatible type, remove the node wrapping and create paragraph
|
|
312
|
+
if (!isTable($next.nodeAfter) && isActionOrDecisionItem($from.parent) || resultOfCurrentFindBlockTaskItem && resultOfCurrentFindBlockTaskItem.blockTaskItemNode && actionDecisionFollowsOrNothing($from) && (
|
|
313
|
+
// only forward delete if the node is same type or compatible
|
|
314
|
+
$next.node().type.name === $from.node().type.name || isNextCompatibleWithBlockTaskItem)) {
|
|
315
|
+
if (dispatch) {
|
|
316
|
+
// If next node is in a blockTaskItem paragraph, we need to get the content of the whole blockTaskItem
|
|
317
|
+
// So we reduce the depth by 1 to get to the blockTaskItem node content
|
|
318
|
+
var taskContent = isNextInBlockTaskItemParagraph ? state.doc.slice($next.start($next.depth - 1), $next.end($next.depth - 1)).content : state.doc.slice($next.start(), $next.end()).content;
|
|
319
|
+
var slice;
|
|
320
|
+
try {
|
|
321
|
+
slice = taskContent.size ? paragraph.createChecked(undefined, taskContent) : paragraph.createChecked();
|
|
322
|
+
|
|
323
|
+
// might be end of document after
|
|
324
|
+
var _tr4 = splitListItemWith(state.tr, slice, $next, false);
|
|
325
|
+
dispatch(_tr4);
|
|
326
|
+
return true;
|
|
327
|
+
} catch (error) {
|
|
328
|
+
// If there's an error creating a paragraph, check if we are in a blockTaskItem
|
|
329
|
+
// Block task item's can have non-text content that cannot be wrapped in a paragraph
|
|
330
|
+
// So if the selection is in a blockTaskItem, just pass the content as is
|
|
331
|
+
if (resultOfNextFindBlockTaskItem && resultOfNextFindBlockTaskItem.blockTaskItemNode) {
|
|
332
|
+
var _$next$node$firstChil;
|
|
333
|
+
// Create an array from the fragment to pass into splitListItemWith, as the `content` property is readonly
|
|
334
|
+
slice = Array.from(taskContent.content);
|
|
335
|
+
var $splitPos = $next;
|
|
336
|
+
if ((_$next$node$firstChil = $next.node().firstChild) !== null && _$next$node$firstChil !== void 0 && _$next$node$firstChil.isTextblock) {
|
|
337
|
+
// set $next to the resolved position of inside the textblock
|
|
338
|
+
$splitPos = $next.doc.resolve($next.pos + 1);
|
|
339
|
+
}
|
|
340
|
+
var _tr5 = splitListItemWith(state.tr, slice, $splitPos, false);
|
|
341
|
+
dispatch(_tr5);
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
} else {
|
|
348
|
+
// only run if cursor is at the end of the node
|
|
349
|
+
if (!isEmptySelectionAtEnd(state) || !dispatch) {
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// look for the node after this current one
|
|
354
|
+
var _$next = walkOut($from);
|
|
355
|
+
|
|
356
|
+
// this is a top-level node it wont have $next.before()
|
|
357
|
+
if (!_$next.parent || _$next.parent.type === doc) {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// if nested, just unindent
|
|
362
|
+
if (_$next.node(_$next.depth - 2).type === taskList ||
|
|
363
|
+
// this is for the case when we are on a non-nested item and next one is nested
|
|
364
|
+
_$next.node(_$next.depth - 1).type === taskList && _$next.parent.type === taskList) {
|
|
365
|
+
liftBlock(tr, _$next, _$next);
|
|
366
|
+
dispatch(tr);
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// if next node is of same type, remove the node wrapping and create paragraph
|
|
371
|
+
if (!isTable(_$next.nodeAfter) && isActionOrDecisionItem($from.parent) && actionDecisionFollowsOrNothing($from) &&
|
|
372
|
+
// only forward delete if the node is same type
|
|
373
|
+
_$next.node().type.name === $from.node().type.name) {
|
|
374
|
+
var _taskContent2 = state.doc.slice(_$next.start(), _$next.end()).content;
|
|
375
|
+
|
|
376
|
+
// might be end of document after
|
|
377
|
+
var _slice2 = _taskContent2.size ? paragraph.createChecked(undefined, _taskContent2) : [];
|
|
378
|
+
dispatch(splitListItemWith(tr, _slice2, _$next, false));
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
289
381
|
}
|
|
290
382
|
return false;
|
|
291
383
|
};
|
|
@@ -333,11 +425,13 @@ var splitListItemWith = function splitListItemWith(tr, content, $from, setSelect
|
|
|
333
425
|
var deleteBlockModifier = 0;
|
|
334
426
|
var shouldSplitBlockTaskItem = true;
|
|
335
427
|
var isGapCursorSelection = false;
|
|
428
|
+
var hasBlockTaskItem = false;
|
|
336
429
|
if (blockTaskItem) {
|
|
337
430
|
var result = findBlockTaskItem($from);
|
|
338
431
|
if (result) {
|
|
339
432
|
var blockTaskItemNode = result.blockTaskItemNode,
|
|
340
433
|
hasParagraph = result.hasParagraph;
|
|
434
|
+
hasBlockTaskItem = fg('platform_editor_blocktaskitem_patch_3') && !!blockTaskItemNode;
|
|
341
435
|
if (blockTaskItemNode) {
|
|
342
436
|
var _$oldAfter$nodeAfter, _$posPreviousSibling$;
|
|
343
437
|
// If the case there is a paragraph in the block task item we need to
|
|
@@ -383,7 +477,9 @@ var splitListItemWith = function splitListItemWith(tr, content, $from, setSelect
|
|
|
383
477
|
if (shouldSplit && !isNestedActionInsideLists) {
|
|
384
478
|
// this only splits a node to delete it, so we probably don't need a random uuid
|
|
385
479
|
// but generate one anyway for correctness
|
|
386
|
-
tr = tr.split($from.pos,
|
|
480
|
+
tr = tr.split($from.pos,
|
|
481
|
+
// eslint-disable-next-line @atlaskit/platform/no-preconditioning
|
|
482
|
+
fg('platform_editor_blocktaskitem_patch_3') && hasBlockTaskItem ? 0 : 1, [{
|
|
387
483
|
type: $from.parent.type,
|
|
388
484
|
attrs: {
|
|
389
485
|
localId: uuid.generate()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-tasks-and-decisions",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "Tasks and decisions plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -29,34 +29,34 @@
|
|
|
29
29
|
],
|
|
30
30
|
"atlaskit:src": "src/index.ts",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@atlaskit/adf-schema": "^51.
|
|
33
|
-
"@atlaskit/analytics-namespaced-context": "^7.
|
|
32
|
+
"@atlaskit/adf-schema": "^51.2.0",
|
|
33
|
+
"@atlaskit/analytics-namespaced-context": "^7.1.0",
|
|
34
34
|
"@atlaskit/analytics-next": "^11.1.0",
|
|
35
35
|
"@atlaskit/css": "^0.14.0",
|
|
36
|
-
"@atlaskit/editor-plugin-analytics": "^
|
|
37
|
-
"@atlaskit/editor-plugin-block-menu": "^
|
|
38
|
-
"@atlaskit/editor-plugin-context-identifier": "^
|
|
39
|
-
"@atlaskit/editor-plugin-editor-viewmode": "^
|
|
40
|
-
"@atlaskit/editor-plugin-selection": "^
|
|
41
|
-
"@atlaskit/editor-plugin-type-ahead": "^
|
|
36
|
+
"@atlaskit/editor-plugin-analytics": "^6.0.0",
|
|
37
|
+
"@atlaskit/editor-plugin-block-menu": "^4.0.0",
|
|
38
|
+
"@atlaskit/editor-plugin-context-identifier": "^6.0.0",
|
|
39
|
+
"@atlaskit/editor-plugin-editor-viewmode": "^8.0.0",
|
|
40
|
+
"@atlaskit/editor-plugin-selection": "^6.0.0",
|
|
41
|
+
"@atlaskit/editor-plugin-type-ahead": "^6.0.0",
|
|
42
42
|
"@atlaskit/editor-prosemirror": "7.0.0",
|
|
43
43
|
"@atlaskit/editor-shared-styles": "^3.6.0",
|
|
44
44
|
"@atlaskit/editor-toolbar": "^0.9.0",
|
|
45
45
|
"@atlaskit/heading": "^5.2.0",
|
|
46
|
-
"@atlaskit/icon": "^28.
|
|
46
|
+
"@atlaskit/icon": "^28.3.0",
|
|
47
47
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
48
48
|
"@atlaskit/popup": "^4.4.0",
|
|
49
49
|
"@atlaskit/primitives": "^14.15.0",
|
|
50
50
|
"@atlaskit/prosemirror-input-rules": "^3.4.0",
|
|
51
51
|
"@atlaskit/task-decision": "^19.2.0",
|
|
52
|
-
"@atlaskit/tmp-editor-statsig": "^12.
|
|
52
|
+
"@atlaskit/tmp-editor-statsig": "^12.31.0",
|
|
53
53
|
"@atlaskit/tokens": "^6.3.0",
|
|
54
54
|
"@babel/runtime": "^7.0.0",
|
|
55
55
|
"@compiled/react": "^0.18.3",
|
|
56
56
|
"bind-event-listener": "^3.0.0"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@atlaskit/editor-common": "^
|
|
59
|
+
"@atlaskit/editor-common": "^110.0.0",
|
|
60
60
|
"react": "^18.2.0",
|
|
61
61
|
"react-dom": "^18.2.0",
|
|
62
62
|
"react-intl-next": "npm:react-intl@^5.18.1"
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@af/integration-testing": "workspace:^",
|
|
66
66
|
"@af/visual-regression": "workspace:^",
|
|
67
67
|
"@atlaskit/ssr": "workspace:^",
|
|
68
|
-
"@atlaskit/util-data-test": "^18.
|
|
68
|
+
"@atlaskit/util-data-test": "^18.3.0",
|
|
69
69
|
"@testing-library/react": "^13.4.0",
|
|
70
70
|
"wait-for-expect": "^1.2.0"
|
|
71
71
|
},
|
|
@@ -113,6 +113,9 @@
|
|
|
113
113
|
},
|
|
114
114
|
"platform_editor_block_menu_format_rank_revised": {
|
|
115
115
|
"type": "boolean"
|
|
116
|
+
},
|
|
117
|
+
"platform_editor_blocktaskitem_patch_3": {
|
|
118
|
+
"type": "boolean"
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
}
|