prosemirror-view 1.27.2 → 1.28.0

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,3 +1,13 @@
1
+ ## 1.28.0 (2022-09-09)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix an issue where the editor wouldn't realize it was focused on IE when IE's resize controls are on an element inside the content. Adjust Chrome click-override behavior to only happen for invisible selections
6
+
7
+ ### New features
8
+
9
+ The new `transformCopied` prop can be used to transform a copied/cut slice before it is serialized to the clipboard. Adjust doc comment
10
+
1
11
  ## 1.27.2 (2022-08-19)
2
12
 
3
13
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -2590,7 +2590,7 @@ function selectionBetween(view, $anchor, $head, bias) {
2590
2590
  }
2591
2591
 
2592
2592
  function hasFocusAndSelection(view) {
2593
- if (view.editable && view.root.activeElement != view.dom) return false;
2593
+ if (view.editable && !view.hasFocus()) return false;
2594
2594
  return hasSelection(view);
2595
2595
  }
2596
2596
 
@@ -2887,10 +2887,14 @@ function captureKeyDown(view, event) {
2887
2887
  }
2888
2888
 
2889
2889
  function serializeForClipboard(view, slice) {
2890
+ view.someProp("transformCopied", function (f) {
2891
+ slice = f(slice);
2892
+ });
2890
2893
  var context = [],
2891
- content = slice.content,
2892
- openStart = slice.openStart,
2893
- openEnd = slice.openEnd;
2894
+ _slice = slice,
2895
+ content = _slice.content,
2896
+ openStart = _slice.openStart,
2897
+ openEnd = _slice.openEnd;
2894
2898
 
2895
2899
  while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild.childCount == 1) {
2896
2900
  openStart--;
@@ -3562,7 +3566,7 @@ var MouseDown = function () {
3562
3566
  setSelectionOrigin(this.view, "pointer");
3563
3567
  } else if (handleSingleClick(this.view, pos.pos, pos.inside, event, this.selectNode)) {
3564
3568
  event.preventDefault();
3565
- } else if (event.button == 0 && (this.flushed || safari && this.mightDrag && !this.mightDrag.node.isAtom || chrome && !(this.view.state.selection instanceof prosemirrorState.TextSelection) && Math.min(Math.abs(pos.pos - this.view.state.selection.from), Math.abs(pos.pos - this.view.state.selection.to)) <= 2)) {
3569
+ } else if (event.button == 0 && (this.flushed || safari && this.mightDrag && !this.mightDrag.node.isAtom || chrome && !this.view.state.selection.visible && Math.min(Math.abs(pos.pos - this.view.state.selection.from), Math.abs(pos.pos - this.view.state.selection.to)) <= 2)) {
3566
3570
  updateSelection(this.view, prosemirrorState.Selection.near(this.view.state.doc.resolve(pos.pos)), "pointer");
3567
3571
  event.preventDefault();
3568
3572
  } else {
@@ -5588,6 +5592,19 @@ var EditorView = function () {
5588
5592
  }, {
5589
5593
  key: "hasFocus",
5590
5594
  value: function hasFocus() {
5595
+ if (ie) {
5596
+ var node = this.root.activeElement;
5597
+ if (node == this.dom) return true;
5598
+ if (!node || !this.dom.contains(node)) return false;
5599
+
5600
+ while (node && this.dom != node && this.dom.contains(node)) {
5601
+ if (node.contentEditable == 'false') return false;
5602
+ node = node.parentElement;
5603
+ }
5604
+
5605
+ return true;
5606
+ }
5607
+
5591
5608
  return this.root.activeElement == this.dom;
5592
5609
  }
5593
5610
  }, {
package/dist/index.d.ts CHANGED
@@ -701,6 +701,11 @@ interface EditorProps<P = any> {
701
701
  */
702
702
  transformPasted?: (this: P, slice: Slice) => Slice;
703
703
  /**
704
+ Can be used to transform copied or cut content before it is
705
+ serialized to the clipboard.
706
+ */
707
+ transformCopied?: (this: P, slice: Slice) => Slice;
708
+ /**
704
709
  Allows you to pass custom rendering and behavior logic for
705
710
  nodes. Should map node names to constructor functions that
706
711
  produce a [`NodeView`](https://prosemirror.net/docs/ref/#view.NodeView) object implementing the
package/dist/index.js CHANGED
@@ -2203,7 +2203,7 @@ function selectionBetween(view, $anchor, $head, bias) {
2203
2203
  || TextSelection.between($anchor, $head, bias);
2204
2204
  }
2205
2205
  function hasFocusAndSelection(view) {
2206
- if (view.editable && view.root.activeElement != view.dom)
2206
+ if (view.editable && !view.hasFocus())
2207
2207
  return false;
2208
2208
  return hasSelection(view);
2209
2209
  }
@@ -2532,6 +2532,7 @@ function captureKeyDown(view, event) {
2532
2532
  }
2533
2533
 
2534
2534
  function serializeForClipboard(view, slice) {
2535
+ view.someProp("transformCopied", f => { slice = f(slice); });
2535
2536
  let context = [], { content, openStart, openEnd } = slice;
2536
2537
  while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild.childCount == 1) {
2537
2538
  openStart--;
@@ -3129,7 +3130,7 @@ class MouseDown {
3129
3130
  // (hidden) cursor is doesn't change the selection, and
3130
3131
  // thus doesn't get a reaction from ProseMirror. This
3131
3132
  // works around that.
3132
- (chrome && !(this.view.state.selection instanceof TextSelection) &&
3133
+ (chrome && !this.view.state.selection.visible &&
3133
3134
  Math.min(Math.abs(pos.pos - this.view.state.selection.from), Math.abs(pos.pos - this.view.state.selection.to)) <= 2))) {
3134
3135
  updateSelection(this.view, Selection.near(this.view.state.doc.resolve(pos.pos)), "pointer");
3135
3136
  event.preventDefault();
@@ -5073,6 +5074,24 @@ class EditorView {
5073
5074
  Query whether the view has focus.
5074
5075
  */
5075
5076
  hasFocus() {
5077
+ // Work around IE not handling focus correctly if resize handles are shown.
5078
+ // If the cursor is inside an element with resize handles, activeElement
5079
+ // will be that element instead of this.dom.
5080
+ if (ie) {
5081
+ // If activeElement is within this.dom, and there are no other elements
5082
+ // setting `contenteditable` to false in between, treat it as focused.
5083
+ let node = this.root.activeElement;
5084
+ if (node == this.dom)
5085
+ return true;
5086
+ if (!node || !this.dom.contains(node))
5087
+ return false;
5088
+ while (node && this.dom != node && this.dom.contains(node)) {
5089
+ if (node.contentEditable == 'false')
5090
+ return false;
5091
+ node = node.parentElement;
5092
+ }
5093
+ return true;
5094
+ }
5076
5095
  return this.root.activeElement == this.dom;
5077
5096
  }
5078
5097
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.27.2",
3
+ "version": "1.28.0",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
package/src/clipboard.ts CHANGED
@@ -3,6 +3,8 @@ import * as browser from "./browser"
3
3
  import {EditorView} from "./index"
4
4
 
5
5
  export function serializeForClipboard(view: EditorView, slice: Slice) {
6
+ view.someProp("transformCopied", f => { slice = f(slice!) })
7
+
6
8
  let context = [], {content, openStart, openEnd} = slice
7
9
  while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild!.childCount == 1) {
8
10
  openStart--
package/src/index.ts CHANGED
@@ -292,6 +292,21 @@ export class EditorView {
292
292
 
293
293
  /// Query whether the view has focus.
294
294
  hasFocus() {
295
+ // Work around IE not handling focus correctly if resize handles are shown.
296
+ // If the cursor is inside an element with resize handles, activeElement
297
+ // will be that element instead of this.dom.
298
+ if (browser.ie) {
299
+ // If activeElement is within this.dom, and there are no other elements
300
+ // setting `contenteditable` to false in between, treat it as focused.
301
+ let node = this.root.activeElement
302
+ if (node == this.dom) return true
303
+ if (!node || !this.dom.contains(node)) return false
304
+ while (node && this.dom != node && this.dom.contains(node)) {
305
+ if ((node as HTMLElement).contentEditable == 'false') return false
306
+ node = node.parentElement
307
+ }
308
+ return true
309
+ }
295
310
  return this.root.activeElement == this.dom
296
311
  }
297
312
 
@@ -636,6 +651,10 @@ export interface EditorProps<P = any> {
636
651
  /// before it is applied to the document.
637
652
  transformPasted?: (this: P, slice: Slice) => Slice
638
653
 
654
+ /// Can be used to transform copied or cut content before it is
655
+ /// serialized to the clipboard.
656
+ transformCopied?: (this: P, slice: Slice) => Slice
657
+
639
658
  /// Allows you to pass custom rendering and behavior logic for
640
659
  /// nodes. Should map node names to constructor functions that
641
660
  /// produce a [`NodeView`](#view.NodeView) object implementing the
package/src/input.ts CHANGED
@@ -388,7 +388,7 @@ class MouseDown {
388
388
  // (hidden) cursor is doesn't change the selection, and
389
389
  // thus doesn't get a reaction from ProseMirror. This
390
390
  // works around that.
391
- (browser.chrome && !(this.view.state.selection instanceof TextSelection) &&
391
+ (browser.chrome && !this.view.state.selection.visible &&
392
392
  Math.min(Math.abs(pos.pos - this.view.state.selection.from),
393
393
  Math.abs(pos.pos - this.view.state.selection.to)) <= 2))) {
394
394
  updateSelection(this.view, Selection.near(this.view.state.doc.resolve(pos.pos)), "pointer")
package/src/selection.ts CHANGED
@@ -181,7 +181,7 @@ export function selectionBetween(view: EditorView, $anchor: ResolvedPos, $head:
181
181
  }
182
182
 
183
183
  export function hasFocusAndSelection(view: EditorView) {
184
- if (view.editable && view.root.activeElement != view.dom) return false
184
+ if (view.editable && !view.hasFocus()) return false
185
185
  return hasSelection(view)
186
186
  }
187
187