@atlaskit/editor-plugin-expand 1.6.2 → 1.6.4

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,19 @@
1
1
  # @atlaskit/editor-plugin-expand
2
2
 
3
+ ## 1.6.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#94988](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/94988) [`8e5daa7c846d`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/8e5daa7c846d) - [ux] [ED-22983] disable editing in singlePlayer expand nodes when editorDisabled state is true. these changes are only applied when the platform.editor.live-view.disable-editing-in-view-mode_fi1rx FF is on, and the singlePlayer expand is used when live view is enabled and the platform.editor.single-player-expand FF is enabled.
8
+
9
+ ## 1.6.3
10
+
11
+ ### Patch Changes
12
+
13
+ - [#95226](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/95226) [`35450b170a19`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/35450b170a19) - [ux] [ED-23152] Expands no longer change state (open/closed) when the page width is toggled by a user (live pages/ single player expands)
14
+ - [#94901](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/94901) [`da964fcdc828`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/da964fcdc828) - [ED-23097] Bump ADF schema to version 35.12.1
15
+ - [#94398](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/94398) [`4df808e35fda`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/4df808e35fda) - [ux] [ED-23108] Solve bug where single player expands would lose their expanded state when adding breakout marks. Single player expands are only used when `platform.editor.single-player-expand` FF AND live page are both enabled.
16
+
3
17
  ## 1.6.2
4
18
 
5
19
  ### Patch Changes
@@ -17,14 +17,17 @@ var _styles = require("@atlaskit/editor-common/styles");
17
17
  var _utils = require("@atlaskit/editor-common/utils");
18
18
  var _model = require("@atlaskit/editor-prosemirror/model");
19
19
  var _state = require("@atlaskit/editor-prosemirror/state");
20
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
20
21
  var _commands = require("../commands");
21
22
  var _NodeView = require("../ui/NodeView");
22
23
  var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
23
- function ExpandNodeView(node, view, getPos, getIntl, isMobile, selectNearNode, api) {
24
+ function ExpandNodeView(_node, view, getPos, getIntl, isMobile, selectNearNode, api) {
24
25
  var _this = this,
25
- _expandedState$get;
26
+ _api$editorDisabled,
27
+ _this$api6;
26
28
  var allowInteractiveExpand = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : true;
27
29
  var __livePage = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false;
30
+ var cleanUpEditorDisabledOnChange = arguments.length > 9 ? arguments[9] : undefined;
28
31
  (0, _classCallCheck2.default)(this, ExpandNodeView);
29
32
  (0, _defineProperty2.default)(this, "allowInteractiveExpand", true);
30
33
  (0, _defineProperty2.default)(this, "isMobile", false);
@@ -83,7 +86,7 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
83
86
  pos: pos,
84
87
  node: _this.node
85
88
  })(_this.view.state, _this.view.dispatch);
86
- _this.updateExpandToggleIcon();
89
+ _this.updateExpandToggleIcon(_this.node);
87
90
  return;
88
91
  }
89
92
  if (target === _this.input) {
@@ -176,7 +179,7 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
176
179
  pos: pos,
177
180
  node: _this.node
178
181
  })(state, dispatch);
179
- _this.updateExpandToggleIcon();
182
+ _this.updateExpandToggleIcon(_this.node);
180
183
  }
181
184
  });
182
185
  (0, _defineProperty2.default)(this, "moveToOutsideOfTitle", function (event) {
@@ -322,14 +325,23 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
322
325
  }
323
326
  }
324
327
  });
328
+ (0, _defineProperty2.default)(this, "getContentEditable", function (node) {
329
+ var contentEditable = !(0, _expand.isExpandCollapsed)(node);
330
+ if ((0, _platformFeatureFlags.getBooleanFF)('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') && _this.api && _this.api.editorDisabled) {
331
+ var _this$api$editorDisab;
332
+ return !((_this$api$editorDisab = _this.api.editorDisabled.sharedState.currentState()) !== null && _this$api$editorDisab !== void 0 && _this$api$editorDisab.editorDisabled) && contentEditable;
333
+ }
334
+ return contentEditable;
335
+ });
325
336
  this.selectNearNode = selectNearNode;
326
337
  this.__livePage = __livePage;
338
+ this.cleanUpEditorDisabledOnChange = cleanUpEditorDisabledOnChange;
327
339
  this.intl = getIntl();
328
340
  this.allowInteractiveExpand = allowInteractiveExpand;
329
341
  this.getPos = getPos;
330
342
  this.view = view;
331
- this.node = node;
332
- var _DOMSerializer$render = _model.DOMSerializer.renderSpec(document, (0, _NodeView.toDOM)(node, this.__livePage, this.intl)),
343
+ this.node = _node;
344
+ var _DOMSerializer$render = _model.DOMSerializer.renderSpec(document, (0, _NodeView.toDOM)(_node, this.__livePage, this.intl, api === null || api === void 0 || (_api$editorDisabled = api.editorDisabled) === null || _api$editorDisabled === void 0 || (_api$editorDisabled = _api$editorDisabled.sharedState.currentState()) === null || _api$editorDisabled === void 0 ? void 0 : _api$editorDisabled.editorDisabled)),
333
345
  dom = _DOMSerializer$render.dom,
334
346
  contentDOM = _DOMSerializer$render.contentDOM;
335
347
  this.dom = dom;
@@ -343,8 +355,7 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
343
355
  if (!_expand.expandedState.has(this.node)) {
344
356
  _expand.expandedState.set(this.node, false);
345
357
  }
