-
Notifications
You must be signed in to change notification settings - Fork 2k
/
BasePlugin.ts
128 lines (103 loc) · 3.13 KB
/
BasePlugin.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* eslint-disable class-methods-use-this */
/**
* 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 Translator from '@uppy/utils/lib/Translator'
import type {
I18n,
Locale,
OptionalPluralizeLocale,
} from '@uppy/utils/lib/Translator'
import type { Body, Meta } from '@uppy/utils/lib/UppyFile'
import type { State, UnknownPlugin, Uppy } from './Uppy'
export type PluginOpts = {
locale?: Locale
id?: string
}
export type OnlyOptionals<T> = Pick<
T,
{
// eslint-disable-next-line @typescript-eslint/ban-types
[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)`.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
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 {}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
update(state: Partial<State<M, B>>): void {}
// Called after every state update, after everything's mounted. Debounced.
afterUpdate(): void {}
}