@atlaskit/editor-plugin-list 8.1.2 → 8.1.3

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,13 @@
1
1
  # @atlaskit/editor-plugin-list
2
2
 
3
+ ## 8.1.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [`8abe663d8d5db`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8abe663d8d5db) -
8
+ Add new list decorations logic
9
+ - Updated dependencies
10
+
3
11
  ## 8.1.2
4
12
 
5
13
  ### Patch Changes
@@ -330,7 +338,6 @@
330
338
  shared context or singletons.
331
339
 
332
340
  **HOW TO ADJUST:**
333
-
334
341
  - Consumers must now explicitly install `@atlaskit/editor-common` in their own project if they use
335
342
  any of these editor plugins.
336
343
  - Ensure the version you install matches the version required by the plugins.
@@ -1008,7 +1015,6 @@
1008
1015
 
1009
1016
  These are no longer available via `@atlaskit/prosemirror-input-rules` but are available from
1010
1017
  `@atlaskit/editor-common/types`:
1011
-
1012
1018
  - InputRuleWrapper
1013
1019
  - InputRuleHandler
1014
1020
  - OnHandlerApply
@@ -1018,7 +1024,6 @@
1018
1024
  need to instantiate a `SafePlugin` (ie. `new SafePlugin(createPlugin( ... ))`).
1019
1025
 
1020
1026
  `SafePlugin` exists in `@atlaskit/editor-common/safe-plugin`.
1021
-
1022
1027
  - createPlugin
1023
1028
  - createInputRulePlugin
1024
1029
 
@@ -1229,19 +1234,13 @@
1229
1234
  auto-join lists together if the order numbers match up.
1230
1235
 
1231
1236
  Eg.
1232
-
1233
1237
  1. A list item
1234
-
1235
1238
  -
1236
-
1237
1239
  50. Another list item
1238
1240
 
1239
1241
  Should NOT auto join to be 1 & 2 in a single list however...
1240
-
1241
1242
  49. A list item
1242
-
1243
1243
  -
1244
-
1245
1244
  50. Another list item
1246
1245
 
1247
1246
  Should join to be 49 & 50 in a single list.
