UNPKG

13.7 kBTypeScriptView Raw
1import { __INTERNAL_REMIRROR_IDENTIFIER_KEY__, ExtensionPriority, RemirrorIdentifier } from '@remirror/core-constants';
2import type { AnyFunction, Dispose, EmptyShape, GetAcceptUndefined, GetConstructorProps, GetCustomHandler, GetFixed, GetFixedDynamic, GetHandler, GetPartialDynamic, GetStatic, IfNoRequiredProperties, LiteralUnion, MakeUndefined, Primitive, RemoveAnnotations, Replace, Shape, StringKey, UndefinedFlipPartialAndRequired, ValidOptions } from '@remirror/core-types';
3import type { OnSetOptionsProps } from '../types';
4declare const IGNORE = "__IGNORE__";
5declare const GENERAL_OPTIONS: "__ALL__";
6export declare abstract class BaseClass<Options extends ValidOptions = EmptyShape, DefaultStaticOptions extends Shape = EmptyShape> {
7 /**
8 * The default options for this extension.
9 *
10 * TODO see if this can be cast to something other than any and allow
11 * composition.
12 */
13 static readonly defaultOptions: any;
14 /**
15 * The static keys for this class.
16 */
17 static readonly staticKeys: string[];
18 /**
19 * The event handler keys.
20 */
21 static readonly handlerKeys: string[];
22 /**
23 * Customize the way the handler should behave.
24 */
25 static handlerKeyOptions: Partial<Record<string, HandlerKeyOptions> & {
26 [GENERAL_OPTIONS]?: HandlerKeyOptions;
27 }>;
28 /**
29 * The custom keys.
30 */
31 static readonly customHandlerKeys: string[];
32 /**
33 * This is not for external use. It is purely here for TypeScript inference of
34 * the generic `Options` type parameter.
35 *
36 * @internal
37 */
38 ['~O']: Options & DefaultStaticOptions;
39 /**
40 * This identifies this as a `Remirror` object. .
41 * @internal
42 */
43 abstract readonly [__INTERNAL_REMIRROR_IDENTIFIER_KEY__]: RemirrorIdentifier;
44 /**
45 * The unique name of this extension.
46 *
47 * @remarks
48 *
49 * Every extension **must** have a name. The name should have a distinct type
50 * to allow for better type inference for end users. By convention the name
51 * should be `camelCased` and unique within your editor instance.
52 *
53 * ```ts
54 * class SimpleExtension extends Extension {
55 * get name() {
56 * return 'simple' as const;
57 * }
58 * }
59 * ```
60 */
61 abstract get name(): string;
62 /**
63 * The options for this extension.
64 *
65 * @remarks
66 *
67 * Options are composed of Static, Dynamic, Handlers and ObjectHandlers.
68 *
69 * - `Static` - set at instantiation by the constructor.
70 * - `Dynamic` - optionally set at instantiation by the constructor and also
71 * set during the runtime.
72 * - `Handlers` - can only be set during the runtime.
73 * - `ObjectHandlers` - Can only be set during the runtime of the extension.
74 */
75 get options(): RemoveAnnotations<GetFixed<Options> & DefaultStaticOptions>;
76 /**
77 * Get the dynamic keys for this extension.
78 */
79 get dynamicKeys(): string[];
80 /**
81 * The options that this instance was created with, merged with all the
82 * default options.
83 */
84 get initialOptions(): RemoveAnnotations<GetFixed<Options> & DefaultStaticOptions>;
85 /**
86 * The initial options at creation (used to reset).
87 */
88 private readonly _initialOptions;
89 /**
90 * All the dynamic keys supported by this extension.
91 */
92 private readonly _dynamicKeys;
93 /**
94 * Private instance of the extension options.
95 */
96 private _options;
97 /**
98 * The mapped function handlers.
99 */
100 private _mappedHandlers;
101 constructor(defaultOptions: DefaultStaticOptions, ...[options]: ConstructorProps<Options, DefaultStaticOptions>);
102 /**
103 * This method is called by the extension constructor. It is not strictly a
104 * lifecycle method since at this point the manager has not yet been
105 * instantiated.
106 *
107 * @remarks
108 *
109 * It should be used instead of overriding the constructor which is strongly
110 * advised against.
111 *
112 * There are some limitations when using this method.
113 *
114 * - Accessing `this.store` will throw an error since the manager hasn't been
115 * created and it hasn't yet been attached to the extensions.
116 * - `this.type` in `NodeExtension` and `MarkExtension` will also throw an
117 * error since the schema hasn't been created yet.
118 *
119 * You should use this to setup any instance properties with the options
120 * provided to the extension.
121 */
122 protected init(): void;
123 /**
124 * Clone the current instance with the provided options. If nothing is
125 * provided it uses the same initial options as the current instance.
126 */
127 abstract clone(...parameters: ConstructorProps<Options, DefaultStaticOptions>): BaseClass<Options, DefaultStaticOptions>;
128 /**
129 * Get the dynamic keys for this extension.
130 */
131 private getDynamicKeys;
132 /**
133 * Throw an error if non dynamic keys are updated.
134 */
135 private ensureAllKeysAreDynamic;
136 /**
137 * Update the properties with the provided partial value when changed.
138 */
139 setOptions(update: GetPartialDynamic<Options>): void;
140 /**
141 * Reset the extension properties to their default values.
142 *
143 * @nonVirtual
144 */
145 resetOptions(): void;
146 /**
147 * Override this to receive updates whenever the options have been updated on
148 * this instance. This method is called after the updates have already been
149 * applied to the instance. If you need more control over exactly how the
150 * option should be applied you should set the option to be `Custom`.
151 *
152 * **Please Note**:
153 *
154 * This must be defined as a instance method and not a property since it is
155 * called in the constructor.
156 *
157 * ```ts
158 * class ThisPreset extends Preset {
159 * // GOOD ✅
160 * onSetOptions(props: OnSetOptionsProps<Options>) {}
161 *
162 * // BAD ❌
163 * onSetOptions = (props: OnSetOptionsProps<Options>) => {}
164 * }
165 * ```
166 *
167 * @abstract
168 */
169 protected onSetOptions?(props: OnSetOptionsProps<Options>): void;
170 /**
171 * Update the private options.
172 */
173 private getDynamicOptions;
174 /**
175 * Update the dynamic options.
176 */
177 private updateDynamicOptions;
178 /**
179 * Set up the mapped handlers object with default values (an empty array);
180 */
181 private populateMappedHandlers;
182 /**
183 * This is currently fudged together, I'm not sure it will work.
184 */
185 private createDefaultHandlerOptions;
186 /**
187 * Add a handler to the event handlers so that it is called along with all the
188 * other handler methods.
189 *
190 * This is helpful for integrating react hooks which can be used in multiple
191 * places. The original problem with fixed properties is that you can only
192 * assign to a method once and it overwrites any other methods. This pattern
193 * for adding handlers allows for multiple usages of the same handler in the
194 * most relevant part of the code.
195 *
196 * More to come on this pattern.
197 *
198 * @nonVirtual
199 */
200 addHandler<Key extends keyof GetHandler<Options>>(key: Key, method: GetHandler<Options>[Key], priority?: ExtensionPriority): Dispose;
201 /**
202 * Determines if handlers exist for the given key.
203 *
204 * Checking the existence of a handler property directly gives wrong results.
205 * `this.options.onHandlerName` is always truthy because it is a reference to
206 * the wrapper function that calls each handler.
207 *
208 * ```ts
209 *
210 * // GOOD ✅
211 * if (!this.hasHandlers('onHandlerName')) {
212 * return;
213 * }
214 *
215 * // BAD ❌
216 * if (!this.options.onHandlerName) {
217 * return;
218 * }
219 * ```
220 *
221 * @param key The handler to test
222 */
223 hasHandlers<Key extends keyof GetHandler<Options>>(key: Key): boolean;
224 private sortHandlers;
225 /**
226 * A method that can be used to add a custom handler. It is up to the
227 * extension creator to manage the handlers and dispose methods.
228 */
229 addCustomHandler<Key extends keyof GetCustomHandler<Options>>(key: Key, value: Required<GetCustomHandler<Options>>[Key]): Dispose;
230 /**
231 * Override this method if you want to set custom handlers on your extension.
232 *
233 * This must return a dispose function.
234 */
235 protected onAddCustomHandler?: AddCustomHandler<Options>;
236}
237/**
238 * @internal
239 */
240export type CustomHandlerMethod<Options extends ValidOptions> = <Key extends keyof GetCustomHandler<Options>>(key: Key, value: Required<GetCustomHandler<Options>>[Key]) => Dispose;
241export type AddCustomHandler<Options extends ValidOptions> = (props: Partial<GetCustomHandler<Options>>) => Dispose | undefined;
242export type AddHandler<Options extends ValidOptions> = <Key extends keyof GetHandler<Options>>(key: Key, method: GetHandler<Options>[Key]) => Dispose;
243/**
244 * TODO see if this is needed or remove.
245 */
246export type AddHandlers<Options extends ValidOptions> = (props: Partial<GetHandler<Options>>) => Dispose;
247export interface HandlerKeyOptions<ReturnType = any, Args extends any[] = any[]> {
248 /**
249 * When this value is encountered the handler will exit early.
250 *
251 * Set the value to `'__IGNORE__'` to ignore the early return value.
252 */
253 earlyReturnValue?: LiteralUnion<typeof IGNORE, Primitive> | ((value: unknown) => boolean);
254 /**
255 * Allows combining the values from the handlers together to produce a single
256 * reduced output value.
257 */
258 reducer?: {
259 /**
260 * Combine the value with the the previous value
261 */
262 accumulator: (accumulated: ReturnType, latestValue: ReturnType, ...args: Args) => ReturnType;
263 /**
264 * The a function that returns the default value for combined handler
265 * values. This is required for setting up a default value.
266 */
267 getDefault: (...args: Args) => ReturnType;
268 };
269}
270export interface BaseClass<Options extends ValidOptions, DefaultStaticOptions extends Shape = EmptyShape> {
271 constructor: BaseClassConstructor<Options, DefaultStaticOptions>;
272}
273export interface BaseClassConstructor<Options extends ValidOptions = EmptyShape, DefaultStaticOptions extends Shape = EmptyShape> extends Function {
274 new (...args: ConstructorProps<Options, DefaultStaticOptions>): any;
275 /**
276 * The identifier for the constructor which can determine whether it is a node
277 * constructor, mark constructor or plain constructor.
278 * @internal
279 */
280 readonly [__INTERNAL_REMIRROR_IDENTIFIER_KEY__]: RemirrorIdentifier;
281 /**
282 * Defines the `defaultOptions` for all extension instances.
283 *
284 * @remarks
285 *
286 * Once set it can't be updated during run time. Some of the settings are
287 * optional and some are not. Any non-required settings must be specified in
288 * the `defaultOptions`.
289 *
290 * **Please note**: There is a slight downside when setting up
291 * `defaultOptions`. `undefined` is not supported for partial settings at this
292 * point in time. As a workaround use `null` as the type and pass it as the
293 * value in the default settings.
294 *
295 * @defaultValue {}
296 *
297 * @internal
298 */
299 readonly defaultOptions: DefaultOptions<Options, DefaultStaticOptions>;
300 /**
301 * An array of the keys that are static for this extension.
302 *
303 * This is actually currently unused, but might become useful in the future.
304 * An auto-fix lint rule will be added should that be the case.
305 */
306 readonly staticKeys: string[];
307 /**
308 * An array of all the keys which correspond to the the event handler options.
309 *
310 * This **MUST** be present if you want to use event handlers in your
311 * extension.
312 *
313 * Every key here is automatically removed from the `setOptions` method and is
314 * added to the `addHandler` method for adding new handlers. The
315 * `this.options[key]` is automatically replaced with a method that combines
316 * all the handlers into one method that can be called effortlessly. All this
317 * work is done for you.
318 */
319 readonly handlerKeys: string[];
320 /**
321 * Customize the way the handler should behave.
322 */
323 readonly handlerKeyOptions: Partial<Record<string, HandlerKeyOptions> & {
324 __ALL__?: HandlerKeyOptions;
325 }>;
326 /**
327 * A list of the custom keys in the extension or preset options.
328 */
329 readonly customHandlerKeys: string[];
330}
331export type AnyBaseClassConstructor = Replace<BaseClassConstructor<any, any>, {
332 new (...args: any[]): AnyFunction;
333}>;
334/**
335 * Auto infers the parameter for the constructor. If there is a required static
336 * option then the TypeScript compiler will error if nothing is passed in.
337 */
338export type ConstructorProps<Options extends ValidOptions, DefaultStaticOptions extends Shape> = IfNoRequiredProperties<GetStatic<Options>, [
339 options?: GetConstructorProps<Options> & DefaultStaticOptions
340], [
341 options: GetConstructorProps<Options> & DefaultStaticOptions
342]>;
343/**
344 * Get the expected type signature for the `defaultOptions`. Requires that every
345 * optional setting key (except for keys which are defined on the
346 * `BaseExtensionOptions`) has a value assigned.
347 */
348export type DefaultOptions<Options extends ValidOptions, DefaultStaticOptions extends Shape> = MakeUndefined<UndefinedFlipPartialAndRequired<GetStatic<Options>> & Partial<DefaultStaticOptions> & GetFixedDynamic<Options>, StringKey<GetAcceptUndefined<Options>>>;
349export interface AnyBaseClassOverrides {
350 addCustomHandler: AnyFunction;
351 addHandler: AnyFunction;
352 clone: AnyFunction;
353}
354export {};
355
\No newline at end of file