346
- this.updateExpandBodyContentEditable();
347
- (0, _NodeView.renderIcon)(this.icon, this.allowInteractiveExpand, (_expandedState$get = _expand.expandedState.get(this.node)) !== null && _expandedState$get !== void 0 ? _expandedState$get : false, this.intl);
358
+ (0, _NodeView.renderIcon)(this.icon, this.allowInteractiveExpand, !(0, _expand.isExpandCollapsed)(this.node), this.intl);
348
359
  if (!this.input || !this.titleContainer || !this.icon) {
349
360
  return;
350
361
  }
@@ -360,6 +371,21 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
360
371
  // Prevent ProseMirror from getting a focus event (causes weird selection issues).
361
372
  this.titleContainer.addEventListener('focus', this.handleFocus);
362
373
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
374
+ if ((_this$api6 = this.api) !== null && _this$api6 !== void 0 && _this$api6.editorDisabled && (0, _platformFeatureFlags.getBooleanFF)('platform.editor.live-view.disable-editing-in-view-mode_fi1rx')) {
375
+ this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
376
+ var editorDisabled = sharedState.nextSharedState.editorDisabled;
377
+ if (_this.input) {
378
+ if (editorDisabled) {
379
+ _this.input.setAttribute('readonly', 'true');
380
+ } else {
381
+ _this.input.removeAttribute('readonly');
382
+ }
383
+ }
384
+ if (_this.content) {
385
+ _this.content.setAttribute('contenteditable', _this.getContentEditable(_this.node) ? 'true' : 'false');
386
+ }
387
+ });
388
+ }
363
389
  }
364
390
  (0, _createClass2.default)(ExpandNodeView, [{
365
391
  key: "stopEvent",
@@ -393,13 +419,27 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
393
419
  _this2.input.value = _this2.node.attrs.title;
394
420
  }
395
421
  });
396
- if (this.node !== node) {
422
+
423
+ // This solves for a bug where the breakout plugin updates the node
424
+ // but by the time it reaches the update, it gives us the expand after
425
+ if (this.node !== node && this.node.attrs.title !== node.attrs.title) {
426
+ var shouldBeExpanded = _expand.expandedState.get(node);
427
+ if (shouldBeExpanded === undefined) {
428
+ _expand.expandedState.set(node, true);
429
+ }
430
+ this.updateExpandToggleIcon(node);
431
+ } else if (this.node !== node) {
432
+ // This checks if the node has been replaced with a different version
433
+ // and updates the state of the new node to match the old one
397
434
  var previousExpandedState = _expand.expandedState.get(this.node);
398
435
  if (previousExpandedState === undefined) {
399
436
  previousExpandedState = true;
400
437
  }
401
438
  _expand.expandedState.set(node, previousExpandedState);
402
- _expand.expandedState.delete(this.node);
439
+ }
440
+ if (this.content) {
441
+ // Disallow interaction/selection inside when collapsed.
442
+ this.content.setAttribute('contenteditable', this.getContentEditable(node) ? 'true' : 'false');
403
443
  }
404
444
  this.node = node;
405
445
  return true;
@@ -408,13 +448,13 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
408
448
  }
409
449
  }, {
410
450
  key: "updateExpandToggleIcon",
411
- value: function updateExpandToggleIcon() {
412
- var expanded = _expand.expandedState.get(this.node) ? _expand.expandedState.get(this.node) : false;
451
+ value: function updateExpandToggleIcon(node) {
452
+ var expanded = _expand.expandedState.get(node) ? _expand.expandedState.get(node) : false;
413
453
  if (this.dom && expanded !== undefined) {
414
- var _expandedState$get2;
415
- this.dom.className = (0, _NodeView.buildExpandClassName)(this.node.type.name, expanded);
454
+ var _expandedState$get;
455
+ this.dom.className = (0, _NodeView.buildExpandClassName)(node.type.name, expanded);
416
456
  // Re-render the icon to update the aria-expanded attribute
417
- (0, _NodeView.renderIcon)(this.icon ? this.icon : null, this.allowInteractiveExpand, (_expandedState$get2 = _expand.expandedState.get(this.node)) !== null && _expandedState$get2 !== void 0 ? _expandedState$get2 : false, this.intl);
457
+ (0, _NodeView.renderIcon)(this.icon ? this.icon : null, this.allowInteractiveExpand, (_expandedState$get = _expand.expandedState.get(node)) !== null && _expandedState$get !== void 0 ? _expandedState$get : false, this.intl);
418
458
  }
419
459
  this.updateExpandBodyContentEditable();
420
460
  }
@@ -441,8 +481,10 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
441
481
  this.titleContainer.removeEventListener('focus', this.handleFocus);
442
482
  this.icon.removeEventListener('keydown', this.handleIconKeyDown);
443
483
  (_this$decorationClean2 = this.decorationCleanup) === null || _this$decorationClean2 === void 0 || _this$decorationClean2.call(this);
484
+ if (this.cleanUpEditorDisabledOnChange) {
485
+ this.cleanUpEditorDisabledOnChange();
486
+ }
444
487
  _reactDom.default.unmountComponentAtNode(this.icon);
445
- _expand.expandedState.delete(this.node);
446
488
  }
447
489
  }]);
448
490
  return ExpandNodeView;
@@ -10,11 +10,12 @@ var _reactDom = _interopRequireDefault(require("react-dom"));
10
10
  var _expand = require("@atlaskit/editor-common/expand");
