@atlaskit/editor-plugin-block-type 12.1.5 → 12.1.7

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,22 @@
1
1
  # @atlaskit/editor-plugin-block-type
2
2
 
3
+ ## 12.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [`9ed32aea2c1d3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9ed32aea2c1d3) -
8
+ Replace feature experiment util with cross platform alternative for platform_editor_block_menu
9
+ - Updated dependencies
10
+
11
+ ## 12.1.6
12
+
13
+ ### Patch Changes
14
+
15
+ - [`16f53ab4d1fee`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/16f53ab4d1fee) -
16
+ Fix small text conversion for nested/indented task lists and prevent fontSize mark from leaking to
17
+ sibling lists
18
+ - Updated dependencies
19
+
3
20
  ## 12.1.5
4
21
 
5
22
  ### Patch Changes
@@ -16,7 +16,6 @@ var _quickInsert = require("@atlaskit/editor-common/quick-insert");
16
16
  var _types = require("@atlaskit/editor-common/types");
17
17
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
18
18
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
19
- var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
20
19
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
21
20
  var _blockType = require("./pm-plugins/commands/block-type");
22
21
  var _inputRule = _interopRequireDefault(require("./pm-plugins/input-rule"));
@@ -139,7 +138,7 @@ var blockTypePlugin = exports.blockTypePlugin = function blockTypePlugin(_ref3)
139
138
  component: primaryToolbarComponent
140
139
  });
141
140
  }
142
- if ((0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_block_menu', 'isEnabled', true)) {
141
+ if ((0, _experiments.editorExperiment)('platform_editor_block_menu', true)) {
143
142
  var _api$blockMenu;
144
143
  api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 || _api$blockMenu.actions.registerBlockMenuComponents((0, _ui.getBlockTypeComponents)(api));
145
144
  }
@@ -145,22 +145,33 @@ function setSmallText() {
145
145
  }
146
146
  var selection = tr.selection;
147
147
  if (selection instanceof _editorTables.CellSelection) {
148
+ var mapFrom = tr.steps.length;
148
149
  selection.forEachCell(function (cell, pos) {
149
- tr.setBlockType(pos, pos + cell.nodeSize, paragraph);
150
+ var mappedPos = tr.mapping.slice(mapFrom).map(pos);
151
+ tr.setBlockType(mappedPos, mappedPos + cell.nodeSize, paragraph);
152
+ (0, _utils2.convertTaskItemsToBlockTaskItems)(tr, mappedPos, mappedPos + cell.nodeSize);
150
153
  (0, _commands.createToggleBlockMarkOnRangeNext)(fontSize, function () {
151
154
  return {
152
155
  fontSize: 'small'
153
156
  };
154
- }, [paragraph])(pos, pos + cell.nodeSize, tr);
157
+ }, [paragraph])(mappedPos, mappedPos + cell.nodeSize, tr);
155
158
  });
156
159
  } else {
160
+ // Step 1. Convert headings to paragraphs (for non-task content)
157
161
  tr.setBlockType(selection.from, selection.to, paragraph);
162
+
163
+ // Step 2. Expand the selection range to include full list nodes
158
164
  var expandedRange = (0, _utils2.getSelectionRangeExpandedToLists)(tr);
165
+
166
+ // Step 3. Convert taskItems → blockTaskItems so their content can hold the fontSize mark
167
+ (0, _utils2.convertTaskItemsToBlockTaskItems)(tr, expandedRange.from, expandedRange.to);
168
+
169
+ // Step 4. Apply fontSize mark to all paragraphs in range (including those inside new blockTaskItems)
159
170
  (0, _commands.createToggleBlockMarkOnRangeNext)(fontSize, function () {
160
171
  return {
161
172
  fontSize: 'small'
162
173
  };
163
- }, [paragraph])(expandedRange.from, expandedRange.to, tr);
174
+ }, [paragraph])(tr.mapping.map(expandedRange.from, -1), tr.mapping.map(expandedRange.to, 1), tr);
164
175
  }
