wallpaper-engine 1.0.1 → 1.0.2

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