11
11
  var _styles = require("@atlaskit/editor-common/styles");
12
12
  var _ui = require("@atlaskit/editor-common/ui");
13
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
14
  var _ExpandButton = require("../ui/ExpandButton");
14
15
  var buildExpandClassName = exports.buildExpandClassName = function buildExpandClassName(type, expanded) {
15
16
  return "".concat(_styles.expandClassNames.prefix, " ").concat(_styles.expandClassNames.type(type), " ").concat(expanded ? _styles.expandClassNames.expanded : '');
16
17
  };
17
- var toDOM = exports.toDOM = function toDOM(node, __livePage, intl) {
18
+ var toDOM = exports.toDOM = function toDOM(node, __livePage, intl, titleReadOnly, contentEditable) {
18
19
  var _expandedState$get;
19
20
  return ['div', {
20
21
  // prettier-ignore
@@ -41,11 +42,12 @@ var toDOM = exports.toDOM = function toDOM(node, __livePage, intl) {
41
42
  'class': _styles.expandClassNames.titleInput,
42
43
  value: node.attrs.title,
43
44
  placeholder: intl && typeof intl.formatMessage === 'function' && intl.formatMessage(_ui.expandMessages.expandPlaceholderText) || _ui.expandMessages.expandPlaceholderText.defaultMessage,
44
- type: 'text'
45
- }]]],
46
- // prettier-ignore
47
- ['div', {
48
- 'class': _styles.expandClassNames.content
45
+ type: 'text',
46
+ readonly: (0, _platformFeatureFlags.getBooleanFF)('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') && titleReadOnly ? 'true' : undefined
47
+ }]]], ['div', {
48
+ // prettier-ignore
49
+ class: _styles.expandClassNames.content,
50
+ contenteditable: (0, _platformFeatureFlags.getBooleanFF)('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') && contentEditable ? contentEditable ? 'true' : 'false' : undefined
49
51
  }, 0]];
50
52
  };
51
53
  var renderIcon = exports.renderIcon = function renderIcon(icon, allowInteractiveExpand, expanded, intl) {
@@ -1,17 +1,18 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import ReactDOM from 'react-dom';
3
3
  import { keyName } from 'w3c-keyname';
4
- import { expandedState } from '@atlaskit/editor-common/expand';
4
+ import { expandedState, isExpandCollapsed } from '@atlaskit/editor-common/expand';
5
5
  import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor-common/selection';
6
6
  import { expandClassNames } from '@atlaskit/editor-common/styles';
7
7
  import { closestElement, isEmptyNode } from '@atlaskit/editor-common/utils';
8
8
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
9
9
  import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
10
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
10
11
  import { deleteExpand, setSelectionInsideExpand, toggleExpandExpanded, updateExpandTitle } from '../commands';
11
12
  import { buildExpandClassName, renderIcon, toDOM } from '../ui/NodeView';
12
13
  export class ExpandNodeView {
13
- constructor(node, view, getPos, getIntl, isMobile, selectNearNode, api, allowInteractiveExpand = true, __livePage = false) {
14
- var _expandedState$get;
14
+ constructor(_node, view, getPos, getIntl, isMobile, selectNearNode, api, allowInteractiveExpand = true, __livePage = false, cleanUpEditorDisabledOnChange) {
15
+ var _api$editorDisabled, _api$editorDisabled$s, _this$api6;
15
16
  _defineProperty(this, "allowInteractiveExpand", true);
16
17
  _defineProperty(this, "isMobile", false);
17
18
  _defineProperty(this, "focusTitle", () => {
@@ -70,7 +71,7 @@ export class ExpandNodeView {
70
71
  pos,
71
72
  node: this.node
72
73
  })(this.view.state, this.view.dispatch);
73
- this.updateExpandToggleIcon();
74
+ this.updateExpandToggleIcon(this.node);
74
75
  return;
75
76
  }
76
77
  if (target === this.input) {
@@ -168,7 +169,7 @@ export class ExpandNodeView {
168
169
  pos,
169
170
  node: this.node
170
171
  })(state, dispatch);
171
- this.updateExpandToggleIcon();
172
+ this.updateExpandToggleIcon(this.node);
172
173
  }
173
174
  });
174
175
  _defineProperty(this, "moveToOutsideOfTitle", event => {
@@ -323,17 +324,26 @@ export class ExpandNodeView {
323
324
  }
324
325
  }
325
326
  });
327
+ _defineProperty(this, "getContentEditable", node => {
328
+ const contentEditable = !isExpandCollapsed(node);
329
+ if (getBooleanFF('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') && this.api && this.api.editorDisabled) {
330
+ var _this$api$editorDisab;
331
+ return !((_this$api$editorDisab = this.api.editorDisabled.sharedState.currentState()) !== null && _this$api$editorDisab !== void 0 && _this$api$editorDisab.editorDisabled) && contentEditable;
332
+ }
333
+ return contentEditable;
334
+ });
326
335
  this.selectNearNode = selectNearNode;
327
336
  this.__livePage = __livePage;
337
+ this.cleanUpEditorDisabledOnChange = cleanUpEditorDisabledOnChange;
328
338
  this.intl = getIntl();
329
339
  this.allowInteractiveExpand = allowInteractiveExpand;
330
340
  this.getPos = getPos;
331
341
  this.view = view;