165
176
  return tr;
166
177
  };
@@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.areBlockTypesDisabled = areBlockTypesDisabled;
7
- exports.createWrappingTextBlockRule = exports.createJoinNodesRule = exports.checkFormattingIsPresent = void 0;
7
+ exports.checkFormattingIsPresent = void 0;
8
+ exports.convertTaskItemsToBlockTaskItems = convertTaskItemsToBlockTaskItems;
9
+ exports.createWrappingTextBlockRule = exports.createJoinNodesRule = void 0;
8
10
  exports.getSelectionRangeExpandedToLists = getSelectionRangeExpandedToLists;
9
11
  exports.isNodeAWrappingBlockNode = exports.hasBlockQuoteInOptions = void 0;
10
12
  exports.isSelectionInsideListNode = isSelectionInsideListNode;
@@ -91,12 +93,10 @@ function areBlockTypesDisabled(state) {
91
93
  blockquote = _state$schema$nodes2.blockquote,
92
94
  bulletList = _state$schema$nodes2.bulletList,
93
95
  orderedList = _state$schema$nodes2.orderedList,
94
- listItem = _state$schema$nodes2.listItem;
95
-
96
- // When the small font size experiment is enabled, allow block type changes inside lists
97
- // so that users can toggle between Normal text and Small text within list contexts.
98
- // Note: taskList/taskItem are not excluded here until blockTaskItem conversion is implemented (WI 4).
99
- var excludedTypes = allowFontSize && (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem] : [panel];
96
+ listItem = _state$schema$nodes2.listItem,
97
+ taskList = _state$schema$nodes2.taskList,
98
+ taskItem = _state$schema$nodes2.taskItem;
99
+ var excludedTypes = allowFontSize && (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem, taskList, taskItem] : [panel];
100
100
  if ((0, _experiments.editorExperiment)('platform_editor_blockquote_in_text_formatting_menu', true)) {
101
101
  var hasQuote = false;
102
102
  var hasNestedListInQuote = false;
@@ -206,22 +206,75 @@ function getSelectionRangeExpandedToLists(tr) {
206
206
  var listNodeTypes = [bulletList, orderedList, taskList];
207
207
  var from = selection.from;
208
208
  var to = selection.to;
209
+
210
+ // Walk up from the selection start to find the outermost list node.
211
+ // We do NOT break at the first list found because task lists nest differently
212
+ // from bullet/ordered lists:
213
+ // - bullet/ordered: bulletList > listItem > bulletList (nested inside listItem)
214
+ // - task: taskList > taskList (nested as direct children)
215
+ // For task lists, breaking at the first list would only capture the innermost
216
+ // taskList, missing sibling task items in parent lists. By continuing to walk
217
+ // up, we find the outermost list and include all nested content.
209
218
  for (var depth = selection.$from.depth; depth > 0; depth--) {
210
219
  var node = selection.$from.node(depth);
211
220
  if (listNodeTypes.indexOf(node.type) >= 0) {
212
221
  from = selection.$from.before(depth);
213
- break;
214
222
  }
215
223
  }
216
224
  for (var _depth = selection.$to.depth; _depth > 0; _depth--) {
217
225
  var _node = selection.$to.node(_depth);
218
226
  if (listNodeTypes.indexOf(_node.type) >= 0) {
219
227
  to = selection.$to.after(_depth);
220
- break;
221
228
  }
222
229
  }
223
230
  return {
224
231
  from: from,
225
232
  to: to
226
233
  };
234
+ }
235
+
236
+ /**
237
+ * Converts all taskItem nodes within the given range to blockTaskItem nodes.
238
+ *
239
+ * taskItem nodes contain inline content directly, which cannot hold block-level
240
+ * marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
241
+ * hold block marks. This conversion is needed when applying small text formatting
242
+ * to task lists.
243
+ *
244
+ * The inline content of each taskItem is wrapped in a paragraph node, and the
245
+ * taskItem is replaced with a blockTaskItem that preserves the original attributes
246
+ * (localId, state).
247
+ *
248
+ * Collects taskItem positions in a forward pass over the unmutated document,
249
+ * then applies replacements in reverse document order so positions remain valid
250
+ * without needing remapping or doc snapshots.
251
+ */
252
+ function convertTaskItemsToBlockTaskItems(tr, from, to) {
253
+ var _tr$doc$type$schema$n2 = tr.doc.type.schema.nodes,
254
+ taskItem = _tr$doc$type$schema$n2.taskItem,
255
+ blockTaskItem = _tr$doc$type$schema$n2.blockTaskItem,
256
+ paragraph = _tr$doc$type$schema$n2.paragraph;
257
+ if (!blockTaskItem || !taskItem) {
258
+ return;
259
+ }
260
+
261
+ // Collect taskItem positions from the current (unmutated) document
262
+ var taskItemsToConvert = [];
263
+ tr.doc.nodesBetween(from, to, function (node, pos) {
264
+ if (node.type === taskItem) {
265
+ taskItemsToConvert.push({
266
+ pos: pos,
267
+ node: node
268
+ });
269
+ }
270
+ });
271
+
272
+ // Replace in reverse document order so earlier positions remain valid
273
+ for (var i = taskItemsToConvert.length - 1; i >= 0; i--) {
274
+ var _taskItemsToConvert$i = taskItemsToConvert[i],
275
+ pos = _taskItemsToConvert$i.pos,
276
+ node = _taskItemsToConvert$i.node;
277
+ var blockTaskNode = blockTaskItem.create(node.attrs, paragraph.create(null, node.content));
278
+ tr.replaceWith(pos, pos + node.nodeSize, blockTaskNode);
279
+ }
227
280
  }
@@ -7,7 +7,6 @@ import { IconHeading, IconQuote } from '@atlaskit/editor-common/quick-insert';
7
7
  import { ToolbarSize } from '@atlaskit/editor-common/types';
8
8
  import { fg } from '@atlaskit/platform-feature-flags';
9
9
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
10
- import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
11
10
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
12
11
  import { clearFormatting, insertBlockQuoteWithAnalytics, insertBlockQuoteWithAnalyticsCommand, setBlockTypeWithAnalytics } from './pm-plugins/commands/block-type';
13
12
  import inputRulePlugin from './pm-plugins/input-rule';
@@ -128,7 +127,7 @@ const blockTypePlugin = ({
128
127
  component: primaryToolbarComponent
129
128
  });
130
129
  }
131
- if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
130
+ if (editorExperiment('platform_editor_block_menu', true)) {
132
131
  var _api$blockMenu;
133
132
  api === null || api === void 0 ? void 0 : (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 ? void 0 : _api$blockMenu.actions.registerBlockMenuComponents(getBlockTypeComponents(api));
134
133
  }
@@ -6,7 +6,7 @@ import { liftTarget } from '@atlaskit/editor-prosemirror/transform';
6
6
  import { CellSelection } from '@atlaskit/editor-tables';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
8
  import { HEADINGS_BY_NAME, NORMAL_TEXT } from '../block-types';
9
- import { getSelectionRangeExpandedToLists } from '../utils';
9
+ import { convertTaskItemsToBlockTaskItems, getSelectionRangeExpandedToLists } from '../utils';
10
10
  import { FORMATTING_NODE_TYPES, FORMATTING_MARK_TYPES, cellSelectionNodesBetween, formatTypes, clearNodeFormattingOnSelection } from './clear-formatting';
11
11
  import { wrapSelectionInBlockType } from './wrapSelectionIn';
12
12
  export function setBlockType(name) {
@@ -144,18 +144,29 @@ export function setSmallText() {
144
144
  selection
145
145
  } = tr;
146
146
  if (selection instanceof CellSelection) {
147
+ const mapFrom = tr.steps.length;
147
148
  selection.forEachCell((cell, pos) => {
148
- tr.setBlockType(pos, pos + cell.nodeSize, paragraph);
149
+ const mappedPos = tr.mapping.slice(mapFrom).map(pos);
150
+ tr.setBlockType(mappedPos, mappedPos + cell.nodeSize, paragraph);
151
+ convertTaskItemsToBlockTaskItems(tr, mappedPos, mappedPos + cell.nodeSize);
149
152
  createToggleBlockMarkOnRangeNext(fontSize, () => ({
150
153
  fontSize: 'small'
151
- }), [paragraph])(pos, pos + cell.nodeSize, tr);
154
+ }), [paragraph])(mappedPos, mappedPos + cell.nodeSize, tr);
152
155
  });
153
156
  } else {
157
+ // Step 1. Convert headings to paragraphs (for non-task content)
154
158
  tr.setBlockType(selection.from, selection.to, paragraph);
159
+
160
+ // Step 2. Expand the selection range to include full list nodes
155
161
  const expandedRange = getSelectionRangeExpandedToLists(tr);
162
+
163
+ // Step 3. Convert taskItems → blockTaskItems so their content can hold the fontSize mark
164
+ convertTaskItemsToBlockTaskItems(tr, expandedRange.from, expandedRange.to);
165
+
166
+ // Step 4. Apply fontSize mark to all paragraphs in range (including those inside new blockTaskItems)
156
167
  createToggleBlockMarkOnRangeNext(fontSize, () => ({
157
168
  fontSize: 'small'
158
- }), [paragraph])(expandedRange.from, expandedRange.to, tr);
169
+ }), [paragraph])(tr.mapping.map(expandedRange.from, -1), tr.mapping.map(expandedRange.to, 1), tr);
159
170
  }
