@atlaskit/editor-plugin-code-block-advanced 11.0.1 → 11.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,19 @@
1
1
  # @atlaskit/editor-plugin-code-block-advanced
2
2
 
3
+ ## 11.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+
9
+ ## 11.0.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [`10408fdb0f64b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/10408fdb0f64b) -
14
+ [ux] [EDITOR-7563] Select the whole node when clicking the border area of a code block
15
+ - Updated dependencies
16
+
3
17
  ## 11.0.1
4
18
 
5
19
  ### Patch Changes
@@ -13,6 +13,7 @@ var _autocomplete = require("@codemirror/autocomplete");
13
13
  var _language = require("@codemirror/language");
14
14
  var _state = require("@codemirror/state");
15
15
  var _view = require("@codemirror/view");
16
+ var _bindEventListener = require("bind-event-listener");
16
17
  var _browser = require("@atlaskit/editor-common/browser");
17
18
  var _codeBlock = require("@atlaskit/editor-common/code-block");
18
19
  var _floatingToolbar = require("@atlaskit/editor-common/floating-toolbar");
@@ -67,6 +68,18 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
67
68
  _this.selectCodeBlockNode(undefined);
68
69
  _this.view.focus();
69
70
  });
71
+ (0, _defineProperty2.default)(this, "handleBorderAreaClick", function (event) {
72
+ if (!_this.isBorderAreaClick(event)) {
73
+ return;
74
+ }
75
+
76
+ // Prevent CodeMirror from restoring its inner selection after we hand focus and selection
77
+ // back to ProseMirror
78
+ event.preventDefault();
79
+ _this.maybeTryingToReachNodeSelection = true;
80
+ _this.view.focus();
81
+ _this.selectCodeBlockNode(undefined);
82
+ });
70
83
  this.config = config;
71
84
  this.node = node;
72
85
  this.view = view;
@@ -193,6 +206,12 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
193
206
  });
194
207
  this.ro.observe(this.cm.contentDOM);
195
208
  }
209
+ if ((0, _expValEquals.expValEquals)('platform_editor_code_block_q4_lovability', 'isEnabled', true)) {
210
+ this.cleanupBorderAreaClick = (0, _bindEventListener.bind)(this.cm.scrollDOM, {
211
+ type: 'click',
212
+ listener: this.handleBorderAreaClick
213
+ });
214
+ }
196
215
 
197
216
  // We append an additional element that fixes a selection bug on chrome if the code block
198
217
  // is the first element followed by subsequent code blocks