332
- this.node = node;
342
+ this.node = _node;
333
343
  const {
334
344
  dom,
335
345
  contentDOM
336
- } = DOMSerializer.renderSpec(document, toDOM(node, this.__livePage, this.intl));
346
+ } = DOMSerializer.renderSpec(document, toDOM(_node, this.__livePage, this.intl, api === null || api === void 0 ? void 0 : (_api$editorDisabled = api.editorDisabled) === null || _api$editorDisabled === void 0 ? void 0 : (_api$editorDisabled$s = _api$editorDisabled.sharedState.currentState()) === null || _api$editorDisabled$s === void 0 ? void 0 : _api$editorDisabled$s.editorDisabled));
337
347
  this.dom = dom;
338
348
  this.contentDOM = contentDOM;
339
349
  this.isMobile = isMobile;
@@ -345,8 +355,7 @@ export class ExpandNodeView {
345
355
  if (!expandedState.has(this.node)) {
346
356
  expandedState.set(this.node, false);
347
357
  }
348
- this.updateExpandBodyContentEditable();
349
- renderIcon(this.icon, this.allowInteractiveExpand, (_expandedState$get = expandedState.get(this.node)) !== null && _expandedState$get !== void 0 ? _expandedState$get : false, this.intl);
358
+ renderIcon(this.icon, this.allowInteractiveExpand, !isExpandCollapsed(this.node), this.intl);
350
359
  if (!this.input || !this.titleContainer || !this.icon) {
351
360
  return;
352
361
  }
@@ -362,6 +371,21 @@ export class ExpandNodeView {
362
371
  // Prevent ProseMirror from getting a focus event (causes weird selection issues).
363
372
  this.titleContainer.addEventListener('focus', this.handleFocus);
364
373
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
374
+ if ((_this$api6 = this.api) !== null && _this$api6 !== void 0 && _this$api6.editorDisabled && getBooleanFF('platform.editor.live-view.disable-editing-in-view-mode_fi1rx')) {
375
+ this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(sharedState => {
376
+ const editorDisabled = sharedState.nextSharedState.editorDisabled;
377
+ if (this.input) {
378
+ if (editorDisabled) {
379
+ this.input.setAttribute('readonly', 'true');
380
+ } else {
381
+ this.input.removeAttribute('readonly');
382
+ }
383
+ }
384
+ if (this.content) {
385
+ this.content.setAttribute('contenteditable', this.getContentEditable(this.node) ? 'true' : 'false');
386
+ }
387
+ });
388
+ }
365
389
  }
366
390
  stopEvent(event) {
367
391
  const target = event.target;
@@ -388,26 +412,40 @@ export class ExpandNodeView {
388
412
  this.input.value = this.node.attrs.title;
389
413
  }
390
414
  });
391
- if (this.node !== node) {
415
+
416
+ // This solves for a bug where the breakout plugin updates the node
417
+ // but by the time it reaches the update, it gives us the expand after
418
+ if (this.node !== node && this.node.attrs.title !== node.attrs.title) {
419
+ let shouldBeExpanded = expandedState.get(node);
420
+ if (shouldBeExpanded === undefined) {
421
+ expandedState.set(node, true);
422
+ }
423
+ this.updateExpandToggleIcon(node);
424
+ } else if (this.node !== node) {
425
+ // This checks if the node has been replaced with a different version
426
+ // and updates the state of the new node to match the old one
392
427
  let previousExpandedState = expandedState.get(this.node);
393
428
  if (previousExpandedState === undefined) {
394
429
  previousExpandedState = true;
395
430
  }
396
431
  expandedState.set(node, previousExpandedState);
397
- expandedState.delete(this.node);
432
+ }
433
+ if (this.content) {
434
+ // Disallow interaction/selection inside when collapsed.
435
+ this.content.setAttribute('contenteditable', this.getContentEditable(node) ? 'true' : 'false');
398
436
  }
399
437
  this.node = node;
400
438
  return true;
401
439
  }
402
440
  return false;
403
441
  }
404
- updateExpandToggleIcon() {
405
- const expanded = expandedState.get(this.node) ? expandedState.get(this.node) : false;
442
+ updateExpandToggleIcon(node) {
443
+ const expanded = expandedState.get(node) ? expandedState.get(node) : false;
406
444
  if (this.dom && expanded !== undefined) {
407
- var _expandedState$get2;
408
- this.dom.className = buildExpandClassName(this.node.type.name, expanded);
445
+ var _expandedState$get;
446
+ this.dom.className = buildExpandClassName(node.type.name, expanded);
409
447
  // Re-render the icon to update the aria-expanded attribute
410
- renderIcon(this.icon ? this.icon : null, this.allowInteractiveExpand, (_expandedState$get2 = expandedState.get(this.node)) !== null && _expandedState$get2 !== void 0 ? _expandedState$get2 : false, this.intl);
448
+ renderIcon(this.icon ? this.icon : null, this.allowInteractiveExpand, (_expandedState$get = expandedState.get(node)) !== null && _expandedState$get !== void 0 ? _expandedState$get : false, this.intl);
411
449
  }
412
450
  this.updateExpandBodyContentEditable();
413
451
  }
@@ -430,8 +468,10 @@ export class ExpandNodeView {
430
468
  this.titleContainer.removeEventListener('focus', this.handleFocus);
431
469
  this.icon.removeEventListener('keydown', this.handleIconKeyDown);
432
470
  (_this$decorationClean2 = this.decorationCleanup) === null || _this$decorationClean2 === void 0 ? void 0 : _this$decorationClean2.call(this);
471
+ if (this.cleanUpEditorDisabledOnChange) {
472
+ this.cleanUpEditorDisabledOnChange();
473
+ }
433
474
  ReactDOM.unmountComponentAtNode(this.icon);
434
- expandedState.delete(this.node);
435
475
  }
436
476
  }
