prosemirror-view 1.38.0 → 1.38.1

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.38.1 (2025-03-04)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix a regression in 1.38.0 that breaks scrolling back to the selection after Chrome tries to reset it on focus.
6
+
7
+ Remove some internally used types from the public type declaration files. Include file extension in web test local imports
8
+
9
+ Fix an issue where scrolling the cursor into view could inappropriately scroll parent nodes of absolutely positioned elements.
10
+
1
11
  ## 1.38.0 (2025-02-12)
2
12
 
3
13
  ### New features
package/dist/index.cjs CHANGED
@@ -200,9 +200,12 @@ function scrollRectIntoView(view, rect, startDOM) {
200
200
  var scrollThreshold = view.someProp("scrollThreshold") || 0,
201
201
  scrollMargin = view.someProp("scrollMargin") || 5;
202
202
  var doc = view.dom.ownerDocument;
203
- for (var parent = startDOM || view.dom;; parent = parentNode(parent)) {
203
+ for (var parent = startDOM || view.dom;;) {
204
204
  if (!parent) break;
205
- if (parent.nodeType != 1) continue;
205
+ if (parent.nodeType != 1) {
206
+ parent = parentNode(parent);
207
+ continue;
208
+ }
206
209
  var elt = parent;
207
210
  var atTop = elt == doc.body;
208
211
  var bounding = atTop ? windowRect(doc) : clientRect(elt);
@@ -228,7 +231,9 @@ function scrollRectIntoView(view, rect, startDOM) {
228
231
  };
229
232
  }
230
233
  }
231
- if (atTop || /^(fixed|sticky)$/.test(getComputedStyle(parent).position)) break;
234
+ var pos = atTop ? "fixed" : getComputedStyle(parent).position;
235
+ if (/^(fixed|sticky)$/.test(pos)) break;
236
+ parent = pos == "absolute" ? parent.offsetParent : parentNode(parent);
232
237
  }
233
238
  }
