@examind/block-types 0.1.25 → 0.1.28

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@examind/block-types",
3
- "version": "0.1.25",
3
+ "version": "0.1.28",
4
4
  "@comment version": [
5
5
  "Don't specify package version here. It will be injected by publish workflow."
6
6
  ],
@@ -4,11 +4,7 @@ import {
4
4
  type Spread,
5
5
  } from '../../lexical';
6
6
 
7
- const JournalTypes = [
8
- 'default',
9
- 'noEntryRequiredCorrect',
10
- 'noEntryRequiredDistractor',
11
- ] as const;
7
+ const JournalTypes = ['default', 'noEntryRequiredCorrect'] as const;
12
8
 
13
9
  export type JournalType = (typeof JournalTypes)[number];
14
10
 
@@ -23,7 +19,7 @@ export type SerializedJournalEntryQuestionItem = {
23
19
  export type SerializedJournalEntryQuestionNode = Spread<
24
20
  {
25
21
  id: string;
26
- journalType: JournalType;
22
+ noEntryRequired: boolean;
27
23
  points: number;
28
24
  errorTolerance?: number;
29
25
  lineItems: Array<SerializedJournalEntryQuestionItem>;
@@ -49,3 +49,4 @@ export declare const ELEMENT_FORMAT_TO_TYPE: Record<number, ElementFormatType>;
49
49
  export declare const TEXT_MODE_TO_TYPE: Record<TextModeType, 0 | 1 | 2>;
50
50
  export declare const TEXT_TYPE_TO_MODE: Record<number, TextModeType>;
51
51
  export declare const NODE_STATE_KEY = "$";
52
+ export declare const PROTOTYPE_CONFIG_METHOD = "$config";
@@ -7,6 +7,7 @@
7
7
  import type { EditorState, SerializedEditorState } from './LexicalEditorState';
8
8
  import type { DOMConversion, DOMConversionMap, DOMExportOutput, DOMExportOutputMap, NodeKey } from './LexicalNode';
9
9
  import { LexicalNode } from './LexicalNode';
10
+ import { SharedNodeState } from './LexicalNodeState';
10
11
  import { UpdateTag } from './LexicalUpdateTags';
11
12
  export type Spread<T1, T2> = Omit<T2, keyof T1> & T1;
12
13
  export type KlassConstructor<Cls extends GenericConstructor<any>> = GenericConstructor<InstanceType<Cls>> & {
@@ -32,9 +33,25 @@ export type TextNodeThemeClasses = {
32
33
  [key: string]: EditorThemeClassName | undefined;
33
34
  };
34
35
  export type EditorUpdateOptions = {
36
+ /**
37
+ * A function to run once the update is complete. See also {@link $onUpdate}.
38
+ */
35
39
  onUpdate?: () => void;
40
+ /**
41
+ * Setting this to true will suppress all node
42
+ * transforms for this update cycle.
43
+ * Useful for synchronizing updates in some cases.
44
+ */
36
45
  skipTransforms?: true;
46
+ /**
47
+ * A tag to identify this update, in an update listener, for instance.
48
+ * See also {@link $addUpdateTag}.
49
+ */
37
50
  tag?: UpdateTag | UpdateTag[];
51
+ /**
52
+ * If true, prevents this update from being batched, forcing it to
53
+ * run synchronously.
54
+ */
38
55
  discrete?: true;
39
56
  /** @internal */
40
57
  event?: undefined | UIEvent | Event | null;
@@ -42,9 +59,13 @@ export type EditorUpdateOptions = {
42
59
  export type EditorSetOptions = {
43
60
  tag?: string;
44
61
  };
45
- export type EditorFocusOptions = {
62
+ export interface EditorFocusOptions {
63
+ /**
64
+ * Where to move selection when the editor is
65
+ * focused. Can be rootStart, rootEnd, or undefined. Defaults to rootEnd.
66
+ */
46
67
  defaultSelection?: 'rootStart' | 'rootEnd';
47
- };
68
+ }
48
69
  export type EditorThemeClasses = {
49
70
  blockCursor?: EditorThemeClassName;
50
71
  characterLimit?: EditorThemeClassName;
@@ -123,11 +144,15 @@ export type HTMLConfig = {
123
144
  export?: DOMExportOutputMap;
124
145
  import?: DOMConversionMap;
125
146
  };
147
+ /**
148
+ * A LexicalNode class or LexicalNodeReplacement configuration
149
+ */
150
+ export type LexicalNodeConfig = Klass<LexicalNode> | LexicalNodeReplacement;
126
151
  export type CreateEditorArgs = {
127
152
  disableEvents?: boolean;
128
153
  editorState?: EditorState;
129
154
  namespace?: string;
130
- nodes?: ReadonlyArray<Klass<LexicalNode> | LexicalNodeReplacement>;
155
+ nodes?: ReadonlyArray<LexicalNodeConfig>;
131
156
  onError?: ErrorHandler;
132
157
  parentEditor?: LexicalEditor;
133
158
  editable?: boolean;
@@ -141,10 +166,11 @@ export type RegisteredNode = {
141
166
  replace: null | ((node: LexicalNode) => LexicalNode);
142
167
  replaceWithKlass: null | Klass<LexicalNode>;
143
168
  exportDOM?: (editor: LexicalEditor, targetNode: LexicalNode) => DOMExportOutput;
169
+ sharedNodeState: SharedNodeState;
144
170
  };
145
171
  export type Transform<T extends LexicalNode> = (node: T) => void;
146
172
  export type ErrorHandler = (error: Error) => void;
147
- export type MutationListeners = Map<MutationListener, Klass<LexicalNode>>;
173
+ export type MutationListeners = Map<MutationListener, Set<Klass<LexicalNode>>>;
148
174
  export type MutatedNodes = Map<Klass<LexicalNode>, Map<NodeKey, NodeMutation>>;
149
175
  export type NodeMutation = 'created' | 'updated' | 'destroyed';
150
176
  export interface MutationListenerOptions {
@@ -443,9 +469,9 @@ export declare class LexicalEditor {
443
469
  */
444
470
  registerMutationListener(klass: Klass<LexicalNode>, listener: MutationListener, options?: MutationListenerOptions): () => void;
445
471
  /** @internal */
446
- private getRegisteredNode;
472
+ getRegisteredNode(klass: Klass<LexicalNode>): RegisteredNode;
447
473
  /** @internal */
448
- private resolveRegisteredNodeAfterReplacements;
474
+ resolveRegisteredNodeAfterReplacements(registeredNode: RegisteredNode): RegisteredNode;
449
475
  /** @internal */
450
476
  private initializeMutationListener;
451
477
  /** @internal */
@@ -546,14 +572,6 @@ export declare class LexicalEditor {
546
572
  * where Lexical editor state can be safely mutated.
547
573
  * @param updateFn - A function that has access to writable editor state.
548
574
  * @param options - A bag of options to control the behavior of the update.
549
- * @param options.onUpdate - A function to run once the update is complete.
550
- * Useful for synchronizing updates in some cases.
551
- * @param options.skipTransforms - Setting this to true will suppress all node
552
- * transforms for this update cycle.
553
- * @param options.tag - A tag to identify this update, in an update listener, for instance.
554
- * Some tags are reserved by the core and control update behavior in different ways.
555
- * @param options.discrete - If true, prevents this update from being batched, forcing it to
556
- * run synchronously.
557
575
  */
558
576
  update(updateFn: () => void, options?: EditorUpdateOptions): void;
559
577
  /**
@@ -564,8 +582,6 @@ export declare class LexicalEditor {
564
582
  *
565
583
  * @param callbackFn - A function to run after the editor is focused.
566
584
  * @param options - A bag of options
567
- * @param options.defaultSelection - Where to move selection when the editor is
568
- * focused. Can be rootStart, rootEnd, or undefined. Defaults to rootEnd.
569
585
  */
570
586
  focus(callbackFn?: () => void, options?: EditorFocusOptions): void;
571
587
  /**
@@ -6,8 +6,9 @@
6
6
 
7
7
  import type { EditorConfig, Klass, KlassConstructor, LexicalEditor } from './LexicalEditor';
8
8
  import type { BaseSelection, RangeSelection } from './LexicalSelection';
9
- import { type DecoratorNode, ElementNode, NODE_STATE_KEY } from '.';
10
- import { type NodeState } from './LexicalNodeState';
9
+ import { type DecoratorNode, type ElementNode, NODE_STATE_KEY } from '.';
10
+ import { PROTOTYPE_CONFIG_METHOD } from './LexicalConstants';
11
+ import { type NodeState, type NodeStateJSON, type Prettify, type RequiredNodeStateConfig } from './LexicalNodeState';
11
12
  export type NodeMap = Map<NodeKey, LexicalNode>;
12
13
  /**
13
14
  * The base type for all serialized nodes
@@ -17,8 +18,134 @@ export type SerializedLexicalNode = {
17
18
  type: string;
18
19
  /** A numeric version for this schema, defaulting to 1, but not generally recommended for use */
19
20
  version: number;
21
+ /**
22
+ * Any state persisted with the NodeState API that is not
23
+ * configured for flat storage
24
+ */
20
25
  [NODE_STATE_KEY]?: Record<string, unknown>;
21
26
  };
27
+ /**
28
+ * EXPERIMENTAL
29
+ * The configuration of a node returned by LexicalNode.$config()
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * class CustomText extends TextNode {
34
+ * $config() {
35
+ * return this.config('custom-text', {extends: TextNode}};
36
+ * }
37
+ * }
38
+ * ```
39
+ */
40
+ export interface StaticNodeConfigValue<T extends LexicalNode, Type extends string> {
41
+ /**
42
+ * The exact type of T.getType(), e.g. 'text' - the method itself must
43
+ * have a more generic 'string' type to be compatible wtih subclassing.
44
+ */
45
+ readonly type?: Type;
46
+ /**
47
+ * An alternative to the internal static transform() method
48
+ * that provides better type inference.
49
+ */
50
+ readonly $transform?: (node: T) => void;
51
+ /**
52
+ * An alternative to the static importJSON() method
53
+ * that provides better type inference.
54
+ */
55
+ readonly $importJSON?: (serializedNode: SerializedLexicalNode) => T;
56
+ /**
57
+ * An alternative to the static importDOM() method
58
+ */
59
+ readonly importDOM?: DOMConversionMap;
60
+ /**
61
+ * EXPERIMENTAL
62
+ *
63
+ * An array of RequiredNodeStateConfig to initialize your node with
64
+ * its state requirements. This may be used to configure serialization of
65
+ * that state.
66
+ *
67
+ * This function will be called (at most) once per editor initialization,
68
+ * directly on your node's prototype. It must not depend on any state
69
+ * initialized in the constructor.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * const flatState = createState("flat", {parse: parseNumber});
74
+ * const nestedState = createState("nested", {parse: parseNumber});
75
+ * class MyNode extends TextNode {
76
+ * $config() {
77
+ * return this.config(
78
+ * 'my-node',
79
+ * {
80
+ * extends: TextNode,
81
+ * stateConfigs: [
82
+ * { stateConfig: flatState, flat: true},
83
+ * nestedState,
84
+ * ]
85
+ * },
86
+ * );
87
+ * }
88
+ * }
89
+ * ```
90
+ */
91
+ readonly stateConfigs?: readonly RequiredNodeStateConfig[];
92
+ /**
93
+ * If specified, this must be the exact superclass of the node. It is not
94
+ * checked at compile time and it is provided automatically at runtime.
95
+ *
96
+ * You would want to specify this when you are extending a node that
97
+ * has non-trivial configuration in its $config such
98
+ * as required state. If you do not specify this, the inferred
99
+ * types for your node class might be missing some of that.
100
+ */
101
+ readonly extends?: Klass<LexicalNode>;
102
+ }
103
+ /**
104
+ * This is the type of LexicalNode.$config() that can be
105
+ * overridden by subclasses.
106
+ */
107
+ export type BaseStaticNodeConfig = {
108
+ readonly [K in string]?: StaticNodeConfigValue<LexicalNode, string>;
109
+ };
110
+ /**
111
+ * Used to extract the node and type from a StaticNodeConfigRecord
112
+ */
113
+ export type StaticNodeConfig<T extends LexicalNode, Type extends string> = BaseStaticNodeConfig & {
114
+ readonly [K in Type]?: StaticNodeConfigValue<T, Type>;
115
+ };
116
+ /**
117
+ * Any StaticNodeConfigValue (for generics and collections)
118
+ */
119
+ export type AnyStaticNodeConfigValue = StaticNodeConfigValue<any, any>;
120
+ /**
121
+ * @internal
122
+ *
123
+ * This is the more specific type than BaseStaticNodeConfig that a subclass
124
+ * should return from $config()
125
+ */
126
+ export type StaticNodeConfigRecord<Type extends string, Config extends AnyStaticNodeConfigValue> = BaseStaticNodeConfig & {
127
+ readonly [K in Type]?: Config;
128
+ };
129
+ /**
130
+ * Extract the type from a node based on its $config
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * type TextNodeType = GetStaticNodeType<TextNode>;
135
+ * // ? 'text'
136
+ * ```
137
+ */
138
+ export type GetStaticNodeType<T extends LexicalNode> = ReturnType<T[typeof PROTOTYPE_CONFIG_METHOD]> extends StaticNodeConfig<T, infer Type> ? Type : string;
139
+ /**
140
+ * The most precise type we can infer for the JSON that will
141
+ * be produced by T.exportJSON().
142
+ *
143
+ * Do not use this for the return type of T.exportJSON()! It must be
144
+ * a more generic type to be compatible with subclassing.
145
+ */
146
+ export type LexicalExportJSON<T extends LexicalNode> = Prettify<Omit<ReturnType<T['exportJSON']>, 'type'> & {
147
+ type: GetStaticNodeType<T>;
148
+ } & NodeStateJSON<T>>;
22
149
  /**
23
150
  * Omit the children, type, and version properties from the given SerializedLexicalNode definition.
24
151
  */
@@ -32,13 +159,26 @@ export interface LexicalPrivateDOM {
32
159
  __lexicalUnmanaged?: boolean | undefined;
33
160
  }
34
161
  export declare function $removeNode(nodeToRemove: LexicalNode, restoreSelection: boolean, preserveEmptyParent?: boolean): void;
162
+ export type DOMConversionProp<T extends HTMLElement> = (node: T) => DOMConversion<T> | null;
163
+ export type DOMConversionPropByTagName<K extends string> = DOMConversionProp<K extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[K] : HTMLElement>;
164
+ export type DOMConversionTagNameMap<K extends string> = {
165
+ [NodeName in K]?: DOMConversionPropByTagName<NodeName>;
166
+ };
167
+ /**
168
+ * An identity function that will infer the type of DOM nodes
169
+ * based on tag names to make it easier to construct a
170
+ * DOMConversionMap.
171
+ */
172
+ export declare function buildImportMap<K extends string>(importMap: {
173
+ [NodeName in K]: DOMConversionPropByTagName<NodeName>;
174
+ }): DOMConversionMap;
35
175
  export type DOMConversion<T extends HTMLElement = HTMLElement> = {
36
176
  conversion: DOMConversionFn<T>;
37
177
  priority?: 0 | 1 | 2 | 3 | 4;
38
178
  };
39
179
  export type DOMConversionFn<T extends HTMLElement = HTMLElement> = (element: T) => DOMConversionOutput | null;
40
180
  export type DOMChildConversion = (lexicalNode: LexicalNode, parentLexicalNode: LexicalNode | null | undefined) => LexicalNode | null | undefined;
41
- export type DOMConversionMap<T extends HTMLElement = HTMLElement> = Record<NodeName, (node: T) => DOMConversion<T> | null>;
181
+ export type DOMConversionMap<T extends HTMLElement = HTMLElement> = Record<NodeName, DOMConversionProp<T>>;
42
182
  type NodeName = string;
43
183
  export type DOMConversionOutput = {
44
184
  after?: (childLexicalNodes: Array<LexicalNode>) => Array<LexicalNode>;
@@ -79,6 +219,28 @@ export declare class LexicalNode {
79
219
  *
80
220
  */
81
221
  static clone(_data: unknown): LexicalNode;
222
+ /**
223
+ * Override this to implement the new static node configuration protocol,
224
+ * this method is called directly on the prototype and must not depend
225
+ * on anything initialized in the constructor. Generally it should be
226
+ * a trivial implementation.
227
+ *
228
+ * @example
229
+ * ```ts
230
+ * class MyNode extends TextNode {
231
+ * $config() {
232
+ * return this.config('my-node', {extends: TextNode});
233
+ * }
234
+ * }
235
+ * ```
236
+ */
237
+ $config(): BaseStaticNodeConfig;
238
+ /**
239
+ * This is a convenience method for $config that
240
+ * aids in type inference. See {@link LexicalNode.$config}
241
+ * for example usage.
242
+ */
243
+ config<Type extends string, Config extends StaticNodeConfigValue<this, Type>>(type: Type, config: Config): StaticNodeConfigRecord<Type, Config>;
82
244
  /**
83
245
  * Perform any state updates on the clone of prevNode that are not already
84
246
  * handled by the constructor call in the static clone method. If you have
@@ -4,50 +4,8 @@
4
4
  // Type definitions based on Lexical
5
5
  // Original copyright: Meta Platforms, Inc. and affiliates.
6
6
 
7
- import type { LexicalNode } from './LexicalNode';
8
- import { NODE_STATE_KEY } from './LexicalConstants';
9
- /**
10
- * The return value of {@link createState}, for use with
11
- * {@link $getState} and {@link $setState}.
12
- */
13
- export declare class StateConfig<K extends string, V> {
14
- /** The string key used when serializing this state to JSON */
15
- readonly key: K;
16
- /** The parse function from the StateValueConfig passed to createState */
17
- readonly parse: (value?: unknown) => V;
18
- /**
19
- * The unparse function from the StateValueConfig passed to createState,
20
- * with a default that is simply a pass-through that assumes the value is
21
- * JSON serializable.
22
- */
23
- readonly unparse: (value: V) => unknown;
24
- /**
25
- * An equality function from the StateValueConfig, with a default of
26
- * Object.is.
27
- */
28
- readonly isEqual: (a: V, b: V) => boolean;
29
- /**
30
- * The result of `stateValueConfig.parse(undefined)`, which is computed only
31
- * once and used as the default value. When the current value `isEqual` to
32
- * the `defaultValue`, it will not be serialized to JSON.
33
- */
34
- readonly defaultValue: V;
35
- constructor(key: K, stateValueConfig: StateValueConfig<V>);
36
- }
37
- /**
38
- * For advanced use cases, using this type is not recommended unless
39
- * it is required (due to TypeScript's lack of features like
40
- * higher-kinded types).
41
- *
42
- * A {@link StateConfig} type with any key and any value that can be
43
- * used in situations where the key and value type can not be known,
44
- * such as in a generic constraint when working with a collection of
45
- * StateConfig.
46
- *
47
- * {@link StateConfigKey} and {@link StateConfigValue} will be
48
- * useful when this is used as a generic constraint.
49
- */
50
- export type AnyStateConfig = StateConfig<any, any>;
7
+ import { type Klass, type LexicalNode, type LexicalNodeConfig, NODE_STATE_KEY, type Spread, type StaticNodeConfigRecord } from '.';
8
+ import { PROTOTYPE_CONFIG_METHOD } from './LexicalConstants';
51
9
  /**
52
10
  * Get the value type (V) from a StateConfig
53
11
  */
@@ -61,6 +19,60 @@ export type StateConfigKey<S extends AnyStateConfig> = S extends StateConfig<inf
61
19
  * {@link $setState} or any user-defined wrappers around it.
62
20
  */
63
21
  export type ValueOrUpdater<V> = V | ((prevValue: V) => V);
22
+ /**
23
+ * A type alias to make it easier to define setter methods on your node class
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const fooState = createState("foo", { parse: ... });
28
+ * class MyClass extends TextNode {
29
+ * // ...
30
+ * setFoo(valueOrUpdater: StateValueOrUpdater<typeof fooState>): this {
31
+ * return $setState(this, fooState, valueOrUpdater);
32
+ * }
33
+ * }
34
+ * ```
35
+ */
36
+ export type StateValueOrUpdater<Cfg extends AnyStateConfig> = ValueOrUpdater<StateConfigValue<Cfg>>;
37
+ export interface NodeStateConfig<S extends AnyStateConfig> {
38
+ stateConfig: S;
39
+ flat?: boolean;
40
+ }
41
+ export type RequiredNodeStateConfig = NodeStateConfig<AnyStateConfig> | AnyStateConfig;
42
+ export type StateConfigJSON<S> = S extends StateConfig<infer K, infer V> ? {
43
+ [Key in K]?: V;
44
+ } : Record<never, never>;
45
+ export type RequiredNodeStateConfigJSON<Config extends RequiredNodeStateConfig, Flat extends boolean> = StateConfigJSON<Config extends NodeStateConfig<infer S> ? Spread<Config, {
46
+ flat: false;
47
+ }> extends {
48
+ flat: Flat;
49
+ } ? S : never : false extends Flat ? Config : never>;
50
+ export type Prettify<T> = {
51
+ [K in keyof T]: T[K];
52
+ } & {};
53
+ export type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never;
54
+ export type CollectStateJSON<Tuple extends readonly RequiredNodeStateConfig[], Flat extends boolean> = UnionToIntersection<{
55
+ [K in keyof Tuple]: RequiredNodeStateConfigJSON<Tuple[K], Flat>;
56
+ }[number]>;
57
+ type GetStaticNodeConfig<T extends LexicalNode> = ReturnType<T[typeof PROTOTYPE_CONFIG_METHOD]> extends infer Record ? Record extends StaticNodeConfigRecord<infer Type, infer Config> ? Config & {
58
+ readonly type: Type;
59
+ } : never : never;
60
+ type GetStaticNodeConfigs<T extends LexicalNode> = GetStaticNodeConfig<T> extends infer OwnConfig ? OwnConfig extends never ? [] : OwnConfig extends {
61
+ extends: Klass<infer Parent>;
62
+ } ? GetStaticNodeConfig<Parent> extends infer ParentNodeConfig ? ParentNodeConfig extends never ? [OwnConfig] : [OwnConfig, ...GetStaticNodeConfigs<Parent>] : OwnConfig : [OwnConfig] : [];
63
+ type CollectStateConfigs<Configs> = Configs extends [
64
+ infer OwnConfig,
65
+ ...infer ParentConfigs
66
+ ] ? OwnConfig extends {
67
+ stateConfigs: infer StateConfigs;
68
+ } ? StateConfigs extends readonly RequiredNodeStateConfig[] ? [...StateConfigs, ...CollectStateConfigs<ParentConfigs>] : CollectStateConfigs<ParentConfigs> : CollectStateConfigs<ParentConfigs> : [];
69
+ export type GetNodeStateConfig<T extends LexicalNode> = CollectStateConfigs<GetStaticNodeConfigs<T>>;
70
+ /**
71
+ * The NodeState JSON produced by this LexicalNode
72
+ */
73
+ export type NodeStateJSON<T extends LexicalNode> = Prettify<{
74
+ [NODE_STATE_KEY]?: Prettify<CollectStateJSON<GetNodeStateConfig<T>, false>>;
75
+ } & CollectStateJSON<GetNodeStateConfig<T>, true>>;
64
76
  /**
65
77
  * Configure a value to be used with StateConfig.
66
78
  *
@@ -140,6 +152,48 @@ export interface StateValueConfig<V> {
140
152
  */
141
153
  isEqual?: (a: V, b: V) => boolean;
142
154
  }
155
+ /**
156
+ * The return value of {@link createState}, for use with
157
+ * {@link $getState} and {@link $setState}.
158
+ */
159
+ export declare class StateConfig<K extends string, V> {
160
+ /** The string key used when serializing this state to JSON */
161
+ readonly key: K;
162
+ /** The parse function from the StateValueConfig passed to createState */
163
+ readonly parse: (value?: unknown) => V;
164
+ /**
165
+ * The unparse function from the StateValueConfig passed to createState,
166
+ * with a default that is simply a pass-through that assumes the value is
167
+ * JSON serializable.
168
+ */
169
+ readonly unparse: (value: V) => unknown;
170
+ /**
171
+ * An equality function from the StateValueConfig, with a default of
172
+ * Object.is.
173
+ */
174
+ readonly isEqual: (a: V, b: V) => boolean;
175
+ /**
176
+ * The result of `stateValueConfig.parse(undefined)`, which is computed only
177
+ * once and used as the default value. When the current value `isEqual` to
178
+ * the `defaultValue`, it will not be serialized to JSON.
179
+ */
180
+ readonly defaultValue: V;
181
+ constructor(key: K, stateValueConfig: StateValueConfig<V>);
182
+ }
183
+ /**
184
+ * For advanced use cases, using this type is not recommended unless
185
+ * it is required (due to TypeScript's lack of features like
186
+ * higher-kinded types).
187
+ *
188
+ * A {@link StateConfig} type with any key and any value that can be
189
+ * used in situations where the key and value type can not be known,
190
+ * such as in a generic constraint when working with a collection of
191
+ * StateConfig.
192
+ *
193
+ * {@link StateConfigKey} and {@link StateConfigValue} will be
194
+ * useful when this is used as a generic constraint.
195
+ */
196
+ export type AnyStateConfig = StateConfig<any, any>;
143
197
  /**
144
198
  * Create a StateConfig for the given string key and StateValueConfig.
145
199
  *
@@ -154,21 +208,6 @@ export interface StateValueConfig<V> {
154
208
  * @returns a StateConfig
155
209
  */
156
210
  export declare function createState<K extends string, V>(key: K, valueConfig: StateValueConfig<V>): StateConfig<K, V>;
157
- /**
158
- * Given two versions of a node and a stateConfig, compare their state values
159
- * using `$getState(nodeVersion, stateConfig, 'direct')`.
160
- * If the values are equal according to `stateConfig.isEqual`, return `null`,
161
- * otherwise return `[value, prevValue]`.
162
- *
163
- * This is useful for implementing updateDOM. Note that the `'direct'`
164
- * version argument is used for both nodes.
165
- *
166
- * @param node Any LexicalNode
167
- * @param prevNode A previous version of node
168
- * @param stateConfig The configuration of the state to read
169
- * @returns `[value, prevValue]` if changed, otherwise `null`
170
- */
171
- export declare function $getStateChange<T extends LexicalNode, K extends string, V>(node: T, prevNode: T, stateConfig: StateConfig<K, V>): null | [value: V, prevValue: V];
172
211
  /**
173
212
  * The accessor for working with node state. This will read the value for the
174
213
  * state on the given node, and will return `stateConfig.defaultValue` if the
@@ -189,6 +228,21 @@ export declare function $getStateChange<T extends LexicalNode, K extends string,
189
228
  * @returns The current value from the state, or the default value provided by the configuration.
190
229
  */
191
230
  export declare function $getState<K extends string, V>(node: LexicalNode, stateConfig: StateConfig<K, V>, version?: 'latest' | 'direct'): V;
231
+ /**
232
+ * Given two versions of a node and a stateConfig, compare their state values
233
+ * using `$getState(nodeVersion, stateConfig, 'direct')`.
234
+ * If the values are equal according to `stateConfig.isEqual`, return `null`,
235
+ * otherwise return `[value, prevValue]`.
236
+ *
237
+ * This is useful for implementing updateDOM. Note that the `'direct'`
238
+ * version argument is used for both nodes.
239
+ *
240
+ * @param node Any LexicalNode
241
+ * @param prevNode A previous version of node
242
+ * @param stateConfig The configuration of the state to read
243
+ * @returns `[value, prevValue]` if changed, otherwise `null`
244
+ */
245
+ export declare function $getStateChange<T extends LexicalNode, K extends string, V>(node: T, prevNode: T, stateConfig: StateConfig<K, V>): null | [value: V, prevValue: V];
192
246
  /**
193
247
  * Set the state defined by stateConfig on node. Like with `React.useState`
194
248
  * you may directly specify the value or use an updater function that will
@@ -213,8 +267,29 @@ export declare function $getState<K extends string, V>(node: LexicalNode, stateC
213
267
  * @returns node
214
268
  */
215
269
  export declare function $setState<Node extends LexicalNode, K extends string, V>(node: Node, stateConfig: StateConfig<K, V>, valueOrUpdater: ValueOrUpdater<V>): Node;
270
+ /**
271
+ * @internal
272
+ *
273
+ * Opaque state to be stored on the editor's RegisterNode for use by NodeState
274
+ */
275
+ export type SharedNodeState = {
276
+ sharedConfigMap: SharedConfigMap;
277
+ flatKeys: Set<string>;
278
+ };
279
+ /**
280
+ * @internal
281
+ *
282
+ * Create the state to store on RegisteredNode
283
+ */
284
+ export declare function createSharedNodeState(nodeConfig: LexicalNodeConfig): SharedNodeState;
216
285
  type KnownStateMap = Map<AnyStateConfig, unknown>;
217
286
  type UnknownStateRecord = Record<string, unknown>;
287
+ /**
288
+ * @internal
289
+ *
290
+ * A Map of string keys to state configurations to be shared across nodes
291
+ * and/or node versions.
292
+ */
218
293
  type SharedConfigMap = Map<string, AnyStateConfig>;
219
294
  /**
220
295
  * @internal
@@ -248,8 +323,7 @@ export declare class NodeState<T extends LexicalNode> {
248
323
  * imported but has not been parsed yet.
249
324
  *
250
325
  * It stays here until a get state requires us to parse it, and since we
251
- * then know the value is safe we move it to knownState and garbage collect
252
- * it at the next version.
326
+ * then know the value is safe we move it to knownState.
253
327
  *
254
328
  * Note that since only string keys are used here, we can only allow this
255
329
  * state to pass-through on export or on the next version since there is
@@ -262,10 +336,11 @@ export declare class NodeState<T extends LexicalNode> {
262
336
  /**
263
337
  * @internal
264
338
  *
265
- * This sharedConfigMap is preserved across all versions of a given node and
266
- * remains writable. It is how keys are resolved to configuration.
339
+ * This sharedNodeState is preserved across all instances of a given
340
+ * node type in an editor and remains writable. It is how keys are resolved
341
+ * to configuration.
267
342
  */
268
- readonly sharedConfigMap: SharedConfigMap;
343
+ readonly sharedNodeState: SharedNodeState;
269
344
  /**
270
345
  * @internal
271
346
  *
@@ -276,8 +351,16 @@ export declare class NodeState<T extends LexicalNode> {
276
351
  /**
277
352
  * @internal
278
353
  */
279
- constructor(node: T, sharedConfigMap?: SharedConfigMap, unknownState?: undefined | UnknownStateRecord, knownState?: KnownStateMap, size?: number | undefined);
280
- /** @internal */
354
+ constructor(node: T, sharedNodeState: SharedNodeState, unknownState?: undefined | UnknownStateRecord, knownState?: KnownStateMap, size?: number | undefined);
355
+ /**
356
+ * @internal
357
+ *
358
+ * Get the value from knownState, or parse it from unknownState
359
+ * if it contains the given key.
360
+ *
361
+ * Updates the sharedConfigMap when no known state is found.
362
+ * Updates unknownState and knownState when an unknownState is parsed.
363
+ */
281
364
  getValue<K extends string, V>(stateConfig: StateConfig<K, V>): V;
282
365
  /**
283
366
  * @internal
@@ -299,9 +382,7 @@ export declare class NodeState<T extends LexicalNode> {
299
382
  * specific entries in the future when nodes can declare what
300
383
  * their required StateConfigs are.
301
384
  */
302
- toJSON(): {
303
- [NODE_STATE_KEY]?: UnknownStateRecord;
304
- };
385
+ toJSON(): NodeStateJSON<T>;
305
386
  /**
306
387
  * @internal
307
388
  *
@@ -357,6 +438,12 @@ export declare class NodeState<T extends LexicalNode> {
357
438
  * {@link $setState}. This is effectively the preamble for {@link $setState}.
358
439
  */
359
440
  export declare function $getWritableNodeState<T extends LexicalNode>(node: T): NodeState<T>;
441
+ /**
442
+ * @internal
443
+ *
444
+ * Get the SharedNodeState for a node on this editor
445
+ */
446
+ export declare function $getSharedNodeState<T extends LexicalNode>(node: T): SharedNodeState;
360
447
  /**
361
448
  * @internal
362
449
  *
@@ -375,5 +462,11 @@ export declare function $updateStateFromJSON<T extends LexicalNode>(node: T, unk
375
462
  * to determine when TextNode are being merged, not a lot of use cases
376
463
  * otherwise.
377
464
  */
378
- export declare function $nodeStatesAreEquivalent<T extends LexicalNode>(a: undefined | NodeState<T>, b: undefined | NodeState<T>): boolean;
465
+ export declare function nodeStatesAreEquivalent<T extends LexicalNode>(a: undefined | NodeState<T>, b: undefined | NodeState<T>): boolean;
466
+ /**
467
+ * @internal
468
+ *
469
+ * Clones the NodeState for a given node. Handles aliasing if the state references the from node.
470
+ */
471
+ export declare function $cloneNodeState<T extends LexicalNode>(from: T, to: T): undefined | NodeState<T>;
379
472
  export {};
@@ -6,16 +6,25 @@
6
6
 
7
7
  import type { CommandPayloadType, EditorThemeClasses, Klass, LexicalCommand, MutatedNodes, MutationListeners, NodeMutation, RegisteredNode, RegisteredNodes, Spread } from './LexicalEditor';
8
8
  import type { EditorState } from './LexicalEditorState';
9
- import type { LexicalNode, NodeKey, NodeMap } from './LexicalNode';
10
9
  import type { BaseSelection, PointType, RangeSelection } from './LexicalSelection';
11
10
  import type { RootNode } from './nodes/LexicalRootNode';
12
- import type { TextFormatType, TextNode } from './nodes/LexicalTextNode';
13
11
  import { DecoratorNode, ElementNode, LineBreakNode, UpdateTag } from '.';
14
12
  import { LexicalEditor } from './LexicalEditor';
13
+ import { LexicalNode, type NodeKey, type NodeMap, type StaticNodeConfigValue } from './LexicalNode';
14
+ import { type TextFormatType, TextNode } from './nodes/LexicalTextNode';
15
15
  export declare const emptyFunction: () => void;
16
+ export declare function setPendingNodeToClone(pendingNode: null | LexicalNode): void;
17
+ export declare function getPendingNodeToClone(): null | LexicalNode;
16
18
  export declare function resetRandomKey(): void;
17
19
  export declare function generateRandomKey(): string;
20
+ /**
21
+ * @internal
22
+ */
18
23
  export declare function getRegisteredNodeOrThrow(editor: LexicalEditor, nodeType: string): RegisteredNode;
24
+ /**
25
+ * @internal
26
+ */
27
+ export declare function getRegisteredNode(editor: LexicalEditor, nodeType: string): undefined | RegisteredNode;
19
28
  export declare const isArray: (arg: any) => arg is any[];
20
29
  export declare const scheduleMicroTask: (fn: () => void) => void;
21
30
  export declare function $isSelectionCapturedInDecorator(node: Node): boolean;
@@ -190,7 +199,11 @@ type ShadowRootNode = Spread<{
190
199
  }, ElementNode>;
191
200
  export declare function $isRootOrShadowRoot(node: null | LexicalNode): node is RootNode | ShadowRootNode;
192
201
  /**
193
- * Returns a shallow clone of node with a new key
202
+ * Returns a shallow clone of node with a new key. All properties of the node
203
+ * will be copied to the new node (by `clone` and then `afterCloneFrom`),
204
+ * except those related to parent/sibling/child
205
+ * relationships in the `EditorState`. This means that the copy must be
206
+ * separately added to the document, and it will not have any children.
194
207
  *
195
208
  * @param node - The node to be copied.
196
209
  * @returns The copy of the node.
@@ -283,7 +296,7 @@ export declare function getCachedTypeToNodeMap(editorState: EditorState): TypeTo
283
296
  * do not try and use this function to duplicate or copy an existing node.
284
297
  *
285
298
  * Does not mutate the EditorState.
286
- * @param node - The node to be cloned.
299
+ * @param latestNode - The node to be cloned.
287
300
  * @returns The clone of the node.
288
301
  */
289
302
  export declare function $cloneWithProperties<T extends LexicalNode>(latestNode: T): T;
@@ -301,4 +314,38 @@ export declare function setDOMUnmanaged(elementDom: HTMLElement): void;
301
314
  * True if this DOM node was marked with {@link setDOMUnmanaged}
302
315
  */
303
316
  export declare function isDOMUnmanaged(elementDom: Node): boolean;
317
+ /**
318
+ * @internal
319
+ */
320
+ export declare function hasOwnStaticMethod(klass: Klass<LexicalNode>, k: keyof Klass<LexicalNode>): boolean;
321
+ /**
322
+ * @internal
323
+ */
324
+ export declare function hasOwnExportDOM(klass: Klass<LexicalNode>): boolean;
325
+ /** @internal */
326
+ export declare function getStaticNodeConfig(klass: Klass<LexicalNode>): {
327
+ ownNodeType: undefined | string;
328
+ ownNodeConfig: undefined | StaticNodeConfigValue<LexicalNode, string>;
329
+ };
330
+ /**
331
+ * Create an node from its class.
332
+ *
333
+ * Note that this will directly construct the final `withKlass` node type,
334
+ * and will ignore the deprecated `with` functions. This allows `$create` to
335
+ * skip any intermediate steps where the replaced node would be created and
336
+ * then immediately discarded (once per configured replacement of that node).
337
+ *
338
+ * This does not support any arguments to the constructor.
339
+ * Setters can be used to initialize your node, and they can
340
+ * be chained. You can of course write your own mutliple-argument functions
341
+ * to wrap that.
342
+ *
343
+ * @example
344
+ * ```ts
345
+ * function $createTokenText(text: string): TextNode {
346
+ * return $create(TextNode).setTextContent(text).setMode('token');
347
+ * }
348
+ * ```
349
+ */
350
+ export declare function $create<T extends LexicalNode>(klass: Klass<T>): T;
304
351
  export {};
@@ -4,7 +4,7 @@
4
4
  // Type definitions based on Lexical
5
5
  // Original copyright: Meta Platforms, Inc. and affiliates.
6
6
 
7
- import type { BaseSelection, DOMConversionMap, DOMExportOutput, EditorConfig, LexicalNode, LexicalUpdateJSON, NodeKey, ParagraphNode, RangeSelection, SerializedElementNode, Spread } from './../';
7
+ import type { BaseSelection, DOMExportOutput, EditorConfig, LexicalNode, LexicalUpdateJSON, NodeKey, ParagraphNode, RangeSelection, SerializedElementNode, Spread } from './../';
8
8
  import { ElementNode, LexicalEditor } from './../';
9
9
  export type SerializedListItemNode = Spread<{
10
10
  checked: boolean | undefined;
@@ -16,15 +16,17 @@ export declare class ListItemNode extends ElementNode {
16
16
  __value: number;
17
17
  /** @internal */
18
18
  __checked?: boolean;
19
- static getType(): string;
20
- static clone(node: ListItemNode): ListItemNode;
21
- constructor(value?: number, checked?: boolean, key?: NodeKey);
19
+ /** @internal */
20
+ $config(): import('./../').StaticNodeConfigRecord<"listitem", {
21
+ $transform: (node: ListItemNode) => void;
22
+ extends: typeof ElementNode;
23
+ importDOM: import('./../').DOMConversionMap<HTMLElement>;
24
+ }>;
25
+ constructor(value?: number, checked?: undefined | boolean, key?: NodeKey);
26
+ afterCloneFrom(prevNode: this): void;
22
27
  createDOM(config: EditorConfig): HTMLElement;
23
28
  updateListItemDOM(prevNode: ListItemNode | null, dom: HTMLLIElement, config: EditorConfig): void;
24
29
  updateDOM(prevNode: ListItemNode, dom: HTMLElement, config: EditorConfig): boolean;
25
- static transform(): (node: LexicalNode) => void;
26
- static importDOM(): DOMConversionMap | null;
27
- static importJSON(serializedNode: SerializedListItemNode): ListItemNode;
28
30
  updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedListItemNode>): this;
29
31
  exportDOM(editor: LexicalEditor): DOMExportOutput;
30
32
  exportJSON(): SerializedListItemNode;
@@ -4,7 +4,7 @@
4
4
  // Type definitions based on Lexical
5
5
  // Original copyright: Meta Platforms, Inc. and affiliates.
6
6
 
7
- import { DOMConversionMap, DOMExportOutput, EditorConfig, ElementNode, LexicalEditor, LexicalNode, LexicalUpdateJSON, NodeKey, SerializedElementNode, Spread } from './../';
7
+ import { DOMExportOutput, EditorConfig, ElementNode, LexicalEditor, LexicalNode, LexicalUpdateJSON, NodeKey, SerializedElementNode, Spread } from './../';
8
8
  export type SerializedListNode = Spread<{
9
9
  listType: ListType;
10
10
  start: number;
@@ -20,9 +20,14 @@ export declare class ListNode extends ElementNode {
20
20
  __start: number;
21
21
  /** @internal */
22
22
  __listType: ListType;
23
- static getType(): string;
24
- static clone(node: ListNode): ListNode;
23
+ /** @internal */
24
+ $config(): import('./../').StaticNodeConfigRecord<"list", {
25
+ $transform: (node: ListNode) => void;
26
+ extends: typeof ElementNode;
27
+ importDOM: import('./../').DOMConversionMap<HTMLElement>;
28
+ }>;
25
29
  constructor(listType?: ListType, start?: number, key?: NodeKey);
30
+ afterCloneFrom(prevNode: this): void;
26
31
  getTag(): ListNodeTagType;
27
32
  setListType(type: ListType): this;
28
33
  getListType(): ListType;
@@ -30,9 +35,6 @@ export declare class ListNode extends ElementNode {
30
35
  setStart(start: number): this;
31
36
  createDOM(config: EditorConfig, _editor?: LexicalEditor): HTMLElement;
32
37
  updateDOM(prevNode: this, dom: HTMLElement, config: EditorConfig): boolean;
33
- static transform(): (node: LexicalNode) => void;
34
- static importDOM(): DOMConversionMap | null;
35
- static importJSON(serializedNode: SerializedListNode): ListNode;
36
38
  updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedListNode>): this;
37
39
  exportDOM(editor: LexicalEditor): DOMExportOutput;
38
40
  exportJSON(): SerializedListNode;