437
477
  export default function ({
@@ -3,11 +3,12 @@ import ReactDOM from 'react-dom';
3
3
  import { expandedState } from '@atlaskit/editor-common/expand';
4
4
  import { expandClassNames } from '@atlaskit/editor-common/styles';
5
5
  import { expandMessages } from '@atlaskit/editor-common/ui';
6
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
6
7
  import { ExpandButton } from '../ui/ExpandButton';
7
8
  export const buildExpandClassName = (type, expanded) => {
8
9
  return `${expandClassNames.prefix} ${expandClassNames.type(type)} ${expanded ? expandClassNames.expanded : ''}`;
9
10
  };
10
- export const toDOM = (node, __livePage, intl) => {
11
+ export const toDOM = (node, __livePage, intl, titleReadOnly, contentEditable) => {
11
12
  var _expandedState$get;
12
13
  return ['div', {
13
14
  // prettier-ignore
@@ -34,11 +35,12 @@ export const toDOM = (node, __livePage, intl) => {
34
35
  'class': expandClassNames.titleInput,
35
36
  value: node.attrs.title,
36
37
  placeholder: intl && typeof intl.formatMessage === 'function' && intl.formatMessage(expandMessages.expandPlaceholderText) || expandMessages.expandPlaceholderText.defaultMessage,
37
- type: 'text'
38
- }]]],
39
- // prettier-ignore
40
- ['div', {
41
- 'class': expandClassNames.content
38
+ type: 'text',
39
+ readonly: getBooleanFF('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') && titleReadOnly ? 'true' : undefined
40
+ }]]], ['div', {
41
+ // prettier-ignore
42
+ class: expandClassNames.content,
43
+ contenteditable: getBooleanFF('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') && contentEditable ? contentEditable ? 'true' : 'false' : undefined
42
44
  }, 0]];
43
45
  };
44
46
  export const renderIcon = (icon, allowInteractiveExpand, expanded, intl) => {
@@ -3,20 +3,23 @@ import _createClass from "@babel/runtime/helpers/createClass";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
4
  import ReactDOM from 'react-dom';
5
5
  import { keyName } from 'w3c-keyname';
6
- import { expandedState } from '@atlaskit/editor-common/expand';
6
+ import { expandedState, isExpandCollapsed } from '@atlaskit/editor-common/expand';
7
7
  import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor-common/selection';
8
8
  import { expandClassNames } from '@atlaskit/editor-common/styles';
9
9
  import { closestElement, isEmptyNode } from '@atlaskit/editor-common/utils';
10
10
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
11
11
  import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
12
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
12
13
  import { deleteExpand, setSelectionInsideExpand, toggleExpandExpanded, updateExpandTitle } from '../commands';
13
14
  import { buildExpandClassName, renderIcon, toDOM } from '../ui/NodeView';
14
15
  export var ExpandNodeView = /*#__PURE__*/function () {
15
- function ExpandNodeView(node, view, getPos, getIntl, isMobile, selectNearNode, api) {
16
+ function ExpandNodeView(_node, view, getPos, getIntl, isMobile, selectNearNode, api) {
16
17
  var _this = this,
17
- _expandedState$get;
18
+ _api$editorDisabled,
19
+ _this$api6;
18
20
  var allowInteractiveExpand = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : true;
19
21
  var __livePage = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : false;
22
+ var cleanUpEditorDisabledOnChange = arguments.length > 9 ? arguments[9] : undefined;
20
23
  _classCallCheck(this, ExpandNodeView);
21
24
  _defineProperty(this, "allowInteractiveExpand", true);
22
25
  _defineProperty(this, "isMobile", false);
@@ -75,7 +78,7 @@ export var ExpandNodeView = /*#__PURE__*/function () {
75
78
  pos: pos,
76
79
  node: _this.node
77
80
  })(_this.view.state, _this.view.dispatch);
78
- _this.updateExpandToggleIcon();
81
+ _this.updateExpandToggleIcon(_this.node);
79
82
  return;
80
83
  }
81
84
  if (target === _this.input) {
@@ -168,7 +171,7 @@ export var ExpandNodeView = /*#__PURE__*/function () {
168
171
  pos: pos,
169
172
  node: _this.node
170
173
  })(state, dispatch);
171
- _this.updateExpandToggleIcon();
174
+ _this.updateExpandToggleIcon(_this.node);
172
175
  }
173
176
  });
174
177
  _defineProperty(this, "moveToOutsideOfTitle", function (event) {
@@ -314,14 +317,23 @@ export var ExpandNodeView = /*#__PURE__*/function () {
314
317
  }
315
318
  }
316
319
  });
320
+ _defineProperty(this, "getContentEditable", function (node) {
321
+ var contentEditable = !isExpandCollapsed(node);
322
+ if (getBooleanFF('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') && _this.api && _this.api.editorDisabled) {
323
+ var _this$api$editorDisab;
324
+ return !((_this$api$editorDisab = _this.api.editorDisabled.sharedState.currentState()) !== null && _this$api$editorDisab !== void 0 && _this$api$editorDisab.editorDisabled) && contentEditable;
325
+ }
326
+ return contentEditable;
327
+ });
317
328
  this.selectNearNode = selectNearNode;
