UNPKG

24.4 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, RenderEnvironment, 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, GetSchema, 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<GetSchema<Extension>>;
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(): this['~Sch'];
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<GetSchema<Extension>>;
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['~Sch']>): 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<GetSchema<Extension>>;
244 /**
245 * Create the editor state from content passed to this extension manager.
246 */
247 createState(props?: CreateEditorStateProps): EditorState<GetSchema<Extension>>;
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 * Make a clone of the manager.
275 *
276 * @internalremarks What about the state stored in the extensions and presets,
277 * does this need to be recreated as well?
278 */
279 clone(): RemirrorManager<Extension>;
280 /**
281 * Recreate the manager with new settings and extensions
282 */
283 recreate<ExtraExtension extends AnyExtension>(extensions?: ExtraExtension[], settings?: Remirror.ManagerSettings): RemirrorManager<Extension | ExtraExtension>;
284 /**
285 * This method should be called to destroy the manager and remove the view.
286 */
287 destroy(): void;
288 /**
289 * Check whether the manager includes the names or constructors provided for
290 * the preset and extensions.
291 *
292 * Returns true if all are included, returns false otherwise.
293 */
294 includes(mustIncludeList: Array<AnyExtensionConstructor | string>): boolean;
295}
296/**
297 * A function that returns the extension to be used in the RemirrorManager. This
298 * is similar to a preset function except that it takes no arguments.
299 *
300 * ```ts
301 * import { RemirrorManager } from 'remirror';
302 * import { BoldExtension, ItalicExtension } from 'remirror/extensions';
303 *
304 * const template = () => [new BoldExtension(), new ItalicExtension()]
305 * const manager = RemirrorManager.create(template);
306 * ```
307 *
308 * If the template is mixed in with other manager creators it will add the
309 * relevant extension provided.
310 */
311export declare type ExtensionTemplate<Extension extends AnyExtension> = () => Extension[];
312export interface ManagerEvents {
313 /**
314 * Called when the state is updated.
315 */
316 stateUpdate: (props: StateUpdateLifecycleProps) => void;
317 /**
318 * Called whenever the manager is cloned with the newly created manager
319 * instance.
320 *
321 * This is mainly used for testing so that the RemirrorTester can always
322 * reference the latest manager.
323 */
324 clone: (manager: AnyRemirrorManager) => void;
325 /**
326 * Called whenever the manager is recreated with the newly created manager
327 * instance.
328 *
329 * This is mainly used for testing so that the RemirrorTester can always
330 * reference the latest manager.
331 */
332 recreate: (manager: AnyRemirrorManager) => void;
333 /**
334 * An event listener which is called whenever the manager is destroyed.
335 */
336 destroy: () => void;
337}
338export declare type AnyRemirrorManager = Simplify<Replace<RemirrorManager<AnyExtension>, {
339 clone: () => AnyRemirrorManager;
340 store: Replace<Remirror.ManagerStore<AnyExtension>, {
341 chain: any;
342 }>;
343 output: Replace<FrameworkOutput<AnyExtension>, {
344 chain: any;
345 manager: AnyRemirrorManager;
346 }> | undefined;
347 view: EditorView;
348 addView: (view: EditorView) => void;
349 attachFramework: (framework: any, updateHandler: (props: StateUpdateLifecycleProps) => void) => void;
350 /** @internal */
351 ['~E']: AnyExtension;
352 /** @internal */
353 ['~Sch']: EditorSchema;
354 /** @internal */
355 ['~AN']: string;
356 /** @internal */
357 ['~N']: string;
358 /** @internal */
359 ['~M']: string;
360 /** @internal */
361 ['~P']: string;
362}>>;
363/**
364 * Checks to see whether the provided value is a `RemirrorManager` instance.
365 *
366 * An optional parameter `mustIncludeList` is available if you want to check
367 * that the manager includes all the listed extensions.
368 *
369 * @param value - the value to check
370 * @param mustIncludeList - an array of presets and extension the manager must
371 * include to pass the test. The identifier can either be the Extension / Preset
372 * name e.g. `bold`, or the Extension / Preset constructor `BoldExtension`
373 */
374export declare function isRemirrorManager<Extension extends AnyExtension = AnyExtension>(value: unknown, mustIncludeList?: Array<AnyExtensionConstructor | string>): value is RemirrorManager<Extension>;
375export interface CreateEditorStateProps extends Omit<StringHandlerProps, 'stringHandler'> {
376 /**
377 * This is where content can be supplied to the Editor.
378 *
379 * @remarks
380 *
381 * Content can either be
382 * - a string (which will be parsed by the stringHandler)
383 * - JSON object matching Prosemirror expected shape
384 * - A top level ProsemirrorNode
385 *
386 * If this is left undefined then the editor will use the default empty `doc`.
387 */
388 content?: RemirrorContentType;
389 /**
390 * The selection that the user should have in the created node.
391 *
392 * @default 'end'
393 */
394 selection?: PrimitiveSelection;
395 /**
396 * A function which transforms a string into a prosemirror node.
397 *
398 * @remarks
399 *
400 * Can be used to transform markdown / html or any other string format into a
401 * prosemirror node.
402 *
403 * See [[`fromHTML`]] for an example of how this could work.
404 */
405 stringHandler?: keyof Remirror.StringHandlers | StringHandler;
406}
407interface RemirrorManagerConstructor extends Function {
408 create<Extension extends AnyExtension>(extension: Extension[], settings?: Remirror.ManagerSettings): RemirrorManager<Extension | BuiltinPreset>;
409}
410export interface RemirrorManager<Extension extends AnyExtension> {
411 /**
412 * The constructor for the [[`RemirrorManager`]].
413 */
414 constructor: RemirrorManagerConstructor;
415 /**
416 * Pseudo type property which contains the recursively extracted `Extension`
417 * stored by this manager.
418 *
419 * @internal
420 */
421 ['~E']: Extension;
422 /**
423 * Pseudo property which is a small hack to store the type of the schema
424 * available from this manager.
425 *
426 * @internal
427 */
428 ['~Sch']: GetSchema<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 * By default remirror will work out whether this is a dom environment or
524 * server environment for SSR rendering. You can override this behaviour here
525 * when required.
526 *
527 * @default undefined
528 */
529 forceEnvironment?: RenderEnvironment;
530 /**
531 * The default named selection. This is used when `manager.createState` is
532 * called without providing a selection.
533 *
534 * @default 'end'
535 */
536 defaultSelection?: 'start' | 'end' | 'all';
537 }
538 /**
539 * Describes the object where the extension manager stores it's data.
540 *
541 * @remarks
542 *
543 * Since this is a global namespace, you can extend the store if your
544 * extension is modifying the shape of the `Manager.store` property.
545 */
546 interface ManagerStore<Extension extends AnyExtension> {
547 /**
548 * The editor view stored by this instance.
549 */
550 view: EditorView<GetSchema<Extension>>;
551 }
552 interface ExtensionStore {
553 /**
554 * Make the remirror manager available to the editor.
555 */
556 manager: AnyRemirrorManager;
557 /**
558 * The list of all extensions included in the editor.
559 */
560 readonly extensions: AnyExtension[];
561 /**
562 * The stage the manager is currently at.
563 */
564 readonly phase: ManagerPhase;
565 /**
566 * The view available to extensions once `addView` has been called on the
567 * `RemirrorManager` instance.
568 */
569 readonly view: EditorView;
570 /**
571 * The latest state.
572 */
573 currentState: EditorState<EditorSchema>;
574 /**
575 * The previous state. Will be undefined when the view is first created.
576 */
577 previousState?: EditorState<EditorSchema>;
578 /**
579 * The root document to be used for the editor. This is mainly used for
580 * SSR.
581 */
582 readonly document: Document;
583 /**
584 * The settings passed to the manager.
585 */
586 readonly managerSettings: ManagerSettings;
587 /**
588 * The names of every node extension.
589 */
590 nodeNames: readonly string[];
591 /**
592 * The names of every mark extension.
593 */
594 markNames: readonly string[];
595 /**
596 * The names of every plain extension.
597 */
598 plainNames: readonly string[];
599 /**
600 * The named string handlers which are supported by the current editor
601 * implementation.
602 */
603 readonly stringHandlers: NamedStringHandlers;
604 /**
605 * Return true when the editor view has been created.
606 */
607 readonly isMounted: () => boolean;
608 /**
609 * A helper method for retrieving the state of the editor
610 */
611 readonly getState: () => EditorState<EditorSchema>;
612 /**
613 * Allow extensions to trigger an update in the prosemirror state. This
614 * should not be used often. It's here in case you need it in an
615 * emergency.
616 *
617 * Internally it's used by the [[`PluginsExtension`]] to create a new
618 * state when the plugins are updated at runtime.
619 */
620 readonly updateState: (state: EditorState<EditorSchema>) => void;
621 /**
622 * Get the extension instance matching the provided constructor from the
623 * manager.
624 *
625 * This will throw an error if not defined.
626 */
627 readonly getExtension: <ExtensionConstructor extends AnyExtensionConstructor>(Constructor: ExtensionConstructor) => InstanceType<ExtensionConstructor>;
628 /**
629 * Get the value of a key from the manager store.
630 */
631 getStoreKey: <Key extends ManagerStoreKeys>(key: Key) => AnyManagerStore[Key];
632 /**
633 * Update the store with a specific key.
634 */
635 setStoreKey: <Key extends ManagerStoreKeys>(key: Key, value: AnyManagerStore[Key]) => void;
636 /**
637 * Set a value on the extension store. One of the design decisions in this `1.0.0`
638 * version of `remirror` was to move away from passing elaborate arguments to each extension
639 * method and allow extensions to interact with a store shared by all
640 * extensions.
641 *
642 * The extension store object is immutable and will throw an error if updated directly.
643 *
644 * ```ts
645 * class MyExtension extends PlainExtension {
646 * get name() {}
647 * }
648 * ```
649 */
650 setExtensionStore: <Key extends keyof ExtensionStore>(key: Key, value: ExtensionStore[Key]) => void;
651 /**
652 * Set the string handler to use for a given name.
653 *
654 * This allows users to set the string handler
655 */
656 setStringHandler: (name: keyof StringHandlers, handler: StringHandler) => void;
657 }
658 }
659}
660export {};
661
\No newline at end of file