@atlaskit/editor-plugin-expand 31.0.6 → 31.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/editor-plugin-expand
2
2
 
3
+ ## 31.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`8cf7f4ad181c4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8cf7f4ad181c4) -
8
+ Backspace in an empty line after a collapsed expand deletes the line and moves the caret to the
9
+ end of the expand title, behind platform_editor_expand_delete_empty_line
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
3
15
  ## 31.0.6
4
16
 
5
17
  ### Patch Changes
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.deleteEmptyLineAfterCollapsedExpand = void 0;
7
+ var _state = require("@atlaskit/editor-prosemirror/state");
8
+ var _utils = require("../utils");
9
+ /**
10
+ * The empty paragraph holding the caret, when its previous sibling is a collapsed expand or nested
11
+ * expand and it is not the last child of its container. The last child is kept so there is always a
12
+ * line to type in after the expand.
13
+ */
14
+ var getEmptyLineAfterCollapsedExpand = function getEmptyLineAfterCollapsedExpand(state, isCollapsed) {
15
+ var $from = state.selection.$from;
16
+ var _state$schema$nodes = state.schema.nodes,
17
+ paragraph = _state$schema$nodes.paragraph,
18
+ expand = _state$schema$nodes.expand,
19
+ nestedExpand = _state$schema$nodes.nestedExpand;
20
+ var textblock = $from.parent;
21
+ if (textblock.type !== paragraph || textblock.content.size > 0) {
22
+ return undefined;
23
+ }
24
+ var container = $from.node(-1);
25
+ var index = $from.index(-1);
26
+ var isLastChild = index === container.childCount - 1;
27
+ if (index === 0 || isLastChild) {
28
+ return undefined;
29
+ }
30
+ var previousSibling = container.child(index - 1);
31
+ var isExpand = previousSibling.type === expand || previousSibling.type === nestedExpand;
32
+ if (!isExpand || !isCollapsed(previousSibling)) {
33
+ return undefined;
34
+ }
35
+ var lineStart = $from.before();
36
+ return {
37
+ expandContentStart: lineStart - previousSibling.nodeSize + 1,
38
+ lineStart: lineStart,
39
+ lineEnd: $from.after()
40
+ };
41
+ };
42
+ /**
43
+ * Backspace in an empty line directly after a collapsed expand: deletes the line and moves focus to
44
+ * the end of the expand title, in one transaction. Returns false, without changing anything, when
45
+ * the caret is anywhere else or the title input cannot be found, so other Backspace handling runs.
46
+ */
47
+ var deleteEmptyLineAfterCollapsedExpand = exports.deleteEmptyLineAfterCollapsedExpand = function deleteEmptyLineAfterCollapsedExpand(_ref) {
48
+ var focusTitle = _ref.focusTitle,
49
+ isCollapsed = _ref.isCollapsed;
50
+ return function (state, dispatch, editorView) {
51
+ if (!editorView || !state.selection.empty) {
52
+ return false;
53
+ }
54
+ var emptyLine = getEmptyLineAfterCollapsedExpand(state, isCollapsed);
55
+ if (!emptyLine) {
56
+ return false;
57
+ }
58
+ var titleInput = (0, _utils.getExpandTitleInput)(editorView, emptyLine.expandContentStart);
59
+ if (!titleInput) {
60
+ return false;
61
+ }
62
+ if (!dispatch) {
63
+ return true;
64
+ }
65
+ var tr = state.tr.delete(emptyLine.lineStart, emptyLine.lineEnd);
66
+ var selectionInsideExpand = _state.Selection.findFrom(tr.doc.resolve(emptyLine.expandContentStart), 1, true);
67
+ if (selectionInsideExpand) {
68
+ tr.setSelection(selectionInsideExpand);
69
+ }
70
+ dispatch(tr);
71
+ var titleInputAfterDelete = (0, _utils.getExpandTitleInput)(editorView, emptyLine.expandContentStart);
72
+ if (!(titleInputAfterDelete !== null && titleInputAfterDelete !== void 0 && titleInputAfterDelete.isConnected)) {
73
+ focusTitle(emptyLine.expandContentStart)(editorView.state, dispatch, editorView);
74
+ return true;
75
+ }
76
+ titleInputAfterDelete.focus();
77
+ var titleEnd = titleInputAfterDelete.value.length;
78
+ titleInputAfterDelete.setSelectionRange(titleEnd, titleEnd);
79
+ return true;
80
+ };
81
+ };
@@ -189,8 +189,7 @@ var insertExpand = exports.insertExpand = function insertExpand(editorAnalyticsA
189
189
  var focusTitle = exports.focusTitle = function focusTitle(pos) {
190
190
  return function (state, dispatch, editorView) {
191
191
  if (editorView) {
192
- var dom = editorView.domAtPos(pos);
193
- var expandWrapper = dom.node.parentElement;
192
+ var expandWrapper = (0, _utils3.getExpandWrapper)(editorView, pos);
194
193
  if (expandWrapper) {
195
194
  setSelectionInsideExpand(pos)(state, dispatch, editorView);
196
195
  var input = expandWrapper.querySelector('input');
@@ -14,7 +14,9 @@ var _utils = require("@atlaskit/editor-common/utils");
14
14
  var _keymap = require("@atlaskit/editor-prosemirror/keymap");
15
15
  var _state = require("@atlaskit/editor-prosemirror/state");
16
16
  var _utils2 = require("@atlaskit/editor-tables/utils");
17
+ var _fg = require("@atlaskit/platform-feature-flags/fg");
17
18
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
19
+ var _deleteEmptyLineAfterCollapsedExpand = require("../../editor-commands/deleteEmptyLineAfterCollapsedExpand");
18
20
  var _commands = require("../commands");
19
21
  var isExpandNode = function isExpandNode(node) {
20
22
  return (node === null || node === void 0 ? void 0 : node.type.name) === 'expand' || (node === null || node === void 0 ? void 0 : node.type.name) === 'nestedExpand';
@@ -24,6 +26,9 @@ var isExpandSelected = function isExpandSelected(selection) {
24
26
  };
25
27
  function expandKeymap(api, options) {
26
28
  var list = {};
29
+ var isCollapsed = function isCollapsed(expandNode) {
30
+ return options.__livePage ? expandNode.attrs.__expanded : !expandNode.attrs.__expanded;
31
+ };
27
32
  (0, _keymaps.bindKeymapWithCommand)(
28
33
  // Ignored via go/ees005
29
34
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -182,7 +187,13 @@ function expandKeymap(api, options) {
182
187
  // @see ED-7977
183
188
  var sel = _state.Selection.findFrom(state.doc.resolve(Math.max(selection.$from.pos - 1, 0)), -1);
184
189
  var expandBefore = (0, _transforms.findExpand)(state, sel);
185
- if (expandBefore && (expandBefore.node.type === expand || expandBefore.node.type === nestedExpand) && (options.__livePage ? expandBefore.node.attrs.__expanded : !expandBefore.node.attrs.__expanded)) {
190
+ if (expandBefore && (expandBefore.node.type === expand || expandBefore.node.type === nestedExpand) && isCollapsed(expandBefore.node)) {
191
+ if ((0, _fg.fg)('platform_editor_expand_delete_empty_line') && (0, _deleteEmptyLineAfterCollapsedExpand.deleteEmptyLineAfterCollapsedExpand)({
192
+ focusTitle: _commands.focusTitle,
193
+ isCollapsed: isCollapsed
194
+ })(state, dispatch, editorView)) {
195
+ return true;
196
+ }
186
197
  return (0, _commands.focusTitle)(expandBefore.start)(state, dispatch, editorView);
187
198
  }
188
199
  return false;
@@ -226,8 +226,7 @@ var updateExpandTitle = exports.updateExpandTitle = function updateExpandTitle(_
226
226
  var focusTitle = exports.focusTitle = function focusTitle(pos) {
227
227
  return function (state, dispatch, editorView) {
228
228
  if (editorView) {
229
- var dom = editorView.domAtPos(pos);
230
- var expandWrapper = dom.node.parentElement;
229
+ var expandWrapper = (0, _utils3.getExpandWrapper)(editorView, pos);
231
230
  if (expandWrapper) {
232
231
  setSelectionInsideExpand(pos)(state, dispatch, editorView);
233
232
  var input = expandWrapper.querySelector('input');
@@ -14,7 +14,9 @@ var _utils = require("@atlaskit/editor-common/utils");
14
14
  var _keymap = require("@atlaskit/editor-prosemirror/keymap");
15
15
  var _state = require("@atlaskit/editor-prosemirror/state");
16
16
  var _utils2 = require("@atlaskit/editor-tables/utils");
17
+ var _fg = require("@atlaskit/platform-feature-flags/fg");
17
18
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
19
+ var _deleteEmptyLineAfterCollapsedExpand = require("../../editor-commands/deleteEmptyLineAfterCollapsedExpand");
18
20
  var _commands = require("../commands");
19
21
  var isExpandNode = function isExpandNode(node) {
20
22
  return (node === null || node === void 0 ? void 0 : node.type.name) === 'expand' || (node === null || node === void 0 ? void 0 : node.type.name) === 'nestedExpand';
@@ -183,6 +185,12 @@ function expandKeymap(api) {
183
185
  var sel = _state.Selection.findFrom(state.doc.resolve(Math.max(selection.$from.pos - 1, 0)), -1);
184
186
  var expandBefore = (0, _transforms.findExpand)(state, sel);
185
187
  if (expandBefore && (expandBefore.node.type === expand || expandBefore.node.type === nestedExpand) && (0, _expand2.isExpandCollapsed)(expandBefore.node)) {
188
+ if ((0, _fg.fg)('platform_editor_expand_delete_empty_line') && (0, _deleteEmptyLineAfterCollapsedExpand.deleteEmptyLineAfterCollapsedExpand)({
189
+ focusTitle: _commands.focusTitle,
190
+ isCollapsed: _expand2.isExpandCollapsed
191
+ })(state, dispatch, editorView)) {
192
+ return true;
193
+ }
186
194
  return (0, _commands.focusTitle)(expandBefore.start)(state, dispatch, editorView);
187
195
  }
188
196
  return false;
package/dist/cjs/utils.js CHANGED
@@ -3,10 +3,21 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.isNestedInExpand = void 0;
6
+ exports.isNestedInExpand = exports.getExpandWrapper = exports.getExpandTitleInput = void 0;
7
7
  var _utils = require("@atlaskit/editor-prosemirror/utils");
8
8
  var isNestedInExpand = exports.isNestedInExpand = function isNestedInExpand(state) {
9
9
  return (0, _utils.hasParentNode)(function (node) {
10
10
  return node.type === state.schema.nodes.expand || node.type === state.schema.nodes.nestedExpand;
11
11
  })(state.selection);
12
+ };
13
+
14
+ /** The element wrapping an expand's title and content, found from a position inside its content. */
15
+ var getExpandWrapper = exports.getExpandWrapper = function getExpandWrapper(editorView, pos) {
16
+ return editorView.domAtPos(pos).node.parentElement;
17
+ };
18
+
19
+ /** The title input of the expand whose content contains `pos`. */
20
+ var getExpandTitleInput = exports.getExpandTitleInput = function getExpandTitleInput(editorView, pos) {
21
+ var _getExpandWrapper$que, _getExpandWrapper;
22
+ return (_getExpandWrapper$que = (_getExpandWrapper = getExpandWrapper(editorView, pos)) === null || _getExpandWrapper === void 0 ? void 0 : _getExpandWrapper.querySelector('input')) !== null && _getExpandWrapper$que !== void 0 ? _getExpandWrapper$que : null;
12
23
  };
@@ -0,0 +1,77 @@
1
+ import { Selection } from '@atlaskit/editor-prosemirror/state';
2
+ import { getExpandTitleInput } from '../utils';
3
+ /**
4
+ * The empty paragraph holding the caret, when its previous sibling is a collapsed expand or nested
5
+ * expand and it is not the last child of its container. The last child is kept so there is always a
6
+ * line to type in after the expand.
7
+ */
8
+ const getEmptyLineAfterCollapsedExpand = (state, isCollapsed) => {
9
+ const {
10
+ $from
11
+ } = state.selection;
12
+ const {
13
+ paragraph,
14
+ expand,
15
+ nestedExpand
16
+ } = state.schema.nodes;
17
+ const textblock = $from.parent;
18
+ if (textblock.type !== paragraph || textblock.content.size > 0) {
19
+ return undefined;
20
+ }
21
+ const container = $from.node(-1);
22
+ const index = $from.index(-1);
23
+ const isLastChild = index === container.childCount - 1;
24
+ if (index === 0 || isLastChild) {
25
+ return undefined;
26
+ }
27
+ const previousSibling = container.child(index - 1);
28
+ const isExpand = previousSibling.type === expand || previousSibling.type === nestedExpand;
29
+ if (!isExpand || !isCollapsed(previousSibling)) {
30
+ return undefined;
31
+ }
32
+ const lineStart = $from.before();
33
+ return {
34
+ expandContentStart: lineStart - previousSibling.nodeSize + 1,
35
+ lineStart,
36
+ lineEnd: $from.after()
37
+ };
38
+ };
39
+ /**
40
+ * Backspace in an empty line directly after a collapsed expand: deletes the line and moves focus to
41
+ * the end of the expand title, in one transaction. Returns false, without changing anything, when
42
+ * the caret is anywhere else or the title input cannot be found, so other Backspace handling runs.
43
+ */
44
+ export const deleteEmptyLineAfterCollapsedExpand = ({
45
+ focusTitle,
46
+ isCollapsed
47
+ }) => (state, dispatch, editorView) => {
48
+ if (!editorView || !state.selection.empty) {
49
+ return false;
50
+ }
51
+ const emptyLine = getEmptyLineAfterCollapsedExpand(state, isCollapsed);
52
+ if (!emptyLine) {
53
+ return false;
54
+ }
55
+ const titleInput = getExpandTitleInput(editorView, emptyLine.expandContentStart);
56
+ if (!titleInput) {
57
+ return false;
58
+ }
59
+ if (!dispatch) {
60
+ return true;
61
+ }
62
+ const tr = state.tr.delete(emptyLine.lineStart, emptyLine.lineEnd);
63
+ const selectionInsideExpand = Selection.findFrom(tr.doc.resolve(emptyLine.expandContentStart), 1, true);
64
+ if (selectionInsideExpand) {
65
+ tr.setSelection(selectionInsideExpand);
66
+ }
67
+ dispatch(tr);
68
+ const titleInputAfterDelete = getExpandTitleInput(editorView, emptyLine.expandContentStart);
69
+ if (!(titleInputAfterDelete !== null && titleInputAfterDelete !== void 0 && titleInputAfterDelete.isConnected)) {
70
+ focusTitle(emptyLine.expandContentStart)(editorView.state, dispatch, editorView);
71
+ return true;
72
+ }
73
+ titleInputAfterDelete.focus();
74
+ const titleEnd = titleInputAfterDelete.value.length;
75
+ titleInputAfterDelete.setSelectionRange(titleEnd, titleEnd);
76
+ return true;
77
+ };
@@ -9,7 +9,7 @@ import { createWrapSelectionTransaction } from '@atlaskit/editor-common/utils/cr
9
9
  import { Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
10
10
  import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
11
11
  import { findTable } from '@atlaskit/editor-tables/utils';
12
- import { isNestedInExpand } from '../utils';
12
+ import { getExpandWrapper, isNestedInExpand } from '../utils';
13
13
  import { createCommand } from './pm-plugins/plugin-factory';
14
14
  export const setExpandRef = ref => createCommand({
15
15
  type: 'SET_EXPAND_REF',
@@ -171,8 +171,7 @@ export const insertExpand = editorAnalyticsAPI => (state, dispatch) => {
171
171
  };
172
172
  export const focusTitle = pos => (state, dispatch, editorView) => {
173
173
  if (editorView) {
174
- const dom = editorView.domAtPos(pos);
175
- const expandWrapper = dom.node.parentElement;
174
+ const expandWrapper = getExpandWrapper(editorView, pos);
176
175
  if (expandWrapper) {
177
176
  setSelectionInsideExpand(pos)(state, dispatch, editorView);
178
177
  const input = expandWrapper.querySelector('input');
@@ -8,7 +8,9 @@ import { isEmptyNode, isPositionNearTableRow } from '@atlaskit/editor-common/uti
8
8
  import { keymap } from '@atlaskit/editor-prosemirror/keymap';
9
9
  import { NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
10
10
  import { isInTable } from '@atlaskit/editor-tables/utils';
11
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
11
12
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
13
+ import { deleteEmptyLineAfterCollapsedExpand } from '../../editor-commands/deleteEmptyLineAfterCollapsedExpand';
12
14
  import { deleteExpand, focusIcon, focusTitle } from '../commands';
13
15
  const isExpandNode = node => {
14
16
  return (node === null || node === void 0 ? void 0 : node.type.name) === 'expand' || (node === null || node === void 0 ? void 0 : node.type.name) === 'nestedExpand';
@@ -16,6 +18,7 @@ const isExpandNode = node => {
16
18
  const isExpandSelected = selection => selection instanceof NodeSelection && isExpandNode(selection.node);
17
19
  export function expandKeymap(api, options) {
18
20
  const list = {};
21
+ const isCollapsed = expandNode => options.__livePage ? expandNode.attrs.__expanded : !expandNode.attrs.__expanded;
19
22
  bindKeymapWithCommand(
20
23
  // Ignored via go/ees005
21
24
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -206,7 +209,13 @@ export function expandKeymap(api, options) {
206
209
  // @see ED-7977
207
210
  const sel = Selection.findFrom(state.doc.resolve(Math.max(selection.$from.pos - 1, 0)), -1);
208
211
  const expandBefore = findExpand(state, sel);
209
- if (expandBefore && (expandBefore.node.type === expand || expandBefore.node.type === nestedExpand) && (options.__livePage ? expandBefore.node.attrs.__expanded : !expandBefore.node.attrs.__expanded)) {
212
+ if (expandBefore && (expandBefore.node.type === expand || expandBefore.node.type === nestedExpand) && isCollapsed(expandBefore.node)) {
213
+ if (fg('platform_editor_expand_delete_empty_line') && deleteEmptyLineAfterCollapsedExpand({
214
+ focusTitle,
215
+ isCollapsed
216
+ })(state, dispatch, editorView)) {
217
+ return true;
218
+ }
210
219
  return focusTitle(expandBefore.start)(state, dispatch, editorView);
211
220
  }
212
221
  return false;
@@ -15,7 +15,7 @@ import { Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
15
15
  import { findParentNodeOfType, safeInsert } from '@atlaskit/editor-prosemirror/utils';
16
16
  import { findTable } from '@atlaskit/editor-tables/utils';
17
17
  import { fg } from '@atlaskit/platform-feature-flags/fg';
18
- import { isNestedInExpand } from '../utils';
18
+ import { getExpandWrapper, isNestedInExpand } from '../utils';
19
19
 
20
20
  // Creates either an expand or a nestedExpand node based on the current selection
21
21
  export const createExpandNode = (state, setExpandedState = true, addLocalId) => {
@@ -209,8 +209,7 @@ export const updateExpandTitle = ({
209
209
  };
210
210
  export const focusTitle = pos => (state, dispatch, editorView) => {
211
211
  if (editorView) {
212
- const dom = editorView.domAtPos(pos);
213
- const expandWrapper = dom.node.parentElement;
212
+ const expandWrapper = getExpandWrapper(editorView, pos);
214
213
  if (expandWrapper) {
215
214
  setSelectionInsideExpand(pos)(state, dispatch, editorView);
216
215
  const input = expandWrapper.querySelector('input');
@@ -8,7 +8,9 @@ import { isEmptyNode, isPositionNearTableRow } from '@atlaskit/editor-common/uti
8
8
  import { keymap } from '@atlaskit/editor-prosemirror/keymap';
9
9
  import { NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
10
10
  import { isInTable } from '@atlaskit/editor-tables/utils';
11
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
11
12
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
13
+ import { deleteEmptyLineAfterCollapsedExpand } from '../../editor-commands/deleteEmptyLineAfterCollapsedExpand';
12
14
  import { deleteExpand, focusIcon, focusTitle } from '../commands';
13
15
  const isExpandNode = node => {
14
16
  return (node === null || node === void 0 ? void 0 : node.type.name) === 'expand' || (node === null || node === void 0 ? void 0 : node.type.name) === 'nestedExpand';
@@ -207,6 +209,12 @@ export function expandKeymap(api) {
207
209
  const sel = Selection.findFrom(state.doc.resolve(Math.max(selection.$from.pos - 1, 0)), -1);
208
210
  const expandBefore = findExpand(state, sel);
209
211
  if (expandBefore && (expandBefore.node.type === expand || expandBefore.node.type === nestedExpand) && isExpandCollapsed(expandBefore.node)) {
212
+ if (fg('platform_editor_expand_delete_empty_line') && deleteEmptyLineAfterCollapsedExpand({
213
+ focusTitle,
214
+ isCollapsed: isExpandCollapsed
215
+ })(state, dispatch, editorView)) {
216
+ return true;
217
+ }
210
218
  return focusTitle(expandBefore.start)(state, dispatch, editorView);
211
219
  }
212
220
  return false;
@@ -1,2 +1,11 @@
1
1
  import { hasParentNode } from '@atlaskit/editor-prosemirror/utils';
2
- export const isNestedInExpand = state => hasParentNode(node => node.type === state.schema.nodes.expand || node.type === state.schema.nodes.nestedExpand)(state.selection);
2
+ export const isNestedInExpand = state => hasParentNode(node => node.type === state.schema.nodes.expand || node.type === state.schema.nodes.nestedExpand)(state.selection);
3
+
4
+ /** The element wrapping an expand's title and content, found from a position inside its content. */
5
+ export const getExpandWrapper = (editorView, pos) => editorView.domAtPos(pos).node.parentElement;
6
+
7
+ /** The title input of the expand whose content contains `pos`. */
8
+ export const getExpandTitleInput = (editorView, pos) => {
9
+ var _getExpandWrapper$que, _getExpandWrapper;
10
+ return (_getExpandWrapper$que = (_getExpandWrapper = getExpandWrapper(editorView, pos)) === null || _getExpandWrapper === void 0 ? void 0 : _getExpandWrapper.querySelector('input')) !== null && _getExpandWrapper$que !== void 0 ? _getExpandWrapper$que : null;
11
+ };
@@ -0,0 +1,75 @@
1
+ import { Selection } from '@atlaskit/editor-prosemirror/state';
2
+ import { getExpandTitleInput } from '../utils';
3
+ /**
4
+ * The empty paragraph holding the caret, when its previous sibling is a collapsed expand or nested
5
+ * expand and it is not the last child of its container. The last child is kept so there is always a
6
+ * line to type in after the expand.
7
+ */
8
+ var getEmptyLineAfterCollapsedExpand = function getEmptyLineAfterCollapsedExpand(state, isCollapsed) {
9
+ var $from = state.selection.$from;
10
+ var _state$schema$nodes = state.schema.nodes,
11
+ paragraph = _state$schema$nodes.paragraph,
12
+ expand = _state$schema$nodes.expand,
13
+ nestedExpand = _state$schema$nodes.nestedExpand;
14
+ var textblock = $from.parent;
15
+ if (textblock.type !== paragraph || textblock.content.size > 0) {
16
+ return undefined;
17
+ }
18
+ var container = $from.node(-1);
19
+ var index = $from.index(-1);
20
+ var isLastChild = index === container.childCount - 1;
21
+ if (index === 0 || isLastChild) {
22
+ return undefined;
23
+ }
24
+ var previousSibling = container.child(index - 1);
25
+ var isExpand = previousSibling.type === expand || previousSibling.type === nestedExpand;
26
+ if (!isExpand || !isCollapsed(previousSibling)) {
27
+ return undefined;
28
+ }
29
+ var lineStart = $from.before();
30
+ return {
31
+ expandContentStart: lineStart - previousSibling.nodeSize + 1,
32
+ lineStart: lineStart,
33
+ lineEnd: $from.after()
34
+ };
35
+ };
36
+ /**
37
+ * Backspace in an empty line directly after a collapsed expand: deletes the line and moves focus to
38
+ * the end of the expand title, in one transaction. Returns false, without changing anything, when
39
+ * the caret is anywhere else or the title input cannot be found, so other Backspace handling runs.
40
+ */
41
+ export var deleteEmptyLineAfterCollapsedExpand = function deleteEmptyLineAfterCollapsedExpand(_ref) {
42
+ var focusTitle = _ref.focusTitle,
43
+ isCollapsed = _ref.isCollapsed;
44
+ return function (state, dispatch, editorView) {
45
+ if (!editorView || !state.selection.empty) {
46
+ return false;
47
+ }
48
+ var emptyLine = getEmptyLineAfterCollapsedExpand(state, isCollapsed);
49
+ if (!emptyLine) {
50
+ return false;
51
+ }
52
+ var titleInput = getExpandTitleInput(editorView, emptyLine.expandContentStart);
53
+ if (!titleInput) {
54
+ return false;
55
+ }
56
+ if (!dispatch) {
57
+ return true;
58
+ }
59
+ var tr = state.tr.delete(emptyLine.lineStart, emptyLine.lineEnd);
60
+ var selectionInsideExpand = Selection.findFrom(tr.doc.resolve(emptyLine.expandContentStart), 1, true);
61
+ if (selectionInsideExpand) {
62
+ tr.setSelection(selectionInsideExpand);
63
+ }
64
+ dispatch(tr);
65
+ var titleInputAfterDelete = getExpandTitleInput(editorView, emptyLine.expandContentStart);
66
+ if (!(titleInputAfterDelete !== null && titleInputAfterDelete !== void 0 && titleInputAfterDelete.isConnected)) {
67
+ focusTitle(emptyLine.expandContentStart)(editorView.state, dispatch, editorView);
68
+ return true;
69
+ }
70
+ titleInputAfterDelete.focus();
71
+ var titleEnd = titleInputAfterDelete.value.length;
72
+ titleInputAfterDelete.setSelectionRange(titleEnd, titleEnd);
73
+ return true;
74
+ };
75
+ };
@@ -12,7 +12,7 @@ import { createWrapSelectionTransaction } from '@atlaskit/editor-common/utils/cr
12
12
  import { Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
13
13
  import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
14
14
  import { findTable } from '@atlaskit/editor-tables/utils';
15
- import { isNestedInExpand } from '../utils';
15
+ import { getExpandWrapper, isNestedInExpand } from '../utils';
16
16
  import { createCommand } from './pm-plugins/plugin-factory';
17
17
  export var setExpandRef = function setExpandRef(ref) {
18
18
  return createCommand({
@@ -182,8 +182,7 @@ export var insertExpand = function insertExpand(editorAnalyticsAPI) {
182
182
  export var focusTitle = function focusTitle(pos) {
183
183
  return function (state, dispatch, editorView) {
184
184
  if (editorView) {
185
- var dom = editorView.domAtPos(pos);
186
- var expandWrapper = dom.node.parentElement;
185
+ var expandWrapper = getExpandWrapper(editorView, pos);
187
186
  if (expandWrapper) {
188
187
  setSelectionInsideExpand(pos)(state, dispatch, editorView);
189
188
  var input = expandWrapper.querySelector('input');
@@ -8,7 +8,9 @@ import { isEmptyNode, isPositionNearTableRow } from '@atlaskit/editor-common/uti
8
8
  import { keymap } from '@atlaskit/editor-prosemirror/keymap';
9
9
  import { NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
10
10
  import { isInTable } from '@atlaskit/editor-tables/utils';
11
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
11
12
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
13
+ import { deleteEmptyLineAfterCollapsedExpand } from '../../editor-commands/deleteEmptyLineAfterCollapsedExpand';
12
14
  import { deleteExpand, focusIcon, focusTitle } from '../commands';
13
15
  var isExpandNode = function isExpandNode(node) {
14
16
  return (node === null || node === void 0 ? void 0 : node.type.name) === 'expand' || (node === null || node === void 0 ? void 0 : node.type.name) === 'nestedExpand';
@@ -18,6 +20,9 @@ var isExpandSelected = function isExpandSelected(selection) {
18
20
  };
19
21
  export function expandKeymap(api, options) {
20
22
  var list = {};
23
+ var isCollapsed = function isCollapsed(expandNode) {
24
+ return options.__livePage ? expandNode.attrs.__expanded : !expandNode.attrs.__expanded;
25
+ };
21
26
  bindKeymapWithCommand(
22
27
  // Ignored via go/ees005
23
28
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -176,7 +181,13 @@ export function expandKeymap(api, options) {
176
181
  // @see ED-7977
177
182
  var sel = Selection.findFrom(state.doc.resolve(Math.max(selection.$from.pos - 1, 0)), -1);
178
183
  var expandBefore = findExpand(state, sel);
179
- if (expandBefore && (expandBefore.node.type === expand || expandBefore.node.type === nestedExpand) && (options.__livePage ? expandBefore.node.attrs.__expanded : !expandBefore.node.attrs.__expanded)) {
184
+ if (expandBefore && (expandBefore.node.type === expand || expandBefore.node.type === nestedExpand) && isCollapsed(expandBefore.node)) {
185
+ if (fg('platform_editor_expand_delete_empty_line') && deleteEmptyLineAfterCollapsedExpand({
186
+ focusTitle: focusTitle,
187
+ isCollapsed: isCollapsed
188
+ })(state, dispatch, editorView)) {
189
+ return true;
190
+ }
180
191
  return focusTitle(expandBefore.start)(state, dispatch, editorView);
181
192
  }
182
193
  return false;
@@ -18,7 +18,7 @@ import { Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
18
18
  import { findParentNodeOfType, safeInsert } from '@atlaskit/editor-prosemirror/utils';
19
19
  import { findTable } from '@atlaskit/editor-tables/utils';
20
20
  import { fg } from '@atlaskit/platform-feature-flags/fg';
21
- import { isNestedInExpand } from '../utils';
21
+ import { getExpandWrapper, isNestedInExpand } from '../utils';
22
22
 
23
23
  // Creates either an expand or a nestedExpand node based on the current selection
24
24
  export var createExpandNode = function createExpandNode(state) {
@@ -222,8 +222,7 @@ export var updateExpandTitle = function updateExpandTitle(_ref2) {
222
222
  export var focusTitle = function focusTitle(pos) {
223
223
  return function (state, dispatch, editorView) {
224
224
  if (editorView) {
225
- var dom = editorView.domAtPos(pos);
226
- var expandWrapper = dom.node.parentElement;
225
+ var expandWrapper = getExpandWrapper(editorView, pos);
227
226
  if (expandWrapper) {
228
227
  setSelectionInsideExpand(pos)(state, dispatch, editorView);
229
228
  var input = expandWrapper.querySelector('input');
@@ -8,7 +8,9 @@ import { isEmptyNode, isPositionNearTableRow } from '@atlaskit/editor-common/uti
8
8
  import { keymap } from '@atlaskit/editor-prosemirror/keymap';
9
9
  import { NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
10
10
  import { isInTable } from '@atlaskit/editor-tables/utils';
11
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
11
12
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
13
+ import { deleteEmptyLineAfterCollapsedExpand } from '../../editor-commands/deleteEmptyLineAfterCollapsedExpand';
12
14
  import { deleteExpand, focusIcon, focusTitle } from '../commands';
13
15
  var isExpandNode = function isExpandNode(node) {
14
16
  return (node === null || node === void 0 ? void 0 : node.type.name) === 'expand' || (node === null || node === void 0 ? void 0 : node.type.name) === 'nestedExpand';
@@ -177,6 +179,12 @@ export function expandKeymap(api) {
177
179
  var sel = Selection.findFrom(state.doc.resolve(Math.max(selection.$from.pos - 1, 0)), -1);
178
180
  var expandBefore = findExpand(state, sel);
179
181
  if (expandBefore && (expandBefore.node.type === expand || expandBefore.node.type === nestedExpand) && isExpandCollapsed(expandBefore.node)) {
182
+ if (fg('platform_editor_expand_delete_empty_line') && deleteEmptyLineAfterCollapsedExpand({
183
+ focusTitle: focusTitle,
184
+ isCollapsed: isExpandCollapsed
185
+ })(state, dispatch, editorView)) {
186
+ return true;
187
+ }
180
188
  return focusTitle(expandBefore.start)(state, dispatch, editorView);
181
189
  }
182
190
  return false;
package/dist/esm/utils.js CHANGED
@@ -3,4 +3,15 @@ export var isNestedInExpand = function isNestedInExpand(state) {
3
3
  return hasParentNode(function (node) {
4
4
  return node.type === state.schema.nodes.expand || node.type === state.schema.nodes.nestedExpand;
5
5
  })(state.selection);
6
+ };
7
+
8
+ /** The element wrapping an expand's title and content, found from a position inside its content. */
9
+ export var getExpandWrapper = function getExpandWrapper(editorView, pos) {
10
+ return editorView.domAtPos(pos).node.parentElement;
11
+ };
12
+
13
+ /** The title input of the expand whose content contains `pos`. */
14
+ export var getExpandTitleInput = function getExpandTitleInput(editorView, pos) {
15
+ var _getExpandWrapper$que, _getExpandWrapper;
16
+ return (_getExpandWrapper$que = (_getExpandWrapper = getExpandWrapper(editorView, pos)) === null || _getExpandWrapper === void 0 ? void 0 : _getExpandWrapper.querySelector('input')) !== null && _getExpandWrapper$que !== void 0 ? _getExpandWrapper$que : null;
6
17
  };
@@ -0,0 +1,14 @@
1
+ import type { Command } from '@atlaskit/editor-common/types/command';
2
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
+ type DeleteEmptyLineAfterCollapsedExpandOptions = {
4
+ /** The plugin's own `focusTitle`, used when the title input is re-rendered by the delete. */
5
+ focusTitle: (pos: number) => Command;
6
+ isCollapsed: (expandNode: PMNode) => boolean;
7
+ };
8
+ /**
9
+ * Backspace in an empty line directly after a collapsed expand: deletes the line and moves focus to
10
+ * the end of the expand title, in one transaction. Returns false, without changing anything, when
11
+ * the caret is anywhere else or the title input cannot be found, so other Backspace handling runs.
12
+ */
13
+ export declare const deleteEmptyLineAfterCollapsedExpand: ({ focusTitle, isCollapsed }: DeleteEmptyLineAfterCollapsedExpandOptions) => Command;
14
+ export {};
@@ -1,2 +1,7 @@
1
1
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
2
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
2
3
  export declare const isNestedInExpand: (state: EditorState) => boolean;
4
+ /** The element wrapping an expand's title and content, found from a position inside its content. */
5
+ export declare const getExpandWrapper: (editorView: EditorView, pos: number) => HTMLElement | null;
6
+ /** The title input of the expand whose content contains `pos`. */
7
+ export declare const getExpandTitleInput: (editorView: EditorView, pos: number) => HTMLInputElement | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-expand",
3
- "version": "31.0.6",
3
+ "version": "31.1.0",
4
4
  "description": "Expand plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -34,7 +34,7 @@
34
34
  "@atlaskit/editor-plugin-selection": "^30.0.0",
35
35
  "@atlaskit/editor-plugin-selection-marker": "^30.0.0",
36
36
  "@atlaskit/editor-prosemirror": "^9.0.0",
37
- "@atlaskit/editor-shared-styles": "^4.6.0",
37
+ "@atlaskit/editor-shared-styles": "^5.0.0",
38
38
  "@atlaskit/editor-tables": "^3.2.0",
39
39
  "@atlaskit/editor-toolbar": "^2.8.0",
40
40
  "@atlaskit/editor-ui-control-model": "^3.0.0",
@@ -52,7 +52,7 @@
52
52
  "w3c-keyname": "^2.1.8"
53
53
  },
54
54
  "peerDependencies": {
55
- "@atlaskit/editor-common": "^134.3.0",
55
+ "@atlaskit/editor-common": "^134.4.0",
56
56
  "react": "^18.2.0 || ^19.2.0",
57
57
  "react-dom": "^18.2.0 || ^19.2.0",
58
58
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
@@ -66,6 +66,9 @@
66
66
  "platform-feature-flags": {
67
67
  "platform_editor_adf_with_localid": {
68
68
  "type": "boolean"
69
+ },
70
+ "platform_editor_expand_delete_empty_line": {
71
+ "type": "boolean"
69
72
  }
70
73
  }
71
74
  }