@lexical/list 0.50.1-nightly.20260916.0 → 0.51.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.
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import { $getNearestNodeOfType, calculateZoomLevel } from '@lexical/utils';
10
- import { $getSelection, $isRangeSelection, $isTextNode, $isRootOrShadowRoot, $createParagraphNode, $copyNode, $isElementNode, $getSlotHost, $isLeafNode, $setPointFromCaret, $normalizeCaret, $getChildCaret, $applyNodeReplacement, ElementNode, buildImportMap, $getSiblingCaret, $insertNodeToNearestRootAtCaret, $rewindSiblingCaret, $getDocument, setDOMStyleFromCSS, isHTMLElement, $isParagraphNode, $setFormatFromDOM, $setDirectionFromDOM, normalizeClassNames, removeClassNamesFromElement, addClassNamesToElement, getStyleObjectFromCSS, createCommand, mergeRegister, COMMAND_PRIORITY_LOW, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_SPACE_COMMAND, $getNearestNodeFromDOMNode, KEY_ARROW_LEFT_COMMAND, $findMatchingParent, getActiveElement, registerEventListeners, IS_FIREFOX, registerEventListener, getNearestEditorFromDOMNode, $addUpdateTag, SKIP_SELECTION_FOCUS_TAG, SKIP_DOM_SELECTION_TAG, $createLineBreakNode, $getNodeByKey, INSERT_PARAGRAPH_COMMAND, KEY_BACKSPACE_COMMAND, COMMAND_PRIORITY_BEFORE_EDITOR, TextNode } from 'lexical';
10
+ import { $getSelection, $isRangeSelection, $isTextNode, $isRootOrShadowRoot, $createParagraphNode, $copyNode, $isElementNode, $getSlotHost, $isLeafNode, $setPointFromCaret, $normalizeCaret, $getChildCaret, getterTableOf, setterTableOf, setterDefaultOf, aliasTableOf, $applyNodeReplacement, ElementNode, buildImportMap, $getSiblingCaret, $insertNodeToNearestRootAtCaret, $rewindSiblingCaret, $getDocument, setDOMStyleFromCSS, isHTMLElement, $isParagraphNode, nodeSchema, withField, numberValue, withAccessors, optional, booleanValue, $setFormatFromDOM, $setDirectionFromDOM, normalizeClassNames, removeClassNamesFromElement, addClassNamesToElement, getStyleObjectFromCSS, enumValue, aliasedValue, createCommand, mergeRegister, COMMAND_PRIORITY_LOW, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_SPACE_COMMAND, $getNearestNodeFromDOMNode, KEY_ARROW_LEFT_COMMAND, $findMatchingParent, getActiveElement, registerEventListeners, IS_FIREFOX, registerEventListener, getNearestEditorFromDOMNode, $addUpdateTag, SKIP_SELECTION_FOCUS_TAG, SKIP_DOM_SELECTION_TAG, $createLineBreakNode, $getNodeByKey, INSERT_PARAGRAPH_COMMAND, KEY_BACKSPACE_COMMAND, COMMAND_PRIORITY_BEFORE_EDITOR, TextNode } from 'lexical';
11
11
  import { effect } from '@lexical/extension/signals';
12
12
  import { namedSignals } from '@lexical/extension/namedSignals';
13
13
  import { sel, isElementOfTag, $propagateTextAlignToBlockChildren, $isBlockLevel, CoreImportExtension, DOMImportExtension, ImportOverlays, defineOverlayRules, createImportState, InlineSchema } from '@lexical/html';
@@ -604,6 +604,269 @@ function $handleListInsertParagraph(restoreNumbering = false) {
604
604
  return true;
605
605
  }
606
606
 