@@ -1263,7 +1262,6 @@
1263
1262
  - [#43646](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43646)
1264
1263
  [`d43f8e9402f`](https://bitbucket.org/atlassian/atlassian-frontend/commits/d43f8e9402f) - Make
1265
1264
  feature flags plugin optional in all plugins including:
1266
-
1267
1265
  - analytics
1268
1266
  - base
1269
1267
  - card
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.pluginKey = exports.getDecorations = exports.createPlugin = void 0;
7
+ exports.updateListDecorations = exports.pluginKey = exports.getDecorations = exports.createPlugin = exports.computeListDecorations = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
10
10
  var _selection = require("@atlaskit/editor-common/selection");
@@ -13,6 +13,7 @@ var _utils = require("@atlaskit/editor-common/utils");
13
13
  var _state = require("@atlaskit/editor-prosemirror/state");
14
14
  var _utils2 = require("@atlaskit/editor-prosemirror/utils");
15
15
  var _view = require("@atlaskit/editor-prosemirror/view");
16
+ var _insm = require("@atlaskit/insm");
16
17
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
17
18
  var _selection2 = require("./utils/selection");
18
19
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
@@ -26,6 +27,79 @@ var initialState = {
26
27
  orderedListDisabled: false,
27
28
  decorationSet: _view.DecorationSet.empty
28
29
  };
30
+ var computeListDecorations = exports.computeListDecorations = function computeListDecorations(doc) {
31
+ var from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
32
+ var to = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : doc.content.size;
33
+ var decorations = [];
34
+
35
+ // this stack keeps track of each (nested) list to calculate the indentation level
36
+ var processedListsStack = [];
37
+ doc.nodesBetween(from, to, function (node, currentNodeStartPos) {
38
+ if (processedListsStack.length > 0) {
39
+ var isOutsideLastList = true;
40
+ while (isOutsideLastList && processedListsStack.length > 0) {
41
+ var lastList = processedListsStack[processedListsStack.length - 1];
42
+ var lastListEndPos = lastList.startPos + lastList.node.nodeSize;
43
+ isOutsideLastList = currentNodeStartPos >= lastListEndPos;
44
+ // once we finish iterating over each innermost list, pop the stack to
45
+ // decrease the indent level attribute accordingly
46
+ if (isOutsideLastList) {
47
+ processedListsStack.pop();
48
+ }
49
+ }
50
+ }
51
+ if ((0, _utils.isListNode)(node)) {
52
+ processedListsStack.push({
53
+ node: node,
54
+ startPos: currentNodeStartPos
55
+ });
56
+ var _from = currentNodeStartPos;
57
+ var _to = currentNodeStartPos + node.nodeSize;
58
+ var depth = processedListsStack.length;
59
+ decorations.push(_view.Decoration.node(_from, _to, {
60
+ 'data-indent-level': "".concat(depth)
61
+ }));
62
+ if (node.type.name === 'orderedList') {
63
+ var _node$attrs;
64
+ // If a numbered list has item counters numbering >= 100, we'll need to add special
65
+ // spacing to account for the extra digit chars
66
+ var digitsSize = (0, _utils.getItemCounterDigitsSize)({
67
+ itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
68
+ order: node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.order
69
+ });
70
+ if (digitsSize && digitsSize > 1) {
71
+ decorations.push(_view.Decoration.node(_from, _to, {
72
+ style: (0, _styles.getOrderedListInlineStyles)(digitsSize, 'string')
73
+ }));
74
+ }
75
+ }
76
+ }
77
+ });
78
+ return decorations;
79
+ };
80
+ var updateListDecorations = exports.updateListDecorations = function updateListDecorations(decorationSet, tr) {
81
+ var nextDecorationSet = decorationSet.map(tr.mapping, tr.doc);
82
+ tr.mapping.maps.forEach(function (stepMap, index) {
83
+ stepMap.forEach(function (oldStart, oldEnd) {
84
+ var start = tr.mapping.slice(index).map(oldStart, -1);
85
+ var end = tr.mapping.slice(index).map(oldEnd);
86
+
87
+ // Remove decorations in this range
88
+ var decorationsToRemove = nextDecorationSet.find(start, end);
89
+ nextDecorationSet = nextDecorationSet.remove(decorationsToRemove);
90
+
91
+ // Recompute decorations for this range
92
+ // Expand the range by 1 on each side to catch adjacent list nodes
93
+ var from = Math.max(0, start - 1);
94
+ var to = Math.min(tr.doc.content.size, end + 1);
95
+ var decorationsToAdd = computeListDecorations(tr.doc, from, to);
96
+ nextDecorationSet = nextDecorationSet.add(tr.doc, decorationsToAdd);
97
+ });
98
+ });
99
+ return nextDecorationSet;
100
+ };
101
+
102
+ // delete getDecorations during platform_editor_new_list_decorations_logic experiment clean up
29
103
  var getDecorations = exports.getDecorations = function getDecorations(doc, state, featureFlags) {
30
104
  var decorations = [];
31
105
 
@@ -57,12 +131,12 @@ var getDecorations = exports.getDecorations = function getDecorations(doc, state
57
131
  'data-indent-level': "".concat(depth)
58
132
  }));
59
133
  if (node.type.name === 'orderedList') {
60
- var _node$attrs;
134
+ var _node$attrs2;
61
135
  // If a numbered list has item counters numbering >= 100, we'll need to add special
62
136
  // spacing to account for the extra digit chars
63
137
  var digitsSize = (0, _utils.getItemCounterDigitsSize)({
64
138
  itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
65
- order: node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.order
139
+ order: node === null || node === void 0 || (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.order
66
140
  });
67
141
  if (digitsSize && digitsSize > 1) {
68
142
  decorations.push(_view.Decoration.node(from, to, {
@@ -125,8 +199,15 @@ var reducer = function reducer() {
125
199
  var createInitialState = function createInitialState(featureFlags, api) {
126
200
  return function (state) {
127
201
  var isToolbarAIFCEnabled = Boolean(api === null || api === void 0 ? void 0 : api.toolbar);
202
+ var getInitialDecorations = function getInitialDecorations() {
203
+ var _insm$session, _insm$session2;
204
+ (_insm$session = _insm.insm.session) === null || _insm$session === void 0 || _insm$session.startFeature('listDecorationsInit');
205
+ var decorations = computeListDecorations(state.doc);
206
+ (_insm$session2 = _insm.insm.session) === null || _insm$session2 === void 0 || _insm$session2.endFeature('listDecorationsInit');
207
+ return decorations;
208
+ };
128
209
  return _objectSpread(_objectSpread({}, isToolbarAIFCEnabled && (0, _expValEquals.expValEquals)('platform_editor_toolbar_aifc_patch_3', 'isEnabled', true) ? getListState(state.doc, state.selection) : initialState), {}, {
129
- decorationSet: getDecorations(state.doc, state, featureFlags)
210
+ decorationSet: (0, _expValEquals.expValEquals)('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? _view.DecorationSet.empty.add(state.doc, getInitialDecorations()) : getDecorations(state.doc, state, featureFlags)
130
211
  });
131
212
  };
132
213
  };
@@ -137,13 +218,39 @@ var createPlugin = exports.createPlugin = function createPlugin(eventDispatch, f
137
218
  }),
138
219
  getPluginState = _pluginFactory.getPluginState,
139
220
  createPluginState = _pluginFactory.createPluginState;
221
+ var pluginState = createPluginState(eventDispatch, createInitialState(featureFlags, api));
222
+ var pluginStateInit = function pluginStateInit(_, state) {
223
+ return createInitialState(featureFlags)(state);
224
+ };
225
+ var pluginStateApply = function pluginStateApply(tr, oldPluginState, _oldEditorState, _newEditorState) {
226
+ var nextPluginState = oldPluginState;
227
+ if (tr.docChanged) {
228
+ var _insm$session3, _insm$session4;
229
+ nextPluginState = handleSelectionChanged(tr, nextPluginState);
230
+ (_insm$session3 = _insm.insm.session) === null || _insm$session3 === void 0 || _insm$session3.startFeature('listDecorationUpdate');
231
+ var nextDecorationSet = updateListDecorations(nextPluginState.decorationSet, tr);
232
+ (_insm$session4 = _insm.insm.session) === null || _insm$session4 === void 0 || _insm$session4.endFeature('listDecorationUpdate');
233
+ nextPluginState = _objectSpread(_objectSpread({}, nextPluginState), {}, {
234
+ decorationSet: nextDecorationSet
235
+ });
236
+ } else if (tr.selectionSet) {
237
+ nextPluginState = handleSelectionChanged(tr, nextPluginState);
238
+ }
239
+ if (nextPluginState !== oldPluginState) {
240
+ eventDispatch(listPluginKey, nextPluginState);
241
+ }
242
+ return nextPluginState;
243
+ };
140
244
  return new _safePlugin.SafePlugin({
141
- state: createPluginState(eventDispatch, createInitialState(featureFlags, api)),
245
+ state: {
246
+ init: (0, _expValEquals.expValEquals)('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateInit : pluginState.init,
247
+ apply: (0, _expValEquals.expValEquals)('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateApply : pluginState.apply
248
+ },
142
249
  key: listPluginKey,
143
250
  props: {
144
251
  decorations: function decorations(state) {
145
- var _getPluginState = getPluginState(state),
146
- decorationSet = _getPluginState.decorationSet;
252
+ var _ref = (0, _expValEquals.expValEquals)('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? listPluginKey.getState(state) : getPluginState(state),
253
+ decorationSet = _ref.decorationSet;
147
254
  return decorationSet;
148
255
  },
149
256
  handleClick: function handleClick(view, pos, event) {
@@ -5,6 +5,7 @@ import { getItemCounterDigitsSize, isListNode, pluginFactory } from '@atlaskit/e
5
5
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
6
  import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
7
7
  import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
+ import { insm } from '@atlaskit/insm';
8
9
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
9
10
  import { isWrappingPossible } from './utils/selection';
10
11
  const listPluginKey = new PluginKey('listPlugin');
@@ -16,12 +17,12 @@ const initialState = {
16
17
  orderedListDisabled: false,
17
18
  decorationSet: DecorationSet.empty
18
19
  };
19
- export const getDecorations = (doc, state, featureFlags) => {
20
+ export const computeListDecorations = (doc, from = 0, to = doc.content.size) => {
20
21
  const decorations = [];
21
22
 
22
23
  // this stack keeps track of each (nested) list to calculate the indentation level
23
24
  const processedListsStack = [];
24
- doc.nodesBetween(0, doc.content.size, (node, currentNodeStartPos) => {
25
+ doc.nodesBetween(from, to, (node, currentNodeStartPos) => {
25
26
  if (processedListsStack.length > 0) {
26
27
  let isOutsideLastList = true;
27
28
  while (isOutsideLastList && processedListsStack.length > 0) {
@@ -62,6 +63,77 @@ export const getDecorations = (doc, state, featureFlags) => {
62
63
  }
63
64
  }
64
65
  });
66
+ return decorations;
67
+ };
68
+ export const updateListDecorations = (decorationSet, tr) => {
69
+ let nextDecorationSet = decorationSet.map(tr.mapping, tr.doc);
70
+ tr.mapping.maps.forEach((stepMap, index) => {
71
+ stepMap.forEach((oldStart, oldEnd) => {
72
+ const start = tr.mapping.slice(index).map(oldStart, -1);
73
+ const end = tr.mapping.slice(index).map(oldEnd);
74
+
75
+ // Remove decorations in this range
76
+ const decorationsToRemove = nextDecorationSet.find(start, end);
77
+ nextDecorationSet = nextDecorationSet.remove(decorationsToRemove);
78
+
79
+ // Recompute decorations for this range
80
+ // Expand the range by 1 on each side to catch adjacent list nodes
81
+ const from = Math.max(0, start - 1);
82
+ const to = Math.min(tr.doc.content.size, end + 1);
83
+ const decorationsToAdd = computeListDecorations(tr.doc, from, to);
84
+ nextDecorationSet = nextDecorationSet.add(tr.doc, decorationsToAdd);
85
+ });
86
+ });
87
+ return nextDecorationSet;
88
+ };
89
+
90
+ // delete getDecorations during platform_editor_new_list_decorations_logic experiment clean up
91
+ export const getDecorations = (doc, state, featureFlags) => {
92
+ const decorations = [];
93
+
94
+ // this stack keeps track of each (nested) list to calculate the indentation level
95
+ const processedListsStack = [];
96
+ doc.nodesBetween(0, doc.content.size, (node, currentNodeStartPos) => {
97
+ if (processedListsStack.length > 0) {
98
+ let isOutsideLastList = true;
99
+ while (isOutsideLastList && processedListsStack.length > 0) {
100
+ const lastList = processedListsStack[processedListsStack.length - 1];
101
+ const lastListEndPos = lastList.startPos + lastList.node.nodeSize;
102
+ isOutsideLastList = currentNodeStartPos >= lastListEndPos;
103
+ // once we finish iterating over each innermost list, pop the stack to
104
+ // decrease the indent level attribute accordingly
105
+ if (isOutsideLastList) {
106
+ processedListsStack.pop();
107
+ }
108
+ }
109
+ }
110
+ if (isListNode(node)) {
111
+ processedListsStack.push({
112
+ node,
113
+ startPos: currentNodeStartPos
114
+ });
115
+ const from = currentNodeStartPos;
116
+ const to = currentNodeStartPos + node.nodeSize;
117
+ const depth = processedListsStack.length;
118
+ decorations.push(Decoration.node(from, to, {
119
+ 'data-indent-level': `${depth}`
120
+ }));
121
+ if (node.type.name === 'orderedList') {
122
+ var _node$attrs2;
123
+ // If a numbered list has item counters numbering >= 100, we'll need to add special
124
+ // spacing to account for the extra digit chars
125
+ const digitsSize = getItemCounterDigitsSize({
126
+ itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
127
+ order: node === null || node === void 0 ? void 0 : (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.order
128
+ });
129
+ if (digitsSize && digitsSize > 1) {
130
+ decorations.push(Decoration.node(from, to, {
131
+ style: getOrderedListInlineStyles(digitsSize, 'string')
132
+ }));
133
+ }
134
+ }
135
+ }
136
+ });
65
137
  return DecorationSet.empty.add(doc, decorations);
66
138
  };
67
139
  const getListState = (doc, selection) => {
@@ -114,11 +186,18 @@ const reducer = () => state => {
114
186
  };
115
187
  const createInitialState = (featureFlags, api) => state => {
116
188
  const isToolbarAIFCEnabled = Boolean(api === null || api === void 0 ? void 0 : api.toolbar);
189
+ const getInitialDecorations = () => {
190
+ var _insm$session, _insm$session2;
191
+ (_insm$session = insm.session) === null || _insm$session === void 0 ? void 0 : _insm$session.startFeature('listDecorationsInit');
192
+ const decorations = computeListDecorations(state.doc);
193
+ (_insm$session2 = insm.session) === null || _insm$session2 === void 0 ? void 0 : _insm$session2.endFeature('listDecorationsInit');
194
+ return decorations;
195
+ };
117
196
  return {
118
197
  // When plugin is initialised, editor state is defined with selection
119
198
  // hence returning the list state based on the selection to avoid list button in primary toolbar flickering during initial load
120
199
  ...(isToolbarAIFCEnabled && expValEquals('platform_editor_toolbar_aifc_patch_3', 'isEnabled', true) ? getListState(state.doc, state.selection) : initialState),
121
- decorationSet: getDecorations(state.doc, state, featureFlags)
200
+ decorationSet: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? DecorationSet.empty.add(state.doc, getInitialDecorations()) : getDecorations(state.doc, state, featureFlags)
122
201
  };
123
202
  };
124
203
  export const createPlugin = (eventDispatch, featureFlags, api) => {
@@ -129,14 +208,41 @@ export const createPlugin = (eventDispatch, featureFlags, api) => {
129
208
  onDocChanged: handleDocChanged(featureFlags),
130
209
  onSelectionChanged: handleSelectionChanged
131
210
  });
211
+ const pluginState = createPluginState(eventDispatch, createInitialState(featureFlags, api));
212
+ const pluginStateInit = (_, state) => {
213
+ return createInitialState(featureFlags)(state);
214
+ };
215
+ const pluginStateApply = (tr, oldPluginState, _oldEditorState, _newEditorState) => {
216
+ let nextPluginState = oldPluginState;
217
+ if (tr.docChanged) {
218
+ var _insm$session3, _insm$session4;
219
+ nextPluginState = handleSelectionChanged(tr, nextPluginState);
220
+ (_insm$session3 = insm.session) === null || _insm$session3 === void 0 ? void 0 : _insm$session3.startFeature('listDecorationUpdate');
221
+ const nextDecorationSet = updateListDecorations(nextPluginState.decorationSet, tr);
222
+ (_insm$session4 = insm.session) === null || _insm$session4 === void 0 ? void 0 : _insm$session4.endFeature('listDecorationUpdate');
223
+ nextPluginState = {
224
+ ...nextPluginState,
225
+ decorationSet: nextDecorationSet
226
+ };
227
+ } else if (tr.selectionSet) {
228
+ nextPluginState = handleSelectionChanged(tr, nextPluginState);
229
+ }
230
+ if (nextPluginState !== oldPluginState) {
231
+ eventDispatch(listPluginKey, nextPluginState);
232
+ }
233
+ return nextPluginState;
234
+ };
132
235
  return new SafePlugin({
133
- state: createPluginState(eventDispatch, createInitialState(featureFlags, api)),
236
+ state: {
237
+ init: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateInit : pluginState.init,
238
+ apply: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateApply : pluginState.apply
239
+ },
134
240
  key: listPluginKey,
135
241
  props: {
136
242
  decorations(state) {
137
243
  const {
138
244
  decorationSet
139
- } = getPluginState(state);
245
+ } = expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? listPluginKey.getState(state) : getPluginState(state);
140
246
  return decorationSet;
141
247
  },
142
248
  handleClick: (view, pos, event) => {
@@ -8,6 +8,7 @@ import { getItemCounterDigitsSize, isListNode, pluginFactory } from '@atlaskit/e
8
8
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
9
9
  import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
10
10
  import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
11
+ import { insm } from '@atlaskit/insm';
11
12
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
12
13
  import { isWrappingPossible } from './utils/selection';
13
14
  var listPluginKey = new PluginKey('listPlugin');
@@ -19,6 +20,79 @@ var initialState = {
19
20
  orderedListDisabled: false,
20
21
  decorationSet: DecorationSet.empty
21
22
  };
23
+ export var computeListDecorations = function computeListDecorations(doc) {
24
+ var from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
25
+ var to = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : doc.content.size;
26
+ var decorations = [];
27
+
28
+ // this stack keeps track of each (nested) list to calculate the indentation level
29
+ var processedListsStack = [];
30
+ doc.nodesBetween(from, to, function (node, currentNodeStartPos) {
31
+ if (processedListsStack.length > 0) {
32
+ var isOutsideLastList = true;
33
+ while (isOutsideLastList && processedListsStack.length > 0) {
34
+ var lastList = processedListsStack[processedListsStack.length - 1];
35
+ var lastListEndPos = lastList.startPos + lastList.node.nodeSize;
36
+ isOutsideLastList = currentNodeStartPos >= lastListEndPos;
37
+ // once we finish iterating over each innermost list, pop the stack to
38
+ // decrease the indent level attribute accordingly
39
+ if (isOutsideLastList) {
40
+ processedListsStack.pop();
41
+ }
42
+ }
43
+ }
44
+ if (isListNode(node)) {
45
+ processedListsStack.push({
46
+ node: node,
47
+ startPos: currentNodeStartPos
48
+ });
49
+ var _from = currentNodeStartPos;
50
+ var _to = currentNodeStartPos + node.nodeSize;
51
+ var depth = processedListsStack.length;
52
+ decorations.push(Decoration.node(_from, _to, {
53
+ 'data-indent-level': "".concat(depth)
54
+ }));
55
+ if (node.type.name === 'orderedList') {
56
+ var _node$attrs;
57
+ // If a numbered list has item counters numbering >= 100, we'll need to add special
58
+ // spacing to account for the extra digit chars
59
+ var digitsSize = getItemCounterDigitsSize({
60
+ itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
61
+ order: node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.order
62
+ });
63
+ if (digitsSize && digitsSize > 1) {
64
+ decorations.push(Decoration.node(_from, _to, {
65
+ style: getOrderedListInlineStyles(digitsSize, 'string')
66
+ }));
67
+ }
68
+ }
69
+ }
70
+ });
71
+ return decorations;
72
+ };
73
+ export var updateListDecorations = function updateListDecorations(decorationSet, tr) {
74
+ var nextDecorationSet = decorationSet.map(tr.mapping, tr.doc);
75
+ tr.mapping.maps.forEach(function (stepMap, index) {
76
+ stepMap.forEach(function (oldStart, oldEnd) {
77
+ var start = tr.mapping.slice(index).map(oldStart, -1);
78
+ var end = tr.mapping.slice(index).map(oldEnd);
79
+
80
+ // Remove decorations in this range
81
+ var decorationsToRemove = nextDecorationSet.find(start, end);
82
+ nextDecorationSet = nextDecorationSet.remove(decorationsToRemove);
83
+
84
+ // Recompute decorations for this range
85
+ // Expand the range by 1 on each side to catch adjacent list nodes
86
+ var from = Math.max(0, start - 1);
87
+ var to = Math.min(tr.doc.content.size, end + 1);
88
+ var decorationsToAdd = computeListDecorations(tr.doc, from, to);
89
+ nextDecorationSet = nextDecorationSet.add(tr.doc, decorationsToAdd);
90
+ });
91
+ });
92
+ return nextDecorationSet;
93
+ };
94
+
95
+ // delete getDecorations during platform_editor_new_list_decorations_logic experiment clean up
22
96
  export var getDecorations = function getDecorations(doc, state, featureFlags) {
23
97
  var decorations = [];
24
98
 
@@ -50,12 +124,12 @@ export var getDecorations = function getDecorations(doc, state, featureFlags) {
50
124
  'data-indent-level': "".concat(depth)
51
125
  }));
52
126
  if (node.type.name === 'orderedList') {
53
- var _node$attrs;
127
+ var _node$attrs2;
54
128
  // If a numbered list has item counters numbering >= 100, we'll need to add special
55
129
  // spacing to account for the extra digit chars
56
130
  var digitsSize = getItemCounterDigitsSize({
57
131
  itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
58
- order: node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.order
132
+ order: node === null || node === void 0 || (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.order
59
133
  });
60
134
  if (digitsSize && digitsSize > 1) {
61
135
  decorations.push(Decoration.node(from, to, {
@@ -118,8 +192,15 @@ var reducer = function reducer() {
118
192
  var createInitialState = function createInitialState(featureFlags, api) {
119
193
  return function (state) {
120
194
  var isToolbarAIFCEnabled = Boolean(api === null || api === void 0 ? void 0 : api.toolbar);
195
+ var getInitialDecorations = function getInitialDecorations() {
196
+ var _insm$session, _insm$session2;
197
+ (_insm$session = insm.session) === null || _insm$session === void 0 || _insm$session.startFeature('listDecorationsInit');
198
+ var decorations = computeListDecorations(state.doc);
199
+ (_insm$session2 = insm.session) === null || _insm$session2 === void 0 || _insm$session2.endFeature('listDecorationsInit');
200
+ return decorations;
201
+ };
121
202
  return _objectSpread(_objectSpread({}, isToolbarAIFCEnabled && expValEquals('platform_editor_toolbar_aifc_patch_3', 'isEnabled', true) ? getListState(state.doc, state.selection) : initialState), {}, {
122
- decorationSet: getDecorations(state.doc, state, featureFlags)
203
+ decorationSet: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? DecorationSet.empty.add(state.doc, getInitialDecorations()) : getDecorations(state.doc, state, featureFlags)
123
204
  });
124
205
  };
125
206
  };
@@ -130,13 +211,39 @@ export var createPlugin = function createPlugin(eventDispatch, featureFlags, api
130
211
  }),
131
212
  getPluginState = _pluginFactory.getPluginState,
132
213
  createPluginState = _pluginFactory.createPluginState;
214
+ var pluginState = createPluginState(eventDispatch, createInitialState(featureFlags, api));
215
+ var pluginStateInit = function pluginStateInit(_, state) {
216
+ return createInitialState(featureFlags)(state);
217
+ };
218
+ var pluginStateApply = function pluginStateApply(tr, oldPluginState, _oldEditorState, _newEditorState) {
219
+ var nextPluginState = oldPluginState;
220
+ if (tr.docChanged) {
221
+ var _insm$session3, _insm$session4;
222
+ nextPluginState = handleSelectionChanged(tr, nextPluginState);
223
+ (_insm$session3 = insm.session) === null || _insm$session3 === void 0 || _insm$session3.startFeature('listDecorationUpdate');
224
+ var nextDecorationSet = updateListDecorations(nextPluginState.decorationSet, tr);
225
+ (_insm$session4 = insm.session) === null || _insm$session4 === void 0 || _insm$session4.endFeature('listDecorationUpdate');
226
+ nextPluginState = _objectSpread(_objectSpread({}, nextPluginState), {}, {
227
+ decorationSet: nextDecorationSet
228
+ });
229
+ } else if (tr.selectionSet) {
230
+ nextPluginState = handleSelectionChanged(tr, nextPluginState);
231
+ }
232
+ if (nextPluginState !== oldPluginState) {
233
+ eventDispatch(listPluginKey, nextPluginState);
234
+ }
235
+ return nextPluginState;
236
+ };
133
237
  return new SafePlugin({
134
- state: createPluginState(eventDispatch, createInitialState(featureFlags, api)),
238
+ state: {
239
+ init: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateInit : pluginState.init,
240
+ apply: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateApply : pluginState.apply
241
+ },
135
242
  key: listPluginKey,
136
243
  props: {
137
244
  decorations: function decorations(state) {
138
- var _getPluginState = getPluginState(state),
139
- decorationSet = _getPluginState.decorationSet;
245
+ var _ref = expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? listPluginKey.getState(state) : getPluginState(state),
246
+ decorationSet = _ref.decorationSet;
140
247
  return decorationSet;
141
248
  },
142
249
  handleClick: function handleClick(view, pos, event) {
@@ -3,10 +3,12 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
3
3
  import type { ExtractInjectionAPI, FeatureFlags } from '@atlaskit/editor-common/types';
4
4
  import type { Node } from '@atlaskit/editor-prosemirror/model';
5
5
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
- import type { EditorState } from '@atlaskit/editor-prosemirror/state';
7
- import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
+ import type { EditorState, ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
7
+ import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
8
  import type { ListPlugin } from '../listPluginType';
9
9
  import type { ListState } from '../types';
10
10
  export declare const pluginKey: PluginKey<ListState>;
11
+ export declare const computeListDecorations: (doc: Node, from?: number, to?: number) => Decoration[];
12
+ export declare const updateListDecorations: (decorationSet: DecorationSet, tr: ReadonlyTransaction) => DecorationSet;
11
13
  export declare const getDecorations: (doc: Node, state: EditorState, featureFlags: FeatureFlags) => DecorationSet;
12
14
  export declare const createPlugin: (eventDispatch: Dispatch, featureFlags: FeatureFlags, api?: ExtractInjectionAPI<ListPlugin>) => SafePlugin;
@@ -3,10 +3,12 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
3
3
  import type { ExtractInjectionAPI, FeatureFlags } from '@atlaskit/editor-common/types';
4
4
  import type { Node } from '@atlaskit/editor-prosemirror/model';
5
5
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
- import type { EditorState } from '@atlaskit/editor-prosemirror/state';
7
- import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
+ import type { EditorState, ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
7
+ import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
8
  import type { ListPlugin } from '../listPluginType';
9
9
  import type { ListState } from '../types';
10
10
  export declare const pluginKey: PluginKey<ListState>;
11
+ export declare const computeListDecorations: (doc: Node, from?: number, to?: number) => Decoration[];
12
+ export declare const updateListDecorations: (decorationSet: DecorationSet, tr: ReadonlyTransaction) => DecorationSet;
11
13
  export declare const getDecorations: (doc: Node, state: EditorState, featureFlags: FeatureFlags) => DecorationSet;
12
14
  export declare const createPlugin: (eventDispatch: Dispatch, featureFlags: FeatureFlags, api?: ExtractInjectionAPI<ListPlugin>) => SafePlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-list",
3
- "version": "8.1.2",
3
+ "version": "8.1.3",
4
4
  "description": "List plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,18 +31,19 @@
31
31
  "@atlaskit/editor-plugin-analytics": "^6.1.0",
32
32
  "@atlaskit/editor-plugin-block-menu": "^4.0.0",
33
33
  "@atlaskit/editor-plugin-feature-flags": "^5.0.0",
34
- "@atlaskit/editor-plugin-toolbar": "^3.2.0",
34
+ "@atlaskit/editor-plugin-toolbar": "^3.3.0",
35
35
  "@atlaskit/editor-prosemirror": "7.0.0",
36
36
  "@atlaskit/editor-toolbar": "^0.15.0",
37
37
  "@atlaskit/icon": "^28.5.0",
38
+ "@atlaskit/insm": "^0.1.0",
38
39
  "@atlaskit/platform-feature-flags": "^1.1.0",
39
40
  "@atlaskit/prosemirror-history": "^0.2.0",
40
41
  "@atlaskit/prosemirror-input-rules": "^3.5.0",
41
- "@atlaskit/tmp-editor-statsig": "^13.10.0",
42
+ "@atlaskit/tmp-editor-statsig": "^13.12.0",
42
43
  "@babel/runtime": "^7.0.0"
43
44
  },
44
45
  "peerDependencies": {
45
- "@atlaskit/editor-common": "^110.10.0",
46
+ "@atlaskit/editor-common": "^110.13.0",
46
47
  "react": "^18.2.0",
47
48
  "react-intl-next": "npm:react-intl@^5.18.1"
48
49
  },