UNPKG

24.1 kBTypeScriptView Raw
1import { Unsubscribe } from 'nanoevents';
2import { __INTERNAL_REMIRROR_IDENTIFIER_KEY__, ExtensionPriority, ManagerPhase, RemirrorIdentifier } from '@remirror/core-constants';
3import type { EditorSchema, EditorView, MarkExtensionSpec, NodeExtensionSpec, PrimitiveSelection, ProsemirrorNode, RemirrorContentType, Replace, Simplify, Transaction } from '@remirror/core-types';
4import { CustomDocumentProps, InvalidContentHandler, NamedStringHandlers, StringHandler, StringHandlerProps } from '@remirror/core-utils';
5import { EditorState } from '@remirror/pm/state';
6import { BuiltinPreset, CombinedTags } from '../builtins';
7import type { AnyExtension, AnyExtensionConstructor, AnyManagerStore, GetExtensions, GetMarkNameUnion, GetNameUnion, GetNodeNameUnion, GetPlainNameUnion, ManagerStoreKeys } from '../extension';
8import type { BaseFramework, FrameworkOutput } from '../framework';
9import type { StateUpdateLifecycleProps } from '../types';
10/**
11 * The `Manager` has multiple hook phases which are able to hook into the
12 * extension manager flow and add new functionality to the editor.
13 *
14 * The `ExtensionEventMethod`s
15 *
16 * - onCreate - when the extension manager is created and after the schema is
17 * made available.
18 * - onView - when the view has been received from the dom ref.
19 */
20/**
21 * A class to manage the extensions and prosemirror interactions within the
22 * editor.
23 *
24 * @remarks
25 *
26 * The RemirrorManager enables the lifecycle methods of the extensions by
27 * calling each method in the distinct phases of the lifecycle.
28 *
29 * - `onCreate` - This happens when the manager is constructed. It calls on the
30 * extension which have an `onCreate` method and allows them to do their work.
31 *
32 * For the built in methods, this is when the `SchemaExtension` creates the
33 * Schema and when the `TagsExtension` combines the tags for the editor
34 * instance.
35 *
36 * ```ts
37 * const manager = Manager.create(() => [
38 * new DocExtension(),
39 * new TextExtension(),
40 * new ParagraphExtension(),
41 * ])
42 * ```
43 *
44 * At this point all the `onCreate` methods have been called. Including the
45 * `onCreate` for the `Schema`.
46 *
47 * - `onView` - This is called the framework instance connects the
48 * `RemirrorManager` to the ProseMirror EditorView.
49 *
50 * ```ts
51 * manager.addView(new EditorView(...))
52 * manager.store.commands.insertText('Hello world');.
53 * ```
54 *
55 * - [[`onStateUpdate`]] - This is the method called every time the ProseMirror
56 * state changes. Both the extensions and the `Framework` listen to this event
57 * and can provide updates in response.
58 */
59export declare class RemirrorManager<Extension extends AnyExtension> {
60 #private;
61 /**
62 * Create the manager for your `Remirror` editor.
63 */
64 static create<Extension extends AnyExtension>(extensions: Extension[] | ExtensionTemplate<Extension>, settings?: Remirror.ManagerSettings): RemirrorManager<Extension | BuiltinPreset>;
65 /**
66 * Identifies this as a `Manager`.
67 *
68 * @internal
69 */
70 get [__INTERNAL_REMIRROR_IDENTIFIER_KEY__](): RemirrorIdentifier.Manager;
71 /**
72 * Returns `true` if the manager has been destroyed.
73 */
74 get destroyed(): boolean;
75 /**
76 * `true` when the view has been added to the UI layer and the editor is
77 * running.
78 */
79 get mounted(): boolean;
80 /**
81 * Retrieve the framework output.
82 *
83 * This be undefined if the manager hasn't been provided to a framework yet
84 * the manager.
85 *
86 * With synchronous frameworks this means that it should only be accessed
87 * after the manager has been applied to the editor creation function.
88 *
89 * For frameworks like React it is only available when the manager is provided
90 * to the `Remirror` component and after the very first render. This means it
91 * is available within the `onRef` callback.
92 *
93 * ```tsx
94 * import React, { useEffect } from 'react';
95 * import { useRemirror, Remirror } from '@remirror/react';
96 *
97 * const Editor = () => {
98 * const { manager } = useRemirror();
99 *
100 * const callback = () => {
101 * return manager.output; // ✅ This is fine.
102 * }
103 *
104 * useEffect(() => {
105 * log(manager.output); // ✅ This is also fine.
106 * }, []);
107 *
108 * log(manager.output); // ❌ This will be undefined on the first render.
109 *
110 * return <Remirror manager={manager} />
111 * }
112 * ```
113 */
114 get output(): FrameworkOutput<Extension> | undefined;
115 /**
116 * Returns true when a framework is attached to the manager.
117 *
118 * This can be used to check if it is safe to call `manager.output`.
119 */
120 get frameworkAttached(): boolean;
121 /**
122 * The extensions stored by this manager
123 */
124 get extensions(): ReadonlyArray<GetExtensions<Extension>>;
125 /**
126 * The registered string handlers provided by the extensions.
127 *
128 * By default this includes `html` and `plainText`
129 */
130 get stringHandlers(): NamedStringHandlers;
131 /**
132 * Get the extension manager store which is accessible at initialization.
133 */
134 get store(): Remirror.ManagerStore<Extension>;
135 /**
136 * Provides access to the extension store.
137 */
138 get extensionStore(): Remirror.ExtensionStore;
139 /**
140 * Shorthand access to the active transaction from the manager. This is the
141 * shared transaction available to all commands and should be used when you
142 * need to make your commands chainable.
143 *
144 * If working with react and setting up your editor as a controlled component
145 * then this is the preferred way to run custom commands, otherwise your
146 * commands will end up being non-chainable and be overwritten by anything
147 * that comes after.
148 */
149 get tr(): Transaction;
150 /**
151 * Returns the stored nodes
152 */
153 get nodes(): Record<this['~N'], NodeExtensionSpec>;
154 /**
155 * Returns the store marks.
156 */
157 get marks(): Record<this['~M'], MarkExtensionSpec>;
158 /**
159 * A shorthand method for retrieving the schema for this extension manager
160 * from the data.
161 */
162 get schema(): EditorSchema;
163 /**
164 * A shorthand getter for retrieving the tags from the extension manager.
165 */
166 get extensionTags(): Readonly<CombinedTags<GetNameUnion<Extension>>>;
167 /**
168 * A shorthand way of retrieving the editor view.
169 */
170 get view(): EditorView;
171 /**
172 * Retrieve the settings used when creating the manager.
173 */
174 get settings(): Remirror.ManagerSettings;
175 /**
176 * The document to use for rendering and outputting HTML.
177 */
178 get document(): Document;
179 /**
180 * Creates the extension manager which is used to simplify the management of
181 * the prosemirror editor.
182 *
183 * This is set to private to encourage using `RemirrorManager.create`
184 * instead of the `new` keyword.
185 */
186 private constructor();
187 /**
188 * Loops through all extensions to set up the lifecycle handlers.
189 */
190 private setupLifecycleHandlers;
191 /**
192 * Set the string handler to use for a given name.
193 *
194 * This allows users to set the string handler
195 */
196 private setStringHandler;
197 /**
198 * Set the manager value for the provided key. This is used by extensions to
199 * add data to the manager.
200 */
201 private setStoreKey;
202 /**
203 * Get the manager value for the provided key. This is used by extensions to
204 * get data from the manager.
205 */
206 private getStoreKey;
207 /**
208 * A method to set values in the extension store which is made available to
209 * extension.
210 *
211 * **NOTE** This method should only be used in the `onCreate` extension method
212 * or it will throw an error.
213 */
214 private setExtensionStore;
215 /**
216 * Create the initial store.
217 */
218 private createExtensionStore;
219 /**
220 * A state getter method which is passed into the params.
221 */
222 private readonly getState;
223 /**
224 * Stores the editor view on the manager
225 *
226 * @param view - the editor view
227 */
228 addView(view: EditorView): this;
229 /**
230 * Attach a framework to the manager.
231 */
232 attachFramework(framework: BaseFramework<Extension>, updateHandler: (props: StateUpdateLifecycleProps) => void): void;
233 /**
234 * Create an empty document for the editor based on the current schema.
235 *
236 * This automatically looks at the supported content for the doc and the
237 * available nodes which fulfil that content in order to create a document
238 * with only the minimal required content.
239 *
240 * This can be used in conjunction with the create state to reset the current
241 * value of the editor.
242 */
243 createEmptyDoc(): ProsemirrorNode;
244 /**
245 * Create the editor state from content passed to this extension manager.
246 */
247 createState(props?: CreateEditorStateProps): EditorState;
248 /**
249 * Add a handler to the manager.
250 *
251 * Currently the only event that can be listened to is the `destroy` event.
252 */
253 addHandler<Key extends keyof ManagerEvents>(event: Key, cb: ManagerEvents[Key]): Unsubscribe;
254 /**
255 * Update the state of the view and trigger the `onStateUpdate` lifecycle
256 * method as well.
257 */
258 private readonly updateState;
259 /**
260 * This method should be called by the view layer every time the state is
261 * updated.
262 *
263 * An example usage of this is within the collaboration extension.
264 */
265 onStateUpdate(props: Omit<StateUpdateLifecycleProps, 'firstUpdate'>): void;
266 /**
267 * Get the extension instance matching the provided constructor from the
268 * manager.
269 *
270 * This will throw an error if non existent.
271 */
272 getExtension<ExtensionConstructor extends AnyExtensionConstructor>(Constructor: ExtensionConstructor): InstanceType<ExtensionConstructor>;
273 /**
274 * Determines in an extension is present by providing the desired
275 * `Constructor`.
276 *
277 * This method can be used as a safer alternative to getExtension which
278 * will throw an error if the constructor doesn't exist within the
279 * extension created by this extension.
280 */
281 hasExtension<ExtensionConstructor extends AnyExtensionConstructor>(Constructor: ExtensionConstructor): boolean;
282 /**
283 * Make a clone of the manager.
284 *
285 * @internalremarks What about the state stored in the extensions and presets,
286 * does this need to be recreated as well?
287 */
288 clone(): RemirrorManager<Extension>;
289 /**
290 * Recreate the manager with new settings and extensions
291 */
292 recreate<ExtraExtension extends AnyExtension>(extensions?: ExtraExtension[], settings?: Remirror.ManagerSettings): RemirrorManager<Extension | ExtraExtension>;
293 /**
294 * This method should be called to destroy the manager and remove the view.
295 */
296 destroy(): void;
297 /**
298 * Check whether the manager includes the names or constructors provided for
299 * the preset and extensions.
300 *
301 * Returns true if all are included, returns false otherwise.
302 */
303 includes(mustIncludeList: Array<AnyExtensionConstructor | string>): boolean;
304}
305/**
306 * A function that returns the extension to be used in the RemirrorManager. This
307 * is similar to a preset function except that it takes no arguments.
308 *
309 * ```ts
310 * import { RemirrorManager } from 'remirror';
311 * import { BoldExtension, ItalicExtension } from 'remirror/extensions';
312 *
313 * const template = () => [new BoldExtension(), new ItalicExtension()]
314 * const manager = RemirrorManager.create(template);
315 * ```
316 *
317 * If the template is mixed in with other manager creators it will add the
318 * relevant extension provided.
319 */
320export declare type ExtensionTemplate<Extension extends AnyExtension> = () => Extension[];
321export interface ManagerEvents {
322 /**
323 * Called when the state is updated.
324 */
325 stateUpdate: (props: StateUpdateLifecycleProps) => void;
326 /**
327 * Called whenever the manager is cloned with the newly created manager
328 * instance.
329 *
330 * This is mainly used for testing so that the RemirrorTester can always
331 * reference the latest manager.
332 */
333 clone: (manager: AnyRemirrorManager) => void;
334 /**
335 * Called whenever the manager is recreated with the newly created manager
336 * instance.
337 *
338 * This is mainly used for testing so that the RemirrorTester can always
339 * reference the latest manager.
340 */
341 recreate: (manager: AnyRemirrorManager) => void;
342 /**
343 * An event listener which is called whenever the manager is destroyed.
344 */
345 destroy: () => void;
346}
347export declare type AnyRemirrorManager = Simplify<Replace<RemirrorManager<AnyExtension>, {
348 clone: () => AnyRemirrorManager;
349 store: Replace<Remirror.ManagerStore<AnyExtension>, {
350 chain: any;
351 }>;
352 output: Replace<FrameworkOutput<AnyExtension>, {
353 chain: any;
354 manager: AnyRemirrorManager;
355 }> | undefined;
356 view: EditorView;
357 addView: (view: EditorView) => void;
358 attachFramework: (framework: any, updateHandler: (props: StateUpdateLifecycleProps) => void) => void;
359 /** @internal */
360 ['~E']: AnyExtension;
361 /** @internal */
362 ['~AN']: string;
363 /** @internal */
364 ['~N']: string;
365 /** @internal */
366 ['~M']: string;
367 /** @internal */
368 ['~P']: string;
369}>>;
370/**
371 * Checks to see whether the provided value is a `RemirrorManager` instance.
372 *
373 * An optional parameter `mustIncludeList` is available if you want to check
374 * that the manager includes all the listed extensions.
375 *
376 * @param value - the value to check
377 * @param mustIncludeList - an array of presets and extension the manager must
378 * include to pass the test. The identifier can either be the Extension / Preset
379 * name e.g. `bold`, or the Extension / Preset constructor `BoldExtension`
380 */
381export declare function isRemirrorManager<Extension extends AnyExtension = AnyExtension>(value: unknown, mustIncludeList?: Array<AnyExtensionConstructor | string>): value is RemirrorManager<Extension>;
382export interface CreateEditorStateProps extends Omit<StringHandlerProps, 'stringHandler'> {
383 /**
384 * This is where content can be supplied to the Editor.
385 *
386 * @remarks
387 *
388 * Content can either be
389 * - a string (which will be parsed by the stringHandler)
390 * - JSON object matching Prosemirror expected shape
391 * - A top level ProsemirrorNode
392 *
393 * If this is left undefined then the editor will use the default empty `doc`.
394 */
395 content?: RemirrorContentType;
396 /**
397 * The selection that the user should have in the created node.
398 *
399 * @defaultValue 'end'
400 */
401 selection?: PrimitiveSelection;
402 /**
403 * A function which transforms a string into a prosemirror node.
404 *
405 * @remarks
406 *
407 * Can be used to transform markdown / html or any other string format into a
408 * prosemirror node.
409 *
410 * See [[`fromHTML`]] for an example of how this could work.
411 */
412 stringHandler?: keyof Remirror.StringHandlers | StringHandler;
413}
414interface RemirrorManagerConstructor extends Function {
415 create<Extension extends AnyExtension>(extension: Extension[], settings?: Remirror.ManagerSettings): RemirrorManager<Extension | BuiltinPreset>;
416}
417export interface RemirrorManager<Extension extends AnyExtension> {
418 /**
419 * The constructor for the [[`RemirrorManager`]].
420 */
421 constructor: RemirrorManagerConstructor;
422 /**
423 * Pseudo type property which contains the recursively extracted `Extension`
424 * stored by this manager.
425 *
426 * @internal
427 */
428 ['~E']: Extension;
429 /**
430 * `AllNames`
431 *
432 * Get all the names of the extensions within this editor.
433 *
434 * @internal
435 */
436 ['~AN']: GetNameUnion<Extension> extends never ? string : GetNameUnion<Extension>;
437 /**
438 * `NodeNames`
439 *
440 * Type inference hack for node extension names. This is the only way I know
441 * to store types on a class.
442 *
443 * @internal
444 */
445 ['~N']: GetNodeNameUnion<Extension> extends never ? string : GetNodeNameUnion<Extension>;
446 /**
447 * `MarkNames`
448 *
449 * Type inference hack for mark extension names. This is the only way I know
450 * to store types on a class.
451 *
452 * @internal
453 */
454 ['~M']: GetMarkNameUnion<Extension> extends never ? string : GetMarkNameUnion<Extension>;
455 /**
456 * `PlainNames`
457 *
458 * Type inference hack for all the plain extension names. This is the only way
459 * I know to store types on a class.
460 *
461 * @internal
462 */
463 ['~P']: GetPlainNameUnion<Extension> extends never ? string : GetPlainNameUnion<Extension>;
464}
465declare global {
466 namespace Remirror {
467 /**
468 * Settings which can be passed into the manager.
469 */
470 interface ManagerSettings extends Partial<CustomDocumentProps> {
471 /**
472 * Set the extension priority for extension's by their name.
473 */
474 priority?: Record<string, ExtensionPriority>;
475 /**
476 * An object which excludes certain functionality from all extensions
477 * within the manager.
478 */
479 exclude?: ExcludeOptions;
480 /**
481 * The error handler which is called when the JSON passed is invalid.
482 *
483 * @remarks
484 *
485 * The following can be used to setup the `onError` handler on the the
486 * manager.
487 *
488 * ```tsx
489 * import React from 'react';
490 * import { Remirror, InvalidContentHandler } from 'remirror';
491 * import { Remirror, useManager } from '@remirror/react';
492 * import { WysiwygPreset } from 'remirror/extensions';
493 *
494 * const Editor = () => {
495 * const onError: InvalidContentHandler = useCallback(({ json, invalidContent, transformers }) => {
496 * // Automatically remove all invalid nodes and marks.
497 * return transformers.remove(json, invalidContent);
498 * }, []);
499 *
500 * const manager = useManager(() => [new WysiwygPreset()], { onError });
501 *
502 * return (
503 * <Remirror manager={manager}>
504 * <div />
505 * </Remirror>
506 * );
507 * };
508 * ```
509 */
510 onError?: InvalidContentHandler;
511 /**
512 * A function which transforms a string into a prosemirror node.
513 *
514 * @remarks
515 *
516 * Can be used to transform markdown / html or any other string format into a
517 * prosemirror node.
518 *
519 * See [[`fromHTML`]] for an example of how this could work.
520 */
521 stringHandler?: keyof Remirror.StringHandlers | StringHandler;
522 /**
523 * The default named selection. This is used when `manager.createState` is
524 * called without providing a selection.
525 *
526 * @defaultValue 'end'
527 */
528 defaultSelection?: 'start' | 'end' | 'all';
529 }
530 /**
531 * Describes the object where the extension manager stores it's data.
532 *
533 * @remarks
534 *
535 * Since this is a global namespace, you can extend the store if your
536 * extension is modifying the shape of the `Manager.store` property.
537 */
538 interface ManagerStore<Extension extends AnyExtension> {
539 /**
540 * The editor view stored by this instance.
541 */
542 view: EditorView;
543 }
544 interface ExtensionStore {
545 /**
546 * Make the remirror manager available to the editor.
547 */
548 manager: AnyRemirrorManager;
549 /**
550 * The list of all extensions included in the editor.
551 */
552 readonly extensions: AnyExtension[];
553 /**
554 * The stage the manager is currently at.
555 */
556 readonly phase: ManagerPhase;
557 /**
558 * The view available to extensions once `addView` has been called on the
559 * `RemirrorManager` instance.
560 */
561 readonly view: EditorView;
562 /**
563 * The latest state.
564 */
565 currentState: EditorState;
566 /**
567 * The previous state. Will be undefined when the view is first created.
568 */
569 previousState?: EditorState;
570 /**
571 * The root document to be used for the editor. This is mainly used for
572 * non-browser environment.
573 */
574 readonly document: Document;
575 /**
576 * The settings passed to the manager.
577 */
578 readonly managerSettings: ManagerSettings;
579 /**
580 * The names of every node extension.
581 */
582 nodeNames: readonly string[];
583 /**
584 * The names of every mark extension.
585 */
586 markNames: readonly string[];
587 /**
588 * The names of every plain extension.
589 */
590 plainNames: readonly string[];
591 /**
592 * The named string handlers which are supported by the current editor
593 * implementation.
594 */
595 readonly stringHandlers: NamedStringHandlers;
596 /**
597 * Return true when the editor view has been created.
598 */
599 readonly isMounted: () => boolean;
600 /**
601 * A helper method for retrieving the state of the editor
602 */
603 readonly getState: () => EditorState;
604 /**
605 * Allow extensions to trigger an update in the prosemirror state. This
606 * should not be used often. It's here in case you need it in an
607 * emergency.
608 *
609 * Internally it's used by the [[`PluginsExtension`]] to create a new
610 * state when the plugins are updated at runtime.
611 */
612 readonly updateState: (state: EditorState) => void;
613 /**
614 * Get the extension instance matching the provided constructor from the
615 * manager.
616 *
617 * This will throw an error if not defined.
618 */
619 readonly getExtension: <ExtensionConstructor extends AnyExtensionConstructor>(Constructor: ExtensionConstructor) => InstanceType<ExtensionConstructor>;
620 /**
621 * Get the value of a key from the manager store.
622 */
623 getStoreKey: <Key extends ManagerStoreKeys>(key: Key) => AnyManagerStore[Key];
624 /**
625 * Update the store with a specific key.
626 */
627 setStoreKey: <Key extends ManagerStoreKeys>(key: Key, value: AnyManagerStore[Key]) => void;
628 /**
629 * Set a value on the extension store. One of the design decisions in this `1.0.0`
630 * version of `remirror` was to move away from passing elaborate arguments to each extension
631 * method and allow extensions to interact with a store shared by all
632 * extensions.
633 *
634 * The extension store object is immutable and will throw an error if updated directly.
635 *
636 * ```ts
637 * class MyExtension extends PlainExtension {
638 * get name() {}
639 * }
640 * ```
641 */
642 setExtensionStore: <Key extends keyof ExtensionStore>(key: Key, value: ExtensionStore[Key]) => void;
643 /**
644 * Set the string handler to use for a given name.
645 *
646 * This allows users to set the string handler
647 */
648 setStringHandler: (name: keyof StringHandlers, handler: StringHandler) => void;
649 }
650 }
651}
652export {};