@atlaskit/editor-plugin-expand 20.0.2 → 20.0.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,24 @@
1
1
  # @atlaskit/editor-plugin-expand
2
2
 
3
+ ## 20.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [`ad905e52e6f1b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/ad905e52e6f1b) -
8
+ CONFCLOUD-84260: Include the expand title in body accessible names, localize the macro role
9
+ description, and keep them updated behind `platform_editor_expand_content_a11y_2`.
10
+ - [`fc26bfc51dd5c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fc26bfc51dd5c) -
11
+ Add sparse block-control surface anchors, intersection-driven candidates, and explicit visibility
12
+ invalidation for registry-backed block controls. Expose registration change subscriptions from the
13
+ UI control registry model, and refresh cached visibility from suggestion and collapse transaction
14
+ metadata. Under `platform_editor_block_control_migration`, use native node-anchor identity across
15
+ Editor and Block Controls, and route expand keyboard focus through the shared Block Controls
16
+ command. Preserve Show Diff visibility checks in both migration cohorts so block controls stay
17
+ hidden while a diff is displayed. Keep the block menu closed when a migrated layout-column handle
18
+ opens the layout menu, and close the layout menu when the selection moves away from its selected
19
+ columns.
20
+ - Updated dependencies
21
+
3
22
  ## 20.0.2
4
23
 
5
24
  ### Patch Changes
@@ -6,12 +6,14 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.ExpandNodeView = void 0;
8
8
  exports.default = _default;
9
+ exports.getExpandBodyAriaLabel = getExpandBodyAriaLabel;
9
10
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
10
11
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
11
12
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
12
13
  var _react = _interopRequireDefault(require("react"));
13
14
  var _uuid = require("uuid");
14
15
  var _w3cKeyname = require("w3c-keyname");
16
+ var _surfaceKeys = require("@atlaskit/editor-common/block-controls/surface-keys");
15
17
  var _selection = require("@atlaskit/editor-common/selection");
16
18
  var _styles = require("@atlaskit/editor-common/styles");
17
19
  var _ui = require("@atlaskit/editor-common/ui");
@@ -32,7 +34,14 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
32
34
  function buildExpandClassName(type, expanded) {
33
35
  return "".concat(_styles.expandClassNames.prefix, " ").concat(_styles.expandClassNames.type(type), " ").concat(expanded ? _styles.expandClassNames.expanded : '');
34
36
  }
37
+ function getExpandBodyAriaLabel(title, intl) {
38
+ var safeTitle = title.trim() || (intl === null || intl === void 0 ? void 0 : intl.formatMessage(_ui.expandMessages.expandBodyAriaLabelUntitled)) || _ui.expandMessages.expandBodyAriaLabelUntitled.defaultMessage;
39
+ return (intl === null || intl === void 0 ? void 0 : intl.formatMessage(_ui.expandMessages.expandBodyAriaLabel, {
40
+ title: safeTitle
41
+ })) || _ui.expandMessages.expandBodyAriaLabel.defaultMessage.replace('{title}', safeTitle);
42
+ }
35
43
  var toDOM = function toDOM(node, __livePage, intl, titleReadOnly, contentEditable) {
44
+ var _node$attrs$title, _intl$formatMessage;
36
45
  return ['div', _objectSpread({
37
46
  // prettier-ignore
38
47
  'class': buildExpandClassName(node.type.name, __livePage ? !node.attrs.__expanded : node.attrs.__expanded),
@@ -64,14 +73,19 @@ var toDOM = function toDOM(node, __livePage, intl, titleReadOnly, contentEditabl
64
73
  placeholder: intl && intl.formatMessage(_ui.expandMessages.expandPlaceholderText) || _ui.expandMessages.expandPlaceholderText.defaultMessage,
65
74
  type: 'text',
66
75
  readonly: titleReadOnly ? 'true' : undefined
67
- }]]], ['div', {
76
+ }]]], [(0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_expand_content_a11y_2') ? 'section' : 'div', _objectSpread(_objectSpread({
68
77
  // prettier-ignore
69
78
  class: "".concat(_styles.expandClassNames.content, " ").concat((__livePage ? !node.attrs.__expanded : node.attrs.__expanded) ? '' : _styles.expandClassNames.contentCollapsed),
70
- contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined,
79
+ contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined
80
+ }, !(0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_expand_content_a11y_2') && {
71
81
  role: 'textbox',
72
82
  'aria-multiline': 'true',
73
- 'aria-label': intl && intl.formatMessage(_ui.expandMessages.expandBodyAriaLabel) || _ui.expandMessages.expandBodyAriaLabel.defaultMessage
74
- }, 0]];
83
+ 'aria-label': intl && intl.formatMessage(_ui.expandMessages.expandBodyAriaLabelOriginal) || _ui.expandMessages.expandBodyAriaLabelOriginal.defaultMessage
84
+ }), (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_expand_content_a11y_2') && {
85
+ 'aria-label': getExpandBodyAriaLabel((_node$attrs$title = node.attrs.title) !== null && _node$attrs$title !== void 0 ? _node$attrs$title : '', intl),
86
+ 'aria-description': (intl === null || intl === void 0 ? void 0 : intl.formatMessage(_ui.expandMessages.expandBodyAriaDescription)) || _ui.expandMessages.expandBodyAriaDescription.defaultMessage,
87
+ 'aria-roledescription': (_intl$formatMessage = intl === null || intl === void 0 ? void 0 : intl.formatMessage(_ui.expandMessages.expandBodyRoleDescription)) !== null && _intl$formatMessage !== void 0 ? _intl$formatMessage : _ui.expandMessages.expandBodyRoleDescription.defaultMessage
88
+ }), 0]];
75
89
  };
76
90
  var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
77
91
  function ExpandNodeView(_node, view, getPos, getIntl, isMobile, selectNearNode, api, nodeViewPortalProviderAPI) {
@@ -202,21 +216,30 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
202
216
  (_this$api3 = _this.api) === null || _this$api3 === void 0 || _this$api3.core.actions.execute(function (_ref) {
203
217
  var tr = _ref.tr;
204
218
  tr.setSelection(_state.NodeSelection.create(state.doc, pos));
205
- // Show the drag handle on the selected expand node
219
+ if ((0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration')) {
220
+ var _this$api4;
221
+ var command = (_this$api4 = _this.api) === null || _this$api4 === void 0 || (_this$api4 = _this$api4.blockControls) === null || _this$api4 === void 0 ? void 0 : _this$api4.commands.showControlAtPosition(pos, _surfaceKeys.BLOCK_CONTROLS_DRAG_HANDLE, {
222
+ isFocused: true
223
+ });
224
+ if (command) {
225
+ return command({
226
+ tr: tr
227
+ });
228
+ }
229
+ return null;
230
+ }
206
231
  var node = state.doc.nodeAt(pos);
207
232
  if (node) {
208
- // Find the anchor name from the DOM
209
233
  var dom = _this.view.nodeDOM(pos);
210
234
  if (dom instanceof HTMLElement) {
211
235
  var anchorName = dom.getAttribute('data-node-anchor');
212
- // Only proceed if we found a valid anchor name
213
236
  if (anchorName) {
214
- var _this$api4;
215
- var command = (_this$api4 = _this.api) === null || _this$api4 === void 0 || (_this$api4 = _this$api4.blockControls) === null || _this$api4 === void 0 ? void 0 : _this$api4.commands.showDragHandleAt(pos, anchorName, node.type.name, {
237
+ var _this$api5;
238
+ var _command = (_this$api5 = _this.api) === null || _this$api5 === void 0 || (_this$api5 = _this$api5.blockControls) === null || _this$api5 === void 0 ? void 0 : _this$api5.commands.showDragHandleAt(pos, anchorName, node.type.name, {
216
239
  isFocused: true
217
240
  });
218
- if (command) {
219
- return command({
241
+ if (_command) {
242
+ return _command({
220
243
  tr: tr
221
244
  });
222
245
  }
@@ -294,8 +317,8 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
294
317
  var state = _this.view.state;
295
318
  var expandNode = _this.node;
296
319
  if (expandNode && (0, _utils.isEmptyNode)(state.schema)(expandNode)) {
297
- var _this$api5;
298
- (0, _commands.deleteExpandAtPos)((_this$api5 = _this.api) === null || _this$api5 === void 0 || (_this$api5 = _this$api5.analytics) === null || _this$api5 === void 0 ? void 0 : _this$api5.actions)(pos, expandNode)(state, _this.view.dispatch);
320
+ var _this$api6;
321
+ (0, _commands.deleteExpandAtPos)((_this$api6 = _this.api) === null || _this$api6 === void 0 || (_this$api6 = _this$api6.analytics) === null || _this$api6 === void 0 ? void 0 : _this$api6.actions)(pos, expandNode)(state, _this.view.dispatch);
299
322
  }
300
323
  });
301
324
  (0, _defineProperty2.default)(this, "toggleExpand", function () {
@@ -304,12 +327,12 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
304
327
  return;
305
328
  }
306
329
  if (_this.allowInteractiveExpand) {
307
- var _this$api6;
330
+ var _this$api7;
308
331
  var _this$view4 = _this.view,
309
332
  state = _this$view4.state,
310
333
  dispatch = _this$view4.dispatch;
311
334
  (0, _commands.toggleExpandExpanded)({
312
- editorAnalyticsAPI: (_this$api6 = _this.api) === null || _this$api6 === void 0 || (_this$api6 = _this$api6.analytics) === null || _this$api6 === void 0 ? void 0 : _this$api6.actions,
335
+ editorAnalyticsAPI: (_this$api7 = _this.api) === null || _this$api7 === void 0 || (_this$api7 = _this$api7.analytics) === null || _this$api7 === void 0 ? void 0 : _this$api7.actions,
313
336
  pos: pos,
314
337
  nodeType: _this.node.type,
315
338
  __livePage: _this.__livePage
@@ -461,13 +484,13 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
461
484
  selectionStart = _this$input6.selectionStart,
462
485
  selectionEnd = _this$input6.selectionEnd;
463
486
  if (selectionStart === selectionEnd && selectionStart === 0) {
464
- var _this$api7;
487
+ var _this$api8;
465
488
  event.preventDefault();
466
489
  var _this$view0 = _this.view,
467
490
  state = _this$view0.state,
468
491
  dispatch = _this$view0.dispatch;
469
492
  _this.view.focus();
470
- var selectionSharedState = ((_this$api7 = _this.api) === null || _this$api7 === void 0 || (_this$api7 = _this$api7.selection) === null || _this$api7 === void 0 ? void 0 : _this$api7.sharedState.currentState()) || {};
493
+ var selectionSharedState = ((_this$api8 = _this.api) === null || _this$api8 === void 0 || (_this$api8 = _this$api8.selection) === null || _this$api8 === void 0 ? void 0 : _this$api8.sharedState.currentState()) || {};
471
494
  // selectionRelativeToNode is undefined when user clicked to select node, then hit left to get focus in title
472
495
  // This is a special case where we want to bypass node selection and jump straight to gap cursor
473
496
  if ((selectionSharedState === null || selectionSharedState === void 0 ? void 0 : selectionSharedState.selectionRelativeToNode) === undefined) {
@@ -554,7 +577,7 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
554
577
  return (0, _createClass2.default)(ExpandNodeView, [{
555
578
  key: "initHandlers",
556
579
  value: function initHandlers() {
557
- var _this$api8,
580
+ var _this$api9,
558
581
  _this2 = this;
559
582
  if (this.dom) {
560
583
  // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
@@ -580,7 +603,7 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
580
603
  // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
581
604
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
582
605
  }
583
- if ((_this$api8 = this.api) !== null && _this$api8 !== void 0 && _this$api8.editorDisabled) {
606
+ if ((_this$api9 = this.api) !== null && _this$api9 !== void 0 && _this$api9.editorDisabled) {
584
607
  this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
585
608
  var editorDisabled = sharedState.nextSharedState.editorDisabled;
586
609
  if (_this2.input) {
@@ -650,13 +673,13 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
650
673
  }, {
651
674
  key: "isLimitedModeEnabled",
652
675
  value: function isLimitedModeEnabled() {
653
- var _this$api9;
676
+ var _this$api0;
654
677
  // Read from `this.view.state` via the exposed plugin key rather than the shared state's
655
678
  // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
656
679
  // API's editor state isn't wired up yet).
657
680
  //
658
681
  // Reads the plugin's derived `enabled`, so this covers every reason limited mode can be on.
659
- return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedMode) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.sharedState.currentState()) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedModePluginKey) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.getState(this.view.state)) === null || _this$api9 === void 0 ? void 0 : _this$api9.enabled);
682
+ return Boolean((_this$api0 = this.api) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.limitedMode) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.sharedState.currentState()) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.limitedModePluginKey) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.getState(this.view.state)) === null || _this$api0 === void 0 ? void 0 : _this$api0.enabled);
660
683
  }
661
684
  }, {
662
685
  key: "stopEvent",
@@ -718,6 +741,12 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
718
741
  _this4.input.value = _this4.node.attrs.title;
719
742
  }
720
743
  });
744
+ if ((0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_expand_content_a11y_2')) {
745
+ if (this.node.attrs.title !== node.attrs.title && this.content) {
746
+ var _node$attrs$title2;
747
+ this.content.setAttribute('aria-label', getExpandBodyAriaLabel((_node$attrs$title2 = node.attrs.title) !== null && _node$attrs$title2 !== void 0 ? _node$attrs$title2 : '', this.intl));
748
+ }
749
+ }
721
750
  this.node = node;
722
751
  return true;
723
752
  }
@@ -12,6 +12,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
12
12
  var _react = _interopRequireDefault(require("react"));
13
13
  var _uuid = require("uuid");
14
14
  var _w3cKeyname = require("w3c-keyname");
15
+ var _surfaceKeys = require("@atlaskit/editor-common/block-controls/surface-keys");
15
16
  var _expand = require("@atlaskit/editor-common/expand");
16
17
  var _selection = require("@atlaskit/editor-common/selection");
17
18
  var _styles = require("@atlaskit/editor-common/styles");
@@ -34,7 +35,7 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
34
35
  var _this = this,
35
36
  _expandedState$get,
36
37
  _api$editorDisabled,
37
- _this$api8;
38
+ _this$api9;
38
39
  var allowInteractiveExpand = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : true;
39
40
  var __livePage = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
40
41
  var cleanUpEditorDisabledOnChange = arguments.length > 10 ? arguments[10] : undefined;
@@ -160,21 +161,30 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
160
161
  (_this$api3 = _this.api) === null || _this$api3 === void 0 || _this$api3.core.actions.execute(function (_ref) {
161
162
  var tr = _ref.tr;
162
163
  tr.setSelection(_state.NodeSelection.create(state.doc, pos));
163
- // Show the drag handle on the selected expand node
164
+ if ((0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_control_migration')) {
165
+ var _this$api4;
166
+ var command = (_this$api4 = _this.api) === null || _this$api4 === void 0 || (_this$api4 = _this$api4.blockControls) === null || _this$api4 === void 0 ? void 0 : _this$api4.commands.showControlAtPosition(pos, _surfaceKeys.BLOCK_CONTROLS_DRAG_HANDLE, {
167
+ isFocused: true
168
+ });
169
+ if (command) {
170
+ return command({
171
+ tr: tr
172
+ });
173
+ }
174
+ return null;
175
+ }
164
176
  var node = state.doc.nodeAt(pos);
165
177
  if (node) {
166
- // Find the anchor name from the DOM
167
178
  var dom = _this.view.nodeDOM(pos);
168
179
  if (dom instanceof HTMLElement) {
169
180
  var anchorName = (0, _expValEquals.expValEquals)('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? dom.getAttribute('data-node-anchor') : dom.getAttribute('data-drag-handler-anchor-name');
170
- // Only proceed if we found a valid anchor name
171
181
  if (anchorName) {
172
- var _this$api4;
173
- var command = (_this$api4 = _this.api) === null || _this$api4 === void 0 || (_this$api4 = _this$api4.blockControls) === null || _this$api4 === void 0 ? void 0 : _this$api4.commands.showDragHandleAt(pos, anchorName, node.type.name, {
182
+ var _this$api5;
183
+ var _command = (_this$api5 = _this.api) === null || _this$api5 === void 0 || (_this$api5 = _this$api5.blockControls) === null || _this$api5 === void 0 ? void 0 : _this$api5.commands.showDragHandleAt(pos, anchorName, node.type.name, {
174
184
  isFocused: true
175
185
  });
176
- if (command) {
177
- return command({
186
+ if (_command) {
187
+ return _command({
178
188
  tr: tr
179
189
  });
180
190
  }
@@ -247,8 +257,8 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
247
257
  return;
248
258
  }
249
259
  if (expandNode && (0, _utils.isEmptyNode)(state.schema)(expandNode)) {
250
- var _this$api5;
251
- (0, _commands.deleteExpand)((_this$api5 = _this.api) === null || _this$api5 === void 0 || (_this$api5 = _this$api5.analytics) === null || _this$api5 === void 0 ? void 0 : _this$api5.actions)(state, _this.view.dispatch);
260
+ var _this$api6;
261
+ (0, _commands.deleteExpand)((_this$api6 = _this.api) === null || _this$api6 === void 0 || (_this$api6 = _this$api6.analytics) === null || _this$api6 === void 0 ? void 0 : _this$api6.actions)(state, _this.view.dispatch);
252
262
  }
253
263
  });
254
264
  (0, _defineProperty2.default)(this, "toggleExpand", function () {
@@ -257,12 +267,12 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
257
267
  return;
258
268
  }
259
269
  if (_this.allowInteractiveExpand) {
260
- var _this$api6;
270
+ var _this$api7;
261
271
  var _this$view3 = _this.view,
262
272
  state = _this$view3.state,
263
273
  dispatch = _this$view3.dispatch;
264
274
  (0, _commands.toggleExpandExpanded)({
265
- editorAnalyticsAPI: (_this$api6 = _this.api) === null || _this$api6 === void 0 || (_this$api6 = _this$api6.analytics) === null || _this$api6 === void 0 ? void 0 : _this$api6.actions,
275
+ editorAnalyticsAPI: (_this$api7 = _this.api) === null || _this$api7 === void 0 || (_this$api7 = _this$api7.analytics) === null || _this$api7 === void 0 ? void 0 : _this$api7.actions,
266
276
  pos: pos,
267
277
  node: _this.node
268
278
  })(state, dispatch);
@@ -416,13 +426,13 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
416
426
  selectionStart = _this$input6.selectionStart,
417
427
  selectionEnd = _this$input6.selectionEnd;
418
428
  if (selectionStart === selectionEnd && selectionStart === 0) {
419
- var _this$api7;
429
+ var _this$api8;
420
430
  event.preventDefault();
421
431
  var _this$view9 = _this.view,
422
432
  state = _this$view9.state,
423
433
  dispatch = _this$view9.dispatch;
424
434
  _this.view.focus();
425
- var selectionSharedState = ((_this$api7 = _this.api) === null || _this$api7 === void 0 || (_this$api7 = _this$api7.selection) === null || _this$api7 === void 0 ? void 0 : _this$api7.sharedState.currentState()) || {};
435
+ var selectionSharedState = ((_this$api8 = _this.api) === null || _this$api8 === void 0 || (_this$api8 = _this$api8.selection) === null || _this$api8 === void 0 ? void 0 : _this$api8.sharedState.currentState()) || {};
426
436
  // selectionRelativeToNode is undefined when user clicked to select node, then hit left to get focus in title
427
437
  // This is a special case where we want to bypass node selection and jump straight to gap cursor
428
438
  if ((selectionSharedState === null || selectionSharedState === void 0 ? void 0 : selectionSharedState.selectionRelativeToNode) === undefined) {
@@ -538,7 +548,7 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
538
548
  // Prevent ProseMirror from getting a focus event (causes weird selection issues).
539
549
  this.titleContainer.addEventListener('focus', this.handleFocus);
540
550
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
541
- if ((_this$api8 = this.api) !== null && _this$api8 !== void 0 && _this$api8.editorDisabled) {
551
+ if ((_this$api9 = this.api) !== null && _this$api9 !== void 0 && _this$api9.editorDisabled) {
542
552
  if ((0, _isExperimentEnabled.isExperimentEnabled)('cc_editor_limited_mode_perf_improvements')) {
543
553
  if (this.content) {
544
554
  this.content.setAttribute('contenteditable', this.getContentEditable(this.node) ? 'true' : 'false');
@@ -610,6 +620,12 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
610
620
  }
611
621
  });
612
622
 
623
+ // Sync up the aria-label with the current expand title.
624
+ if ((0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_expand_content_a11y_2') && this.node.attrs.title !== node.attrs.title && this.content) {
625
+ var _node$attrs$title;
626
+ this.content.setAttribute('aria-label', (0, _NodeView.getExpandBodyAriaLabel)((_node$attrs$title = node.attrs.title) !== null && _node$attrs$title !== void 0 ? _node$attrs$title : '', this.intl));
627
+ }
628
+
613
629
  // This checks if the node has been replaced with a different version
614
630
  // and updates the state of the new node to match the old one
615
631
  // Eg. typing in a node changes it to a new node so it must be updated
@@ -666,13 +682,13 @@ var ExpandNodeView = exports.ExpandNodeView = /*#__PURE__*/function () {
666
682
  }, {
667
683
  key: "isLimitedModeEnabled",
668
684
  value: function isLimitedModeEnabled() {
669
- var _this$api9;
685
+ var _this$api0;
670
686
  // Read from `this.view.state` via the exposed plugin key rather than the shared state's
671
687
  // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
672
688
  // API's editor state isn't wired up yet).
673
689
  //
674
690
  // Reads the plugin's derived `enabled`, so this covers every reason limited mode can be on.
675
- return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedMode) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.sharedState.currentState()) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedModePluginKey) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.getState(this.view.state)) === null || _this$api9 === void 0 ? void 0 : _this$api9.enabled);
691
+ return Boolean((_this$api0 = this.api) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.limitedMode) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.sharedState.currentState()) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.limitedModePluginKey) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.getState(this.view.state)) === null || _this$api0 === void 0 ? void 0 : _this$api0.enabled);
676
692
  }
677
693
  }, {
678
694
  key: "updateDisplayStyle",
@@ -4,19 +4,26 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.toDOM = exports.buildExpandClassName = void 0;
7
+ exports.toDOM = exports.getExpandBodyAriaLabel = exports.buildExpandClassName = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _expand = require("@atlaskit/editor-common/expand");
10
10
  var _styles = require("@atlaskit/editor-common/styles");
11
11
  var _ui = require("@atlaskit/editor-common/ui");
12
+ var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
12
13
  var _fg = require("@atlaskit/platform-feature-flags/fg");
13
14
  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; }
14
15
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
15
16
  var buildExpandClassName = exports.buildExpandClassName = function buildExpandClassName(type, expanded) {
16
17
  return "".concat(_styles.expandClassNames.prefix, " ").concat(_styles.expandClassNames.type(type), " ").concat(expanded ? _styles.expandClassNames.expanded : '');
17
18
  };
19
+ var getExpandBodyAriaLabel = exports.getExpandBodyAriaLabel = function getExpandBodyAriaLabel(title, intl) {
20
+ var safeTitle = title.trim() || (intl === null || intl === void 0 ? void 0 : intl.formatMessage(_ui.expandMessages.expandBodyAriaLabelUntitled)) || _ui.expandMessages.expandBodyAriaLabelUntitled.defaultMessage;
21
+ return (intl === null || intl === void 0 ? void 0 : intl.formatMessage(_ui.expandMessages.expandBodyAriaLabel, {
22
+ title: safeTitle
23
+ })) || _ui.expandMessages.expandBodyAriaLabel.defaultMessage.replace('{title}', safeTitle);
24
+ };
18
25
  var toDOM = exports.toDOM = function toDOM(node, __livePage, intl, titleReadOnly, contentEditable) {
19
- var _expandedState$get;
26
+ var _expandedState$get, _node$attrs$title, _intl$formatMessage;
20
27
  return ['div', _objectSpread({
21
28
  // prettier-ignore
22
29
  'class': buildExpandClassName(node.type.name, (_expandedState$get = _expand.expandedState.get(node)) !== null && _expandedState$get !== void 0 ? _expandedState$get : false),
@@ -48,12 +55,17 @@ var toDOM = exports.toDOM = function toDOM(node, __livePage, intl, titleReadOnly
48
55
  placeholder: intl && typeof intl.formatMessage === 'function' && intl.formatMessage(_ui.expandMessages.expandPlaceholderText) || _ui.expandMessages.expandPlaceholderText.defaultMessage,
49
56
  type: 'text',
50
57
  readonly: titleReadOnly ? 'true' : undefined
51
- }]]], ['div', {
58
+ }]]], [(0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_expand_content_a11y_2') ? 'section' : 'div', _objectSpread(_objectSpread({
52
59
  // prettier-ignore
53
60
  class: "".concat(_styles.expandClassNames.content, " ").concat(_expand.expandedState.get(node) ? '' : _styles.expandClassNames.contentCollapsed),
54
- contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined,
61
+ contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined
62
+ }, !(0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_expand_content_a11y_2') && {
55
63
  role: 'textbox',
56
64
  'aria-multiline': 'true',
57
- 'aria-label': intl && intl.formatMessage(_ui.expandMessages.expandBodyAriaLabel) || _ui.expandMessages.expandBodyAriaLabel.defaultMessage
58
- }, 0]];
65
+ 'aria-label': intl && intl.formatMessage(_ui.expandMessages.expandBodyAriaLabelOriginal) || _ui.expandMessages.expandBodyAriaLabelOriginal.defaultMessage
66
+ }), (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_expand_content_a11y_2') && {
67
+ 'aria-label': getExpandBodyAriaLabel((_node$attrs$title = node.attrs.title) !== null && _node$attrs$title !== void 0 ? _node$attrs$title : '', intl),
68
+ 'aria-description': (intl === null || intl === void 0 ? void 0 : intl.formatMessage(_ui.expandMessages.expandBodyAriaDescription)) || _ui.expandMessages.expandBodyAriaDescription.defaultMessage,
69
+ 'aria-roledescription': (_intl$formatMessage = intl === null || intl === void 0 ? void 0 : intl.formatMessage(_ui.expandMessages.expandBodyRoleDescription)) !== null && _intl$formatMessage !== void 0 ? _intl$formatMessage : _ui.expandMessages.expandBodyRoleDescription.defaultMessage
70
+ }), 0]];
59
71
  };
@@ -3,6 +3,7 @@ import React from 'react';
3
3
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
4
4
  import { v4 as uuid } from 'uuid';
5
5
  import { keyName } from 'w3c-keyname';
6
+ import { BLOCK_CONTROLS_DRAG_HANDLE } from '@atlaskit/editor-common/block-controls/surface-keys';
6
7
  import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor-common/selection';
7
8
  import { expandClassNames } from '@atlaskit/editor-common/styles';
8
9
  import { expandMessages } from '@atlaskit/editor-common/ui';
@@ -21,46 +22,62 @@ import { ExpandIconButton } from '../ui/ExpandIconButton';
21
22
  function buildExpandClassName(type, expanded) {
22
23
  return `${expandClassNames.prefix} ${expandClassNames.type(type)} ${expanded ? expandClassNames.expanded : ''}`;
23
24
  }
24
- const toDOM = (node, __livePage, intl, titleReadOnly, contentEditable) => ['div', {
25
- // prettier-ignore
26
- 'class': buildExpandClassName(node.type.name, __livePage ? !node.attrs.__expanded : node.attrs.__expanded),
27
- 'data-node-type': node.type.name,
28
- 'data-title': node.attrs.title,
29
- ...(fg('platform_editor_adf_with_localid') && {
30
- 'data-local-id': node.attrs.localId
31
- })
32
- }, ['div', {
33
- // prettier-ignore
34
- 'class': expandClassNames.titleContainer,
35
- contenteditable: 'false',
36
- // Element gains access to focus events.
37
- // This is needed to prevent PM gaining access
38
- // on interacting with our controls.
39
- tabindex: '-1'
40
- },
41
- // prettier-ignore
42
- ['div', {
43
- 'class': expandClassNames.icon,
44
- style: `display: flex; width: ${"var(--ds-space-300, 24px)"}; height: ${"var(--ds-space-300, 24px)"}`
45
- }], ['div', {
46
- // prettier-ignore
47
- 'class': expandClassNames.inputContainer
48
- }, ['input', {
49
- // prettier-ignore
50
- 'class': expandClassNames.titleInput,
51
- 'aria-label': intl && intl.formatMessage(expandMessages.expandArialabel) || expandMessages.expandArialabel.defaultMessage,
52
- value: node.attrs.title,
53
- placeholder: intl && intl.formatMessage(expandMessages.expandPlaceholderText) || expandMessages.expandPlaceholderText.defaultMessage,
54
- type: 'text',
55
- readonly: titleReadOnly ? 'true' : undefined
56
- }]]], ['div', {
25
+ export function getExpandBodyAriaLabel(title, intl) {
26
+ const safeTitle = title.trim() || (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaLabelUntitled)) || expandMessages.expandBodyAriaLabelUntitled.defaultMessage;
27
+ return (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaLabel, {
28
+ title: safeTitle
29
+ })) || expandMessages.expandBodyAriaLabel.defaultMessage.replace('{title}', safeTitle);
30
+ }
31
+ const toDOM = (node, __livePage, intl, titleReadOnly, contentEditable) => {
32
+ var _node$attrs$title, _intl$formatMessage;
33
+ return ['div', {
34
+ // prettier-ignore
35
+ 'class': buildExpandClassName(node.type.name, __livePage ? !node.attrs.__expanded : node.attrs.__expanded),
36
+ 'data-node-type': node.type.name,
37
+ 'data-title': node.attrs.title,
38
+ ...(fg('platform_editor_adf_with_localid') && {
39
+ 'data-local-id': node.attrs.localId
40
+ })
41
+ }, ['div', {
42
+ // prettier-ignore
43
+ 'class': expandClassNames.titleContainer,
44
+ contenteditable: 'false',
45
+ // Element gains access to focus events.
46
+ // This is needed to prevent PM gaining access
47
+ // on interacting with our controls.
48
+ tabindex: '-1'
49
+ },
57
50
  // prettier-ignore
58
- class: `${expandClassNames.content} ${(__livePage ? !node.attrs.__expanded : node.attrs.__expanded) ? '' : expandClassNames.contentCollapsed}`,
59
- contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined,
60
- role: 'textbox',
61
- 'aria-multiline': 'true',
62
- 'aria-label': intl && intl.formatMessage(expandMessages.expandBodyAriaLabel) || expandMessages.expandBodyAriaLabel.defaultMessage
63
- }, 0]];
51
+ ['div', {
52
+ 'class': expandClassNames.icon,
53
+ style: `display: flex; width: ${"var(--ds-space-300, 24px)"}; height: ${"var(--ds-space-300, 24px)"}`
54
+ }], ['div', {
55
+ // prettier-ignore
56
+ 'class': expandClassNames.inputContainer
57
+ }, ['input', {
58
+ // prettier-ignore
59
+ 'class': expandClassNames.titleInput,
60
+ 'aria-label': intl && intl.formatMessage(expandMessages.expandArialabel) || expandMessages.expandArialabel.defaultMessage,
61
+ value: node.attrs.title,
62
+ placeholder: intl && intl.formatMessage(expandMessages.expandPlaceholderText) || expandMessages.expandPlaceholderText.defaultMessage,
63
+ type: 'text',
64
+ readonly: titleReadOnly ? 'true' : undefined
65
+ }]]], [isExperimentEnabled('platform_editor_expand_content_a11y_2') ? 'section' : 'div', {
66
+ // prettier-ignore
67
+ class: `${expandClassNames.content} ${(__livePage ? !node.attrs.__expanded : node.attrs.__expanded) ? '' : expandClassNames.contentCollapsed}`,
68
+ contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined,
69
+ ...(!isExperimentEnabled('platform_editor_expand_content_a11y_2') && {
70
+ role: 'textbox',
71
+ 'aria-multiline': 'true',
72
+ 'aria-label': intl && intl.formatMessage(expandMessages.expandBodyAriaLabelOriginal) || expandMessages.expandBodyAriaLabelOriginal.defaultMessage
73
+ }),
74
+ ...(isExperimentEnabled('platform_editor_expand_content_a11y_2') && {
75
+ 'aria-label': getExpandBodyAriaLabel((_node$attrs$title = node.attrs.title) !== null && _node$attrs$title !== void 0 ? _node$attrs$title : '', intl),
76
+ 'aria-description': (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaDescription)) || expandMessages.expandBodyAriaDescription.defaultMessage,
77
+ 'aria-roledescription': (_intl$formatMessage = intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyRoleDescription)) !== null && _intl$formatMessage !== void 0 ? _intl$formatMessage : expandMessages.expandBodyRoleDescription.defaultMessage
78
+ })
79
+ }, 0]];
80
+ };
64
81
  export class ExpandNodeView {
65
82
  constructor(_node, view, getPos, getIntl, isMobile, selectNearNode, api, nodeViewPortalProviderAPI, allowInteractiveExpand = true, __livePage = false, cleanUpEditorDisabledOnChange) {
66
83
  var _api$editorDisabled, _api$editorDisabled$s;
@@ -191,17 +208,26 @@ export class ExpandNodeView {
191
208
  tr
192
209
  }) => {
193
210
  tr.setSelection(NodeSelection.create(state.doc, pos));
194
- // Show the drag handle on the selected expand node
211
+ if (isExperimentEnabled('platform_editor_block_control_migration')) {
212
+ var _this$api4, _this$api4$blockContr;
213
+ const command = (_this$api4 = this.api) === null || _this$api4 === void 0 ? void 0 : (_this$api4$blockContr = _this$api4.blockControls) === null || _this$api4$blockContr === void 0 ? void 0 : _this$api4$blockContr.commands.showControlAtPosition(pos, BLOCK_CONTROLS_DRAG_HANDLE, {
214
+ isFocused: true
215
+ });
216
+ if (command) {
217
+ return command({
218
+ tr
219
+ });
220
+ }
221
+ return null;
222
+ }
195
223
  const node = state.doc.nodeAt(pos);
196
224
  if (node) {
197
- // Find the anchor name from the DOM
198
225
  const dom = this.view.nodeDOM(pos);
199
226
  if (dom instanceof HTMLElement) {
200
227
  const anchorName = dom.getAttribute('data-node-anchor');
201
- // Only proceed if we found a valid anchor name
202
228
  if (anchorName) {
203
- var _this$api4, _this$api4$blockContr;
204
- const command = (_this$api4 = this.api) === null || _this$api4 === void 0 ? void 0 : (_this$api4$blockContr = _this$api4.blockControls) === null || _this$api4$blockContr === void 0 ? void 0 : _this$api4$blockContr.commands.showDragHandleAt(pos, anchorName, node.type.name, {
229
+ var _this$api5, _this$api5$blockContr;
230
+ const command = (_this$api5 = this.api) === null || _this$api5 === void 0 ? void 0 : (_this$api5$blockContr = _this$api5.blockControls) === null || _this$api5$blockContr === void 0 ? void 0 : _this$api5$blockContr.commands.showDragHandleAt(pos, anchorName, node.type.name, {
205
231
  isFocused: true
206
232
  });
207
233
  if (command) {
@@ -286,8 +312,8 @@ export class ExpandNodeView {
286
312
  } = this.view;
287
313
  const expandNode = this.node;
288
314
  if (expandNode && isEmptyNode(state.schema)(expandNode)) {
289
- var _this$api5, _this$api5$analytics;
290
- deleteExpandAtPos((_this$api5 = this.api) === null || _this$api5 === void 0 ? void 0 : (_this$api5$analytics = _this$api5.analytics) === null || _this$api5$analytics === void 0 ? void 0 : _this$api5$analytics.actions)(pos, expandNode)(state, this.view.dispatch);
315
+ var _this$api6, _this$api6$analytics;
316
+ deleteExpandAtPos((_this$api6 = this.api) === null || _this$api6 === void 0 ? void 0 : (_this$api6$analytics = _this$api6.analytics) === null || _this$api6$analytics === void 0 ? void 0 : _this$api6$analytics.actions)(pos, expandNode)(state, this.view.dispatch);
291
317
  }
292
318
  });
293
319
  _defineProperty(this, "toggleExpand", () => {
@@ -296,13 +322,13 @@ export class ExpandNodeView {
296
322
  return;
297
323
  }
298
324
  if (this.allowInteractiveExpand) {
299
- var _this$api6, _this$api6$analytics;
325
+ var _this$api7, _this$api7$analytics;
300
326
  const {
301
327
  state,
302
328
  dispatch
303
329
  } = this.view;
304
330
  toggleExpandExpanded({
305
- editorAnalyticsAPI: (_this$api6 = this.api) === null || _this$api6 === void 0 ? void 0 : (_this$api6$analytics = _this$api6.analytics) === null || _this$api6$analytics === void 0 ? void 0 : _this$api6$analytics.actions,
331
+ editorAnalyticsAPI: (_this$api7 = this.api) === null || _this$api7 === void 0 ? void 0 : (_this$api7$analytics = _this$api7.analytics) === null || _this$api7$analytics === void 0 ? void 0 : _this$api7$analytics.actions,
306
332
  pos,
307
333
  nodeType: this.node.type,
308
334
  __livePage: this.__livePage
@@ -464,14 +490,14 @@ export class ExpandNodeView {
464
490
  selectionEnd
465
491
  } = this.input;
466
492
  if (selectionStart === selectionEnd && selectionStart === 0) {
467
- var _this$api7, _this$api7$selection;
493
+ var _this$api8, _this$api8$selection;
468
494
  event.preventDefault();
469
495
  const {
470
496
  state,
471
497
  dispatch
472
498
  } = this.view;
473
499
  this.view.focus();
474
- const selectionSharedState = ((_this$api7 = this.api) === null || _this$api7 === void 0 ? void 0 : (_this$api7$selection = _this$api7.selection) === null || _this$api7$selection === void 0 ? void 0 : _this$api7$selection.sharedState.currentState()) || {};
500
+ const selectionSharedState = ((_this$api8 = this.api) === null || _this$api8 === void 0 ? void 0 : (_this$api8$selection = _this$api8.selection) === null || _this$api8$selection === void 0 ? void 0 : _this$api8$selection.sharedState.currentState()) || {};
475
501
  // selectionRelativeToNode is undefined when user clicked to select node, then hit left to get focus in title
476
502
  // This is a special case where we want to bypass node selection and jump straight to gap cursor
477
503
  if ((selectionSharedState === null || selectionSharedState === void 0 ? void 0 : selectionSharedState.selectionRelativeToNode) === undefined) {
@@ -557,7 +583,7 @@ export class ExpandNodeView {
557
583
  this.initHandlers();
558
584
  }
559
585
  initHandlers() {
560
- var _this$api8;
586
+ var _this$api9;
561
587
  if (this.dom) {
562
588
  // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
563
589
  this.dom.addEventListener('click', this.handleClick);
@@ -582,7 +608,7 @@ export class ExpandNodeView {
582
608
  // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
583
609
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
584
610
  }
585
- if ((_this$api8 = this.api) !== null && _this$api8 !== void 0 && _this$api8.editorDisabled) {
611
+ if ((_this$api9 = this.api) !== null && _this$api9 !== void 0 && _this$api9.editorDisabled) {
586
612
  this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(sharedState => {
587
613
  const editorDisabled = sharedState.nextSharedState.editorDisabled;
588
614
  if (this.input) {
@@ -642,13 +668,13 @@ export class ExpandNodeView {
642
668
  }
643
669
  }
644
670
  isLimitedModeEnabled() {
645
- var _this$api9, _this$api9$limitedMod, _this$api9$limitedMod2, _this$api9$limitedMod3, _this$api9$limitedMod4;
671
+ var _this$api0, _this$api0$limitedMod, _this$api0$limitedMod2, _this$api0$limitedMod3, _this$api0$limitedMod4;
646
672
  // Read from `this.view.state` via the exposed plugin key rather than the shared state's
647
673
  // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
648
674
  // API's editor state isn't wired up yet).
649
675
  //
650
676
  // Reads the plugin's derived `enabled`, so this covers every reason limited mode can be on.
651
- return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 ? void 0 : (_this$api9$limitedMod = _this$api9.limitedMode) === null || _this$api9$limitedMod === void 0 ? void 0 : (_this$api9$limitedMod2 = _this$api9$limitedMod.sharedState.currentState()) === null || _this$api9$limitedMod2 === void 0 ? void 0 : (_this$api9$limitedMod3 = _this$api9$limitedMod2.limitedModePluginKey) === null || _this$api9$limitedMod3 === void 0 ? void 0 : (_this$api9$limitedMod4 = _this$api9$limitedMod3.getState(this.view.state)) === null || _this$api9$limitedMod4 === void 0 ? void 0 : _this$api9$limitedMod4.enabled);
677
+ return Boolean((_this$api0 = this.api) === null || _this$api0 === void 0 ? void 0 : (_this$api0$limitedMod = _this$api0.limitedMode) === null || _this$api0$limitedMod === void 0 ? void 0 : (_this$api0$limitedMod2 = _this$api0$limitedMod.sharedState.currentState()) === null || _this$api0$limitedMod2 === void 0 ? void 0 : (_this$api0$limitedMod3 = _this$api0$limitedMod2.limitedModePluginKey) === null || _this$api0$limitedMod3 === void 0 ? void 0 : (_this$api0$limitedMod4 = _this$api0$limitedMod3.getState(this.view.state)) === null || _this$api0$limitedMod4 === void 0 ? void 0 : _this$api0$limitedMod4.enabled);
652
678
  }
653
679
  stopEvent(event) {
654
680
  // Ignored via go/ees005
@@ -701,6 +727,12 @@ export class ExpandNodeView {
701
727
  this.input.value = this.node.attrs.title;
702
728
  }
703
729
  });
730
+ if (isExperimentEnabled('platform_editor_expand_content_a11y_2')) {
731
+ if (this.node.attrs.title !== node.attrs.title && this.content) {
732
+ var _node$attrs$title2;
733
+ this.content.setAttribute('aria-label', getExpandBodyAriaLabel((_node$attrs$title2 = node.attrs.title) !== null && _node$attrs$title2 !== void 0 ? _node$attrs$title2 : '', this.intl));
734
+ }
735
+ }
704
736
  this.node = node;
705
737
  return true;
706
738
  }
@@ -3,6 +3,7 @@ import React from 'react';
3
3
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
4
4
  import { v4 as uuid } from 'uuid';
5
5
  import { keyName } from 'w3c-keyname';
6
+ import { BLOCK_CONTROLS_DRAG_HANDLE } from '@atlaskit/editor-common/block-controls/surface-keys';
6
7
  import { expandedState, isExpandCollapsed } from '@atlaskit/editor-common/expand';
7
8
  import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor-common/selection';
8
9
  import { expandClassNames } from '@atlaskit/editor-common/styles';
@@ -17,13 +18,13 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
17
18
  import { renderExpandButton } from '../../ui/renderExpandButton';
18
19
  import { deleteExpand, setSelectionInsideExpand, toggleExpandExpanded, updateExpandTitle } from '../commands';
19
20
  import { ExpandButton } from '../ui/ExpandButton';
20
- import { buildExpandClassName, toDOM } from '../ui/NodeView';
21
+ import { buildExpandClassName, getExpandBodyAriaLabel, toDOM } from '../ui/NodeView';
21
22
  import { findReplaceExpandDecorations } from '../utils';
22
23
  export class ExpandNodeView {
23
24
  constructor(_node, view, getPos, getIntl, isMobile, selectNearNode, api, nodeViewPortalProviderAPI, allowInteractiveExpand = true, __livePage = false, cleanUpEditorDisabledOnChange, isExpanded = {
24
25
  expanded: false
25
26
  }) {
26
- var _expandedState$get, _api$editorDisabled, _api$editorDisabled$s, _this$api8;
27
+ var _expandedState$get, _api$editorDisabled, _api$editorDisabled$s, _this$api9;
27
28
  _defineProperty(this, "allowInteractiveExpand", true);
28
29
  _defineProperty(this, "isMobile", false);
29
30
  _defineProperty(this, "focusTitle", () => {
@@ -147,17 +148,26 @@ export class ExpandNodeView {
147
148
  tr
148
149
  }) => {
149
150
  tr.setSelection(NodeSelection.create(state.doc, pos));
150
- // Show the drag handle on the selected expand node
151
+ if (isExperimentEnabled('platform_editor_block_control_migration')) {
152
+ var _this$api4, _this$api4$blockContr;
153
+ const command = (_this$api4 = this.api) === null || _this$api4 === void 0 ? void 0 : (_this$api4$blockContr = _this$api4.blockControls) === null || _this$api4$blockContr === void 0 ? void 0 : _this$api4$blockContr.commands.showControlAtPosition(pos, BLOCK_CONTROLS_DRAG_HANDLE, {
154
+ isFocused: true
155
+ });
156
+ if (command) {
157
+ return command({
158
+ tr
159
+ });
160
+ }
161
+ return null;
162
+ }
151
163
  const node = state.doc.nodeAt(pos);
152
164
  if (node) {
153
- // Find the anchor name from the DOM
154
165
  const dom = this.view.nodeDOM(pos);
155
166
  if (dom instanceof HTMLElement) {
156
167
  const anchorName = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? dom.getAttribute('data-node-anchor') : dom.getAttribute('data-drag-handler-anchor-name');
157
- // Only proceed if we found a valid anchor name
158
168
  if (anchorName) {
159
- var _this$api4, _this$api4$blockContr;
160
- const command = (_this$api4 = this.api) === null || _this$api4 === void 0 ? void 0 : (_this$api4$blockContr = _this$api4.blockControls) === null || _this$api4$blockContr === void 0 ? void 0 : _this$api4$blockContr.commands.showDragHandleAt(pos, anchorName, node.type.name, {
169
+ var _this$api5, _this$api5$blockContr;
170
+ const command = (_this$api5 = this.api) === null || _this$api5 === void 0 ? void 0 : (_this$api5$blockContr = _this$api5.blockControls) === null || _this$api5$blockContr === void 0 ? void 0 : _this$api5$blockContr.commands.showDragHandleAt(pos, anchorName, node.type.name, {
161
171
  isFocused: true
162
172
  });
163
173
  if (command) {
@@ -237,8 +247,8 @@ export class ExpandNodeView {
237
247
  return;
238
248
  }
239
249
  if (expandNode && isEmptyNode(state.schema)(expandNode)) {
240
- var _this$api5, _this$api5$analytics;
241
- deleteExpand((_this$api5 = this.api) === null || _this$api5 === void 0 ? void 0 : (_this$api5$analytics = _this$api5.analytics) === null || _this$api5$analytics === void 0 ? void 0 : _this$api5$analytics.actions)(state, this.view.dispatch);
250
+ var _this$api6, _this$api6$analytics;
251
+ deleteExpand((_this$api6 = this.api) === null || _this$api6 === void 0 ? void 0 : (_this$api6$analytics = _this$api6.analytics) === null || _this$api6$analytics === void 0 ? void 0 : _this$api6$analytics.actions)(state, this.view.dispatch);
242
252
  }
243
253
  });
244
254
  _defineProperty(this, "toggleExpand", () => {
@@ -247,13 +257,13 @@ export class ExpandNodeView {
247
257
  return;
248
258
  }
249
259
  if (this.allowInteractiveExpand) {
250
- var _this$api6, _this$api6$analytics;
260
+ var _this$api7, _this$api7$analytics;
251
261
  const {
252
262
  state,
253
263
  dispatch
254
264
  } = this.view;
255
265
  toggleExpandExpanded({
256
- editorAnalyticsAPI: (_this$api6 = this.api) === null || _this$api6 === void 0 ? void 0 : (_this$api6$analytics = _this$api6.analytics) === null || _this$api6$analytics === void 0 ? void 0 : _this$api6$analytics.actions,
266
+ editorAnalyticsAPI: (_this$api7 = this.api) === null || _this$api7 === void 0 ? void 0 : (_this$api7$analytics = _this$api7.analytics) === null || _this$api7$analytics === void 0 ? void 0 : _this$api7$analytics.actions,
257
267
  pos,
258
268
  node: this.node
259
269
  })(state, dispatch);
@@ -417,14 +427,14 @@ export class ExpandNodeView {
417
427
  selectionEnd
418
428
  } = this.input;
419
429
  if (selectionStart === selectionEnd && selectionStart === 0) {
420
- var _this$api7, _this$api7$selection;
430
+ var _this$api8, _this$api8$selection;
421
431
  event.preventDefault();
422
432
  const {
423
433
  state,
424
434
  dispatch
425
435
  } = this.view;
426
436
  this.view.focus();
427
- const selectionSharedState = ((_this$api7 = this.api) === null || _this$api7 === void 0 ? void 0 : (_this$api7$selection = _this$api7.selection) === null || _this$api7$selection === void 0 ? void 0 : _this$api7$selection.sharedState.currentState()) || {};
437
+ const selectionSharedState = ((_this$api8 = this.api) === null || _this$api8 === void 0 ? void 0 : (_this$api8$selection = _this$api8.selection) === null || _this$api8$selection === void 0 ? void 0 : _this$api8$selection.sharedState.currentState()) || {};
428
438
  // selectionRelativeToNode is undefined when user clicked to select node, then hit left to get focus in title
429
439
  // This is a special case where we want to bypass node selection and jump straight to gap cursor
430
440
  if ((selectionSharedState === null || selectionSharedState === void 0 ? void 0 : selectionSharedState.selectionRelativeToNode) === undefined) {
@@ -539,7 +549,7 @@ export class ExpandNodeView {
539
549
  // Prevent ProseMirror from getting a focus event (causes weird selection issues).
540
550
  this.titleContainer.addEventListener('focus', this.handleFocus);
541
551
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
542
- if ((_this$api8 = this.api) !== null && _this$api8 !== void 0 && _this$api8.editorDisabled) {
552
+ if ((_this$api9 = this.api) !== null && _this$api9 !== void 0 && _this$api9.editorDisabled) {
543
553
  if (isExperimentEnabled('cc_editor_limited_mode_perf_improvements')) {
544
554
  if (this.content) {
545
555
  this.content.setAttribute('contenteditable', this.getContentEditable(this.node) ? 'true' : 'false');
@@ -604,6 +614,12 @@ export class ExpandNodeView {
604
614
  }
605
615
  });
606
616
 
617
+ // Sync up the aria-label with the current expand title.
618
+ if (isExperimentEnabled('platform_editor_expand_content_a11y_2') && this.node.attrs.title !== node.attrs.title && this.content) {
619
+ var _node$attrs$title;
620
+ this.content.setAttribute('aria-label', getExpandBodyAriaLabel((_node$attrs$title = node.attrs.title) !== null && _node$attrs$title !== void 0 ? _node$attrs$title : '', this.intl));
621
+ }
622
+
607
623
  // This checks if the node has been replaced with a different version
608
624
  // and updates the state of the new node to match the old one
609
625
  // Eg. typing in a node changes it to a new node so it must be updated
@@ -652,13 +668,13 @@ export class ExpandNodeView {
652
668
  };
653
669
  }
654
670
  isLimitedModeEnabled() {
655
- var _this$api9, _this$api9$limitedMod, _this$api9$limitedMod2, _this$api9$limitedMod3, _this$api9$limitedMod4;
671
+ var _this$api0, _this$api0$limitedMod, _this$api0$limitedMod2, _this$api0$limitedMod3, _this$api0$limitedMod4;
656
672
  // Read from `this.view.state` via the exposed plugin key rather than the shared state's
657
673
  // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
658
674
  // API's editor state isn't wired up yet).
659
675
  //
660
676
  // Reads the plugin's derived `enabled`, so this covers every reason limited mode can be on.
661
- return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 ? void 0 : (_this$api9$limitedMod = _this$api9.limitedMode) === null || _this$api9$limitedMod === void 0 ? void 0 : (_this$api9$limitedMod2 = _this$api9$limitedMod.sharedState.currentState()) === null || _this$api9$limitedMod2 === void 0 ? void 0 : (_this$api9$limitedMod3 = _this$api9$limitedMod2.limitedModePluginKey) === null || _this$api9$limitedMod3 === void 0 ? void 0 : (_this$api9$limitedMod4 = _this$api9$limitedMod3.getState(this.view.state)) === null || _this$api9$limitedMod4 === void 0 ? void 0 : _this$api9$limitedMod4.enabled);
677
+ return Boolean((_this$api0 = this.api) === null || _this$api0 === void 0 ? void 0 : (_this$api0$limitedMod = _this$api0.limitedMode) === null || _this$api0$limitedMod === void 0 ? void 0 : (_this$api0$limitedMod2 = _this$api0$limitedMod.sharedState.currentState()) === null || _this$api0$limitedMod2 === void 0 ? void 0 : (_this$api0$limitedMod3 = _this$api0$limitedMod2.limitedModePluginKey) === null || _this$api0$limitedMod3 === void 0 ? void 0 : (_this$api0$limitedMod4 = _this$api0$limitedMod3.getState(this.view.state)) === null || _this$api0$limitedMod4 === void 0 ? void 0 : _this$api0$limitedMod4.enabled);
662
678
  }
663
679
  updateDisplayStyle(node) {
664
680
  if (this.content) {
@@ -1,12 +1,19 @@
1
1
  import { expandedState } from '@atlaskit/editor-common/expand';
2
2
  import { expandClassNames } from '@atlaskit/editor-common/styles';
3
3
  import { expandMessages } from '@atlaskit/editor-common/ui';
4
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
4
5
  import { fg } from '@atlaskit/platform-feature-flags/fg';
5
6
  export const buildExpandClassName = (type, expanded) => {
6
7
  return `${expandClassNames.prefix} ${expandClassNames.type(type)} ${expanded ? expandClassNames.expanded : ''}`;
7
8
  };
9
+ export const getExpandBodyAriaLabel = (title, intl) => {
10
+ const safeTitle = title.trim() || (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaLabelUntitled)) || expandMessages.expandBodyAriaLabelUntitled.defaultMessage;
11
+ return (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaLabel, {
12
+ title: safeTitle
13
+ })) || expandMessages.expandBodyAriaLabel.defaultMessage.replace('{title}', safeTitle);
14
+ };
8
15
  export const toDOM = (node, __livePage, intl, titleReadOnly, contentEditable) => {
9
- var _expandedState$get;
16
+ var _expandedState$get, _node$attrs$title, _intl$formatMessage;
10
17
  return ['div', {
11
18
  // prettier-ignore
12
19
  'class': buildExpandClassName(node.type.name, (_expandedState$get = expandedState.get(node)) !== null && _expandedState$get !== void 0 ? _expandedState$get : false),
@@ -39,12 +46,19 @@ export const toDOM = (node, __livePage, intl, titleReadOnly, contentEditable) =>
39
46
  placeholder: intl && typeof intl.formatMessage === 'function' && intl.formatMessage(expandMessages.expandPlaceholderText) || expandMessages.expandPlaceholderText.defaultMessage,
40
47
  type: 'text',
41
48
  readonly: titleReadOnly ? 'true' : undefined
42
- }]]], ['div', {
49
+ }]]], [isExperimentEnabled('platform_editor_expand_content_a11y_2') ? 'section' : 'div', {
43
50
  // prettier-ignore
44
51
  class: `${expandClassNames.content} ${expandedState.get(node) ? '' : expandClassNames.contentCollapsed}`,
45
52
  contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined,
46
- role: 'textbox',
47
- 'aria-multiline': 'true',
48
- 'aria-label': intl && intl.formatMessage(expandMessages.expandBodyAriaLabel) || expandMessages.expandBodyAriaLabel.defaultMessage
53
+ ...(!isExperimentEnabled('platform_editor_expand_content_a11y_2') && {
54
+ role: 'textbox',
55
+ 'aria-multiline': 'true',
56
+ 'aria-label': intl && intl.formatMessage(expandMessages.expandBodyAriaLabelOriginal) || expandMessages.expandBodyAriaLabelOriginal.defaultMessage
57
+ }),
58
+ ...(isExperimentEnabled('platform_editor_expand_content_a11y_2') && {
59
+ 'aria-label': getExpandBodyAriaLabel((_node$attrs$title = node.attrs.title) !== null && _node$attrs$title !== void 0 ? _node$attrs$title : '', intl),
60
+ 'aria-description': (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaDescription)) || expandMessages.expandBodyAriaDescription.defaultMessage,
61
+ 'aria-roledescription': (_intl$formatMessage = intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyRoleDescription)) !== null && _intl$formatMessage !== void 0 ? _intl$formatMessage : expandMessages.expandBodyRoleDescription.defaultMessage
62
+ })
49
63
  }, 0]];
50
64
  };
@@ -7,6 +7,7 @@ import React from 'react';
7
7
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
8
8
  import { v4 as uuid } from 'uuid';
9
9
  import { keyName } from 'w3c-keyname';
10
+ import { BLOCK_CONTROLS_DRAG_HANDLE } from '@atlaskit/editor-common/block-controls/surface-keys';
10
11
  import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor-common/selection';
11
12
  import { expandClassNames } from '@atlaskit/editor-common/styles';
12
13
  import { expandMessages } from '@atlaskit/editor-common/ui';
@@ -25,7 +26,14 @@ import { ExpandIconButton } from '../ui/ExpandIconButton';
25
26
  function buildExpandClassName(type, expanded) {
26
27
  return "".concat(expandClassNames.prefix, " ").concat(expandClassNames.type(type), " ").concat(expanded ? expandClassNames.expanded : '');
27
28
  }
29
+ export function getExpandBodyAriaLabel(title, intl) {
30
+ var safeTitle = title.trim() || (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaLabelUntitled)) || expandMessages.expandBodyAriaLabelUntitled.defaultMessage;
31
+ return (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaLabel, {
32
+ title: safeTitle
33
+ })) || expandMessages.expandBodyAriaLabel.defaultMessage.replace('{title}', safeTitle);
34
+ }
28
35
  var toDOM = function toDOM(node, __livePage, intl, titleReadOnly, contentEditable) {
36
+ var _node$attrs$title, _intl$formatMessage;
29
37
  return ['div', _objectSpread({
30
38
  // prettier-ignore
31
39
  'class': buildExpandClassName(node.type.name, __livePage ? !node.attrs.__expanded : node.attrs.__expanded),
@@ -57,14 +65,19 @@ var toDOM = function toDOM(node, __livePage, intl, titleReadOnly, contentEditabl
57
65
  placeholder: intl && intl.formatMessage(expandMessages.expandPlaceholderText) || expandMessages.expandPlaceholderText.defaultMessage,
58
66
  type: 'text',
59
67
  readonly: titleReadOnly ? 'true' : undefined
60
- }]]], ['div', {
68
+ }]]], [isExperimentEnabled('platform_editor_expand_content_a11y_2') ? 'section' : 'div', _objectSpread(_objectSpread({
61
69
  // prettier-ignore
62
70
  class: "".concat(expandClassNames.content, " ").concat((__livePage ? !node.attrs.__expanded : node.attrs.__expanded) ? '' : expandClassNames.contentCollapsed),
63
- contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined,
71
+ contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined
72
+ }, !isExperimentEnabled('platform_editor_expand_content_a11y_2') && {
64
73
  role: 'textbox',
65
74
  'aria-multiline': 'true',
66
- 'aria-label': intl && intl.formatMessage(expandMessages.expandBodyAriaLabel) || expandMessages.expandBodyAriaLabel.defaultMessage
67
- }, 0]];
75
+ 'aria-label': intl && intl.formatMessage(expandMessages.expandBodyAriaLabelOriginal) || expandMessages.expandBodyAriaLabelOriginal.defaultMessage
76
+ }), isExperimentEnabled('platform_editor_expand_content_a11y_2') && {
77
+ 'aria-label': getExpandBodyAriaLabel((_node$attrs$title = node.attrs.title) !== null && _node$attrs$title !== void 0 ? _node$attrs$title : '', intl),
78
+ 'aria-description': (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaDescription)) || expandMessages.expandBodyAriaDescription.defaultMessage,
79
+ 'aria-roledescription': (_intl$formatMessage = intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyRoleDescription)) !== null && _intl$formatMessage !== void 0 ? _intl$formatMessage : expandMessages.expandBodyRoleDescription.defaultMessage
80
+ }), 0]];
68
81
  };
69
82
  export var ExpandNodeView = /*#__PURE__*/function () {
70
83
  function ExpandNodeView(_node, view, getPos, getIntl, isMobile, selectNearNode, api, nodeViewPortalProviderAPI) {
@@ -195,21 +208,30 @@ export var ExpandNodeView = /*#__PURE__*/function () {
195
208
  (_this$api3 = _this.api) === null || _this$api3 === void 0 || _this$api3.core.actions.execute(function (_ref) {
196
209
  var tr = _ref.tr;
197
210
  tr.setSelection(NodeSelection.create(state.doc, pos));
198
- // Show the drag handle on the selected expand node
211
+ if (isExperimentEnabled('platform_editor_block_control_migration')) {
212
+ var _this$api4;
213
+ var command = (_this$api4 = _this.api) === null || _this$api4 === void 0 || (_this$api4 = _this$api4.blockControls) === null || _this$api4 === void 0 ? void 0 : _this$api4.commands.showControlAtPosition(pos, BLOCK_CONTROLS_DRAG_HANDLE, {
214
+ isFocused: true
215
+ });
216
+ if (command) {
217
+ return command({
218
+ tr: tr
219
+ });
220
+ }
221
+ return null;
222
+ }
199
223
  var node = state.doc.nodeAt(pos);
200
224
  if (node) {
201
- // Find the anchor name from the DOM
202
225
  var dom = _this.view.nodeDOM(pos);
203
226
  if (dom instanceof HTMLElement) {
204
227
  var anchorName = dom.getAttribute('data-node-anchor');
205
- // Only proceed if we found a valid anchor name
206
228
  if (anchorName) {
207
- var _this$api4;
208
- var command = (_this$api4 = _this.api) === null || _this$api4 === void 0 || (_this$api4 = _this$api4.blockControls) === null || _this$api4 === void 0 ? void 0 : _this$api4.commands.showDragHandleAt(pos, anchorName, node.type.name, {
229
+ var _this$api5;
230
+ var _command = (_this$api5 = _this.api) === null || _this$api5 === void 0 || (_this$api5 = _this$api5.blockControls) === null || _this$api5 === void 0 ? void 0 : _this$api5.commands.showDragHandleAt(pos, anchorName, node.type.name, {
209
231
  isFocused: true
210
232
  });
211
- if (command) {
212
- return command({
233
+ if (_command) {
234
+ return _command({
213
235
  tr: tr
214
236
  });
215
237
  }
@@ -287,8 +309,8 @@ export var ExpandNodeView = /*#__PURE__*/function () {
287
309
  var state = _this.view.state;
288
310
  var expandNode = _this.node;
289
311
  if (expandNode && isEmptyNode(state.schema)(expandNode)) {
290
- var _this$api5;
291
- deleteExpandAtPos((_this$api5 = _this.api) === null || _this$api5 === void 0 || (_this$api5 = _this$api5.analytics) === null || _this$api5 === void 0 ? void 0 : _this$api5.actions)(pos, expandNode)(state, _this.view.dispatch);
312
+ var _this$api6;
313
+ deleteExpandAtPos((_this$api6 = _this.api) === null || _this$api6 === void 0 || (_this$api6 = _this$api6.analytics) === null || _this$api6 === void 0 ? void 0 : _this$api6.actions)(pos, expandNode)(state, _this.view.dispatch);
292
314
  }
293
315
  });
294
316
  _defineProperty(this, "toggleExpand", function () {
@@ -297,12 +319,12 @@ export var ExpandNodeView = /*#__PURE__*/function () {
297
319
  return;
298
320
  }
299
321
  if (_this.allowInteractiveExpand) {
300
- var _this$api6;
322
+ var _this$api7;
301
323
  var _this$view4 = _this.view,
302
324
  state = _this$view4.state,
303
325
  dispatch = _this$view4.dispatch;
304
326
  toggleExpandExpanded({
305
- editorAnalyticsAPI: (_this$api6 = _this.api) === null || _this$api6 === void 0 || (_this$api6 = _this$api6.analytics) === null || _this$api6 === void 0 ? void 0 : _this$api6.actions,
327
+ editorAnalyticsAPI: (_this$api7 = _this.api) === null || _this$api7 === void 0 || (_this$api7 = _this$api7.analytics) === null || _this$api7 === void 0 ? void 0 : _this$api7.actions,
306
328
  pos: pos,
307
329
  nodeType: _this.node.type,
308
330
  __livePage: _this.__livePage
@@ -454,13 +476,13 @@ export var ExpandNodeView = /*#__PURE__*/function () {
454
476
  selectionStart = _this$input6.selectionStart,
455
477
  selectionEnd = _this$input6.selectionEnd;
456
478
  if (selectionStart === selectionEnd && selectionStart === 0) {
457
- var _this$api7;
479
+ var _this$api8;
458
480
  event.preventDefault();
459
481
  var _this$view0 = _this.view,
460
482
  state = _this$view0.state,
461
483
  dispatch = _this$view0.dispatch;
462
484
  _this.view.focus();
463
- var selectionSharedState = ((_this$api7 = _this.api) === null || _this$api7 === void 0 || (_this$api7 = _this$api7.selection) === null || _this$api7 === void 0 ? void 0 : _this$api7.sharedState.currentState()) || {};
485
+ var selectionSharedState = ((_this$api8 = _this.api) === null || _this$api8 === void 0 || (_this$api8 = _this$api8.selection) === null || _this$api8 === void 0 ? void 0 : _this$api8.sharedState.currentState()) || {};
464
486
  // selectionRelativeToNode is undefined when user clicked to select node, then hit left to get focus in title
465
487
  // This is a special case where we want to bypass node selection and jump straight to gap cursor
466
488
  if ((selectionSharedState === null || selectionSharedState === void 0 ? void 0 : selectionSharedState.selectionRelativeToNode) === undefined) {
@@ -547,7 +569,7 @@ export var ExpandNodeView = /*#__PURE__*/function () {
547
569
  return _createClass(ExpandNodeView, [{
548
570
  key: "initHandlers",
549
571
  value: function initHandlers() {
550
- var _this$api8,
572
+ var _this$api9,
551
573
  _this2 = this;
552
574
  if (this.dom) {
553
575
  // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
@@ -573,7 +595,7 @@ export var ExpandNodeView = /*#__PURE__*/function () {
573
595
  // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
574
596
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
575
597
  }
576
- if ((_this$api8 = this.api) !== null && _this$api8 !== void 0 && _this$api8.editorDisabled) {
598
+ if ((_this$api9 = this.api) !== null && _this$api9 !== void 0 && _this$api9.editorDisabled) {
577
599
  this.cleanUpEditorDisabledOnChange = this.api.editorDisabled.sharedState.onChange(function (sharedState) {
578
600
  var editorDisabled = sharedState.nextSharedState.editorDisabled;
579
601
  if (_this2.input) {
@@ -643,13 +665,13 @@ export var ExpandNodeView = /*#__PURE__*/function () {
643
665
  }, {
644
666
  key: "isLimitedModeEnabled",
645
667
  value: function isLimitedModeEnabled() {
646
- var _this$api9;
668
+ var _this$api0;
647
669
  // Read from `this.view.state` via the exposed plugin key rather than the shared state's
648
670
  // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
649
671
  // API's editor state isn't wired up yet).
650
672
  //
651
673
  // Reads the plugin's derived `enabled`, so this covers every reason limited mode can be on.
652
- return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedMode) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.sharedState.currentState()) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedModePluginKey) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.getState(this.view.state)) === null || _this$api9 === void 0 ? void 0 : _this$api9.enabled);
674
+ return Boolean((_this$api0 = this.api) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.limitedMode) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.sharedState.currentState()) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.limitedModePluginKey) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.getState(this.view.state)) === null || _this$api0 === void 0 ? void 0 : _this$api0.enabled);
653
675
  }
654
676
  }, {
655
677
  key: "stopEvent",
@@ -711,6 +733,12 @@ export var ExpandNodeView = /*#__PURE__*/function () {
711
733
  _this4.input.value = _this4.node.attrs.title;
712
734
  }
713
735
  });
736
+ if (isExperimentEnabled('platform_editor_expand_content_a11y_2')) {
737
+ if (this.node.attrs.title !== node.attrs.title && this.content) {
738
+ var _node$attrs$title2;
739
+ this.content.setAttribute('aria-label', getExpandBodyAriaLabel((_node$attrs$title2 = node.attrs.title) !== null && _node$attrs$title2 !== void 0 ? _node$attrs$title2 : '', this.intl));
740
+ }
741
+ }
714
742
  this.node = node;
715
743
  return true;
716
744
  }
@@ -5,6 +5,7 @@ import React from 'react';
5
5
  // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
6
6
  import { v4 as uuid } from 'uuid';
7
7
  import { keyName } from 'w3c-keyname';
8
+ import { BLOCK_CONTROLS_DRAG_HANDLE } from '@atlaskit/editor-common/block-controls/surface-keys';
8
9
  import { expandedState, isExpandCollapsed } from '@atlaskit/editor-common/expand';
9
10
  import { GapCursorSelection, RelativeSelectionPos, Side } from '@atlaskit/editor-common/selection';
10
11
  import { expandClassNames } from '@atlaskit/editor-common/styles';
@@ -19,14 +20,14 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
19
20
  import { renderExpandButton } from '../../ui/renderExpandButton';
20
21
  import { deleteExpand, setSelectionInsideExpand, toggleExpandExpanded, updateExpandTitle } from '../commands';
21
22
  import { ExpandButton } from '../ui/ExpandButton';
22
- import { buildExpandClassName, toDOM } from '../ui/NodeView';
23
+ import { buildExpandClassName, getExpandBodyAriaLabel, toDOM } from '../ui/NodeView';
23
24
  import { findReplaceExpandDecorations } from '../utils';
24
25
  export var ExpandNodeView = /*#__PURE__*/function () {
25
26
  function ExpandNodeView(_node, view, getPos, getIntl, isMobile, selectNearNode, api, nodeViewPortalProviderAPI) {
26
27
  var _this = this,
27
28
  _expandedState$get,
28
29
  _api$editorDisabled,
29
- _this$api8;
30
+ _this$api9;
30
31
  var allowInteractiveExpand = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : true;
31
32
  var __livePage = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
32
33
  var cleanUpEditorDisabledOnChange = arguments.length > 10 ? arguments[10] : undefined;
@@ -152,21 +153,30 @@ export var ExpandNodeView = /*#__PURE__*/function () {
152
153
  (_this$api3 = _this.api) === null || _this$api3 === void 0 || _this$api3.core.actions.execute(function (_ref) {
153
154
  var tr = _ref.tr;
154
155
  tr.setSelection(NodeSelection.create(state.doc, pos));
155
- // Show the drag handle on the selected expand node
156
+ if (isExperimentEnabled('platform_editor_block_control_migration')) {
157
+ var _this$api4;
158
+ var command = (_this$api4 = _this.api) === null || _this$api4 === void 0 || (_this$api4 = _this$api4.blockControls) === null || _this$api4 === void 0 ? void 0 : _this$api4.commands.showControlAtPosition(pos, BLOCK_CONTROLS_DRAG_HANDLE, {
159
+ isFocused: true
160
+ });
161
+ if (command) {
162
+ return command({
163
+ tr: tr
164
+ });
165
+ }
166
+ return null;
167
+ }
156
168
  var node = state.doc.nodeAt(pos);
157
169
  if (node) {
158
- // Find the anchor name from the DOM
159
170
  var dom = _this.view.nodeDOM(pos);
160
171
  if (dom instanceof HTMLElement) {
161
172
  var anchorName = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? dom.getAttribute('data-node-anchor') : dom.getAttribute('data-drag-handler-anchor-name');
162
- // Only proceed if we found a valid anchor name
163
173
  if (anchorName) {
164
- var _this$api4;
165
- var command = (_this$api4 = _this.api) === null || _this$api4 === void 0 || (_this$api4 = _this$api4.blockControls) === null || _this$api4 === void 0 ? void 0 : _this$api4.commands.showDragHandleAt(pos, anchorName, node.type.name, {
174
+ var _this$api5;
175
+ var _command = (_this$api5 = _this.api) === null || _this$api5 === void 0 || (_this$api5 = _this$api5.blockControls) === null || _this$api5 === void 0 ? void 0 : _this$api5.commands.showDragHandleAt(pos, anchorName, node.type.name, {
166
176
  isFocused: true
167
177
  });
168
- if (command) {
169
- return command({
178
+ if (_command) {
179
+ return _command({
170
180
  tr: tr
171
181
  });
172
182
  }
@@ -239,8 +249,8 @@ export var ExpandNodeView = /*#__PURE__*/function () {
239
249
  return;
240
250
  }
241
251
  if (expandNode && isEmptyNode(state.schema)(expandNode)) {
242
- var _this$api5;
243
- deleteExpand((_this$api5 = _this.api) === null || _this$api5 === void 0 || (_this$api5 = _this$api5.analytics) === null || _this$api5 === void 0 ? void 0 : _this$api5.actions)(state, _this.view.dispatch);
252
+ var _this$api6;
253
+ deleteExpand((_this$api6 = _this.api) === null || _this$api6 === void 0 || (_this$api6 = _this$api6.analytics) === null || _this$api6 === void 0 ? void 0 : _this$api6.actions)(state, _this.view.dispatch);
244
254
  }
245
255
  });
246
256
  _defineProperty(this, "toggleExpand", function () {
@@ -249,12 +259,12 @@ export var ExpandNodeView = /*#__PURE__*/function () {
249
259
  return;
250
260
  }
251
261
  if (_this.allowInteractiveExpand) {
252
- var _this$api6;
262
+ var _this$api7;
253
263
  var _this$view3 = _this.view,
254
264
  state = _this$view3.state,
255
265
  dispatch = _this$view3.dispatch;
256
266
  toggleExpandExpanded({
257
- editorAnalyticsAPI: (_this$api6 = _this.api) === null || _this$api6 === void 0 || (_this$api6 = _this$api6.analytics) === null || _this$api6 === void 0 ? void 0 : _this$api6.actions,
267
+ editorAnalyticsAPI: (_this$api7 = _this.api) === null || _this$api7 === void 0 || (_this$api7 = _this$api7.analytics) === null || _this$api7 === void 0 ? void 0 : _this$api7.actions,
258
268
  pos: pos,
259
269
  node: _this.node
260
270
  })(state, dispatch);
@@ -408,13 +418,13 @@ export var ExpandNodeView = /*#__PURE__*/function () {
408
418
  selectionStart = _this$input6.selectionStart,
409
419
  selectionEnd = _this$input6.selectionEnd;
410
420
  if (selectionStart === selectionEnd && selectionStart === 0) {
411
- var _this$api7;
421
+ var _this$api8;
412
422
  event.preventDefault();
413
423
  var _this$view9 = _this.view,
414
424
  state = _this$view9.state,
415
425
  dispatch = _this$view9.dispatch;
416
426
  _this.view.focus();
417
- var selectionSharedState = ((_this$api7 = _this.api) === null || _this$api7 === void 0 || (_this$api7 = _this$api7.selection) === null || _this$api7 === void 0 ? void 0 : _this$api7.sharedState.currentState()) || {};
427
+ var selectionSharedState = ((_this$api8 = _this.api) === null || _this$api8 === void 0 || (_this$api8 = _this$api8.selection) === null || _this$api8 === void 0 ? void 0 : _this$api8.sharedState.currentState()) || {};
418
428
  // selectionRelativeToNode is undefined when user clicked to select node, then hit left to get focus in title
419
429
  // This is a special case where we want to bypass node selection and jump straight to gap cursor
420
430
  if ((selectionSharedState === null || selectionSharedState === void 0 ? void 0 : selectionSharedState.selectionRelativeToNode) === undefined) {
@@ -530,7 +540,7 @@ export var ExpandNodeView = /*#__PURE__*/function () {
530
540
  // Prevent ProseMirror from getting a focus event (causes weird selection issues).
531
541
  this.titleContainer.addEventListener('focus', this.handleFocus);
532
542
  this.icon.addEventListener('keydown', this.handleIconKeyDown);
533
- if ((_this$api8 = this.api) !== null && _this$api8 !== void 0 && _this$api8.editorDisabled) {
543
+ if ((_this$api9 = this.api) !== null && _this$api9 !== void 0 && _this$api9.editorDisabled) {
534
544
  if (isExperimentEnabled('cc_editor_limited_mode_perf_improvements')) {
535
545
  if (this.content) {
536
546
  this.content.setAttribute('contenteditable', this.getContentEditable(this.node) ? 'true' : 'false');
@@ -602,6 +612,12 @@ export var ExpandNodeView = /*#__PURE__*/function () {
602
612
  }
603
613
  });
604
614
 
615
+ // Sync up the aria-label with the current expand title.
616
+ if (isExperimentEnabled('platform_editor_expand_content_a11y_2') && this.node.attrs.title !== node.attrs.title && this.content) {
617
+ var _node$attrs$title;
618
+ this.content.setAttribute('aria-label', getExpandBodyAriaLabel((_node$attrs$title = node.attrs.title) !== null && _node$attrs$title !== void 0 ? _node$attrs$title : '', this.intl));
619
+ }
620
+
605
621
  // This checks if the node has been replaced with a different version
606
622
  // and updates the state of the new node to match the old one
607
623
  // Eg. typing in a node changes it to a new node so it must be updated
@@ -658,13 +674,13 @@ export var ExpandNodeView = /*#__PURE__*/function () {
658
674
  }, {
659
675
  key: "isLimitedModeEnabled",
660
676
  value: function isLimitedModeEnabled() {
661
- var _this$api9;
677
+ var _this$api0;
662
678
  // Read from `this.view.state` via the exposed plugin key rather than the shared state's
663
679
  // `enabled`, which reads a stale `false` during initial EditorView construction (the injection
664
680
  // API's editor state isn't wired up yet).
665
681
  //
666
682
  // Reads the plugin's derived `enabled`, so this covers every reason limited mode can be on.
667
- return Boolean((_this$api9 = this.api) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedMode) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.sharedState.currentState()) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.limitedModePluginKey) === null || _this$api9 === void 0 || (_this$api9 = _this$api9.getState(this.view.state)) === null || _this$api9 === void 0 ? void 0 : _this$api9.enabled);
683
+ return Boolean((_this$api0 = this.api) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.limitedMode) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.sharedState.currentState()) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.limitedModePluginKey) === null || _this$api0 === void 0 || (_this$api0 = _this$api0.getState(this.view.state)) === null || _this$api0 === void 0 ? void 0 : _this$api0.enabled);
668
684
  }
669
685
  }, {
670
686
  key: "updateDisplayStyle",
@@ -4,12 +4,19 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  import { expandedState } from '@atlaskit/editor-common/expand';
5
5
  import { expandClassNames } from '@atlaskit/editor-common/styles';
6
6
  import { expandMessages } from '@atlaskit/editor-common/ui';
7
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
7
8
  import { fg } from '@atlaskit/platform-feature-flags/fg';
8
9
  export var buildExpandClassName = function buildExpandClassName(type, expanded) {
9
10
  return "".concat(expandClassNames.prefix, " ").concat(expandClassNames.type(type), " ").concat(expanded ? expandClassNames.expanded : '');
10
11
  };
12
+ export var getExpandBodyAriaLabel = function getExpandBodyAriaLabel(title, intl) {
13
+ var safeTitle = title.trim() || (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaLabelUntitled)) || expandMessages.expandBodyAriaLabelUntitled.defaultMessage;
14
+ return (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaLabel, {
15
+ title: safeTitle
16
+ })) || expandMessages.expandBodyAriaLabel.defaultMessage.replace('{title}', safeTitle);
17
+ };
11
18
  export var toDOM = function toDOM(node, __livePage, intl, titleReadOnly, contentEditable) {
12
- var _expandedState$get;
19
+ var _expandedState$get, _node$attrs$title, _intl$formatMessage;
13
20
  return ['div', _objectSpread({
14
21
  // prettier-ignore
15
22
  'class': buildExpandClassName(node.type.name, (_expandedState$get = expandedState.get(node)) !== null && _expandedState$get !== void 0 ? _expandedState$get : false),
@@ -41,12 +48,17 @@ export var toDOM = function toDOM(node, __livePage, intl, titleReadOnly, content
41
48
  placeholder: intl && typeof intl.formatMessage === 'function' && intl.formatMessage(expandMessages.expandPlaceholderText) || expandMessages.expandPlaceholderText.defaultMessage,
42
49
  type: 'text',
43
50
  readonly: titleReadOnly ? 'true' : undefined
44
- }]]], ['div', {
51
+ }]]], [isExperimentEnabled('platform_editor_expand_content_a11y_2') ? 'section' : 'div', _objectSpread(_objectSpread({
45
52
  // prettier-ignore
46
53
  class: "".concat(expandClassNames.content, " ").concat(expandedState.get(node) ? '' : expandClassNames.contentCollapsed),
47
- contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined,
54
+ contenteditable: contentEditable !== undefined ? contentEditable ? 'true' : 'false' : undefined
55
+ }, !isExperimentEnabled('platform_editor_expand_content_a11y_2') && {
48
56
  role: 'textbox',
49
57
  'aria-multiline': 'true',
50
- 'aria-label': intl && intl.formatMessage(expandMessages.expandBodyAriaLabel) || expandMessages.expandBodyAriaLabel.defaultMessage
51
- }, 0]];
58
+ 'aria-label': intl && intl.formatMessage(expandMessages.expandBodyAriaLabelOriginal) || expandMessages.expandBodyAriaLabelOriginal.defaultMessage
59
+ }), isExperimentEnabled('platform_editor_expand_content_a11y_2') && {
60
+ 'aria-label': getExpandBodyAriaLabel((_node$attrs$title = node.attrs.title) !== null && _node$attrs$title !== void 0 ? _node$attrs$title : '', intl),
61
+ 'aria-description': (intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyAriaDescription)) || expandMessages.expandBodyAriaDescription.defaultMessage,
62
+ 'aria-roledescription': (_intl$formatMessage = intl === null || intl === void 0 ? void 0 : intl.formatMessage(expandMessages.expandBodyRoleDescription)) !== null && _intl$formatMessage !== void 0 ? _intl$formatMessage : expandMessages.expandBodyRoleDescription.defaultMessage
63
+ }), 0]];
52
64
  };
@@ -5,6 +5,7 @@ import type { ExtractInjectionAPI, getPosHandler, getPosHandlerNode } from '@atl
5
5
  import type { Node as PmNode } from '@atlaskit/editor-prosemirror/model';
6
6
  import type { Decoration, EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
7
7
  import type { ExpandPlugin } from '../../types';
8
+ export declare function getExpandBodyAriaLabel(title: string, intl?: IntlShape): string;
8
9
  export declare class ExpandNodeView implements NodeView {
9
10
  private selectNearNode;
10
11
  private __livePage;
@@ -1,4 +1,5 @@
1
1
  import type { IntlShape } from 'react-intl';
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 getExpandBodyAriaLabel: (title: string, intl?: IntlShape) => string;
4
5
  export declare const toDOM: (node: PmNode, __livePage: boolean, intl?: IntlShape, titleReadOnly?: boolean, contentEditable?: boolean) => DOMOutputSpec;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-expand",
3
- "version": "20.0.2",
3
+ "version": "20.0.3",
4
4
  "description": "Expand plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -22,9 +22,9 @@
22
22
  "atlaskit:src": "src/index.ts",
23
23
  "dependencies": {
24
24
  "@atlaskit/adf-schema": "^57.5.0",
25
- "@atlaskit/button": "^25.3.0",
25
+ "@atlaskit/button": "^25.4.0",
26
26
  "@atlaskit/editor-plugin-analytics": "^19.0.0",
27
- "@atlaskit/editor-plugin-block-controls": "^20.0.0",
27
+ "@atlaskit/editor-plugin-block-controls": "^20.1.0",
28
28
  "@atlaskit/editor-plugin-block-menu": "^18.0.0",
29
29
  "@atlaskit/editor-plugin-decorations": "^19.0.0",
30
30
  "@atlaskit/editor-plugin-editor-disabled": "^19.0.0",
@@ -37,7 +37,7 @@
37
37
  "@atlaskit/editor-shared-styles": "^4.3.0",
38
38
  "@atlaskit/editor-tables": "^3.2.0",
39
39
  "@atlaskit/editor-toolbar": "^2.7.0",
40
- "@atlaskit/editor-ui-control-model": "^2.9.0",
40
+ "@atlaskit/editor-ui-control-model": "^2.10.0",
41
41
  "@atlaskit/icon": "^37.7.0",
42
42
  "@atlaskit/icon-lab": "^7.9.0",
43
43
  "@atlaskit/platform-feature-experiments": "^0.3.0",
@@ -52,7 +52,7 @@
52
52
  "w3c-keyname": "^2.1.8"
53
53
  },
54
54
  "peerDependencies": {
55
- "@atlaskit/editor-common": "^123.2.0",
55
+ "@atlaskit/editor-common": "^123.3.0",
56
56
  "react": "^18.2.0 || ^19.2.0",
57
57
  "react-dom": "^18.2.0 || ^19.2.0",
58
58
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"