318
329
  this.__livePage = __livePage;
330
+ this.cleanUpEditorDisabledOnChange = cleanUpEditorDisabledOnChange;
319
331
  this.intl = getIntl();
320
332
  this.allowInteractiveExpand = allowInteractiveExpand;
321
333
  this.getPos = getPos;
322
334
  this.view = view;
323
- this.node = node;
324
- var _DOMSerializer$render = DOMSerializer.renderSpec(document, toDOM(node, this.__livePage, this.intl)),
335
+ this.node = _node;
336
+ var _DOMSerializer$render = DOMSerializer.renderSpec(document, toDOM(_node, this.__livePage, this.intl, api === null || api === void 0 || (_api$editorDisabled = api.editorDisabled) === null || _api$editorDisabled === void 0 || (_api$editorDisabled = _api$editorDisabled.sharedState.currentState()) === null || _api$editorDisabled === void 0 ? void 0 : _api$editorDisabled.editorDisabled)),
325
337
  dom = _DOMSerializer$render.dom,
326
338
  contentDOM = _DOMSerializer$render.contentDOM;
327
339
  this.dom = dom;
@@ -335,8 +347,7 @@ export var ExpandNodeView = /*#__PURE__*/function () {
335
347
  if (!expandedState.has(this.node)) {
336
348
  expandedState.set(this.node, false);
337
349
  }
338
- this.updateExpandBodyContentEditable();
339
- renderIcon(this.icon, this.allowInteractiveExpand, (_expandedState$get = expandedState.get(this.node)) !== null && _expandedState$get !== void 0 ? _expandedState$get : false, this.intl);
350
+ renderIcon(this.icon, this.allowInteractiveExpand, !isExpandCollapsed(this.node), this.intl);
340
351
  if (!this.input || !this.titleContainer || !this.icon) {
341
352
  return;
342
353
  }
@@ -352,6 +363,21 @@ export var ExpandNodeView = /*#__PURE__*/function () {
352
363
  // Prevent ProseMirror from getting a focus event (causes weird selection issues).
353
364
  this.titleContainer.addEventListener('focus', this.handleFocus);
354
365
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
366
+ if ((_this$api6 = this.api) !== null && _this$api6 !== void 0 && _this$api6.editorDisabled && getBooleanFF('platform.editor.live-view.disable-editing-in-view-mode_fi1rx')) {
367
+ this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
368
+ var editorDisabled = sharedState.nextSharedState.editorDisabled;
369
+ if (_this.input) {
370
+ if (editorDisabled) {
371
+ _this.input.setAttribute('readonly', 'true');
372
+ } else {
373
+ _this.input.removeAttribute('readonly');
374
+ }
375
+ }
376
+ if (_this.content) {
377
+ _this.content.setAttribute('contenteditable', _this.getContentEditable(_this.node) ? 'true' : 'false');
378
+ }
379
+ });
380
+ }
355
381
  }
356
382
  _createClass(ExpandNodeView, [{
357
383
  key: "stopEvent",
@@ -385,13 +411,27 @@ export var ExpandNodeView = /*#__PURE__*/function () {
385
411
  _this2.input.value = _this2.node.attrs.title;
386
412
  }
387
413
  });
388
- if (this.node !== node) {
414
+
415
+ // This solves for a bug where the breakout plugin updates the node
416
+ // but by the time it reaches the update, it gives us the expand after
417
+ if (this.node !== node && this.node.attrs.title !== node.attrs.title) {
418
+ var shouldBeExpanded = expandedState.get(node);
419
+ if (shouldBeExpanded === undefined) {
420
+ expandedState.set(node, true);
421
+ }
422
+ this.updateExpandToggleIcon(node);
423
+ } else if (this.node !== node) {
424
+ // This checks if the node has been replaced with a different version
425
+ // and updates the state of the new node to match the old one
389
426
  var previousExpandedState = expandedState.get(this.node);
390
427
  if (previousExpandedState === undefined) {
391
428
  previousExpandedState = true;
392
429
  }
393
430
  expandedState.set(node, previousExpandedState);
394
- expandedState.delete(this.node);
431
+ }
432
+ if (this.content) {
433
+ // Disallow interaction/selection inside when collapsed.
434
+ this.content.setAttribute('contenteditable', this.getContentEditable(node) ? 'true' : 'false');
395
435
  }
396
436
  this.node = node;
397
437
  return true;
@@ -400,13 +440,13 @@ export var ExpandNodeView = /*#__PURE__*/function () {
400
440
  }
401
441
  }, {
402
442
  key: "updateExpandToggleIcon",
403
- value: function updateExpandToggleIcon() {
404
- var expanded = expandedState.get(this.node) ? expandedState.get(this.node) : false;
443
+ value: function updateExpandToggleIcon(node) {
444
+ var expanded = expandedState.get(node) ? expandedState.get(node) : false;
405
445
  if (this.dom && expanded !== undefined) {
406
- var _expandedState$get2;
407
- this.dom.className = buildExpandClassName(this.node.type.name, expanded);
446
+ var _expandedState$get;
447
+ this.dom.className = buildExpandClassName(node.type.name, expanded);
408
448
  // Re-render the icon to update the aria-expanded attribute
409
- renderIcon(this.icon ? this.icon : null, this.allowInteractiveExpand, (_expandedState$get2 = expandedState.get(this.node)) !== null && _expandedState$get2 !== void 0 ? _expandedState$get2 : false, this.intl);
449
+ renderIcon(this.icon ? this.icon : null, this.allowInteractiveExpand, (_expandedState$get = expandedState.get(node)) !== null && _expandedState$get !== void 0 ? _expandedState$get : false, this.intl);
410
450
  }
411
451
  this.updateExpandBodyContentEditable();
412
452
  }
@@ -433,8 +473,10 @@ export var ExpandNodeView = /*#__PURE__*/function () {
433
473
  this.titleContainer.removeEventListener('focus', this.handleFocus);
434
474
  this.icon.removeEventListener('keydown', this.handleIconKeyDown);
435
475
  (_this$decorationClean2 = this.decorationCleanup) === null || _this$decorationClean2 === void 0 || _this$decorationClean2.call(this);
476
+ if (this.cleanUpEditorDisabledOnChange) {
477
+ this.cleanUpEditorDisabledOnChange();
478
+ }
436
479
  ReactDOM.unmountComponentAtNode(this.icon);
437
- expandedState.delete(this.node);
438
480
  }
439
481
  }]);