160
171
  return tr;
161
172
  };
@@ -79,13 +79,11 @@ export function areBlockTypesDisabled(state, allowFontSize = false) {
79
79
  blockquote,
80
80
  bulletList,
81
81
  orderedList,
82
- listItem
82
+ listItem,
83
+ taskList,
84
+ taskItem
83
85
  } = state.schema.nodes;
84
-
85
- // When the small font size experiment is enabled, allow block type changes inside lists
86
- // so that users can toggle between Normal text and Small text within list contexts.
87
- // Note: taskList/taskItem are not excluded here until blockTaskItem conversion is implemented (WI 4).
88
- const excludedTypes = allowFontSize && expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem] : [panel];
86
+ const excludedTypes = allowFontSize && expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem, taskList, taskItem] : [panel];
89
87
  if (editorExperiment('platform_editor_blockquote_in_text_formatting_menu', true)) {
90
88
  let hasQuote = false;
91
89
  let hasNestedListInQuote = false;
@@ -199,22 +197,79 @@ export function getSelectionRangeExpandedToLists(tr) {
199
197
  const listNodeTypes = [bulletList, orderedList, taskList];
200
198
  let from = selection.from;
201
199
  let to = selection.to;
200
+
201
+ // Walk up from the selection start to find the outermost list node.
202
+ // We do NOT break at the first list found because task lists nest differently
203
+ // from bullet/ordered lists:
204
+ // - bullet/ordered: bulletList > listItem > bulletList (nested inside listItem)
205
+ // - task: taskList > taskList (nested as direct children)
206
+ // For task lists, breaking at the first list would only capture the innermost
207
+ // taskList, missing sibling task items in parent lists. By continuing to walk
208
+ // up, we find the outermost list and include all nested content.
202
209
  for (let depth = selection.$from.depth; depth > 0; depth--) {
203
210
  const node = selection.$from.node(depth);
204
211
  if (listNodeTypes.indexOf(node.type) >= 0) {
205
212
  from = selection.$from.before(depth);
206
- break;
207
213
  }
208
214
  }
209
215
  for (let depth = selection.$to.depth; depth > 0; depth--) {
210
216
  const node = selection.$to.node(depth);
211
217
  if (listNodeTypes.indexOf(node.type) >= 0) {
212
218
  to = selection.$to.after(depth);
213
- break;
214
219
  }
215
220
  }
216
221
  return {
217
222
  from,
218
223
  to
219
224
  };
225
+ }
226
+
227
+ /**
228
+ * Converts all taskItem nodes within the given range to blockTaskItem nodes.
229
+ *
230
+ * taskItem nodes contain inline content directly, which cannot hold block-level
231
+ * marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
232
+ * hold block marks. This conversion is needed when applying small text formatting
233
+ * to task lists.
234
+ *
235
+ * The inline content of each taskItem is wrapped in a paragraph node, and the
236
+ * taskItem is replaced with a blockTaskItem that preserves the original attributes
237
+ * (localId, state).
238
+ *
239
+ * Collects taskItem positions in a forward pass over the unmutated document,
240
+ * then applies replacements in reverse document order so positions remain valid
241
+ * without needing remapping or doc snapshots.
242
+ */
243
+ export function convertTaskItemsToBlockTaskItems(tr, from, to) {
244
+ const {
245
+ nodes: {
246
+ taskItem,
247
+ blockTaskItem,
248
+ paragraph
249
+ }
250
+ } = tr.doc.type.schema;
251
+ if (!blockTaskItem || !taskItem) {
252
+ return;
253
+ }
254
+
255
+ // Collect taskItem positions from the current (unmutated) document
256
+ const taskItemsToConvert = [];
257
+ tr.doc.nodesBetween(from, to, (node, pos) => {
258
+ if (node.type === taskItem) {
259
+ taskItemsToConvert.push({
260
+ pos,
261
+ node
262
+ });
263
+ }
264
+ });
265
+
266
+ // Replace in reverse document order so earlier positions remain valid
267
+ for (let i = taskItemsToConvert.length - 1; i >= 0; i--) {
268
+ const {
269
+ pos,
270
+ node
271
+ } = taskItemsToConvert[i];
272
+ const blockTaskNode = blockTaskItem.create(node.attrs, paragraph.create(null, node.content));
273
+ tr.replaceWith(pos, pos + node.nodeSize, blockTaskNode);
274
+ }
220
275
  }
@@ -11,7 +11,6 @@ import { IconHeading, IconQuote } from '@atlaskit/editor-common/quick-insert';
11
11
  import { ToolbarSize } from '@atlaskit/editor-common/types';
12
12
  import { fg } from '@atlaskit/platform-feature-flags';
13
13
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
14
- import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
15
14
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
16
15
  import { clearFormatting as _clearFormatting, insertBlockQuoteWithAnalytics, insertBlockQuoteWithAnalyticsCommand, setBlockTypeWithAnalytics } from './pm-plugins/commands/block-type';
17
16
  import inputRulePlugin from './pm-plugins/input-rule';
@@ -132,7 +131,7 @@ var blockTypePlugin = function blockTypePlugin(_ref3) {
132
131
  component: primaryToolbarComponent
133
132
  });