607
+ /**
608
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
609
+ *
610
+ * This source code is licensed under the MIT license found in the
611
+ * LICENSE file in the root directory of this source tree.
612
+ *
613
+ */
614
+
615
+
616
+ // The JSON number grammar, anchored, matching numberValue: `Number()` alone
617
+ // reads '0x10' as 16 and '' as 0, and neither is a shape a JSON encoder
618
+ // produces. Emitted from the same source the codegen verified against, so the
619
+ // two cannot be different functions.
620
+ const JSON_NUMBER = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
621
+ function num(v, d) {
622
+ if (typeof v === 'number') {
623
+ return Number.isFinite(v) ? v : d;
624
+ }
625
+ if (typeof v !== 'string' || !JSON_NUMBER.test(v)) {
626
+ return d;
627
+ }
628
+ const n = Number(v);
629
+ return Number.isFinite(n) ? n : d;
630
+ }
631
+ function numC(v, d, min, max, integer) {
632
+ const n = num(v, d);
633
+ return n >= min && n <= max && (false || Number.isInteger(n)) ? n : d;
634
+ }
635
+ function numK(v, d, min, max, integer) {
636
+ const n = num(v, NaN);
637
+ if (!Number.isFinite(n) || !Number.isInteger(n)) {
638
+ return d;
639
+ }
640
+ return n < min ? min : n > max ? max : n;
641
+ }
642
+
643
+ /**
644
+ * ListNode's schema-declared fields, for a clone. Generated from that
645
+ * schema; do not edit by hand.
646
+ *
647
+ * @internal
648
+ */
649
+ function afterCloneListNode(node, prevNode) {
650
+ node.__listType = prevNode.__listType;
651
+ node.__start = prevNode.__start;
652
+ node.__tag = prevNode.__tag;
653
+ }
654
+
655
+ /** ListNode's generated implementations, for its `$config`. @internal */
656
+ const GENERATED_LIST = fields => {
657
+ const LIST_FORMAT_GETTER = getterTableOf(fields, 'format');
658
+ const LIST_FORMAT_SETTER = setterTableOf(fields, 'format');
659
+ const LIST_FORMAT_SETTER_DEFAULT = setterDefaultOf(fields, 'format');
660
+ const LIST_LISTTYPE_ALIAS = aliasTableOf(fields, 'listType', 0);
661
+
662
+ /** Generated from ListNode's serialization schema. Do not edit by hand. */
663
+ function exportListNode(node) {
664
+ const textFormat = node.__textFormat;
665
+ const textStyle = node.__textStyle;
666
+ const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
667
+ return {
668
+ children: [],
669
+ listType: node.__listType,
670
+ start: node.__start,
671
+ tag: node.__tag,
672
+ direction: node.__dir,
673
+ format: LIST_FORMAT_GETTER[node.__format],
674
+ indent: node.__indent,
675
+ textFormat: textFormat !== 0 && shouldSerializeTextStyles ? textFormat : undefined,
676
+ textStyle: textStyle !== '' && shouldSerializeTextStyles ? textStyle : undefined,
677
+ type: node.__type,
678
+ version: 1
679
+ };
680
+ }
681
+
682
+ /** Generated from ListNode's serialization schema. Do not edit by hand. */
683
+ function exportCompactListNode(node) {
684
+ const textFormat = node.__textFormat;
685
+ const textStyle = node.__textStyle;
686
+ const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
687
+ const json = {
688
+ type: node.__type,
689
+ children: []
690
+ };
691
+ const listType = node.__listType;
692
+ if (listType !== undefined && listType !== 'number') {
693
+ json.listType = listType;
694
+ }
695
+ const start = node.__start;
696
+ if (start !== undefined && start !== 1) {
697
+ json.start = start;
698
+ }
699
+ const direction = node.__dir;
700
+ if (direction != null) {
701
+ json.direction = direction;
702
+ }
703
+ const format = LIST_FORMAT_GETTER[node.__format];
704
+ if (format !== undefined && format !== '') {
705
+ json.format = format;
706
+ }
707
+ const indent = node.__indent;
708
+ if (indent !== undefined && indent !== 0) {
709
+ json.indent = indent;
710
+ }
711
+ if (textFormat !== undefined && textFormat !== 0 && shouldSerializeTextStyles) {
712
+ json.textFormat = textFormat;
713
+ }
714
+ if (textStyle !== undefined && textStyle !== '' && shouldSerializeTextStyles) {
715
+ json.textStyle = textStyle;
716
+ }
717
+ return json;
718
+ }
719
+
720
+ /** Generated from ListNode's serialization schema. Do not edit by hand. */
721
+ function updateListNode(node, json) {
722
+ const direction = json.direction;
723
+ node.__dir = direction === null || direction === 'ltr' || direction === 'rtl' ? direction : null;
724
+ const format = json.format;
725
+ node.__format = typeof format === 'string' && format in LIST_FORMAT_SETTER ? LIST_FORMAT_SETTER[format] : LIST_FORMAT_SETTER_DEFAULT;
726
+ node.__indent = numC(json.indent, 0, 0, Infinity);
727
+ node.__textFormat = num(json.textFormat, 0);
728
+ const textStyle = json.textStyle;
729
+ node.__textStyle = typeof textStyle === 'string' ? textStyle : '';
730
+ const listType = json.listType;
731
+ node.setListType(typeof listType === 'string' && listType in LIST_LISTTYPE_ALIAS ? LIST_LISTTYPE_ALIAS[listType] : listType === 'number' || listType === 'bullet' || listType === 'check' ? listType : 'number');
732
+ node.__start = num(json.start, 1);
733
+ return node;
734
+ }
735
+ return {
736
+ exportJSON: exportListNode,
737
+ exportCompactJSON: exportCompactListNode,
738
+ updateFromJSON: updateListNode,
739
+ afterCloneFrom: afterCloneListNode
740
+ };
741
+ };
742
+
743
+ /**
744
+ * ListItemNode's schema-declared fields, for a clone. Generated from that
745
+ * schema; do not edit by hand.
746
+ *
747
+ * @internal
748
+ */
749
+ function afterCloneListItemNode(node, prevNode) {
750
+ node.__checked = prevNode.__checked;
751
+ node.__value = prevNode.__value;
752
+ }
753
+
754
+ /** ListItemNode's generated implementations, for its `$config`. @internal */
755
+ const GENERATED_LISTITEM = fields => {
756
+ const LISTITEM_FORMAT_GETTER = getterTableOf(fields, 'format');
757
+ const LISTITEM_FORMAT_SETTER = setterTableOf(fields, 'format');
758
+ const LISTITEM_FORMAT_SETTER_DEFAULT = setterDefaultOf(fields, 'format');
759
+
760
+ /** Generated from ListItemNode's serialization schema. Do not edit by hand. */
761
+ function exportListItemNode(node) {
762
+ const textFormat = node.__textFormat;
763
+ const textStyle = node.__textStyle;
764
+ const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
765
+ return {
766
+ children: [],
767
+ checked: node.getChecked(),
768
+ indent: node.getIndent(),
769
+ value: node.__value,
770
+ direction: node.__dir,
771
+ format: LISTITEM_FORMAT_GETTER[node.__format],
772
+ textFormat: textFormat !== 0 && shouldSerializeTextStyles ? textFormat : undefined,
773
+ textStyle: textStyle !== '' && shouldSerializeTextStyles ? textStyle : undefined,
774
+ type: node.__type,
775
+ version: 1
776
+ };
777
+ }
778
+
779
+ /** Generated from ListItemNode's serialization schema. Do not edit by hand. */
780
+ function exportCompactListItemNode(node) {
781
+ const textFormat = node.__textFormat;
782
+ const textStyle = node.__textStyle;
783
+ const shouldSerializeTextStyles = (textFormat !== 0 || textStyle !== '') && node.shouldSerializeTextStyles();
784
+ const json = {
785
+ type: node.__type,
786
+ children: []
787
+ };
788
+ const checked = node.getChecked();
789
+ if (checked !== undefined) {
790
+ json.checked = checked;
791
+ }
792
+ const indent = node.getIndent();
793
+ if (indent !== undefined && indent !== 0) {
794
+ json.indent = indent;
795
+ }
796
+ const value = node.__value;
797
+ if (value !== undefined && value !== 1) {
798
+ json.value = value;
799
+ }
800
+ const direction = node.__dir;
801
+ if (direction != null) {
802
+ json.direction = direction;
803
+ }
804
+ const format = LISTITEM_FORMAT_GETTER[node.__format];
805
+ if (format !== undefined && format !== '') {
806
+ json.format = format;
807
+ }
808
+ if (textFormat !== undefined && textFormat !== 0 && shouldSerializeTextStyles) {
809
+ json.textFormat = textFormat;
810
+ }
811
+ if (textStyle !== undefined && textStyle !== '' && shouldSerializeTextStyles) {
812
+ json.textStyle = textStyle;
813
+ }
814
+ return json;
815
+ }
816
+
817
+ /** Generated from ListItemNode's serialization schema. Do not edit by hand. */
818
+ function updateListItemNode(node, json) {
819
+ const direction = json.direction;
820
+ node.__dir = direction === null || direction === 'ltr' || direction === 'rtl' ? direction : null;
821
+ const format = json.format;
822
+ node.__format = typeof format === 'string' && format in LISTITEM_FORMAT_SETTER ? LISTITEM_FORMAT_SETTER[format] : LISTITEM_FORMAT_SETTER_DEFAULT;
823
+ node.setIndent(numK(json.indent, 0, 0, 128));
824
+ node.__textFormat = num(json.textFormat, 0);
825
+ const textStyle = json.textStyle;
826
+ node.__textStyle = typeof textStyle === 'string' ? textStyle : '';
827
+ const checked = json.checked;
828
+ node.__checked = checked === undefined ? undefined : typeof checked === 'boolean' ? checked : false;
829
+ node.__value = num(json.value, 1);
830
+ return node;
831
+ }
832
+ return {
833
+ exportJSON: exportListItemNode,
834
+ exportCompactJSON: exportCompactListItemNode,
835
+ updateFromJSON: updateListItemNode,
836
+ afterCloneFrom: afterCloneListItemNode
837
+ };
838
+ };
839
+
840
+ /**
841
+ * The deepest list nesting `setIndent` will walk to. Each level it steps
842
+ * through nests or unwraps a whole list, so this bounds work an untrusted
843
+ * `indent` could otherwise make unbounded.
844
+ */
845
+ const MAX_LIST_ITEM_INDENT = 128;
846
+ const listItemNodeSchema = /* @__PURE__ */nodeSchema()({
847
+ // getChecked computes from the parent list's type, so the getter stays a
848
+ // method; setChecked is a bare field write.
849
+ checked: /* @__PURE__ */withAccessors(/* @__PURE__ */optional(/* @__PURE__ */booleanValue()), {
850
+ setter: {
851
+ field: '__checked'
852
+ }
853
+ }),
854
+ // Overrides the inherited ElementNode field to bound it. This indent is
855
+ // structural — applying it nests or unwraps one whole list per level — so an
856
+ // unbounded value out of untrusted JSON would build millions of nodes.
857
+ // `clamp`, because the plain bounds fall back to the *default* for a value
858
+ // outside them, which would read an over-deep item as indent 0 instead of as
859
+ // deeply nested.
860
+ indent: /* @__PURE__ */numberValue(0, {
861
+ clamp: true,
862
+ integer: true,
863
+ max: MAX_LIST_ITEM_INDENT,
864
+ min: 0
865
+ }),
866
+ value: /* @__PURE__ */withField(/* @__PURE__ */numberValue(1), {
867
+ field: '__value'
868
+ })
869
+ });
607
870
  function applyMarkerStyles(dom, node, prevNode) {
608
871
  const nextTextStyle = node.__textStyle;
609
872
  const prevTextStyle = prevNode ? prevNode.__textStyle : '';
@@ -623,7 +886,10 @@ function applyMarkerStyles(dom, node, prevNode) {
623
886
  }
624
887
  }
