wallpaper-engine 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +337 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# wallpaper-engine
|
|
4
|
+
|
|
5
|
+
TypeScript type definitions, a Vite plugin, and runtime helpers for building [Wallpaper Engine](https://www.wallpaperengine.io/) web wallpapers.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/wallpaper-engine)
|
|
8
|
+
[](https://github.com/ShadowNineX/wallpaper-engine/actions)
|
|
9
|
+
[](https://codecov.io/gh/ShadowNineX/wallpaper-engine)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
|
|
12
|
+
[:package: Installation](#installation) · [:electric_plug: Vite Plugin](#vite-plugin) · [:muscle: Strong Typing](#strong-property-typing) · [:wrench: Helpers](#helpers) · [:window: Window Augmentation](#window-augmentation) · [:books: Type Reference](#full-type-reference)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
- **Full type coverage** for the entire Wallpaper Engine Web API — property listeners, media integration, audio, iCUE/LED plugins, and `window` augmentation
|
|
17
|
+
- **Vite plugin** that auto-generates `project.json` at build time with full IntelliSense on your property definitions
|
|
18
|
+
- **Strong inference** — define your properties once and TypeScript automatically types every key in `applyUserProperties`
|
|
19
|
+
- **Tree-shakeable helpers** for color conversion, audio processing, file URLs, LED encoding, and FPS-limited animation loops
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## <a id="installation"></a>:package: Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bun add wallpaper-engine
|
|
27
|
+
# or
|
|
28
|
+
npm install wallpaper-engine
|
|
29
|
+
# or
|
|
30
|
+
pnpm add wallpaper-engine
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Vite is an optional peer dependency, required only if you use `wallpaper-engine/plugin`:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
bun add -d vite
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## <a id="package-exports"></a>:inbox_tray: Package Exports
|
|
42
|
+
|
|
43
|
+
| Import path | Contents |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `wallpaper-engine` | All TypeScript types + `window` augmentation |
|
|
46
|
+
| `wallpaper-engine/plugin` | Vite plugin, property builders, `WallpaperUserPropertiesOf<T>` |
|
|
47
|
+
| `wallpaper-engine/helpers` | Runtime utility functions |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## <a id="vite-plugin"></a>:electric_plug: Vite Plugin
|
|
52
|
+
|
|
53
|
+
The plugin emits a `project.json` asset alongside your build so Wallpaper Engine can load the wallpaper without any manual file maintenance.
|
|
54
|
+
|
|
55
|
+
### Basic setup
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// vite.config.ts
|
|
59
|
+
import { defineConfig } from 'vite';
|
|
60
|
+
import { wallpaperEnginePlugin, colorProperty, sliderProperty, boolProperty } from 'wallpaper-engine/plugin';
|
|
61
|
+
|
|
62
|
+
export default defineConfig({
|
|
63
|
+
plugins: [
|
|
64
|
+
wallpaperEnginePlugin({
|
|
65
|
+
title: 'My Wallpaper',
|
|
66
|
+
supportsAudioProcessing: true,
|
|
67
|
+
properties: {
|
|
68
|
+
bgcolor: colorProperty({ text: 'Background Color', value: '1 1 1' }),
|
|
69
|
+
speed: sliderProperty({ text: 'Speed', value: 1, min: 0, max: 10 }),
|
|
70
|
+
showClock: boolProperty({ text: 'Show Clock', value: true }),
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This outputs a `project.json` alongside your build:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"file": "index.html",
|
|
82
|
+
"title": "My Wallpaper",
|
|
83
|
+
"type": "web",
|
|
84
|
+
"supportsaudioprocessing": true,
|
|
85
|
+
"general": {
|
|
86
|
+
"properties": {
|
|
87
|
+
"bgcolor": { "type": "color", "text": "Background Color", "value": "1 1 1", "index": 0, "order": 0 },
|
|
88
|
+
"speed": { "type": "slider", "text": "Speed", "value": 1, "index": 1, "order": 1, "min": 0, "max": 10 },
|
|
89
|
+
"showClock": { "type": "bool", "text": "Show Clock", "value": true, "index": 2, "order": 2 }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Property builder reference
|
|
96
|
+
|
|
97
|
+
| Builder | Property type | Runtime value |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `colorProperty` | Color picker | `WallpaperColorValue` — `value: "R G B"` (0–1 per channel) |
|
|
100
|
+
| `sliderProperty` | Numeric slider | `WallpaperSliderValue` — `value: number` |
|
|
101
|
+
| `boolProperty` | Checkbox | `WallpaperBoolValue` — `value: boolean` |
|
|
102
|
+
| `comboProperty` | Dropdown | `WallpaperComboValue` — `value: string` (hidden key), `text: string` (label) |
|
|
103
|
+
| `textInputProperty` | Text input | `WallpaperTextValue` — `value: string` |
|
|
104
|
+
| `fileProperty` | File picker | `WallpaperFileValue` — `value: string` (path, prefix with `file:///`) |
|
|
105
|
+
| `directoryProperty` | Directory picker | `WallpaperDirectoryValue` — `value: string` (path) |
|
|
106
|
+
|
|
107
|
+
### Localization
|
|
108
|
+
|
|
109
|
+
Property labels starting with `ui_` are resolved against the localization map:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
wallpaperEnginePlugin({
|
|
113
|
+
title: 'My Wallpaper',
|
|
114
|
+
properties: {
|
|
115
|
+
bgcolor: colorProperty({ text: 'ui_bgcolor', value: '0 0 0' }),
|
|
116
|
+
},
|
|
117
|
+
localization: {
|
|
118
|
+
'en-us': { 'ui_bgcolor': 'Background Color' },
|
|
119
|
+
'de-de': { 'ui_bgcolor': 'Hintergrundfarbe' },
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## <a id="strong-property-typing"></a>:muscle: Strong Property Typing
|
|
127
|
+
|
|
128
|
+
Define your properties in a dedicated file, then import it in both `vite.config.ts` and your wallpaper source. `WallpaperUserPropertiesOf<T>` maps each definition to its exact runtime value type automatically.
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
// src/properties.ts
|
|
132
|
+
import { colorProperty, sliderProperty, boolProperty } from 'wallpaper-engine/plugin';
|
|
133
|
+
|
|
134
|
+
export const myProperties = {
|
|
135
|
+
bgcolor: colorProperty({ text: 'Background Color', value: '0 0 0' }),
|
|
136
|
+
speed: sliderProperty({ text: 'Speed', value: 1, min: 0, max: 5 }),
|
|
137
|
+
showClock: boolProperty({ text: 'Show Clock', value: true }),
|
|
138
|
+
};
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
// vite.config.ts
|
|
143
|
+
import { wallpaperEnginePlugin } from 'wallpaper-engine/plugin';
|
|
144
|
+
import { myProperties } from './src/properties';
|
|
145
|
+
|
|
146
|
+
export default defineConfig({
|
|
147
|
+
plugins: [wallpaperEnginePlugin({ title: 'My Wallpaper', properties: myProperties })],
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
// src/wallpaper.ts
|
|
153
|
+
import type { WallpaperUserPropertiesOf } from 'wallpaper-engine/plugin';
|
|
154
|
+
import type { myProperties } from './properties';
|
|
155
|
+
import { wallpaperColorToRgb } from 'wallpaper-engine/helpers';
|
|
156
|
+
|
|
157
|
+
type MyProps = WallpaperUserPropertiesOf<typeof myProperties>;
|
|
158
|
+
// → { bgcolor: WallpaperColorValue; speed: WallpaperSliderValue; showClock: WallpaperBoolValue }
|
|
159
|
+
|
|
160
|
+
window.wallpaperPropertyListener = {
|
|
161
|
+
applyUserProperties(props: Partial<MyProps>) {
|
|
162
|
+
if (props.bgcolor) document.body.style.background = wallpaperColorToRgb(props.bgcolor.value);
|
|
163
|
+
if (props.speed) setSpeed(props.speed.value); // inferred as number ✓
|
|
164
|
+
if (props.showClock) toggle(props.showClock.value); // inferred as boolean ✓
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## <a id="helpers"></a>:wrench: Helpers
|
|
172
|
+
|
|
173
|
+
All helpers are side-effect-free and individually tree-shakeable.
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import {
|
|
177
|
+
parseWallpaperColor,
|
|
178
|
+
wallpaperColorToRgb,
|
|
179
|
+
wallpaperColorToHex,
|
|
180
|
+
toFileUrl,
|
|
181
|
+
clampAudio,
|
|
182
|
+
leftChannel,
|
|
183
|
+
rightChannel,
|
|
184
|
+
encodeCanvasForLed,
|
|
185
|
+
createFpsLimiter,
|
|
186
|
+
} from 'wallpaper-engine/helpers';
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Color
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
// "R G B" string (0–1 per channel) → { r, g, b } (0–255)
|
|
193
|
+
const { r, g, b } = parseWallpaperColor(props.bgcolor.value);
|
|
194
|
+
|
|
195
|
+
// → CSS "rgb(255,128,0)"
|
|
196
|
+
el.style.color = wallpaperColorToRgb(props.bgcolor.value);
|
|
197
|
+
|
|
198
|
+
// → CSS "#ff8000"
|
|
199
|
+
el.style.color = wallpaperColorToHex(props.bgcolor.value);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Files
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
// Prefix a WE path with file:/// before using it as an <img> or <video> src
|
|
206
|
+
img.src = toFileUrl(props.myimage.value);
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Audio
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
window.wallpaperRegisterAudioListener((raw) => {
|
|
213
|
+
const audio = clampAudio(raw); // clamp all 128 values to 0–1
|
|
214
|
+
const left = leftChannel(audio); // indices 0–63 (bass → treble)
|
|
215
|
+
const right = rightChannel(audio); // indices 64–127 (bass → treble)
|
|
216
|
+
renderBars(left, right);
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
> [!IMPORTANT]
|
|
221
|
+
> **Always use `window.wallpaperRegisterAudioListener`, not `globalThis.`.**
|
|
222
|
+
> Wallpaper Engine scans your compiled JS for this exact call to detect that the wallpaper uses audio and automatically sets `"supportsaudioprocessing": true` in its internal `project.json`. Without that flag, WE will **not** send audio data in live desktop mode (the editor preview always sends audio regardless, which can mask the problem).
|
|
223
|
+
>
|
|
224
|
+
> If audio works in the WE editor but not as a live wallpaper, open the wallpaper in the WE editor and click **Edit → Save** to force WE to write the updated `project.json`. After saving, re-apply the wallpaper as your desktop background.
|
|
225
|
+
|
|
226
|
+
### LED / RGB
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
// Encode a canvas as the RGB byte string expected by setAllDevicesByImageData
|
|
230
|
+
const canvas = document.getElementById('RGBCanvas') as HTMLCanvasElement;
|
|
231
|
+
const encoded = encodeCanvasForLed(canvas);
|
|
232
|
+
window.wpPlugins.led.setAllDevicesByImageData(encoded, canvas.width, canvas.height);
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### FPS-limited animation loop
|
|
236
|
+
|
|
237
|
+
Mirrors the FPS cap delivered by `applyGeneralProperties`. Pass `0` for unlimited.
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
const loop = createFpsLimiter((dt) => renderFrame(dt));
|
|
241
|
+
|
|
242
|
+
window.wallpaperPropertyListener = {
|
|
243
|
+
applyGeneralProperties(props) {
|
|
244
|
+
if (props.fps !== undefined) loop.setLimit(props.fps);
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
window.onload = () => loop.start();
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## <a id="window-augmentation"></a>:window: Window Augmentation
|
|
254
|
+
|
|
255
|
+
If you're not using Vite or don't need the plugin, the main `wallpaper-engine` entry is all you need. A single side-effect import augments the global `Window` interface so every WE API is fully typed — no manual `declare` blocks, no runtime cost.
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
import 'wallpaper-engine';
|
|
259
|
+
|
|
260
|
+
// All of these are now fully typed:
|
|
261
|
+
window.wallpaperPropertyListener = { ... };
|
|
262
|
+
window.wallpaperRegisterAudioListener((audio) => { ... });
|
|
263
|
+
window.wallpaperRequestRandomFileForProperty('mydir');
|
|
264
|
+
window.wallpaperPluginListener = { onPluginLoaded(name, version) { ... } };
|
|
265
|
+
window.wpPlugins.led.setAllDevicesByImageData(encoded, w, h);
|
|
266
|
+
window.cue.setLedsColorsAsync(deviceIndex, leds);
|
|
267
|
+
|
|
268
|
+
// Media integration
|
|
269
|
+
window.wallpaperRegisterMediaPropertiesListener((e) => { /* e.title, e.artist, ... */ });
|
|
270
|
+
window.wallpaperRegisterMediaPlaybackListener((e) => { /* e.state */ });
|
|
271
|
+
window.wallpaperRegisterMediaThumbnailListener((e) => { /* e.thumbnail (base64 PNG) */ });
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The import is erased at compile time — nothing is added to your bundle.
|
|
275
|
+
|
|
276
|
+
Two alternatives that also work without an `import` in your source:
|
|
277
|
+
|
|
278
|
+
**`tsconfig.json`** — applies the augmentation project-wide, no import needed anywhere:
|
|
279
|
+
```json
|
|
280
|
+
{
|
|
281
|
+
"compilerOptions": {
|
|
282
|
+
"types": ["wallpaper-engine"]
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Triple-slash reference** — per-file, useful if you only want types in specific files:
|
|
288
|
+
```ts
|
|
289
|
+
/// <reference types="wallpaper-engine" />
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## <a id="full-type-reference"></a>:books: Full Type Reference
|
|
295
|
+
|
|
296
|
+
All types are exported from `wallpaper-engine` (main entry).
|
|
297
|
+
|
|
298
|
+
### Property definition types (`project.json`)
|
|
299
|
+
|
|
300
|
+
`WallpaperColorProperty` · `WallpaperSliderProperty` · `WallpaperBoolProperty` · `WallpaperComboProperty` · `WallpaperTextInputProperty` · `WallpaperFileProperty` · `WallpaperDirectoryProperty` · `WallpaperPropertyDefinition` · `WallpaperProject` · `WallpaperProjectGeneral` · `WallpaperLocalization`
|
|
301
|
+
|
|
302
|
+
### Runtime value types (`applyUserProperties`)
|
|
303
|
+
|
|
304
|
+
`WallpaperColorValue` · `WallpaperSliderValue` · `WallpaperBoolValue` · `WallpaperComboValue` · `WallpaperTextValue` · `WallpaperFileValue` · `WallpaperDirectoryValue` · `WallpaperUserProperties` · `WallpaperGeneralProperties`
|
|
305
|
+
|
|
306
|
+
### Listener interfaces
|
|
307
|
+
|
|
308
|
+
`WallpaperPropertyListener` · `WallpaperPluginListener`
|
|
309
|
+
|
|
310
|
+
### Media integration
|
|
311
|
+
|
|
312
|
+
`WallpaperMediaStatusEvent` · `WallpaperMediaPropertiesEvent` · `WallpaperMediaThumbnailEvent` · `WallpaperMediaPlaybackEvent` · `WallpaperMediaPlaybackState` · `WallpaperMediaTimelineEvent`
|
|
313
|
+
|
|
314
|
+
### iCUE / LED
|
|
315
|
+
|
|
316
|
+
`WallpaperCuePlugin` · `WallpaperLedPlugin` · `CueDeviceInfo` · `CueLedColor` · `CueLedPosition` · `CueProtocolDetails`
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## <a id="building"></a>:building_construction: Building
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
bun run build # production build (ESM + CJS + .d.ts)
|
|
324
|
+
bun run dev # watch mode
|
|
325
|
+
bun run typecheck # type-check without emitting
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Output goes to `dist/` with the following structure:
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
dist/
|
|
332
|
+
index.js / index.cjs / index.d.ts
|
|
333
|
+
helpers.js / helpers.cjs / helpers.d.ts
|
|
334
|
+
plugin/
|
|
335
|
+
index.js / index.cjs / index.d.ts
|
|
336
|
+
```
|
|
337
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallpaper-engine",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "TypeScript types, Vite plugin, and runtime helpers for Wallpaper Engine web wallpapers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wallpaper-engine",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"typecheck": "tsc --noEmit",
|
|
52
52
|
"test": "vitest",
|
|
53
53
|
"test:run": "vitest run",
|
|
54
|
-
"prepublishOnly": "bun run --cwd ../.. build"
|
|
54
|
+
"prepublishOnly": "bun run --cwd ../.. build && node -e \"require('fs').copyFileSync('../../README.md', 'README.md')\""
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"vite": ">=5.0.0"
|