@atlaskit/editor-plugin-expand 20.0.1 → 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.
@@ -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
  }
@@ -2,11 +2,11 @@ import React from 'react';
2
2
  import { expandWithNestedExpand } from '@atlaskit/adf-schema/expand';
3
3
  import { nestedExpand } from '@atlaskit/adf-schema/nested-expand';
4
4
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
5
+ import { IconExpand } from '@atlaskit/editor-common/assets';
5
6
  import { TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM, TRANSFORM_STRUCTURE_MENU_SECTION, TRANSFORM_STRUCTURE_MENU_SECTION_RANK } from '@atlaskit/editor-common/block-menu';
6
7
  import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
7
- import { IconExpand } from '@atlaskit/editor-common/assets';
8
- import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
9
8
  import { createWrapSelectionTransaction } from '@atlaskit/editor-common/utils';
9
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
10
10
  import { toggleExpandRange } from '../editor-commands/toggleExpandRange';
11
11
  import { createExpandBlockMenuItem } from '../ui/ExpandBlockMenuItem';
12
12
  import { getExpandQuickInsertComponents } from '../ui/quick-insert/getExpandQuickInsertComponents';
@@ -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) {
@@ -2,9 +2,9 @@ import React from 'react';
2
2
  import { expandWithNestedExpand, expandWithNestedExpandLocalId } from '@atlaskit/adf-schema/expand';
3
3
  import { nestedExpand, nestedExpandWithLocalId } from '@atlaskit/adf-schema/nested-expand';
4
4
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
5
+ import { IconExpand } from '@atlaskit/editor-common/assets';
5
6
  import { TRANSFORM_STRUCTURE_EXPAND_MENU_ITEM, TRANSFORM_STRUCTURE_MENU_SECTION, TRANSFORM_STRUCTURE_MENU_SECTION_RANK } from '@atlaskit/editor-common/block-menu';
6
7
  import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
7
- import { IconExpand } from '@atlaskit/editor-common/assets';
8
8
  import { createWrapSelectionTransaction } from '@atlaskit/editor-common/utils';
9
9
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
10
10
  import { fg } from '@atlaskit/platform-feature-flags/fg';
@@ -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
  };
@@ -5,8 +5,8 @@ import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks'
5
5
  import { toolbarInsertBlockMessages as messages } from '@atlaskit/editor-common/messages';
6
6
  import { QuickInsertMenuItem } from '@atlaskit/editor-common/quick-insert/menu-item';
7
7
  import { createWrapSelectionTransaction } from '@atlaskit/editor-common/utils';
8
- import { fg } from '@atlaskit/platform-feature-flags/fg';
9
8
  import ExpandElementIcon from '@atlaskit/icon-lab/core/expand-element';
9
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
10
10
  import { createExpandNode as createLegacyExpandNode } from '../../legacyExpand/commands';
11
11
  import { createExpandNode as createSinglePlayerExpandNode, wrapSelectionAndSetExpandedState } from '../../singlePlayerExpand/commands';
12
12
  export const ExpandQuickInsertMenuItem = ({
@@ -1,2 +1,3 @@
1
1
  /* eslint-disable @atlaskit/editor/no-re-export */
2
+
2
3
  export { expandPlugin } from '../plugin';