234
239
  function storeScrollPos(view) {
@@ -4369,6 +4374,7 @@ var DOMObserver = function () {
4369
4374
  view.input.lastFocus = 0;
4370
4375
  selectionToDOM(view);
4371
4376
  this.currentSelection.set(sel);
4377
+ view.scrollToSelection();
4372
4378
  } else if (from > -1 || newSel) {
4373
4379
  if (from > -1) {
4374
4380
  view.docView.markDirty(from, to);
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { EditorState, Transaction, Selection, Plugin } from 'prosemirror-state';
2
- import { Mark, Node, TagParseRule, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
2
+ import { Mark, Node, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
3
3
  import { Mapping } from 'prosemirror-transform';
4
4
 
5
5
  type DOMNode = InstanceType<typeof window.Node>;
@@ -234,7 +234,6 @@ declare class DecorationGroup implements DecorationSource {
234
234
 
235
235
  declare global {
236
236
  interface Node {
237
- pmViewDesc?: ViewDesc;
238
237
  }
239
238
  }
240
239
  /**
@@ -361,104 +360,6 @@ interface MarkView {
361
360
  */
362
361
  destroy?: () => void;
363
362
  }
364
- declare class ViewDesc {
365
- parent: ViewDesc | undefined;
366
- children: ViewDesc[];
367
- dom: DOMNode;
368
- contentDOM: HTMLElement | null;
369
- dirty: number;
370
- node: Node | null;
371
- constructor(parent: ViewDesc | undefined, children: ViewDesc[], dom: DOMNode, contentDOM: HTMLElement | null);
372
- matchesWidget(widget: Decoration): boolean;
373
- matchesMark(mark: Mark): boolean;
374
- matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
375
- matchesHack(nodeName: string): boolean;
376
- parseRule(): Omit<TagParseRule, "tag"> | null;
377
- stopEvent(event: Event): boolean;
378
- get size(): number;
379
- get border(): number;
380
- destroy(): void;
381
- posBeforeChild(child: ViewDesc): number;
382
- get posBefore(): number;
383
- get posAtStart(): number;
384
- get posAfter(): number;
385
- get posAtEnd(): number;
386
- localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
387
- nearestDesc(dom: DOMNode): ViewDesc | undefined;
388
- nearestDesc(dom: DOMNode, onlyNodes: true): NodeViewDesc | undefined;
389
- getDesc(dom: DOMNode): ViewDesc | undefined;
390
- posFromDOM(dom: DOMNode, offset: number, bias: number): number;
391
- descAt(pos: number): ViewDesc | undefined;
392
- domFromPos(pos: number, side: number): {
393
- node: DOMNode;
394
- offset: number;
395
- atom?: number;
396
- };
397
- parseRange(from: number, to: number, base?: number): {
398
- node: DOMNode;
399
- from: number;
400
- to: number;
401
- fromOffset: number;
402
- toOffset: number;
403
- };
404
- emptyChildAt(side: number): boolean;
405
- domAfterPos(pos: number): DOMNode;
406
- setSelection(anchor: number, head: number, view: EditorView, force?: boolean): void;
407
- ignoreMutation(mutation: ViewMutationRecord): boolean;
408
- get contentLost(): boolean | null;
409
- markDirty(from: number, to: number): void;
410
- markParentsDirty(): void;
411
- get domAtom(): boolean;
412
- get ignoreForCoords(): boolean;
413
- isText(text: string): boolean;
414
- }
415
- declare class NodeViewDesc extends ViewDesc {
416
- node: Node;
417
- outerDeco: readonly Decoration[];
418
- innerDeco: DecorationSource;
419
- readonly nodeDOM: DOMNode;
420
- constructor(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, dom: DOMNode, contentDOM: HTMLElement | null, nodeDOM: DOMNode, view: EditorView, pos: number);
421
- static create(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView, pos: number): NodeViewDesc | TextViewDesc;
422
- parseRule(): Omit<TagParseRule, "tag"> | null;
423
- matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
424
- get size(): number;
425
- get border(): 0 | 1;
426
- updateChildren(view: EditorView, pos: number): void;
427
- localCompositionInfo(view: EditorView, pos: number): {
428
- node: Text;
429
- pos: number;
430
- text: string;
431
- } | null;
432
- protectLocalComposition(view: EditorView, { node, pos, text }: {
433
- node: Text;
434
- pos: number;
435
- text: string;
436
- }): void;
437
- update(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): boolean;
438
- updateInner(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): void;
439
- updateOuterDeco(outerDeco: readonly Decoration[]): void;
440
- selectNode(): void;
441
- deselectNode(): void;
442
- get domAtom(): boolean;
443
- }
444
- declare class TextViewDesc extends NodeViewDesc {
445
- constructor(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, dom: DOMNode, nodeDOM: DOMNode, view: EditorView);
446
- parseRule(): {
447
- skip: any;
448
- };
449
- update(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): boolean;
450
- inParent(): boolean;
451
- domFromPos(pos: number): {
452
- node: globalThis.Node;
453
- offset: number;
454
- };
455
- localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
456
- ignoreMutation(mutation: ViewMutationRecord): boolean;
457
- slice(from: number, to: number, view: EditorView): TextViewDesc;
458
- markDirty(from: number, to: number): void;
459
- get domAtom(): boolean;
460
- isText(text: string): boolean;
461
- }
462
363
 
463
364
  /**
464
365
  An editor view manages the DOM structure that represents an
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { EditorState, Transaction, Selection, Plugin } from 'prosemirror-state';
2
- import { Mark, Node, TagParseRule, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
2
+ import { Mark, Node, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
3
3
  import { Mapping } from 'prosemirror-transform';
4
4
 
5
5
  type DOMNode = InstanceType<typeof window.Node>;
@@ -234,7 +234,6 @@ declare class DecorationGroup implements DecorationSource {
234
234
 
235
235
  declare global {
236
236
  interface Node {
237
- pmViewDesc?: ViewDesc;
238
237
  }
239
238
  }
240
239
  /**
@@ -361,104 +360,6 @@ interface MarkView {
361
360
  */
362
361
  destroy?: () => void;
363
362
  }
364
- declare class ViewDesc {
365
- parent: ViewDesc | undefined;
366
- children: ViewDesc[];
367
- dom: DOMNode;
368
- contentDOM: HTMLElement | null;
369
- dirty: number;
370
- node: Node | null;
371
- constructor(parent: ViewDesc | undefined, children: ViewDesc[], dom: DOMNode, contentDOM: HTMLElement | null);
372
- matchesWidget(widget: Decoration): boolean;
373
- matchesMark(mark: Mark): boolean;
374
- matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
375
- matchesHack(nodeName: string): boolean;
376
- parseRule(): Omit<TagParseRule, "tag"> | null;
377
- stopEvent(event: Event): boolean;
378
- get size(): number;
379
- get border(): number;
380
- destroy(): void;
381
- posBeforeChild(child: ViewDesc): number;
382
- get posBefore(): number;
383
- get posAtStart(): number;
384
- get posAfter(): number;
385
- get posAtEnd(): number;
386
- localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
387
- nearestDesc(dom: DOMNode): ViewDesc | undefined;
388
- nearestDesc(dom: DOMNode, onlyNodes: true): NodeViewDesc | undefined;
389
- getDesc(dom: DOMNode): ViewDesc | undefined;
390
- posFromDOM(dom: DOMNode, offset: number, bias: number): number;
391
- descAt(pos: number): ViewDesc | undefined;
392
- domFromPos(pos: number, side: number): {
393
- node: DOMNode;
394
- offset: number;
395
- atom?: number;
396
- };
397
- parseRange(from: number, to: number, base?: number): {
398
- node: DOMNode;
399
- from: number;
400
- to: number;
401
- fromOffset: number;
402
- toOffset: number;
403
- };
404
- emptyChildAt(side: number): boolean;
405
- domAfterPos(pos: number): DOMNode;
406
- setSelection(anchor: number, head: number, view: EditorView, force?: boolean): void;
407
- ignoreMutation(mutation: ViewMutationRecord): boolean;
408
- get contentLost(): boolean | null;
409
- markDirty(from: number, to: number): void;
410
- markParentsDirty(): void;
411
- get domAtom(): boolean;
412
- get ignoreForCoords(): boolean;
413
- isText(text: string): boolean;
414
- }
415
- declare class NodeViewDesc extends ViewDesc {
416
- node: Node;
417
- outerDeco: readonly Decoration[];
418
- innerDeco: DecorationSource;
419
- readonly nodeDOM: DOMNode;
420
- constructor(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, dom: DOMNode, contentDOM: HTMLElement | null, nodeDOM: DOMNode, view: EditorView, pos: number);
421
- static create(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView, pos: number): NodeViewDesc | TextViewDesc;
422
- parseRule(): Omit<TagParseRule, "tag"> | null;
423
- matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
424
- get size(): number;
425
- get border(): 0 | 1;
426
- updateChildren(view: EditorView, pos: number): void;
427
- localCompositionInfo(view: EditorView, pos: number): {
428
- node: Text;
429
- pos: number;
430
- text: string;
431
- } | null;
432
- protectLocalComposition(view: EditorView, { node, pos, text }: {
433
- node: Text;
434
- pos: number;
435
- text: string;
436
- }): void;
437
- update(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): boolean;
438
- updateInner(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): void;
439
- updateOuterDeco(outerDeco: readonly Decoration[]): void;
440
- selectNode(): void;
441
- deselectNode(): void;
442
- get domAtom(): boolean;
443
- }
444
- declare class TextViewDesc extends NodeViewDesc {
445
- constructor(parent: ViewDesc | undefined, node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, dom: DOMNode, nodeDOM: DOMNode, view: EditorView);
446
- parseRule(): {
447
- skip: any;
448
- };
449
- update(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource, view: EditorView): boolean;
450
- inParent(): boolean;
451
- domFromPos(pos: number): {
452
- node: globalThis.Node;
453
- offset: number;
454
- };
455
- localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
456
- ignoreMutation(mutation: ViewMutationRecord): boolean;
457
- slice(from: number, to: number, view: EditorView): TextViewDesc;
458
- markDirty(from: number, to: number): void;
459
- get domAtom(): boolean;
460
- isText(text: string): boolean;
461
- }
462
363
 
463
364
  /**
464
365
  An editor view manages the DOM structure that represents an
package/dist/index.js CHANGED
@@ -201,11 +201,13 @@ function clientRect(node) {
201
201
  function scrollRectIntoView(view, rect, startDOM) {
202
202
  let scrollThreshold = view.someProp("scrollThreshold") || 0, scrollMargin = view.someProp("scrollMargin") || 5;
203
203
  let doc = view.dom.ownerDocument;
204
- for (let parent = startDOM || view.dom;; parent = parentNode(parent)) {
204
+ for (let parent = startDOM || view.dom;;) {
205
205
  if (!parent)
206
206
  break;
207
- if (parent.nodeType != 1)
207
+ if (parent.nodeType != 1) {
208
+ parent = parentNode(parent);
208
209
  continue;
210
+ }
209
211
  let elt = parent;
210
212
  let atTop = elt == doc.body;
211
213
  let bounding = atTop ? windowRect(doc) : clientRect(elt);
@@ -234,8 +236,10 @@ function scrollRectIntoView(view, rect, startDOM) {
234
236
  rect = { left: rect.left - dX, top: rect.top - dY, right: rect.right - dX, bottom: rect.bottom - dY };
235
237
  }
236
238
  }
237
- if (atTop || /^(fixed|sticky)$/.test(getComputedStyle(parent).position))
239
+ let pos = atTop ? "fixed" : getComputedStyle(parent).position;
240
+ if (/^(fixed|sticky)$/.test(pos))
238
241
  break;
242
+ parent = pos == "absolute" ? parent.offsetParent : parentNode(parent);
239
243
  }
240
244
  }
241
245
  // Store the scroll position of the editor's parent nodes, along with
@@ -4705,6 +4709,7 @@ class DOMObserver {
4705
4709
  view.input.lastFocus = 0;
4706
4710
  selectionToDOM(view);
4707
4711
  this.currentSelection.set(sel);
4712
+ view.scrollToSelection();
4708
4713
  }
4709
4714
  else if (from > -1 || newSel) {
4710
4715
  if (from > -1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.38.0",
3
+ "version": "1.38.1",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
package/src/domcoords.ts CHANGED
@@ -32,9 +32,9 @@ function clientRect(node: HTMLElement): Rect {
32
32
  export function scrollRectIntoView(view: EditorView, rect: Rect, startDOM: Node) {
33
33
  let scrollThreshold = view.someProp("scrollThreshold") || 0, scrollMargin = view.someProp("scrollMargin") || 5
34
34
  let doc = view.dom.ownerDocument
35
- for (let parent: Node | null = startDOM || view.dom;; parent = parentNode(parent)) {
35
+ for (let parent: Node | null = startDOM || view.dom;;) {
36
36
  if (!parent) break
37
- if (parent.nodeType != 1) continue
37
+ if (parent.nodeType != 1) { parent = parentNode(parent); continue }
38
38
  let elt = parent as HTMLElement
39
39
  let atTop = elt == doc.body
40
40
  let bounding = atTop ? windowRect(doc) : clientRect(elt as HTMLElement)
@@ -60,7 +60,9 @@ export function scrollRectIntoView(view: EditorView, rect: Rect, startDOM: Node)
60
60
  rect = {left: rect.left - dX, top: rect.top - dY, right: rect.right - dX, bottom: rect.bottom - dY}
61
61
  }
62
62
  }
63
- if (atTop || /^(fixed|sticky)$/.test(getComputedStyle(parent as HTMLElement).position)) break
63
+ let pos: string = atTop ? "fixed" : getComputedStyle(parent as HTMLElement).position
64
+ if (/^(fixed|sticky)$/.test(pos)) break
65
+ parent = pos == "absolute" ? (parent as HTMLElement).offsetParent : parentNode(parent)
64
66
  }
65
67
  }
66
68
 
@@ -211,6 +211,7 @@ export class DOMObserver {
211
211
  view.input.lastFocus = 0
212
212
  selectionToDOM(view)
213
213
  this.currentSelection.set(sel)
214
+ view.scrollToSelection()
214
215
  } else if (from > -1 || newSel) {
215
216
  if (from > -1) {
216
217
  view.docView.markDirty(from, to)
package/src/viewdesc.ts CHANGED
@@ -7,7 +7,10 @@ import {Decoration, DecorationSource, WidgetConstructor, WidgetType, NodeType} f
7
7
  import {EditorView} from "./index"
8
8
 
9
9
  declare global {
10
- interface Node { pmViewDesc?: ViewDesc }
10
+ interface Node {
11
+ /// @internal
12
+ pmViewDesc?: ViewDesc
13
+ }
11
14
  }
12
15
 
13
16
  /// A ViewMutationRecord represents a DOM