440
482
  return ExpandNodeView;
@@ -3,11 +3,12 @@ import ReactDOM from 'react-dom';
3
3
  import { expandedState } from '@atlaskit/editor-common/expand';
4
4
  import { expandClassNames } from '@atlaskit/editor-common/styles';
5
5
  import { expandMessages } from '@atlaskit/editor-common/ui';
6
+ import { getBooleanFF } from '@atlaskit/platform-feature-flags';
6
7
  import { ExpandButton } from '../ui/ExpandButton';
7
8
  export var buildExpandClassName = function buildExpandClassName(type, expanded) {
8
9
  return "".concat(expandClassNames.prefix, " ").concat(expandClassNames.type(type), " ").concat(expanded ? expandClassNames.expanded : '');
9
10
  };
10
- export var toDOM = function toDOM(node, __livePage, intl) {
11
+ export var toDOM = function toDOM(node, __livePage, intl, titleReadOnly, contentEditable) {
11
12
  var _expandedState$get;
12
13
  return ['div', {
13
14
  // prettier-ignore
@@ -34,11 +35,12 @@ export var toDOM = function toDOM(node, __livePage, intl) {
34
35
  'class': expandClassNames.titleInput,
35
36
  value: node.attrs.title,
36
37
  placeholder: intl && typeof intl.formatMessage === 'function' && intl.formatMessage(expandMessages.expandPlaceholderText) || expandMessages.expandPlaceholderText.defaultMessage,
37
- type: 'text'
38
- }]]],
39
- // prettier-ignore
40
- ['div', {
41
- 'class': expandClassNames.content
38
+ type: 'text',
39
+ readonly: getBooleanFF('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') && titleReadOnly ? 'true' : undefined
40
+ }]]], ['div', {
41
+ // prettier-ignore
42
+ class: expandClassNames.content,
43
+ contenteditable: getBooleanFF('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') && contentEditable ? contentEditable ? 'true' : 'false' : undefined
42
44
  }, 0]];
43
45
  };
