0
# Plugin System
1
2
Extensible plugin architecture that allows customization of Radium's style processing behavior through a modular system of processing functions.
3
4
## Capabilities
5
6
### Plugin Interface
7
8
Plugins are functions that process style objects and return modifications to component props, styles, or global state.
9
10
```javascript { .api }
11
/**
12
* Plugin function interface
13
* @param config - Plugin configuration object with utilities and current state
14
* @returns Plugin result with optional modifications to component
15
*/
16
interface Plugin {
17
(config: PluginConfig): PluginResult | void;
18
}
19
20
interface PluginConfig {
21
/** Component name (may not be available if minified) */
22
componentName: string;
23
/** Current Radium configuration */
24
config: RadiumConfig;
25
/** Current element props (can be modified by previous plugins) */
26
props: object;
27
/** Current element style (can be modified by previous plugins) */
28
style: object;
29
30
// Utility functions
31
/** Add CSS to global stylesheet */
32
addCSS: (css: string) => { remove: () => void };
33
/** Add !important to all values in style object */
34
appendImportantToEachValue: (style: object) => object;
35
/** Convert CSS rules object to string */
36
cssRuleSetToString: (selector: string, rules: object, userAgent?: string) => string;
37
/** Get component field value */
38
getComponentField: (key: string) => any;
39
/** Get global state value */
40
getGlobalState: (key: string) => any;
41
/** Get element state (hover, focus, active) */
42
getState: (stateKey: string, elementKey?: string) => any;
43
/** Generate hash from string */
44
hash: (data: string) => string;
45
/** Check if value is nested style object */
46
isNestedStyle: (value: any) => boolean;
47
/** Merge array of style objects */
48
mergeStyles: (styles: object[]) => object;
49
/** Set component state */
50
setState: (stateKey: string, value: any, elementKey?: string) => void;
51
/** Environment detection utilities */
52
ExecutionEnvironment: {
53
canUseEventListeners: boolean;
54
canUseDOM: boolean;
55
};
56
}
57
58
interface PluginResult {
59
/** Fields to merge into component instance */
60
componentFields?: object;
61
/** Values to merge into global state */
62
globalState?: object;
63
/** Props to merge into element */
64
props?: object;
65
/** Style object to replace current style */
66
style?: object;
67
}
68
```
69
70
### Built-in Plugins
71
72
Radium includes a comprehensive set of built-in plugins that handle core functionality.
73
74
```javascript { .api }
75
interface BuiltinPlugins {
76
/** Validates style properties and detects common issues */
77
checkProps: Plugin;
78
/** Processes keyframe animation objects */
79
keyframes: Plugin;
80
/** Merges arrays of style objects intelligently */
81
mergeStyleArray: Plugin;
82
/** Adds vendor prefixes to CSS properties */
83
prefix: Plugin;
84
/** Extracts nested style objects for processing */
85
removeNestedStyles: Plugin;
86
/** Handles :hover, :focus, :active pseudo-classes */
87
resolveInteractionStyles: Plugin;
88
/** Processes @media query styles */
89
resolveMediaQueries: Plugin;
90
/** Handles :visited pseudo-class styles */
91
visited: Plugin;
92
}
93
```
94
95
**Usage Examples:**
96
97
```javascript
98
import Radium from 'radium';
99
100
// Access built-in plugins
101
const { Plugins } = Radium;
102
103
// Default plugin order
104
const defaultPlugins = [
105
Plugins.mergeStyleArray,
106
Plugins.checkProps,
107
Plugins.resolveMediaQueries,
108
Plugins.resolveInteractionStyles,
109
Plugins.keyframes,
110
Plugins.visited,
111
Plugins.removeNestedStyles,
112
Plugins.prefix,
113
Plugins.checkProps // Run again after processing
114
];
115
```
116
117
### Custom Plugins
118
119
Create custom plugins to extend Radium's functionality.
120
121
**Usage Examples:**
122
123
```javascript
124
// Simple logging plugin
125
function loggingPlugin({ componentName, style }) {
126
console.log(`Styling component: ${componentName}`, style);
127
// Return nothing - no modifications
128
}
129
130
// Style transformation plugin
131
function uppercaseTextPlugin({ style }) {
132
if (style.textTransform === 'uppercase-all') {
133
return {
134
style: {
135
...style,
136
textTransform: 'uppercase',
137
fontWeight: 'bold',
138
letterSpacing: '1px'
139
}
140
};
141
}
142
}
143
144
// Plugin that adds CSS to global stylesheet
145
function globalStylesPlugin({ addCSS, hash }) {
146
const css = `
147
.custom-utility {
148
display: flex;
149
align-items: center;
150
justify-content: center;
151
}
152
`;
153
154
const id = hash(css);
155
if (!document.getElementById(id)) {
156
const { remove } = addCSS(css);
157
// Store remove function if needed later
158
}
159
}
160
161
// Use custom plugins
162
const MyComponent = Radium({
163
plugins: [
164
Plugins.mergeStyleArray,
165
loggingPlugin,
166
uppercaseTextPlugin,
167
Plugins.checkProps,
168
Plugins.resolveMediaQueries,
169
Plugins.resolveInteractionStyles,
170
globalStylesPlugin,
171
Plugins.prefix,
172
Plugins.checkProps
173
]
174
})(BaseComponent);
175
```
176
177
### Plugin Execution Order
178
179
Plugins are executed in the order they appear in the configuration array. Each plugin receives the result of previous plugins.
180
181
**Usage Examples:**
182
183
```javascript
184
// Plugin execution order matters
185
const orderedPlugins = [
186
// 1. First, merge style arrays
187
Plugins.mergeStyleArray,
188
189
// 2. Validate initial styles
190
Plugins.checkProps,
191
192
// 3. Process special style objects that create new styles
193
Plugins.resolveMediaQueries,
194
Plugins.resolveInteractionStyles,
195
Plugins.keyframes,
196
Plugins.visited,
197
198
// 4. Extract nested styles
199
Plugins.removeNestedStyles,
200
201
// 5. Add vendor prefixes
202
Plugins.prefix,
203
204
// 6. Final validation
205
Plugins.checkProps
206
];
207
```
208
209
### Plugin Development
210
211
Guidelines for developing custom plugins.
212
213
```javascript { .api }
214
/**
215
* Plugin development template
216
*/
217
function customPlugin({
218
componentName,
219
config,
220
props,
221
style,
222
addCSS,
223
getState,
224
setState,
225
isNestedStyle,
226
mergeStyles
227
}) {
228
// 1. Check if plugin should run
229
if (!shouldProcessStyle(style)) {
230
return; // No modifications
231
}
232
233
// 2. Process style object
234
const processedStyle = processStyle(style);
235
236
// 3. Add any necessary CSS
237
if (needsGlobalCSS(processedStyle)) {
238
addCSS(generateCSS(processedStyle));
239
}
240
241
// 4. Return modifications
242
return {
243
style: processedStyle,
244
props: {
245
...props,
246
'data-processed': true
247
}
248
};
249
}
250
```
251
252
**Usage Examples:**
253
254
```javascript
255
// Responsive utilities plugin
256
function responsiveUtilitiesPlugin({ style, addCSS, hash }) {
257
const responsiveProps = ['responsiveWidth', 'responsiveHeight'];
258
const hasResponsiveProps = responsiveProps.some(prop => style[prop]);
259
260
if (!hasResponsiveProps) return;
261
262
const newStyle = { ...style };
263
264
if (style.responsiveWidth) {
265
const breakpoints = style.responsiveWidth;
266
Object.keys(breakpoints).forEach(breakpoint => {
267
const css = `
268
@media (min-width: ${breakpoint}) {
269
.responsive-width-${hash(breakpoint)} {
270
width: ${breakpoints[breakpoint]};
271
}
272
}
273
`;
274
addCSS(css);
275
});
276
277
newStyle.className = `responsive-width-${hash(JSON.stringify(breakpoints))}`;
278
delete newStyle.responsiveWidth;
279
}
280
281
return { style: newStyle };
282
}
283
```
284
285
### Plugin Configuration
286
287
Plugins can be configured globally or per-component.
288
289
**Usage Examples:**
290
291
```javascript
292
// Global plugin configuration
293
const GlobalRadium = Radium({
294
plugins: [
295
...Radium.Plugins,
296
customPlugin
297
]
298
});
299
300
// Per-component configuration
301
const SpecialComponent = Radium({
302
plugins: [
303
Plugins.mergeStyleArray,
304
specialComponentPlugin,
305
Plugins.prefix
306
]
307
})(BaseComponent);
308
309
// Runtime configuration via props
310
<MyComponent
311
radiumConfig={{
312
plugins: [...customPlugins]
313
}}
314
/>
315
```
316
317
## Built-in Plugin Details
318
319
### mergeStyleArray
320
321
Intelligently merges arrays of style objects with deep merging for nested styles.
322
323
```javascript { .api }
324
interface MergeStyleArrayPlugin {
325
/** Processes style arrays into single style object */
326
(config: PluginConfig): PluginResult;
327
}
328
```
329
330
### checkProps
331
332
Validates style properties and usage patterns, warning about common issues.
333
334
```javascript { .api }
335
interface CheckPropsPlugin {
336
/** Validates style objects and usage patterns */
337
(config: PluginConfig): void;
338
}
339
```
340
341
### resolveMediaQueries
342
343
Processes `@media` query styles and applies them based on current media conditions.
344
345
```javascript { .api }
346
interface ResolveMediaQueriesPlugin {
347
/** Processes @media query styles */
348
(config: PluginConfig): PluginResult;
349
}
350
```
351
352
### resolveInteractionStyles
353
354
Handles `:hover`, `:focus`, and `:active` pseudo-class styles by setting up event listeners.
355
356
```javascript { .api }
357
interface ResolveInteractionStylesPlugin {
358
/** Handles pseudo-class styles */
359
(config: PluginConfig): PluginResult;
360
}
361
```
362
363
### prefix
364
365
Adds vendor prefixes to CSS properties and values based on browser detection.
366
367
```javascript { .api }
368
interface PrefixPlugin {
369
/** Adds vendor prefixes to styles */
370
(config: PluginConfig): PluginResult;
371
}
372
```
373
374
## Types
375
376
```javascript { .api }
377
interface Plugin {
378
(config: PluginConfig): PluginResult | void;
379
}
380
381
interface PluginConfig {
382
componentName: string;
383
config: RadiumConfig;
384
props: object;
385
style: object;
386
addCSS: (css: string) => { remove: () => void };
387
appendImportantToEachValue: (style: object) => object;
388
cssRuleSetToString: (selector: string, rules: object, userAgent?: string) => string;
389
getComponentField: (key: string) => any;
390
getGlobalState: (key: string) => any;
391
getState: (stateKey: string, elementKey?: string) => any;
392
hash: (data: string) => string;
393
isNestedStyle: (value: any) => boolean;
394
mergeStyles: (styles: object[]) => object;
395
setState: (stateKey: string, value: any, elementKey?: string) => void;
396
ExecutionEnvironment: {
397
canUseEventListeners: boolean;
398
canUseDOM: boolean;
399
};
400
}
401
402
interface PluginResult {
403
componentFields?: object;
404
globalState?: object;
405
props?: object;
406
style?: object;
407
}
408
```