UNPKG

@uppy/core

Version:

Core module for the extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:

120 lines (95 loc) 2.96 kB
/** * Core plugin logic that all plugins share. * * BasePlugin does not contain DOM rendering so it can be used for plugins * without a user interface. * * See `Plugin` for the extended version with Preact rendering for interfaces. */ import type { Body, I18n, Meta, OptionalPluralizeLocale } from '@uppy/utils' import { Translator } from '@uppy/utils' import type { State, UnknownPlugin, Uppy } from './Uppy.js' export type PluginOpts = { locale?: OptionalPluralizeLocale id?: string } export type OnlyOptionals<T> = Pick< T, { // biome-ignore lint/complexity/noBannedTypes: ... [K in keyof T]-?: {} extends Pick<T, K> ? K : never }[keyof T] > /** * DefinePluginOpts marks all of the passed AlwaysDefinedKeys as “required” or “always defined”. */ export type DefinePluginOpts< Opts, AlwaysDefinedKeys extends keyof OnlyOptionals<Opts>, > = Opts & Required<Pick<Opts, AlwaysDefinedKeys>> export default class BasePlugin< Opts extends PluginOpts, M extends Meta, B extends Body, PluginState extends Record<string, unknown> = Record<string, unknown>, > { uppy: Uppy<M, B> opts: Opts id!: string defaultLocale: OptionalPluralizeLocale i18n!: I18n i18nArray!: Translator['translateArray'] type!: string VERSION!: string constructor(uppy: Uppy<M, B>, opts?: Opts) { this.uppy = uppy this.opts = opts ?? ({} as Opts) } getPluginState(): PluginState { const { plugins } = this.uppy.getState() return (plugins?.[this.id] || {}) as PluginState } setPluginState(update?: Partial<PluginState>): void { const { plugins } = this.uppy.getState() this.uppy.setState({ plugins: { ...plugins, [this.id]: { ...plugins[this.id], ...update, }, }, }) } setOptions(newOpts: Partial<Opts>): void { this.opts = { ...this.opts, ...newOpts } this.setPluginState(undefined) // so that UI re-renders with new options this.i18nInit() } i18nInit(): void { const translator = new Translator([ this.defaultLocale, this.uppy.locale, this.opts.locale, ]) this.i18n = translator.translate.bind(translator) this.i18nArray = translator.translateArray.bind(translator) this.setPluginState(undefined) // so that UI re-renders and we see the updated locale } /** * Extendable methods * ================== * These methods are here to serve as an overview of the extendable methods as well as * making them not conditional in use, such as `if (this.afterUpdate)`. */ addTarget(plugin: UnknownPlugin<M, B>): HTMLElement | null { throw new Error( "Extend the addTarget method to add your plugin to another plugin's target", ) } install(): void {} uninstall(): void {} update(state: Partial<State<M, B>>): void {} // Called after every state update, after everything's mounted. Debounced. afterUpdate(): void {} }