44
46
  export var renderIcon = function renderIcon(icon, allowInteractiveExpand, expanded, intl) {
@@ -7,6 +7,7 @@ import type { ExpandPlugin } from '../../types';
7
7
  export declare class ExpandNodeView implements NodeView {
8
8
  private selectNearNode;
9
9
  private __livePage;
10
+ private cleanUpEditorDisabledOnChange?;
10
11
  node: PmNode;
11
12
  view: EditorView;
12
13
  dom: HTMLElement;
@@ -21,7 +22,7 @@ export declare class ExpandNodeView implements NodeView {
21
22
  isMobile: boolean;
22
23
  api: ExtractInjectionAPI<ExpandPlugin> | undefined;
23
24
  decorationCleanup?: () => boolean | undefined;
24
- constructor(node: PmNode, view: EditorView, getPos: getPosHandlerNode, getIntl: () => IntlShape, isMobile: boolean, selectNearNode: SetSelectionRelativeToNode | undefined, api: ExtractInjectionAPI<ExpandPlugin> | undefined, allowInteractiveExpand?: boolean, __livePage?: boolean);
25
+ constructor(node: PmNode, view: EditorView, getPos: getPosHandlerNode, getIntl: () => IntlShape, isMobile: boolean, selectNearNode: SetSelectionRelativeToNode | undefined, api: ExtractInjectionAPI<ExpandPlugin> | undefined, allowInteractiveExpand?: boolean, __livePage?: boolean, cleanUpEditorDisabledOnChange?: (() => void) | undefined);
25
26
  private focusTitle;
26
27
  private handleIconKeyDown;
27
28
  private handleClick;
@@ -38,13 +39,14 @@ export declare class ExpandNodeView implements NodeView {
38
39
  private setLeftGapCursor;
39
40
  private handleArrowRightFromTitle;
40
41
  private handleArrowLeftFromTitle;
42
+ private getContentEditable;
41
43
  stopEvent(event: Event): boolean;
42
44
  ignoreMutation(mutationRecord: MutationRecord | {
43
45
  type: 'selection';
44
46
  target: Element;
45
47
  }): boolean;
46
48
  update(node: PmNode, _decorations: readonly Decoration[]): boolean;
47
- updateExpandToggleIcon(): void;
49
+ updateExpandToggleIcon(node: PmNode): void;
48
50
  updateExpandBodyContentEditable(): void;
49
51
  destroy(): void;
50
52
  }
@@ -1,5 +1,5 @@
1
1
  import type { IntlShape } from 'react-intl-next';
2
2
  import type { DOMOutputSpec, Node as PmNode } from '@atlaskit/editor-prosemirror/model';
3
3
  export declare const buildExpandClassName: (type: string, expanded: boolean) => string;
4
- export declare const toDOM: (node: PmNode, __livePage: boolean, intl?: IntlShape) => DOMOutputSpec;
4
+ export declare const toDOM: (node: PmNode, __livePage: boolean, intl?: IntlShape, titleReadOnly?: boolean, contentEditable?: boolean) => DOMOutputSpec;
5
5
  export declare const renderIcon: (icon: HTMLElement | null, allowInteractiveExpand: boolean, expanded: boolean, intl?: IntlShape) => void;
@@ -7,6 +7,7 @@ import type { ExpandPlugin } from '../../types';
7
7
  export declare class ExpandNodeView implements NodeView {
8
8
  private selectNearNode;
9
9
  private __livePage;
10
+ private cleanUpEditorDisabledOnChange?;
10
11
  node: PmNode;
11
12
  view: EditorView;
12
13
  dom: HTMLElement;
@@ -21,7 +22,7 @@ export declare class ExpandNodeView implements NodeView {
21
22
  isMobile: boolean;
22
23
  api: ExtractInjectionAPI<ExpandPlugin> | undefined;
23
24
  decorationCleanup?: () => boolean | undefined;
24
- constructor(node: PmNode, view: EditorView, getPos: getPosHandlerNode, getIntl: () => IntlShape, isMobile: boolean, selectNearNode: SetSelectionRelativeToNode | undefined, api: ExtractInjectionAPI<ExpandPlugin> | undefined, allowInteractiveExpand?: boolean, __livePage?: boolean);
25
+ constructor(node: PmNode, view: EditorView, getPos: getPosHandlerNode, getIntl: () => IntlShape, isMobile: boolean, selectNearNode: SetSelectionRelativeToNode | undefined, api: ExtractInjectionAPI<ExpandPlugin> | undefined, allowInteractiveExpand?: boolean, __livePage?: boolean, cleanUpEditorDisabledOnChange?: (() => void) | undefined);
25
26
  private focusTitle;
26
27
  private handleIconKeyDown;
27
28
  private handleClick;
@@ -38,13 +39,14 @@ export declare class ExpandNodeView implements NodeView {
38
39
  private setLeftGapCursor;
39
40
  private handleArrowRightFromTitle;
40
41
  private handleArrowLeftFromTitle;
42
+ private getContentEditable;
41
43
  stopEvent(event: Event): boolean;
42
44
  ignoreMutation(mutationRecord: MutationRecord | {
43
45
  type: 'selection';
44
46
  target: Element;
45
47
  }): boolean;
46
48
  update(node: PmNode, _decorations: readonly Decoration[]): boolean;
47
- updateExpandToggleIcon(): void;
49
+ updateExpandToggleIcon(node: PmNode): void;
48
50
  updateExpandBodyContentEditable(): void;
49
51
  destroy(): void;
50
52
  }
@@ -1,5 +1,5 @@
1
1
  import type { IntlShape } from 'react-intl-next';
2
2
  import type { DOMOutputSpec, Node as PmNode } from '@atlaskit/editor-prosemirror/model';
3
3
  export declare const buildExpandClassName: (type: string, expanded: boolean) => string;
4
- export declare const toDOM: (node: PmNode, __livePage: boolean, intl?: IntlShape) => DOMOutputSpec;
4
+ export declare const toDOM: (node: PmNode, __livePage: boolean, intl?: IntlShape, titleReadOnly?: boolean, contentEditable?: boolean) => DOMOutputSpec;
5
5
  export declare const renderIcon: (icon: HTMLElement | null, allowInteractiveExpand: boolean, expanded: boolean, intl?: IntlShape) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-expand",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "description": "Expand plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -33,9 +33,9 @@
33
33
  ".": "./src/index.ts"
34
34
  },
35
35
  "dependencies": {
36
- "@atlaskit/adf-schema": "^35.10.0",
36
+ "@atlaskit/adf-schema": "^35.12.1",
37
37
  "@atlaskit/button": "^17.14.0",
38
- "@atlaskit/editor-common": "^78.33.0",
38
+ "@atlaskit/editor-common": "^78.36.0",
39
39
  "@atlaskit/editor-plugin-analytics": "^1.1.0",
40
40
  "@atlaskit/editor-plugin-decorations": "^1.1.0",
41
41
  "@atlaskit/editor-plugin-editor-disabled": "^1.1.0",
@@ -61,7 +61,7 @@
61
61
  "@atlaskit/editor-plugin-content-insertion": "^1.1.0",
62
62
  "@atlaskit/editor-plugin-guideline": "^1.1.0",
63
63
  "@atlaskit/editor-plugin-quick-insert": "^1.1.0",
64
- "@atlaskit/editor-plugin-table": "^7.10.0",
64
+ "@atlaskit/editor-plugin-table": "^7.11.0",
65
65
  "@atlaskit/editor-plugin-type-ahead": "^1.1.0",
66
66
  "@atlaskit/editor-plugin-width": "^1.1.0",
67
67
  "@atlassian/atlassian-frontend-prettier-config-1.0.0": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.0",