625
888
 
889
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
890
+
626
891
  /** @noInheritDoc */
892
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
627
893
  class ListItemNode extends ElementNode {
628
894
  /** @internal */
629
895
  __value;
@@ -674,12 +940,14 @@ class ListItemNode extends ElementNode {
674
940
  }
675
941
  },
676
942
  extends: ElementNode,
943
+ generated: GENERATED_LISTITEM,
677
944
  importDOM: buildImportMap({
678
945
  li: () => ({
679
946
  conversion: $convertListItemElement,
680
947
  priority: 0
681
948
  })
682
- })
949
+ }),
950
+ json: listItemNodeSchema
683
951
  });
684
952
  }
685
953
  constructor(value = 1, checked = undefined, key) {
@@ -687,11 +955,6 @@ class ListItemNode extends ElementNode {
687
955
  this.__value = value === undefined ? 1 : value;
688
956
  this.__checked = checked;
689
957
  }
690
- afterCloneFrom(prevNode) {
691
- super.afterCloneFrom(prevNode);
692
- this.__value = prevNode.__value;
693
- this.__checked = prevNode.__checked;
694
- }
695
958
  createDOM(config) {
696
959
  const element = $getDocument().createElement('li');
697
960
  this.updateListItemDOM(null, element, config);
@@ -714,9 +977,6 @@ class ListItemNode extends ElementNode {
714
977
  this.updateListItemDOM(prevNode, element, config);
715
978
  return false;
716
979
  }
717
- updateFromJSON(serializedNode) {
718
- return super.updateFromJSON(serializedNode).setValue(serializedNode.value).setChecked(serializedNode.checked);
719
- }
720
980
  exportDOM(editor) {
721
981
  const element = this.createDOM(editor._config);
722
982
  const formatType = this.getFormatType();
@@ -748,13 +1008,6 @@ class ListItemNode extends ElementNode {
748
1008
  element
749
1009
  };
750
1010
  }
751
- exportJSON() {
752
- return {
753
- ...super.exportJSON(),
754
- checked: this.getChecked(),
755
- value: this.getValue()
756
- };
757
- }
758
1011
  append(...nodes) {
759
1012
  for (let i = 0; i < nodes.length; i++) {
760
1013
  const node = nodes[i];
@@ -949,10 +1202,15 @@ class ListItemNode extends ElementNode {
949
1202
  indent = Math.floor(indent);
950
1203
  if (!(indent >= 0)) {
951
1204
  formatDevErrorMessage(`Indent value must be non-negative.`);
952
- }
1205
+ } // Deliberately not clamped here: the bound belongs on the parse path (see
1206
+ // listItemNodeSchema), because clamping the target of a walk that starts
1207
+ // from the node's *current* indent would outdent an item that is already
1208
+ // nested deeper than the bound — making `item.setIndent(item.getIndent())`
1209
+ // destroy structure rather than do nothing.
1210
+ const target = indent;
953
1211
  let currentIndent = this.getIndent();
954
- while (currentIndent !== indent) {
955
- if (currentIndent < indent) {
1212
+ while (currentIndent !== target) {
1213
+ if (currentIndent < target) {
956
1214
  $handleIndent(this);
957
1215
  currentIndent++;
958
1216
  } else {
@@ -1130,7 +1388,42 @@ function $isListItemNode(node) {
1130
1388
  *
1131
1389
  */
1132
1390
 
1391
+ // A literal rather than a `Record<string, ListType>` so that the alias table
1392
+ // below keeps its keys: they are what the schema reports as the legacy
1393
+ // spellings it accepts.
1394
+ const TAG_TO_LIST_TYPE = {
1395
+ ol: 'number',
1396
+ ul: 'bullet'
1397
+ };
1398
+ const listNodeSchema = /* @__PURE__ */nodeSchema()({
1399
+ // 'ul'/'ol' are the legacy tag-form listType some older documents carry,
1400
+ // stated as an alias table rather than a transform: the mapping is data, so
1401
+ // the codegen can compile this property's parse, where an arbitrary
1402
+ // function would have taken the whole class out of the import half.
1403
+ // Read straight off the field; applied through setListType, which also
1404
+ // maintains the derived __tag, so the setter stays a method.
1405
+ listType: /* @__PURE__ */withAccessors(/* @__PURE__ */aliasedValue(/* @__PURE__ */enumValue(['number', 'bullet', 'check']), TAG_TO_LIST_TYPE), {
1406
+ getter: {
1407
+ field: '__listType'
1408
+ }
1409
+ }),
1410
+ start: /* @__PURE__ */withField(/* @__PURE__ */numberValue(1), {
1411
+ field: '__start'
1412
+ }),
1413
+ // Derived from listType rather than stored: written on export, and
1414
+ // deliberately not applied on import.
1415
+ tag: /* @__PURE__ */withAccessors(/* @__PURE__ */enumValue(['ul', 'ol']), {
1416
+ getter: {
1417
+ field: '__tag'
1418
+ },
1419
+ setter: null
1420
+ })
1421
+ });
1422
+
1423
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
1424
+
1133
1425
  /** @noInheritDoc */
1426
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
1134
1427
  class ListNode extends ElementNode {
1135
1428
  /** @internal */
1136
1429
  __tag;
@@ -1147,6 +1440,7 @@ class ListNode extends ElementNode {
1147
1440
  updateChildrenListItemValue(node);
1148
1441
  },
1149
1442
  extends: ElementNode,
1443
+ generated: GENERATED_LIST,
1150
1444
  importDOM: buildImportMap({
1151
1445
  ol: () => ({
1152
1446
  conversion: $convertListNode,
@@ -1156,22 +1450,19 @@ class ListNode extends ElementNode {
1156
1450
  conversion: $convertListNode,
1157
1451
  priority: 0
1158
1452
  })
1159
- })
1453
+ }),
1454
+ json: listNodeSchema
1160
1455
  });
1161
1456
  }
1162
1457
  constructor(listType = 'number', start = 1, key) {
1163
1458
  super(key);
1459
+ // Widened for the lookup: the parameter's type excludes the legacy tag
1460
+ // spellings, and this normalizes them for a caller that passes one anyway.
1164
1461
  const _listType = TAG_TO_LIST_TYPE[listType] || listType;
1165
1462
  this.__listType = _listType;
1166
1463
  this.__tag = _listType === 'number' ? 'ol' : 'ul';
1167
1464
  this.__start = start;
1168
1465
  }
1169
- afterCloneFrom(prevNode) {
1170
- super.afterCloneFrom(prevNode);
1171
- this.__listType = prevNode.__listType;
1172
- this.__tag = prevNode.__tag;
1173
- this.__start = prevNode.__start;
1174
- }
1175
1466
  getTag() {
1176
1467
  return this.getLatest().__tag;
1177
1468
  }
@@ -1216,9 +1507,6 @@ class ListNode extends ElementNode {
1216
1507
  }
1217
1508
  return false;
1218
1509
  }
1219
- updateFromJSON(serializedNode) {
1220
- return super.updateFromJSON(serializedNode).setListType(serializedNode.listType).setStart(serializedNode.start);
1221
- }
1222
1510
  exportDOM(editor) {
1223
1511
  const element = this.createDOM(editor._config, editor);
1224
1512
  if (isHTMLElement(element)) {
@@ -1240,14 +1528,6 @@ class ListNode extends ElementNode {
1240
1528
  element
1241
1529
  };
1242
1530
  }
1243
- exportJSON() {
1244
- return {
1245
- ...super.exportJSON(),
1246
- listType: this.getListType(),
1247
- start: this.getStart(),
1248
- tag: this.getTag()
1249
- };
1250
- }
1251
1531
  canBeEmpty() {
1252
1532
  return false;
1253
1533
  }
@@ -1400,10 +1680,6 @@ function $convertListNode(domNode) {
1400
1680
  node
1401
1681
  };
1402
1682
  }
1403
- const TAG_TO_LIST_TYPE = {
1404
- ol: 'number',
1405
- ul: 'bullet'
1406
- };
1407
1683
 
1408
1684
  /**
1409
1685
  * Creates a ListNode of listType.
@@ -15,6 +15,7 @@ import type {
15
15
  RangeSelection,
16
16
  LexicalCommand,
17
17
  SerializedElementNode,
18
+ SerializedPartial,
18
19
  LexicalExtension,
19
20
  ExtensionConfigBase,
20
21
  } from 'lexical';
@@ -62,7 +63,17 @@ declare export class ListItemNode extends ElementNode {
62
63
  getChecked(): boolean | void;
63
64
  setChecked(boolean): this;
64
65
  toggleChecked(): void;
65
- static importJSON(serializedNode: SerializedListItemNode): ListItemNode;
66
+ // Both forms, because a Flow object property is invariant: `SerializedPartial`
67
+ // makes each property optional, and an optional property is not a supertype
68
+ // of a required one there, so naming only the relaxed form made the *full*
69
+ // serialized type unassignable — `ListItemNode.importJSON(node.exportJSON())`
70
+ // stopped type-checking. TypeScript needs no union: a required property
71
+ // satisfies an optional one structurally.
72
+ static importJSON(
73
+ serializedNode:
74
+ | SerializedListItemNode
75
+ | SerializedPartial<SerializedListItemNode>,
76
+ ): ListItemNode;
66
77
  }
67
78
  declare export class ListNode extends ElementNode {
68
79
  __tag: ListNodeTagType;
@@ -72,7 +83,17 @@ declare export class ListNode extends ElementNode {
72
83
  getTag(): ListNodeTagType;
73
84
  getStart(): number;
74
85
  getListType(): ListType;
75
- static importJSON(serializedNode: SerializedListNode): ListNode;
86
+ // Both forms, because a Flow object property is invariant: `SerializedPartial`
87
+ // makes each property optional, and an optional property is not a supertype
88
+ // of a required one there, so naming only the relaxed form made the *full*
89
+ // serialized type unassignable — `ListNode.importJSON(node.exportJSON())`
90
+ // stopped type-checking. TypeScript needs no union: a required property
91
+ // satisfies an optional one structurally.
92
+ static importJSON(
93
+ serializedNode:
94
+ | SerializedListNode
95
+ | SerializedPartial<SerializedListNode>,
96
+ ): ListNode;
76
97
  }
77
98
  declare export function outdentList(): void;
78
99
  declare export function $removeList(): void;