@@ -226,11 +245,12 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
226
245
  return (0, _createClass2.default)(CodeBlockAdvancedNodeView, [{
227
246
  key: "destroy",
228
247
  value: function destroy() {
229
- var _this$cleanupDisabled;
248
+ var _this$cleanupBorderAr, _this$cleanupDisabled;
230
249
  // ED-27428: CodeMirror gets into an infinite loop as it detects mutations on removed
231
250
  // decorations. When we change the breakout we destroy the node and cleanup these decorations from
232
251
  // codemirror
233
252
  this.clearProseMirrorDecorations();
253
+ (_this$cleanupBorderAr = this.cleanupBorderAreaClick) === null || _this$cleanupBorderAr === void 0 || _this$cleanupBorderAr.call(this);
234
254
  (_this$cleanupDisabled = this.cleanupDisabledState) === null || _this$cleanupDisabled === void 0 || _this$cleanupDisabled.call(this);
235
255
  if ((0, _expValEquals.expValEquals)('confluence_compact_text_format', 'isEnabled', true)) {
236
256
  var _this$unsubscribeCont;
@@ -462,6 +482,18 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
462
482
  });
463
483
  this.updating = false;
464
484
  }
485
+ }, {
486
+ key: "isBorderAreaClick",
487
+ value: function isBorderAreaClick(event) {
488
+ var target = event.target;
489
+ if (!(target instanceof HTMLElement)) {
490
+ return false;
491
+ }
492
+
493
+ // CodeMirror does not expose a stable gutter DOM handle, so this relies on its
494
+ // class names to distinguish interactive content/gutters from border-area clicks.
495
+ return !target.closest('.cm-gutters') && !target.closest('.cm-line');
496
+ }
465
497
  }, {
466
498
  key: "stopEvent",
467
499
  value: function stopEvent(e) {
@@ -3,6 +3,7 @@ import { closeBrackets } from '@codemirror/autocomplete';
3
3
  import { syntaxHighlighting, bracketMatching } from '@codemirror/language';
4
4
  import { Compartment, Facet, EditorState as CodeMirrorState } from '@codemirror/state';
5
5
  import { EditorView as CodeMirror, lineNumbers, gutters } from '@codemirror/view';
6
+ import { bind } from 'bind-event-listener';
6
7
  import { getBrowserInfo } from '@atlaskit/editor-common/browser';
7
8
  import { areCodeBlockLineNumbersHidden, isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
8
9
  import { messages as floatingToolbarMessages } from '@atlaskit/editor-common/floating-toolbar';
@@ -47,6 +48,18 @@ class CodeBlockAdvancedNodeView {
47
48
  this.selectCodeBlockNode(undefined);
48
49
  this.view.focus();
49
50
  });
51
+ _defineProperty(this, "handleBorderAreaClick", event => {
52
+ if (!this.isBorderAreaClick(event)) {
53
+ return;
54
+ }
55
+
56
+ // Prevent CodeMirror from restoring its inner selection after we hand focus and selection
57
+ // back to ProseMirror
58
+ event.preventDefault();
59
+ this.maybeTryingToReachNodeSelection = true;
60
+ this.view.focus();
61
+ this.selectCodeBlockNode(undefined);
62
+ });
50
63
  this.config = config;
51
64
  this.node = node;
52
65
  this.view = view;
@@ -161,6 +174,12 @@ class CodeBlockAdvancedNodeView {
161
174
  });
162
175
  this.ro.observe(this.cm.contentDOM);
163
176
  }
177
+ if (expValEquals('platform_editor_code_block_q4_lovability', 'isEnabled', true)) {
178
+ this.cleanupBorderAreaClick = bind(this.cm.scrollDOM, {
179
+ type: 'click',
180
+ listener: this.handleBorderAreaClick
181
+ });
182
+ }
164
183
 
165
184
  // We append an additional element that fixes a selection bug on chrome if the code block
166
185
  // is the first element followed by subsequent code blocks
@@ -192,11 +211,12 @@ class CodeBlockAdvancedNodeView {
192
211
  }
193
212
  }
194
213
  destroy() {
195
- var _this$cleanupDisabled;
214
+ var _this$cleanupBorderAr, _this$cleanupDisabled;
196
215
  // ED-27428: CodeMirror gets into an infinite loop as it detects mutations on removed
197
216
  // decorations. When we change the breakout we destroy the node and cleanup these decorations from
198
217
  // codemirror
199
218
  this.clearProseMirrorDecorations();
219
+ (_this$cleanupBorderAr = this.cleanupBorderAreaClick) === null || _this$cleanupBorderAr === void 0 ? void 0 : _this$cleanupBorderAr.call(this);
200
220
  (_this$cleanupDisabled = this.cleanupDisabledState) === null || _this$cleanupDisabled === void 0 ? void 0 : _this$cleanupDisabled.call(this);
201
221
  if (expValEquals('confluence_compact_text_format', 'isEnabled', true)) {
202
222
  var _this$unsubscribeCont;
@@ -390,6 +410,16 @@ class CodeBlockAdvancedNodeView {
390
410
  });
391
411
  this.updating = false;
392
412
  }