134
133
  }
135
- if (expValEqualsNoExposure('platform_editor_block_menu', 'isEnabled', true)) {
134
+ if (editorExperiment('platform_editor_block_menu', true)) {
136
135
  var _api$blockMenu;
137
136
  api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 || _api$blockMenu.actions.registerBlockMenuComponents(getBlockTypeComponents(api));
138
137
  }
@@ -9,7 +9,7 @@ import { liftTarget } from '@atlaskit/editor-prosemirror/transform';
9
9
  import { CellSelection } from '@atlaskit/editor-tables';
10
10
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
11
11
  import { HEADINGS_BY_NAME, NORMAL_TEXT } from '../block-types';
12
- import { getSelectionRangeExpandedToLists } from '../utils';
12
+ import { convertTaskItemsToBlockTaskItems, getSelectionRangeExpandedToLists } from '../utils';
13
13
  import { FORMATTING_NODE_TYPES, FORMATTING_MARK_TYPES, cellSelectionNodesBetween, formatTypes, clearNodeFormattingOnSelection } from './clear-formatting';
14
14
  import { wrapSelectionInBlockType } from './wrapSelectionIn';
15
15
  export function setBlockType(name) {
@@ -128,22 +128,33 @@ export function setSmallText() {
128
128
  }
129
129
  var selection = tr.selection;
130
130
  if (selection instanceof CellSelection) {
131
+ var mapFrom = tr.steps.length;
131
132
  selection.forEachCell(function (cell, pos) {
132
- tr.setBlockType(pos, pos + cell.nodeSize, paragraph);
133
+ var mappedPos = tr.mapping.slice(mapFrom).map(pos);
134
+ tr.setBlockType(mappedPos, mappedPos + cell.nodeSize, paragraph);
135
+ convertTaskItemsToBlockTaskItems(tr, mappedPos, mappedPos + cell.nodeSize);
133
136
  createToggleBlockMarkOnRangeNext(fontSize, function () {
134
137
  return {
135
138
  fontSize: 'small'
136
139
  };
137
- }, [paragraph])(pos, pos + cell.nodeSize, tr);
140
+ }, [paragraph])(mappedPos, mappedPos + cell.nodeSize, tr);
138
141
  });
139
142
  } else {
143
+ // Step 1. Convert headings to paragraphs (for non-task content)
140
144
  tr.setBlockType(selection.from, selection.to, paragraph);
145
+
146
+ // Step 2. Expand the selection range to include full list nodes
141
147
  var expandedRange = getSelectionRangeExpandedToLists(tr);
148
+
149
+ // Step 3. Convert taskItems → blockTaskItems so their content can hold the fontSize mark
150
+ convertTaskItemsToBlockTaskItems(tr, expandedRange.from, expandedRange.to);
151
+
152
+ // Step 4. Apply fontSize mark to all paragraphs in range (including those inside new blockTaskItems)
142
153
  createToggleBlockMarkOnRangeNext(fontSize, function () {
143
154
  return {
144
155
  fontSize: 'small'
145
156
  };
146
- }, [paragraph])(expandedRange.from, expandedRange.to, tr);
157
+ }, [paragraph])(tr.mapping.map(expandedRange.from, -1), tr.mapping.map(expandedRange.to, 1), tr);
147
158
  }
