@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
646 lines (645 loc) • 28.5 kB
TypeScript
import { type Listener } from '../event-dispatcher';
import type { CorePlugin, DefaultEditorPlugin, DependencyPlugin, NextEditorPlugin, NextEditorPluginMetadata, OptionalPlugin, PluginDependenciesAPI } from '../types';
import type { EditorPlugin } from '../types/editor-plugin';
import type { EditorPluginInjectionAPI } from './plugin-injection-api';
/*********************
* *
* BASE TYPES *
* *
**********************/
/**
* 🧱 Internal Type: Editor FE Platform
*
*/
type MaybePlugin<T extends PresetPlugin> = T | undefined;
/**
* 🧱 Internal Type: Editor FE Platform
*
*/
type DependencyErrorMessage<Message extends string> = {
errorMessage: Message;
};
/**
* 🧱 Internal Type: Editor FE Platform
*
*/
type PluginWithConfiguration<Plugin> = undefined extends ExtractPluginConfiguration<Plugin> ? [
Plugin,
ExtractPluginConfiguration<Plugin>?
] : [
Plugin,
ExtractPluginConfiguration<Plugin>
];
/****************************************************
* *
* METADATA PROPERTIES EXTRACTION TYPES *
* *
****************************************************/
/**
* 🧱 Internal Type: Editor FE Platform
*
* Extracts the configuration type from a given plugin.
*
*
* @returns The extracted plugin configuration type if applicable, or `never`.
*
* @example
* ```typescript
* type DogPlugin = NextEditorPlugin<'dog'>;
*
* // it returns never, since Dog has no configuration
* type MyPluginConfiguration = ExtractPluginConfiguration<MyPlugin>;
*
*
* type CatPlugin = NextEditorPlugin<'cat', { configuration: { color: 'red' | 'blue' } }>;
*
* // it returns this type { color: 'red' | 'blue' }
* type MyPluginConfiguration = ExtractPluginConfiguration<MyPlugin>;
* ```
*/
type ExtractPluginConfiguration<Plugin> = Plugin extends NextEditorPlugin<any, any> ? Plugin extends (props: {
api: any;
config: any;
}) => DefaultEditorPlugin<any, infer Metadata> ? ExtractPluginConfigurationFromMetadata<Metadata> : never : never;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Extracts and filters the plugin dependencies from the plugin metadata, excluding
* optional dependencies.
*
* This type first checks if the `dependencies` property in the given `Metadata` type
* is an array of `DependencyPlugin`. If true, it applies `FilterOptionalPlugins` to
* filter out the optional dependencies. If the `dependencies` property does not exist
* or is not an array of `DependencyPlugin`, the type resolves to an empty array.
*
* @returns An array of filtered plugin dependencies or an empty array.
*
* @example
* ```typescript
* type DogPlugin = NextEditorPlugin<'dog'>;
* type LoudPlugin = NextEditorPlugin<'loud'>;
* type BarkMetadata = {dependencies: [
* OptionalPlugin<LoudPlugin>,
* DogPlugin,
* ]}
* type BarkPlugin = NextEditorPlugin<'bark', BarkMetadata>;
*
* // It returns [DogPlugin]
* type RequiredDependencies = ExtractPluginDependenciesFromMetadataWithoutOptionals<BarkMetadata>;
*
* ```
*
* You probably wants to use this other type util @see ExtractPluginDependencies
* since you wouldn't need to infer the Metadata twice
*/
type ExtractPluginDependenciesFromMetadataWithoutOptionals<Metadata extends NextEditorPluginMetadata> = Metadata['dependencies'] extends DependencyPlugin[] ? FilterOptionalPlugins<Metadata['dependencies']> : [
];
/**
* 🧱 Internal Type: Editor FE Platform
*
* Extracts the plugin configuration from the given plugin metadata if the
* `pluginConfiguration` property exists.
*
* This type conditionally checks if the `Metadata` type includes a `pluginConfiguration`
* key. If such a key exists, the type of `pluginConfiguration` is returned. If not,
* the type resolves to `never`.
*/
type ExtractPluginConfigurationFromMetadata<Metadata> = 'pluginConfiguration' extends keyof Metadata ? Metadata['pluginConfiguration'] : never;
/********************************
* *
* TYPE INFER *
* *
*********************************/
/**
* 🧱 Internal Type: Editor FE Platform
*
* Extracts the NextEditorPlugin type from a PresetPuglin,
* this is useful because the EditorPresetBuilder can accept the plugin in multiple ways:
*
* @example
* ```
* preset
* // valid
* .add([plugin, { myConfiguration }] // Type: [NextEditorPlugin, Configuration]
*
* // valid
* .add([plugin]) // Type: [NextEditorPlugin, Configuration?]
*
* // valid
* .add(plugin) // Type: NextEditorPlugin
*
* ```
*
* This type conditionally checks if `Plugin` is an array. If it is an array, it then checks if the first element
* (`MPlugin`) extends `NextEditorPlugin`. But if `Plugin` directly extends `NextEditorPlugin`, it returns the `Plugin`
* type itself. Otherwise, it resolves to `never`.
*
* You probably wants to use this if you need to extract the NextEditorPlugin from a @see PresetPlugin .
* Since the PresetPlugin is an union between a tuple and a plugin.
*/
type ExtractPluginAllBuilderPlugins<Plugin extends PresetPlugin> = Plugin extends Array<any> ? Plugin extends [
infer MPlugin,
...any
] ? MPlugin extends NextEditorPlugin<infer _Name, any> ? MPlugin : never : never : Plugin extends NextEditorPlugin<infer _Name, any> ? Plugin : never;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Extracts non-optional plugin dependencies, excluding any optional dependencies, from a given plugin's metadata.
*
* We can declare the depencies like this:
*
* @example
* ```typescript
* NextEditorPlugin<'bark', {
* dependencies: [DogPlugin, Optional<LoudPlugin>]
* }>
*
* ```
*
*
* This tyope is similar to @see ExtractPluginDependenciesFromMetadataWithoutOptionals
* but you can use it to extract the non-optional-dependencies from any NextEditorPlugin without infer the metadata
*
* @example
* ```typescript
* type BarkPlugin = NextEditorPlugin<'bark', {
* dependencies: [DogPlugin, Optional<LoudPlugin>]
* }>
*
* type PluginDependencies = ExtractPluginDependencies<BarkPlugin>; // Type: [DogPlugin]
* ```
*/
type ExtractPluginDependencies<Plugin> = Plugin extends NextEditorPlugin<any, infer Metadata> ? ExtractPluginDependenciesFromMetadataWithoutOptionals<Metadata> : never;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Extracts the NextEditorPlugin type from a PluginWithConfiguration.
*
*
* You probably wants to use this if you need to extract the NextEditorPlugin from a @see PresetPlugin .
* Since the PresetPlugin is an union between a tuple and a plugin.
*/
type ExtractNextEditorPluginFromPluginWithConfiguration<Plugin> = Plugin extends PluginWithConfiguration<any> ? Plugin[0] : never;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Extracts the plugin name from a PresetPlugins.
*
* @example
* ```typescript
* ExtractPluginNameFromAllBuilderPlugins<NextEditorPlugin<'bark'>> // 'bark'
*
* ExtractPluginNameFromAllBuilderPlugins<[NextEditorPlugin<'dog'>, { configuration: {} }> // 'dog'
*
* ```
* Similar to @see ExtractPluginAllBuilderPlugins, this type conditionally checks if `Plugin` is an array. If it is,
* it attempts to extract the name of the first plugin (`MPlugin`) in the array that extends `NextEditorPlugin` with
* a name and any metadata. If `Plugin` itself directly extends `NextEditorPlugin`, it extracts the plugin's name.
* If none of these conditions are met, it resolves to `never`.
*
*/
type ExtractPluginNameFromAllBuilderPlugins<Plugin extends PresetPlugin> = Plugin extends Array<any> ? Plugin extends [
infer MPlugin,
...any
] ? MPlugin extends NextEditorPlugin<infer Name, any> ? Name : never : never : Plugin extends NextEditorPlugin<infer Name, any> ? Name : never;
/******************************
* *
* MAPPED TUPLES *
* *
******************************/
/**
* 🧱 Internal Type: Editor FE Platform
*
* Filters out optional plugins from a tuple of dependency plugins.
*
*
* This type is using the Tail Head trick to map a tuple to another one.
* It does this by conditionally iterating over each element in the tuple: if the head of the tuple (the first element)
* is an optional plugin, it is excluded from the resulting tuple; otherwise, it is included. This process is repeated
* for the tail (the remaining elements) of the tuple until all elements have been evaluated.
*
*/
type FilterOptionalPlugins<T extends DependencyPlugin[]> = T extends [
infer Head,
...infer Tail
] ? Tail extends DependencyPlugin[] ? Head extends OptionalPlugin<NextEditorPlugin<any, any>> ? FilterOptionalPlugins<Tail> : [
Head,
...FilterOptionalPlugins<Tail>
] : T : T;
/**
* 🧱 Internal Type: Editor FE Platform
*
* One of the main type system for the EditorPresetBuilder.
*
* Verifies if a given plugin's dependencies are satisfied within a provided stack of plugins.
*
* Usually, the stack of plugins are coming from a generic parameter in the EditorPresetBuilder<PluginNames, PluginStack>.
*
* This type checks if the dependencies of the given `Plugin` are included in the provided `PluginsStack`.
*
* - If the plugin has no dependencies, it simply returns the plugin itself, (provided it is either a `PluginWithConfiguration` or `NextEditorPlugin`, in case someone tries to add a non-NextEditorPlugin to the Preset)
*
* - If the plugin has dependencies, it verifies each dependency against the `PluginsStack` to ensure
* they are present. This includes checking direct dependencies as well as dependencies hidden inside tuples (by unwrapping
* them). If all dependencies are satisfied, it returns the plugin; otherwise, it resolves to `never`.
*
*
* @example
* ```typescript
* type DogPlugin = NextEditorPlugin<'dog'>;
* type LoudPlugin = NextEditorPlugin<'loud'>;
* type BarkPlugin = NextEditorPlugin<'bark', { dependencies: [DogPlugin, LoudPlugin] }>;
*
*
* // When there we are missing dependencies
* VerifyPluginDependencies<BarkPlugin, [DogPlugin]> // Type: never
*
*
* // When there all dependencies are already added on the stack
* VerifyPluginDependencies<BarkPlugin, [DogPlugin, LoudPlugin]> // Type: BarkPlugin
*
* ```
*/
type VerifyPluginDependencies<Plugin, PluginsStack extends AllEditorPresetPluginTypes[]> = ExtractPluginDependencies<Plugin> extends [
] ? Plugin extends PluginWithConfiguration<any> | NextEditorPlugin<any, any> ? Plugin : never :
/**
* case 1: We're looking for its dependent plugins indexed on `AllEditorPresetPluginTypes`
*/
ExtractPluginDependencies<Plugin>[number] extends (ExtractPluginDependencies<Plugin>[number] & PluginsStack[number])
/**
* case 2:
* Otherwise check whether the dependent-plugin, is hidden inside a tuple,
* unwrapping `Plugins` via `ExtractNextEditorPluginFromPluginWithConfiguration`
*/
| (ExtractPluginDependencies<Plugin>[number] & ExtractNextEditorPluginFromPluginWithConfiguration<PluginsStack[number]>) ? Plugin : never;
/********************************
* *
* BETTER ERROR MESSAGE TYPES *
* *
*********************************/
/**
* 🧱 Internal Type: Editor FE Platform
*
* TypeScript doesn't allow custom error messages (yet). So, use this type to force a specific error message to the user.
*
* This is useful because in a situation where a Preset has too many plugins, its become really hard to understand what the error message is.
*
* Extracts the names of required dependencies for a given plugin, or provides an error message if dependencies are
* missing, invalid, or if the plugin itself is not a recognized NextEditorPlugin.
*
* This type evaluates whether a given `Plugin` has defined dependencies. If dependencies are absent, it returns
* a message indicating no dependencies were found. If dependencies are present but do not conform to expected types,
* or if an unspecified issue occurs, appropriate error messages are generated. Valid dependencies result in the
* extraction of their names; otherwise, an error message specific to the situation is returned.
*
* It is used by the @see GetDependencyErrorMessage to group all error messages when a new plugin is being added into a preset.
*/
type ExtractRequiredDependencies<Plugin, PluginsStack extends AllEditorPresetPluginTypes[]> = Plugin extends NextEditorPlugin<infer PluginName, infer Metadata> ? Metadata['dependencies'] extends undefined ? DependencyErrorMessage<'No found dependencies'> : Metadata['dependencies'] extends DependencyPlugin[] ? FilterOptionalPlugins<FilterExistingPlugins<Metadata['dependencies'], PluginsStack>>[number] extends NextEditorPlugin<infer Name, any> ? Name : DependencyErrorMessage<`Invalid dependency for ${PluginName}`> : DependencyErrorMessage<`Invalid dependencies for ${PluginName}`> : DependencyErrorMessage<'Plugin is not NextEditorPlugin'>;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Retrieves an error message if any dependency-related issues are detected for a given plugin within a specified
* plugin stack. This includes missing dependencies or other errors as identified by `ExtractRequiredDependencies`.
*
* It attempts to extract required dependencies for the `Plugin` from the `StackPlugins`. If the result is a string,
* it indicates a missing dependency and constructs an error message accordingly. Otherwise, it directly returns the
* result from `ExtractRequiredDependencies`, which could be an error message detailing the issue encountered.
*
* It is used by the @see SafePresetCheck to make improve the error message
*/
type GetDependencyErrorMessage<Plugin, StackPlugins extends AllEditorPresetPluginTypes[]> = ExtractRequiredDependencies<Plugin, StackPlugins> extends string ? DependencyErrorMessage<`Missing dependency: ${ExtractRequiredDependencies<Plugin, StackPlugins>}Plugin`> : ExtractRequiredDependencies<Plugin, StackPlugins>;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Filters through an array of dependency plugins, removing any that do not exist in the provided plugins stack.
*
* This type recursively checks each plugin dependency against the provided `PluginsStack`. If a dependency is found
* within the stack, it is included in the result; otherwise, it is excluded. This process helps in identifying
* missing plugins from a set of required dependencies.
*
*/
type FilterExistingPlugins<T extends DependencyPlugin[], PluginsStack extends AllEditorPresetPluginTypes[]> = T extends [
infer CurrentPluginDependency,
...infer RemainingPluginDependencies
] ? RemainingPluginDependencies extends DependencyPlugin[] ? CurrentPluginDependency extends PluginsStack[number] ? FilterExistingPlugins<RemainingPluginDependencies, PluginsStack> : [
CurrentPluginDependency,
...FilterExistingPlugins<RemainingPluginDependencies, PluginsStack>
] : T : T;
/*****************************
* *
* VALIDATION HELPER TYPES *
* *
******************************/
/**
* 🧱 Internal Type: Editor FE Platform
*
* Checks for duplicate plugin entries within a stack of plugins. If a duplicate is found, it returns an error message;
* otherwise, it proceeds without error.
*
* This type primarily serves to ensure that each plugin in the plugin stack is unique, preventing issues related to
* duplicate plugin registration. It also includes a check to accommodate scenarios where strict typing is bypassed.
*
* If the plugin is used with other configuration this type will not complain.
*/
type CheckDuplicatePlugin<Plugin, StackPlugins extends AllEditorPresetPluginTypes[]> = Plugin extends NextEditorPlugin<infer PluginName, any> ? Plugin extends StackPlugins[number] ? unknown extends StackPlugins[number] ? unknown : DependencyErrorMessage<`Duplicate plugin: ${PluginName}`> : unknown : unknown;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Verifies if a given plugin meets basic requirements to be considered a valid editor plugin.
*
* This type checks if the plugin is a function that matches the expected signature for an next editor plugin. If it does,
* it further checks the plugin's configuration requirements to ensure compatibility and adherence to expected
* configurations.
*
*/
type CheckBasicPlugin<Plugin> = Plugin extends (args: any, api: any) => EditorPlugin ? CheckTupleRequirements<Plugin, ExtractPluginConfiguration<Plugin>, PluginWithConfiguration<Plugin>> : never;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Evaluates whether a plugin's configuration meets the requirements to be used either as a standalone plugin or
* as part of a plugin-with-configuration tuple.
*
* This type assesses the plugin configuration's status—whether it's optional, mandatory, or not present—and determines
* the valid ways in which the plugin can be registered or used. This is crucial for maintaining backward compatibility
* and ensuring plugins are correctly configured upon registration into the Preset
*
*/
type CheckTupleRequirements<Plugin, Config, ArrayType> = unknown extends Config ? Plugin | ArrayType : undefined extends Config ? Plugin | ArrayType : [
Config
] extends [
never
] ? Plugin : ArrayType;
/*****************************
* *
* EDITOR API HELPER TYPES *
* *
******************************/
/**
* 🧱 Internal Type: Editor FE Platform
*
* Extracts the numeric indices as literal types from a tuple.
*
* This utility type takes a tuple and produces a union of its numeric indices as literal types. It's useful for
* iterating over tuples with TypeScript's mapped types, allowing for operations on each tuple element based on its index.
*
* It is being used to separate plugins registred with `preset.maybeAdd` and `preset.add`.
*/
type TupleIndices<T extends readonly any[]> = Extract<keyof T, `${number}`> extends `${infer N extends number}` ? N : never;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Constructs a plugin api type with optional properties based on the optional plugins from a given tuple of plugins.
*
* This type iterates over a tuple of plugins and checks for plugins marked as optional (indicated by the presence
* of `undefined`). For each optional plugin, it attempts to extract the plugin's name and corresponding
* `PluginDependenciesAPI` type. The resulting object type has properties with these plugin names as keys and their
* respective APIs as optional values.
*
* @example
* ```typescript
* type DogPlugin = NextEditorPlugin<'dog'>;
* type CatPlugin = NextEditorPlugin<'cat'>;
*
*
* BuildOptionalAPIEntry<[DogPlugin, MaybePlugin<CatPlugin>]> // Type: { cat?: { } }
*
* ```
*/
type BuildOptionalAPIEntry<T extends AllEditorPresetPluginTypes[]> = {
[K in TupleIndices<T> as undefined extends T[K] ? T[K] extends MaybePlugin<infer P> ? ExtractPluginNameFromAllBuilderPlugins<P> : never : never]?: undefined extends T[K] ? T[K] extends MaybePlugin<infer P> ? PluginDependenciesAPI<ExtractPluginAllBuilderPlugins<P>> | undefined : never : never;
};
/**
* 🧱 Internal Type: Editor FE Platform
* Generates a plugin api type with properties based on the required plugins from a given tuple of plugins.
*
* This type traverses a tuple of plugins, focusing on those not marked as optional. For each required plugin,
* it extracts the plugin's name to use as a key and determines the corresponding `PluginDependenciesAPI` type
* for the value. The resulting object type includes these key-value pairs, ensuring that each required plugin
* has a defined API entry in the object.
*
* @example
* ```typescript
* type DogPlugin = NextEditorPlugin<'dog'>;
* type CatPlugin = NextEditorPlugin<'cat'>;
*
*
* BuildOptionalAPIEntry<[DogPlugin, MaybePlugin<CatPlugin>]> // Type: { dog?: { } }
*
* ```
*/
type BuildRequiredAPIEntry<T extends AllEditorPresetPluginTypes[]> = {
[K in TupleIndices<T> as undefined extends T[K] ? never : T[K] extends PresetPlugin ? ExtractPluginNameFromAllBuilderPlugins<T[K]> : never]: undefined extends T[K] ? never : T[K] extends PresetPlugin ? PluginDependenciesAPI<ExtractPluginAllBuilderPlugins<T[K]>> : never;
};
/**
* 🧱 Internal Type: Editor FE Platform
*
* Forces the expansion (simplification/normalization) of conditional and mapped types.
* This can be particularly useful for making the types more readable and manageable in
* environments like IntelliSense or when generating type documentation.
*
* More info {@link https://github.com/microsoft/TypeScript/issues/47980 TypeScript/issues/47980}
*/
type Expand<T> = T extends Function ? T : T extends unknown ? {
[K in keyof T]: Expand<T[K]>;
} : never;
/*************************
* *
* PUBLIC TYPES *
* *
*************************/
/**
* 🧱 Internal Type: Editor FE Platform
*
* Represents a utility type that wraps a string type in a tuple, often used to denote
* plugin names that might be optionally included or excluded in certain contexts within
* the editor preset builder.
*/
export type MaybePluginName<T extends string> = [
T
];
/**
* 🧱 Internal Type: Editor FE Platform
*
* A union type that represents a plugin which could either be a standalone `NextEditorPlugin`
* or a `PluginWithConfiguration` that bundles a plugin with its specific configuration.
*
* This type is fundamental in managing plugins within presets, allowing for flexible plugin
* registration that accommodates plugins with or without explicit configurations.
*/
export type PresetPlugin = PluginWithConfiguration<NextEditorPlugin<any, any>> | NextEditorPlugin<any, any>;
/**
* 🧱 Internal Type: Editor FE Platform
*
* A union type that aggregates all possible plugin name representations within the editor preset builder,
* including simple strings for direct plugin names and wrapped strings in tuples when a plugin is registred with `maybeAdd`.
*
*/
export type AllPluginNames = string | MaybePluginName<string>;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Represents all possible types of plugins that can be included within an editor preset.
* This includes both `PresetPlugin` types and `MaybePlugin` types, accommodating a wide range
* of plugin registration scenarios likw:
*
* @example
* ```typescript
* preset
* .add([plugin, { myConfiguration }]
* .add([plugin])
* .add(plugin)
* .maybeAdd(plugin, () => true);
* .maybeAdd([plugin], () => true);
* .maybeAdd([plugin, { myConfiguration }], () => true);
*
* ```
*/
export type AllEditorPresetPluginTypes = PresetPlugin | MaybePlugin<NextEditorPlugin<any, any>>;
/**
* 🧱 Internal Type: Editor FE Platform
*
* Performs a series of checks to ensure that a given plugin can be safely added to a preset.
* This includes verifying the plugin's dependencies, checking for duplicate registrations, and ensuring
* the plugin meets basic criteria for being considered a valid plugin.
*
* @returns The plugin type if all checks pass, or error messages detailing why the plugin cannot be added.
*/
export type SafePresetCheck<Plugin, StackPlugins extends AllEditorPresetPluginTypes[]> = Plugin extends Plugin & VerifyPluginDependencies<Plugin, StackPlugins> ? Plugin extends NextEditorPlugin<any, any> ? CheckDuplicatePlugin<Plugin, StackPlugins> & CheckBasicPlugin<Plugin> : never : GetDependencyErrorMessage<Plugin, StackPlugins>;
/**
* 📢 Public Type API
*
* Extracts the complete API surface for a given editor preset, including both core and plugin-specific APIs.
* This type dynamically assembles the API object based on the included plugins, differentiating between
* optional and required plugins to accurately reflect the available API calls.
*
* @template Preset The editor preset builder instance from which to extract the API.
* @returns An object type representing the complete API surface for the given preset.
*
* @example
* ```typescript
* const dogPlugin: NextEditorPlugin<'dog'>;
* const catPlugin: NextEditorPlugin<'cat'>;
*
* const myPreset = new EditorPresetBuilder()
* .add(dogPlugin)
* .maybeAdd(catPlugin, () => true)
*
* const api: ExtractPresetAPI<typeof myPreset>;
*
*
* // Core is always available
* api.core.actions
*
* // Dog was registred with `add`, so it will always be available
* api.dog.actions
*
* // Cat was registred with `maybeAdd`, so it may not be available on runtime
* api.cat?.actions
* ```
*/
export type ExtractPresetAPI<Preset extends EditorPresetBuilder<any, any>> = Preset extends EditorPresetBuilder<any, infer Plugins> ? Expand<{
core: PluginDependenciesAPI<CorePlugin>;
} & BuildOptionalAPIEntry<Plugins> & BuildRequiredAPIEntry<Plugins>> : never;
/*************************
* *
* PROP TYPES *
* *
*************************/
type OldAndDeprecatedAddFunction<T> = (pluginToAdd: T, builder: EditorPresetBuilder<any, any>) => EditorPresetBuilder<any, any>;
type BuildProps = {
excludePlugins?: Set<string>;
pluginInjectionAPI?: EditorPluginInjectionAPI;
};
/**
* This class is the main way to build an Editor.
*
* A Preset is an immutable object, any modification like `.add` or `.maybeAdd`
* will always result in a new preset instance.
*
* ⚠️⚠️⚠️ ATTENTION ⚠️⚠️⚠️
* For ComposableEditor, a new Preset means a full redraw,
* it is one of the most expensive operation.
* Please make sure you aren't recreating this all the time.
*
* EditorAPI:
* In case you need access to the EditorAPI type definition based in the preset you have.
* Please use the util type exported in this package: @see ExtractPresetAPI<Preset>
*
* ```typescript
* const myPreset = new EditorPresetBuilder()
* .add(pluginDog)
* .add(pluginCat);
*
*
* function someFunc(myApi: ExtractPresetAPI<typeof myPreset>) {
*
* }
* ```
*
* If your code is inside an EditorPlugin you should be using the @see ExtractInjectionAPI.
*/
export declare class EditorPresetBuilder<PluginNames extends AllPluginNames[] = [
], StackPlugins extends AllEditorPresetPluginTypes[] = [
]> {
private readonly data;
/**
* @deprecated Use `apiResolver` instead
*/
apiPromise: Promise<unknown>;
private resolver;
/**
* Returns the editor API when resolved.
* This occurs when the preset is initially built.
*/
apiResolver: APIDispatcher;
private apiEmitter;
constructor(...more: [
...StackPlugins
]);
add<NewPlugin extends PresetPlugin>(nextOrTuple: SafePresetCheck<NewPlugin, StackPlugins>): EditorPresetBuilder<[
ExtractPluginNameFromAllBuilderPlugins<NewPlugin>,
...PluginNames
], [
NewPlugin,
...StackPlugins
]>;
maybeAdd<ToAddPlugin extends PresetPlugin>(pluginToAdd: SafePresetCheck<ToAddPlugin, StackPlugins>, shouldAdd: boolean | (() => boolean) | OldAndDeprecatedAddFunction<ToAddPlugin>): EditorPresetBuilder<[
MaybePluginName<ExtractPluginNameFromAllBuilderPlugins<ToAddPlugin>>,
...PluginNames
], [
MaybePlugin<ToAddPlugin>,
...StackPlugins
]>;
has(plugin: AllEditorPresetPluginTypes): boolean;
build({ pluginInjectionAPI, excludePlugins: maybeExcludePlugins, }?: BuildProps): EditorPlugin[];
private verifyDuplicatedPlugins;
private processEditorPlugins;
private removeExcludedPlugins;
private safeEntry;
}
type Emitter = (value: unknown) => void;
/**
* WARNING: Internal object
*
* Dedicated wrapper around EventDispatcher for public API around the editor API.
* This only has the public method `on` which is used to listen to updates to the editor API.
*
* This shouldn't really be used externally - the `editorAPI` should be accessed via `usePreset`.
*/
declare class APIDispatcher {
private emitter;
private eventDispatcher;
private key;
private initialEvent;
constructor(emitter: (emitter: Emitter) => void);
/**
* Used to observe Editor API events
*
* @param cb Callback to listen to the editor API.
* This will also emit the last event if the stream has already started.
* @returns Cleanup function to cleanup the listener
*/
on(cb: Listener<unknown>): () => void;
destroy(): void;
}
export {};