413
+ isBorderAreaClick(event) {
414
+ const target = event.target;
415
+ if (!(target instanceof HTMLElement)) {
416
+ return false;
417
+ }
418
+
419
+ // CodeMirror does not expose a stable gutter DOM handle, so this relies on its
420
+ // class names to distinguish interactive content/gutters from border-area clicks.
421
+ return !target.closest('.cm-gutters') && !target.closest('.cm-line');
422
+ }
393
423
  stopEvent(e) {
394
424
  var _this$getPos5;
395
425
  // If we have selected the node we should not stop these events
@@ -11,6 +11,7 @@ import { closeBrackets } from '@codemirror/autocomplete';
11
11
  import { syntaxHighlighting, bracketMatching } from '@codemirror/language';
12
12
  import { Compartment, Facet, EditorState as CodeMirrorState } from '@codemirror/state';
13
13
  import { EditorView as CodeMirror, lineNumbers, gutters } from '@codemirror/view';
14
+ import { bind } from 'bind-event-listener';
14
15
  import { getBrowserInfo } from '@atlaskit/editor-common/browser';
15
16
  import { areCodeBlockLineNumbersHidden, isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
16
17
  import { messages as floatingToolbarMessages } from '@atlaskit/editor-common/floating-toolbar';
@@ -61,6 +62,18 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
61
62
  _this.selectCodeBlockNode(undefined);
62
63
  _this.view.focus();
63
64
  });
65
+ _defineProperty(this, "handleBorderAreaClick", function (event) {
66
+ if (!_this.isBorderAreaClick(event)) {
67
+ return;
68
+ }
69
+
70
+ // Prevent CodeMirror from restoring its inner selection after we hand focus and selection
71
+ // back to ProseMirror
72
+ event.preventDefault();
73
+ _this.maybeTryingToReachNodeSelection = true;
74
+ _this.view.focus();
75
+ _this.selectCodeBlockNode(undefined);
76
+ });
64
77
  this.config = config;
65
78
  this.node = node;
66
79
  this.view = view;
@@ -187,6 +200,12 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
187
200
  });
188
201
  this.ro.observe(this.cm.contentDOM);
189
202
  }
203
+ if (expValEquals('platform_editor_code_block_q4_lovability', 'isEnabled', true)) {
204
+ this.cleanupBorderAreaClick = bind(this.cm.scrollDOM, {
205
+ type: 'click',
206
+ listener: this.handleBorderAreaClick
207
+ });
208
+ }
190
209
 
191
210
  // We append an additional element that fixes a selection bug on chrome if the code block
192
211
  // is the first element followed by subsequent code blocks