148
159
  return tr;
149
160
  };
@@ -81,12 +81,10 @@ export function areBlockTypesDisabled(state) {
81
81
  blockquote = _state$schema$nodes2.blockquote,
82
82
  bulletList = _state$schema$nodes2.bulletList,
83
83
  orderedList = _state$schema$nodes2.orderedList,
84
- listItem = _state$schema$nodes2.listItem;
85
-
86
- // When the small font size experiment is enabled, allow block type changes inside lists
87
- // so that users can toggle between Normal text and Small text within list contexts.
88
- // Note: taskList/taskItem are not excluded here until blockTaskItem conversion is implemented (WI 4).
89
- var excludedTypes = allowFontSize && expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem] : [panel];
84
+ listItem = _state$schema$nodes2.listItem,
85
+ taskList = _state$schema$nodes2.taskList,
86
+ taskItem = _state$schema$nodes2.taskItem;
87
+ var excludedTypes = allowFontSize && expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem, taskList, taskItem] : [panel];
90
88
  if (editorExperiment('platform_editor_blockquote_in_text_formatting_menu', true)) {
91
89
  var hasQuote = false;
92
90
  var hasNestedListInQuote = false;
@@ -196,22 +194,75 @@ export function getSelectionRangeExpandedToLists(tr) {
196
194
  var listNodeTypes = [bulletList, orderedList, taskList];
197
195
  var from = selection.from;
198
196
  var to = selection.to;
197
+
198
+ // Walk up from the selection start to find the outermost list node.
199
+ // We do NOT break at the first list found because task lists nest differently
200
+ // from bullet/ordered lists:
201
+ // - bullet/ordered: bulletList > listItem > bulletList (nested inside listItem)
202
+ // - task: taskList > taskList (nested as direct children)
203
+ // For task lists, breaking at the first list would only capture the innermost
204
+ // taskList, missing sibling task items in parent lists. By continuing to walk
205
+ // up, we find the outermost list and include all nested content.
199
206
  for (var depth = selection.$from.depth; depth > 0; depth--) {
200
207
  var node = selection.$from.node(depth);
201
208
  if (listNodeTypes.indexOf(node.type) >= 0) {
202
209
  from = selection.$from.before(depth);
203
- break;
204
210
  }
205
211
  }
206
212
  for (var _depth = selection.$to.depth; _depth > 0; _depth--) {
207
213
  var _node = selection.$to.node(_depth);
208
214
  if (listNodeTypes.indexOf(_node.type) >= 0) {
209
215
  to = selection.$to.after(_depth);
210
- break;
211
216
  }
212
217
  }
213
218
  return {
214
219
  from: from,
215
220
  to: to
216
221
  };
222
+ }
223
+
224
+ /**
225
+ * Converts all taskItem nodes within the given range to blockTaskItem nodes.
226
+ *
227
+ * taskItem nodes contain inline content directly, which cannot hold block-level
228
+ * marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
229
+ * hold block marks. This conversion is needed when applying small text formatting
230
+ * to task lists.
231
+ *
232
+ * The inline content of each taskItem is wrapped in a paragraph node, and the
233
+ * taskItem is replaced with a blockTaskItem that preserves the original attributes
234
+ * (localId, state).
235
+ *
236
+ * Collects taskItem positions in a forward pass over the unmutated document,
237
+ * then applies replacements in reverse document order so positions remain valid
238
+ * without needing remapping or doc snapshots.
239
+ */
240
+ export function convertTaskItemsToBlockTaskItems(tr, from, to) {
241
+ var _tr$doc$type$schema$n2 = tr.doc.type.schema.nodes,
242
+ taskItem = _tr$doc$type$schema$n2.taskItem,
243
+ blockTaskItem = _tr$doc$type$schema$n2.blockTaskItem,
244
+ paragraph = _tr$doc$type$schema$n2.paragraph;
245
+ if (!blockTaskItem || !taskItem) {
246
+ return;
247
+ }
248
+
249
+ // Collect taskItem positions from the current (unmutated) document
250
+ var taskItemsToConvert = [];
251
+ tr.doc.nodesBetween(from, to, function (node, pos) {
252
+ if (node.type === taskItem) {
253
+ taskItemsToConvert.push({
254
+ pos: pos,
255
+ node: node
256
+ });
257
+ }
258
+ });
259
+
260
+ // Replace in reverse document order so earlier positions remain valid
261
+ for (var i = taskItemsToConvert.length - 1; i >= 0; i--) {
262
+ var _taskItemsToConvert$i = taskItemsToConvert[i],
263
+ pos = _taskItemsToConvert$i.pos,
264
+ node = _taskItemsToConvert$i.node;
265
+ var blockTaskNode = blockTaskItem.create(node.attrs, paragraph.create(null, node.content));
266
+ tr.replaceWith(pos, pos + node.nodeSize, blockTaskNode);
267
+ }
217
268
  }
@@ -26,10 +26,11 @@ export interface BlockTypePluginOptions {
26
26
  exclude?: Array<AllowedBlockTypes>;
27
27
  };
28
28
  /**
29
- * Add ability to enable/disable the font size feature which. Currently only 'small text' is supported.
29
+ * Add ability to toggle paragraph size variations.
30
30
  *
31
31
  * Note: Feature is in development and logic is under an experiment.
32
32
  * Note: `fontSize` mark must be supported in the ADF schema for this feature to work.
33
+ * Note: To support fontSize variatons in tasks, allowBlockTaskItem must be enabled for tasksAndDecisionsPlugin
33
34
  */
34
35
  allowFontSize?: boolean;
35
36
  includeBlockQuoteAsTextstyleOption?: boolean;
@@ -32,4 +32,21 @@ export declare function getSelectionRangeExpandedToLists(tr: Transaction): {
32
32
  from: number;
33
33
  to: number;
34
34
  };
35
+ /**
36
+ * Converts all taskItem nodes within the given range to blockTaskItem nodes.
37
+ *
38
+ * taskItem nodes contain inline content directly, which cannot hold block-level
39
+ * marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
40
+ * hold block marks. This conversion is needed when applying small text formatting
41
+ * to task lists.
42
+ *
43
+ * The inline content of each taskItem is wrapped in a paragraph node, and the
44
+ * taskItem is replaced with a blockTaskItem that preserves the original attributes
45
+ * (localId, state).
46
+ *
47
+ * Collects taskItem positions in a forward pass over the unmutated document,
48
+ * then applies replacements in reverse document order so positions remain valid
49
+ * without needing remapping or doc snapshots.
50
+ */
51
+ export declare function convertTaskItemsToBlockTaskItems(tr: Transaction, from: number, to: number): void;
35
52
  export {};
@@ -26,10 +26,11 @@ export interface BlockTypePluginOptions {
26
26
  exclude?: Array<AllowedBlockTypes>;
27
27
  };
28
28
  /**
29
- * Add ability to enable/disable the font size feature which. Currently only 'small text' is supported.
29
+ * Add ability to toggle paragraph size variations.
30
30
  *
31
31
  * Note: Feature is in development and logic is under an experiment.
32
32
  * Note: `fontSize` mark must be supported in the ADF schema for this feature to work.
33
+ * Note: To support fontSize variatons in tasks, allowBlockTaskItem must be enabled for tasksAndDecisionsPlugin
33
34
  */
34
35
  allowFontSize?: boolean;
35
36
  includeBlockQuoteAsTextstyleOption?: boolean;
@@ -32,4 +32,21 @@ export declare function getSelectionRangeExpandedToLists(tr: Transaction): {
32
32
  from: number;
33
33
  to: number;
34
34
  };
35
+ /**
36
+ * Converts all taskItem nodes within the given range to blockTaskItem nodes.
37
+ *
38
+ * taskItem nodes contain inline content directly, which cannot hold block-level
39
+ * marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
40
+ * hold block marks. This conversion is needed when applying small text formatting
41
+ * to task lists.
42
+ *
43
+ * The inline content of each taskItem is wrapped in a paragraph node, and the
44
+ * taskItem is replaced with a blockTaskItem that preserves the original attributes
45
+ * (localId, state).
46
+ *
47
+ * Collects taskItem positions in a forward pass over the unmutated document,
48
+ * then applies replacements in reverse document order so positions remain valid
49
+ * without needing remapping or doc snapshots.
50
+ */
51
+ export declare function convertTaskItemsToBlockTaskItems(tr: Transaction, from: number, to: number): void;
35
52
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-type",
3
- "version": "12.1.5",
3
+ "version": "12.1.7",
4
4
  "description": "BlockType plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -50,7 +50,7 @@
50
50
  "@atlaskit/prosemirror-history": "^0.2.0",
51
51
  "@atlaskit/prosemirror-input-rules": "^3.6.0",
52
52
  "@atlaskit/theme": "^22.0.0",
53
- "@atlaskit/tmp-editor-statsig": "^42.0.0",
53
+ "@atlaskit/tmp-editor-statsig": "^43.0.0",
54
54
  "@atlaskit/tokens": "^11.1.0",
55
55
  "@babel/runtime": "^7.0.0",
56
56
  "@compiled/react": "^0.20.0",