0
# Plugin System
1
2
Extensible plugin architecture for adding custom behaviors like overscroll effects, custom easing, or specialized scrolling modes. The plugin system provides lifecycle hooks and delta transformation capabilities.
3
4
## Capabilities
5
6
### ScrollbarPlugin Base Class
7
8
Base class for creating custom scrollbar plugins with lifecycle management and event transformation.
9
10
```typescript { .api }
11
/**
12
* Base class for scrollbar plugins
13
*/
14
class ScrollbarPlugin {
15
/** Plugin identifier - must be set by subclasses */
16
static pluginName: string;
17
18
/** Default options for the plugin */
19
static defaultOptions: any;
20
21
/** Reference to the scrollbar instance */
22
readonly scrollbar: Scrollbar;
23
24
/** Plugin configuration options */
25
readonly options: any;
26
27
/** Plugin name (same as pluginName) */
28
readonly name: string;
29
30
constructor(scrollbar: Scrollbar, options?: any);
31
}
32
```
33
34
### Plugin Lifecycle Hooks
35
36
Methods called during various phases of the scrollbar lifecycle.
37
38
```typescript { .api }
39
/**
40
* Called when the plugin is initialized
41
*/
42
onInit(): void;
43
44
/**
45
* Called when the plugin is being destroyed
46
*/
47
onDestroy(): void;
48
49
/**
50
* Called when the scrollbar updates (e.g., after resize)
51
*/
52
onUpdate(): void;
53
54
/**
55
* Called during each render frame with remaining momentum
56
* @param remainMomentum - Remaining scroll momentum after frame
57
*/
58
onRender(remainMomentum: Data2d): void;
59
```
60
61
### Delta Transformation
62
63
Method for intercepting and modifying scroll events before they're processed.
64
65
```typescript { .api }
66
/**
67
* Transforms scroll delta values from input events
68
* @param delta - Original scroll delta from input event
69
* @param evt - The original input event (wheel, touch, etc.)
70
* @returns Modified delta to be used for scrolling
71
*/
72
transformDelta(delta: Data2d, evt: Event): Data2d;
73
```
74
75
## Built-in Plugins
76
77
### OverscrollPlugin
78
79
Built-in plugin providing overscroll effects with bounce and glow animations.
80
81
```typescript { .api }
82
class OverscrollPlugin extends ScrollbarPlugin {
83
static pluginName: "overscroll";
84
static defaultOptions: {
85
effect: "bounce";
86
damping: 0.2;
87
maxOverscroll: 150;
88
glowColor: "#87ceeb";
89
onScroll: null;
90
};
91
92
readonly options: OverscrollOptions;
93
}
94
95
interface OverscrollOptions {
96
/** Effect type: 'bounce' or 'glow' */
97
effect?: OverscrollEffect;
98
99
/** Callback function called during overscroll */
100
onScroll?: OnScrollCallback;
101
102
/** Overscroll damping factor (0-1) */
103
damping: number;
104
105
/** Maximum overscroll distance in pixels */
106
maxOverscroll: number;
107
108
/** Color for glow effect */
109
glowColor: string;
110
}
111
112
enum OverscrollEffect {
113
BOUNCE = "bounce",
114
GLOW = "glow"
115
}
116
117
interface OnScrollCallback {
118
(this: OverscrollPlugin, position: Data2d): void;
119
}
120
121
type Position = Data2d;
122
```
123
124
**Usage Examples:**
125
126
```typescript
127
import Scrollbar from "smooth-scrollbar";
128
import OverscrollPlugin from "smooth-scrollbar/plugins/overscroll";
129
130
// Register the plugin
131
Scrollbar.use(OverscrollPlugin);
132
133
// Use with bounce effect
134
const scrollbar = Scrollbar.init(container, {
135
plugins: {
136
overscroll: {
137
effect: "bounce",
138
damping: 0.2,
139
maxOverscroll: 150
140
}
141
}
142
});
143
144
// Use with glow effect
145
const scrollbar2 = Scrollbar.init(container2, {
146
plugins: {
147
overscroll: {
148
effect: "glow",
149
glowColor: "#ff6b6b",
150
maxOverscroll: 100,
151
onScroll(position) {
152
console.log(`Overscroll: x=${position.x}, y=${position.y}`);
153
}
154
}
155
}
156
});
157
```
158
159
## Creating Custom Plugins
160
161
### Basic Plugin Structure
162
163
Template for creating custom plugins with proper lifecycle implementation.
164
165
```typescript
166
import { ScrollbarPlugin } from "smooth-scrollbar";
167
168
class CustomPlugin extends ScrollbarPlugin {
169
static pluginName = "custom-plugin";
170
static defaultOptions = {
171
customOption: true,
172
threshold: 100
173
};
174
175
onInit() {
176
// Setup plugin resources
177
console.log("Custom plugin initialized");
178
}
179
180
onDestroy() {
181
// Clean up plugin resources
182
console.log("Custom plugin destroyed");
183
}
184
185
onUpdate() {
186
// Handle scrollbar updates
187
this.adjustToNewSize();
188
}
189
190
onRender(remainMomentum) {
191
// Custom rendering logic
192
if (Math.abs(remainMomentum.y) > this.options.threshold) {
193
this.triggerCustomEffect();
194
}
195
}
196
197
transformDelta(delta, fromEvent) {
198
// Modify scroll behavior
199
if (fromEvent.type === "wheel") {
200
return {
201
x: delta.x * 0.8, // Reduce horizontal scroll speed
202
y: delta.y * 1.2 // Increase vertical scroll speed
203
};
204
}
205
return delta;
206
}
207
208
private adjustToNewSize() {
209
// Custom logic for size changes
210
}
211
212
private triggerCustomEffect() {
213
// Custom effect implementation
214
}
215
}
216
217
// Register and use the plugin
218
Scrollbar.use(CustomPlugin);
219
220
const scrollbar = Scrollbar.init(container, {
221
plugins: {
222
"custom-plugin": {
223
customOption: false,
224
threshold: 50
225
}
226
}
227
});
228
```
229
230
### Advanced Plugin Example
231
232
Example of a more complex plugin that adds momentum-based effects.
233
234
```typescript
235
import { ScrollbarPlugin } from "smooth-scrollbar";
236
237
class MomentumEffectsPlugin extends ScrollbarPlugin {
238
static pluginName = "momentum-effects";
239
static defaultOptions = {
240
fadeOnScroll: true,
241
blurOnScroll: false,
242
scaleOnScroll: false,
243
maxEffect: 1.0
244
};
245
246
private lastMomentum = { x: 0, y: 0 };
247
248
onInit() {
249
// Initialize effect elements if needed
250
this.setupEffectElements();
251
}
252
253
onRender(remainMomentum) {
254
const { fadeOnScroll, blurOnScroll, scaleOnScroll, maxEffect } = this.options;
255
const intensity = Math.min(
256
Math.sqrt(remainMomentum.x ** 2 + remainMomentum.y ** 2) / 100,
257
maxEffect
258
);
259
260
if (fadeOnScroll) {
261
this.scrollbar.contentEl.style.opacity = (1 - intensity * 0.3).toString();
262
}
263
264
if (blurOnScroll) {
265
this.scrollbar.contentEl.style.filter = `blur(${intensity * 2}px)`;
266
}
267
268
if (scaleOnScroll) {
269
const scale = 1 - intensity * 0.05;
270
this.scrollbar.contentEl.style.transform = `scale(${scale})`;
271
}
272
273
this.lastMomentum = remainMomentum;
274
}
275
276
transformDelta(delta, fromEvent) {
277
// Add momentum-based resistance
278
const resistance = this.calculateResistance();
279
return {
280
x: delta.x * resistance,
281
y: delta.y * resistance
282
};
283
}
284
285
private setupEffectElements() {
286
// Setup any DOM elements needed for effects
287
}
288
289
private calculateResistance() {
290
// Calculate scroll resistance based on current momentum
291
const momentum = Math.abs(this.lastMomentum.x) + Math.abs(this.lastMomentum.y);
292
return Math.max(0.3, 1 - momentum / 1000);
293
}
294
}
295
```
296
297
## Plugin Registration and Management
298
299
```typescript { .api }
300
/**
301
* Global plugin management functions
302
*/
303
304
/** Register plugins globally for all scrollbar instances */
305
function addPlugins(...Plugins: (typeof ScrollbarPlugin)[]): void;
306
307
/** Initialize plugins for a specific scrollbar instance */
308
function initPlugins(scrollbar: Scrollbar, options: any): ScrollbarPlugin[];
309
310
/** Global plugin registry */
311
interface PluginMap {
312
order: Set<string>;
313
constructors: {
314
[name: string]: typeof ScrollbarPlugin;
315
};
316
}
317
```