@@ -220,11 +239,12 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
220
239
  return _createClass(CodeBlockAdvancedNodeView, [{
221
240
  key: "destroy",
222
241
  value: function destroy() {
223
- var _this$cleanupDisabled;
242
+ var _this$cleanupBorderAr, _this$cleanupDisabled;
224
243
  // ED-27428: CodeMirror gets into an infinite loop as it detects mutations on removed
225
244
  // decorations. When we change the breakout we destroy the node and cleanup these decorations from
226
245
  // codemirror
227
246
  this.clearProseMirrorDecorations();
247
+ (_this$cleanupBorderAr = this.cleanupBorderAreaClick) === null || _this$cleanupBorderAr === void 0 || _this$cleanupBorderAr.call(this);
228
248
  (_this$cleanupDisabled = this.cleanupDisabledState) === null || _this$cleanupDisabled === void 0 || _this$cleanupDisabled.call(this);
229
249
  if (expValEquals('confluence_compact_text_format', 'isEnabled', true)) {
230
250
  var _this$unsubscribeCont;
@@ -456,6 +476,18 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
456
476
  });
457
477
  this.updating = false;
458
478
  }
479
+ }, {
480
+ key: "isBorderAreaClick",
481
+ value: function isBorderAreaClick(event) {
482
+ var target = event.target;
483
+ if (!(target instanceof HTMLElement)) {
484
+ return false;
485
+ }
486
+
487
+ // CodeMirror does not expose a stable gutter DOM handle, so this relies on its
488
+ // class names to distinguish interactive content/gutters from border-area clicks.
489
+ return !target.closest('.cm-gutters') && !target.closest('.cm-line');
490
+ }
459
491
  }, {
460
492
  key: "stopEvent",
461
493
  value: function stopEvent(e) {
@@ -34,6 +34,7 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
34
34
  private unsubscribeContentFormat;
35
35
  private invisibleAriaDescription?;
36
36
  private config;
37
+ private cleanupBorderAreaClick;
37
38
  constructor(node: PMNode, view: EditorView, getPos: getPosHandlerNode, innerDecorations: DecorationSource, config: ConfigProps);
38
39
  destroy(): void;
39
40
  forwardUpdate(update: ViewUpdate): void;
@@ -62,6 +63,8 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
62
63
  */
63
64
  private getProseMirrorDecorationEffects;
64
65
  private clearProseMirrorDecorations;
66
+ private handleBorderAreaClick;
67
+ private isBorderAreaClick;
65
68
  stopEvent(e: Event): boolean;
66
69
  }
67
70
  export declare const getCodeBlockAdvancedNodeView: (props: ConfigProps) => (node: PMNode, view: EditorView, getPos: getPosHandler, innerDecorations: DecorationSource) => CodeBlockAdvancedNodeView;
@@ -34,6 +34,7 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
34
34
  private unsubscribeContentFormat;
35
35
  private invisibleAriaDescription?;
36
36
  private config;
37
+ private cleanupBorderAreaClick;
37
38
  constructor(node: PMNode, view: EditorView, getPos: getPosHandlerNode, innerDecorations: DecorationSource, config: ConfigProps);
38
39
  destroy(): void;
39
40
  forwardUpdate(update: ViewUpdate): void;
@@ -62,6 +63,8 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
62
63
  */
63
64
  private getProseMirrorDecorationEffects;
64
65
  private clearProseMirrorDecorations;
66
+ private handleBorderAreaClick;
67
+ private isBorderAreaClick;
65
68
  stopEvent(e: Event): boolean;
66
69
  }
67
70
  export declare const getCodeBlockAdvancedNodeView: (props: ConfigProps) => (node: PMNode, view: EditorView, getPos: getPosHandler, innerDecorations: DecorationSource) => CodeBlockAdvancedNodeView;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-code-block-advanced",
3
- "version": "11.0.1",
3
+ "version": "11.0.3",
4
4
  "description": "CodeBlockAdvanced plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -30,7 +30,7 @@
30
30
  "dependencies": {
31
31
  "@atlaskit/adf-schema": "^52.16.0",
32
32
  "@atlaskit/code": "^17.5.0",
33
- "@atlaskit/editor-plugin-code-block": "^13.0.0",
33
+ "@atlaskit/editor-plugin-code-block": "^13.1.0",
34
34
  "@atlaskit/editor-plugin-editor-disabled": "^11.0.0",
35
35
  "@atlaskit/editor-plugin-find-replace": "^11.0.0",
36
36
  "@atlaskit/editor-plugin-selection": "^11.0.0",
@@ -38,8 +38,8 @@
38
38
  "@atlaskit/editor-prosemirror": "^7.3.0",
39
39
  "@atlaskit/platform-feature-flags": "^1.1.0",
40
40
  "@atlaskit/prosemirror-history": "^0.2.0",
41
- "@atlaskit/tmp-editor-statsig": "^89.0.0",
42
- "@atlaskit/tokens": "^13.1.0",
41
+ "@atlaskit/tmp-editor-statsig": "^90.0.0",
42
+ "@atlaskit/tokens": "^13.3.0",
43
43
  "@babel/runtime": "^7.0.0",
44
44
  "@codemirror/autocomplete": "6.18.4",
45
45
  "@codemirror/commands": "6.7.1",
@@ -51,11 +51,12 @@
51
51
  "@lezer/highlight": "1.2.1",
52
52
  "@lezer/lr": "^1.4.2",
53
53
  "@xiechao/codemirror-lang-handlebars": "^1.0.4",
54
+ "bind-event-listener": "^3.0.0",
54
55
  "cm6-graphql": "0.2.0",
55
56
  "codemirror-lang-elixir": "4.0.0"
56
57
  },
57
58
  "peerDependencies": {
58
- "@atlaskit/editor-common": "^115.2.0",
59
+ "@atlaskit/editor-common": "^115.7.0",
59
60
  "react": "^18.2.0",
60
61
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
61
62
  },
@@ -4,6 +4,7 @@ import { Compartment, Facet, EditorState as CodeMirrorState } from '@codemirror/
4
4
  import type { Extension, StateEffect } from '@codemirror/state';
5
5
  import { EditorView as CodeMirror, lineNumbers, gutters } from '@codemirror/view';
6
6
  import type { ViewUpdate } from '@codemirror/view';
7
+ import { bind } from 'bind-event-listener';
7
8
  import type { IntlShape } from 'react-intl';
8
9
 
9
10
  import { getBrowserInfo } from '@atlaskit/editor-common/browser';
@@ -89,6 +90,7 @@ class CodeBlockAdvancedNodeView implements NodeView {
89
90
  private unsubscribeContentFormat: (() => void) | undefined;
90
91
  private invisibleAriaDescription?: HTMLSpanElement;
91
92
  private config: ConfigProps;
93
+ private cleanupBorderAreaClick: (() => void) | undefined;
92
94
 
93
95
  constructor(
94
96
  node: PMNode,
@@ -265,6 +267,13 @@ class CodeBlockAdvancedNodeView implements NodeView {
265
267
  this.ro.observe(this.cm.contentDOM);
266
268
  }
267
269
 
270
+ if (expValEquals('platform_editor_code_block_q4_lovability', 'isEnabled', true)) {
271
+ this.cleanupBorderAreaClick = bind(this.cm.scrollDOM, {
272
+ type: 'click',
273
+ listener: this.handleBorderAreaClick,
274
+ });
275
+ }
276
+
268
277
  // We append an additional element that fixes a selection bug on chrome if the code block
269
278
  // is the first element followed by subsequent code blocks
270
279
  const spaceContainer = document.createElement('span');
@@ -305,6 +314,7 @@ class CodeBlockAdvancedNodeView implements NodeView {
305
314
  // decorations. When we change the breakout we destroy the node and cleanup these decorations from
306
315
  // codemirror
307
316
  this.clearProseMirrorDecorations();
317
+ this.cleanupBorderAreaClick?.();
308
318
  this.cleanupDisabledState?.();
309
319
  if (expValEquals('confluence_compact_text_format', 'isEnabled', true)) {
310
320
  this.unsubscribeContentFormat?.();
@@ -533,6 +543,31 @@ class CodeBlockAdvancedNodeView implements NodeView {
533
543
  this.updating = false;
534
544
  }
535
545
 
546
+ private handleBorderAreaClick = (event: MouseEvent) => {
547
+ if (!this.isBorderAreaClick(event)) {
548
+ return;
549
+ }
550
+
551
+ // Prevent CodeMirror from restoring its inner selection after we hand focus and selection
552
+ // back to ProseMirror
553
+ event.preventDefault();
554
+ this.maybeTryingToReachNodeSelection = true;
555
+
556
+ this.view.focus();
557
+ this.selectCodeBlockNode(undefined);
558
+ };
559
+
560
+ private isBorderAreaClick(event: MouseEvent): boolean {
561
+ const target = event.target;
562
+ if (!(target instanceof HTMLElement)) {
563
+ return false;
564
+ }
565
+
566
+ // CodeMirror does not expose a stable gutter DOM handle, so this relies on its
567
+ // class names to distinguish interactive content/gutters from border-area clicks.
568
+ return !target.closest('.cm-gutters') && !target.closest('.cm-line');
569
+ }
570
+
536
571
  stopEvent(e: Event): boolean {
537
572
  // If we have selected the node we should not stop these events
538
573
  if (