@fluxlay/react 1.1.0 → 1.1.1

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 CHANGED
@@ -82,10 +82,10 @@ function Wallpaper() {
82
82
  }
83
83
  ```
84
84
 
85
- | Field | Type | Description |
86
- |-------|------|-------------|
87
- | `rms` | `number` | RMS (Root Mean Square) volume level (0.0 – 1.0). |
88
- | `peak` | `number` | Peak volume level (0.0 – 1.0). |
85
+ | Field | Type | Description |
86
+ | ---------- | ---------- | ------------------------------------------------------------------------------- |
87
+ | `rms` | `number` | RMS (Root Mean Square) volume level (0.0 – 1.0). |
88
+ | `peak` | `number` | Peak volume level (0.0 – 1.0). |
89
89
  | `spectrum` | `number[]` | Frequency spectrum split into 32 logarithmically-scaled bands (0.0 – 1.0 each). |
90
90
 
91
91
  ### `useMediaMetadata()`
@@ -115,16 +115,16 @@ sdk:
115
115
  interval_ms: 1000
116
116
  ```
117
117
 
118
- | Field | Type | Description |
119
- |-------|------|-------------|
120
- | `title` | `string \| null` | Track title. |
121
- | `artist` | `string \| null` | Artist name. |
122
- | `album` | `string \| null` | Album name. |
123
- | `artwork` | `string \| null` | Artwork as a data URL (`data:image/...;base64,...`). |
124
- | `duration` | `number \| null` | Track duration in seconds. |
125
- | `elapsedTime` | `number \| null` | Elapsed playback time in seconds. |
126
- | `playbackRate` | `number \| null` | Playback rate (0.0 = paused, 1.0 = playing). |
127
- | `isPlaying` | `boolean` | Whether media is currently playing. |
118
+ | Field | Type | Description |
119
+ | -------------- | ---------------- | ---------------------------------------------------- |
120
+ | `title` | `string \| null` | Track title. |
121
+ | `artist` | `string \| null` | Artist name. |
122
+ | `album` | `string \| null` | Album name. |
123
+ | `artwork` | `string \| null` | Artwork as a data URL (`data:image/...;base64,...`). |
124
+ | `duration` | `number \| null` | Track duration in seconds. |
125
+ | `elapsedTime` | `number \| null` | Elapsed playback time in seconds. |
126
+ | `playbackRate` | `number \| null` | Playback rate (0.0 = paused, 1.0 = playing). |
127
+ | `isPlaying` | `boolean` | Whether media is currently playing. |
128
128
 
129
129
  ### `useShell(commandId, options?)`
130
130
 
@@ -135,20 +135,20 @@ import { useShell } from "@fluxlay/react";
135
135
 
136
136
  function Wallpaper() {
137
137
  const { result, isRunning } = useShell("my-command", {
138
- refreshInterval: 5000, // re-run every 5 seconds
138
+ refreshInterval: 5000 // re-run every 5 seconds
139
139
  });
140
140
  return <pre>{result?.stdout}</pre>;
141
141
  }
142
142
  ```
143
143
 
144
- | Option | Type | Default | Description |
145
- |--------|------|---------|-------------|
146
- | `refreshInterval` | `number` | `30000` | Auto-refresh interval in ms. `0` to disable. |
147
- | `showStdout` | `boolean` | `true` | Write stdout to the linked terminal. |
148
- | `showStderr` | `boolean` | `false` | Write stderr to the linked terminal. |
149
- | `terminal` | `TerminalInstance` | — | Terminal instance from `useTerminal`. |
150
- | `columns` | `number` | — | Pseudo-terminal column width. |
151
- | `lines` | `number` | — | Pseudo-terminal row height. |
144
+ | Option | Type | Default | Description |
145
+ | ----------------- | ------------------ | ------- | -------------------------------------------- |
146
+ | `refreshInterval` | `number` | `30000` | Auto-refresh interval in ms. `0` to disable. |
147
+ | `showStdout` | `boolean` | `true` | Write stdout to the linked terminal. |
148
+ | `showStderr` | `boolean` | `false` | Write stderr to the linked terminal. |
149
+ | `terminal` | `TerminalInstance` | — | Terminal instance from `useTerminal`. |
150
+ | `columns` | `number` | — | Pseudo-terminal column width. |
151
+ | `lines` | `number` | — | Pseudo-terminal row height. |
152
152
 
153
153
  Returns `{ execute, isRunning, error, result }`.
154
154
 
@@ -162,18 +162,18 @@ import { useTerminal, useShell, TerminalThemes } from "@fluxlay/react";
162
162
  function Wallpaper() {
163
163
  const { terminalRef, instance } = useTerminal({
164
164
  fontSize: 13,
165
- theme: TerminalThemes.tokyoNight,
165
+ theme: TerminalThemes.tokyoNight
166
166
  });
167
167
  useShell("my-command", { terminal: instance });
168
168
  return <div ref={terminalRef} />;
169
169
  }
170
170
  ```
171
171
 
172
- | Option | Type | Default | Description |
173
- |--------|------|---------|-------------|
174
- | `fontSize` | `number` | `12` | Font size in pixels. |
175
- | `fontFamily` | `string` | system monospace | CSS font-family string. |
176
- | `theme` | `ITheme` | `TerminalThemes.dark.default` | xterm color theme. |
172
+ | Option | Type | Default | Description |
173
+ | ------------ | -------- | ----------------------------- | ----------------------- |
174
+ | `fontSize` | `number` | `12` | Font size in pixels. |
175
+ | `fontFamily` | `string` | system monospace | CSS font-family string. |
176
+ | `theme` | `ITheme` | `TerminalThemes.dark.default` | xterm color theme. |
177
177
 
178
178
  Returns `{ terminalRef, instance }`.
179
179
 
@@ -192,17 +192,17 @@ console.log(result.stdout);
192
192
 
193
193
  Pre-built xterm color themes to pass to `useTerminal`.
194
194
 
195
- | Key | Variants |
196
- |-----|----------|
197
- | `dark` | `default`, `modern` |
198
- | `light` | `default`, `modern` |
199
- | `nord` | — |
200
- | `dracula` | — |
201
- | `gruvbox` | `dark`, `light` |
202
- | `solarized` | `dark`, `light` |
203
- | `oneDark` | — |
195
+ | Key | Variants |
196
+ | ------------ | --------------------------------------- |
197
+ | `dark` | `default`, `modern` |
198
+ | `light` | `default`, `modern` |
199
+ | `nord` | — |
200
+ | `dracula` | — |
201
+ | `gruvbox` | `dark`, `light` |
202
+ | `solarized` | `dark`, `light` |
203
+ | `oneDark` | — |
204
204
  | `catppuccin` | `latte`, `frappe`, `macchiato`, `mocha` |
205
- | `monokaiPro` | — |
206
- | `tokyoNight` | — |
207
- | `nightOwl` | — |
208
- | `everforest` | `dark`, `light` |
205
+ | `monokaiPro` | — |
206
+ | `tokyoNight` | — |
207
+ | `nightOwl` | — |
208
+ | `everforest` | `dark`, `light` |
@@ -0,0 +1,383 @@
1
+ import * as _$react from "react";
2
+ import { FitAddon } from "@xterm/addon-fit";
3
+ import * as _$_xterm_xterm0 from "@xterm/xterm";
4
+ import { ITheme, Terminal } from "@xterm/xterm";
5
+ //#region src/transport/index.d.ts
6
+ /** The result returned after executing a shell command. */
7
+ interface ShellResult {
8
+ /** Standard output produced by the command. */
9
+ stdout: string;
10
+ /** Standard error produced by the command. */
11
+ stderr: string;
12
+ /** Exit status code of the process, or `null` if the process was terminated by a signal. */
13
+ statusCode: number | null;
14
+ /** Whether the command exited successfully (status code 0). */
15
+ success: boolean;
16
+ /** Signal number that terminated the process, or `null` if it exited normally. */
17
+ signal: number | null;
18
+ }
19
+ /** System audio information streamed from the Fluxlay backend. */
20
+ interface AudioInfo {
21
+ /** RMS (Root Mean Square) volume level (0.0 - 1.0). */
22
+ rms: number;
23
+ /** Peak volume level (0.0 - 1.0). */
24
+ peak: number;
25
+ /** Frequency spectrum split into logarithmically-scaled bands (0.0 - 1.0 each). The number of bands is configurable via `useAudio({ numBands })`. */
26
+ spectrum: number[];
27
+ }
28
+ /** System hardware and performance information streamed from the Fluxlay backend. */
29
+ interface SystemMonitorInfo {
30
+ /** Overall CPU usage percentage (0.0 - 100.0). */
31
+ cpuUsage: number;
32
+ /** Per-core CPU usage percentages (0.0 - 100.0 each). */
33
+ cpuPerCore: number[];
34
+ /** Per-core CPU frequency in MHz. */
35
+ cpuFrequencyMhz: number[];
36
+ /** Total physical memory in bytes. */
37
+ memoryTotal: number;
38
+ /** Used physical memory in bytes. */
39
+ memoryUsed: number;
40
+ /** Memory usage percentage (0.0 - 100.0). */
41
+ memoryUsage: number;
42
+ /** Total swap space in bytes. */
43
+ swapTotal: number;
44
+ /** Used swap space in bytes. */
45
+ swapUsed: number;
46
+ /** Swap usage percentage (0.0 - 100.0). */
47
+ swapUsage: number;
48
+ /** Battery charge level (0.0 - 100.0), or `null` if no battery is present. */
49
+ batteryLevel: number | null;
50
+ /** Whether the battery is currently charging, or `null` if no battery is present. */
51
+ batteryCharging: boolean | null;
52
+ /** Network receive speed in bytes per second. */
53
+ networkRxBytesPerSec: number;
54
+ /** Network transmit speed in bytes per second. */
55
+ networkTxBytesPerSec: number;
56
+ /** Disk read speed in bytes per second. */
57
+ diskReadBytesPerSec: number;
58
+ /** Disk write speed in bytes per second. */
59
+ diskWriteBytesPerSec: number;
60
+ /** Number of running processes. */
61
+ processCount: number;
62
+ /** System uptime in seconds. */
63
+ uptimeSecs: number;
64
+ /** Load average for the past 1, 5, and 15 minutes. */
65
+ loadAverage: [number, number, number];
66
+ /** Per-disk storage information. */
67
+ disks: DiskInfo[];
68
+ /** System hostname. */
69
+ hostname: string;
70
+ /** Operating system name and version. */
71
+ osName: string;
72
+ /** CPU model name (e.g. "Apple M2 Pro"). */
73
+ cpuBrand: string;
74
+ /** Number of physical CPU cores. */
75
+ physicalCoreCount: number;
76
+ /** Number of logical CPU cores (threads). */
77
+ logicalCoreCount: number;
78
+ /** CPU architecture (e.g. "aarch64", "x86_64"). */
79
+ cpuArch: string;
80
+ /** Kernel version string. */
81
+ kernelVersion: string;
82
+ }
83
+ /** Storage information for a single disk/volume. */
84
+ interface DiskInfo {
85
+ /** Mount point path (e.g. "/", "/home"). */
86
+ mountPoint: string;
87
+ /** Disk/volume name. */
88
+ name: string;
89
+ /** Total capacity in bytes. */
90
+ totalBytes: number;
91
+ /** Available (free) space in bytes. */
92
+ availableBytes: number;
93
+ /** Usage percentage (0.0 - 100.0). */
94
+ usage: number;
95
+ }
96
+ /** Media metadata information for the currently playing track. */
97
+ interface MediaMetadataInfo {
98
+ /** Track title, or `null` if unavailable. */
99
+ title: string | null;
100
+ /** Artist name, or `null` if unavailable. */
101
+ artist: string | null;
102
+ /** Album name, or `null` if unavailable. */
103
+ album: string | null;
104
+ /** Artwork as a data URL (e.g. "data:image/jpeg;base64,..."), or `null` if unavailable. */
105
+ artwork: string | null;
106
+ /** Track duration in seconds, or `null` if unavailable. */
107
+ duration: number | null;
108
+ /** Elapsed playback time in seconds, or `null` if unavailable. */
109
+ elapsedTime: number | null;
110
+ /** Playback rate (0.0 = paused, 1.0 = playing), or `null` if unavailable. */
111
+ playbackRate: number | null;
112
+ /** Whether media is currently playing. */
113
+ isPlaying: boolean;
114
+ }
115
+ /** Custom property values set by the end user via the Fluxlay settings UI. */
116
+ type PropertyValues = Record<string, number | string | boolean>;
117
+ //#endregion
118
+ //#region src/hooks/use-audio.d.ts
119
+ /** Options for the audio stream. */
120
+ interface AudioOptions {
121
+ /** Number of frequency spectrum bands. Default is 32. */
122
+ numBands?: number;
123
+ }
124
+ /**
125
+ * React hook that subscribes to system audio information streamed from
126
+ * the Fluxlay backend.
127
+ *
128
+ * Returns the current audio state including RMS volume, peak level,
129
+ * and frequency spectrum data, useful for building audio visualizers.
130
+ *
131
+ * @param options - Optional audio configuration.
132
+ * @returns The current audio info as `{ rms, peak, spectrum }`.
133
+ */
134
+ declare function useAudio(options?: AudioOptions): AudioInfo;
135
+ //#endregion
136
+ //#region src/hooks/use-media-metadata.d.ts
137
+ /** Options for the media metadata stream. */
138
+ interface MediaMetadataOptions {
139
+ /** Polling interval in milliseconds. Default is 1000. */
140
+ intervalMs?: number;
141
+ }
142
+ /**
143
+ * React hook that subscribes to media metadata streamed from the
144
+ * Fluxlay backend.
145
+ *
146
+ * Returns information about the currently playing track from system
147
+ * media players (e.g. Spotify, Apple Music), including title, artist,
148
+ * album artwork, and playback state — useful for building
149
+ * music-reactive wallpapers.
150
+ *
151
+ * @param options - Optional media metadata configuration.
152
+ * @returns The current media metadata info.
153
+ */
154
+ declare function useMediaMetadata(options?: MediaMetadataOptions): MediaMetadataInfo;
155
+ //#endregion
156
+ //#region src/hooks/use-mouse.d.ts
157
+ /**
158
+ * React hook that subscribes to global mouse position events streamed from
159
+ * the Fluxlay backend.
160
+ *
161
+ * The Y axis is inverted so that positive values point upward, matching a
162
+ * standard mathematical coordinate system rather than the screen coordinate
163
+ * system where Y grows downward.
164
+ *
165
+ * The subscription is scoped to the window identified by the `window_label`
166
+ * query parameter of the current URL, defaulting to `"main"`.
167
+ *
168
+ * @returns The current mouse position as `{ x, y }`.
169
+ */
170
+ declare function useMousePosition(): {
171
+ x: number;
172
+ y: number;
173
+ };
174
+ //#endregion
175
+ //#region src/hooks/use-properties.d.ts
176
+ /**
177
+ * React hook that provides the current custom property values defined
178
+ * in the wallpaper manifest and customized by the end user.
179
+ *
180
+ * Fetches initial values on mount and subscribes to real-time updates
181
+ * via the properties stream.
182
+ *
183
+ * @typeParam T - Shape of the property values object.
184
+ * @returns The current property values typed as `T`.
185
+ */
186
+ declare function useProperties<T extends PropertyValues = PropertyValues>(): T;
187
+ //#endregion
188
+ //#region src/shell.d.ts
189
+ /** Options that control how a shell command is executed. */
190
+ interface ShellOptions {
191
+ /** Number of columns (character width) of the pseudo-terminal. */
192
+ columns?: number;
193
+ /** Number of rows (line height) of the pseudo-terminal. */
194
+ lines?: number;
195
+ }
196
+ /**
197
+ * Runs a pre-declared shell command from fluxlay.yaml.
198
+ *
199
+ * @param commandId The ID of the command declared in the manifest's `shell` section.
200
+ * @param options Options for command execution.
201
+ * @returns The standard output and error of the command.
202
+ * @throws An error if the command fails or the ID is invalid.
203
+ */
204
+ declare function runShell(commandId: string, options?: ShellOptions): Promise<ShellResult>;
205
+ //#endregion
206
+ //#region src/hooks/use-terminal.d.ts
207
+ /** Options for the {@link useTerminal} hook. */
208
+ interface UseTerminalOptions {
209
+ /**
210
+ * Font size in pixels used by the terminal.
211
+ * @defaultValue 12
212
+ */
213
+ fontSize?: number;
214
+ /**
215
+ * CSS font-family string applied to the terminal.
216
+ * Defaults to a system monospace font stack.
217
+ */
218
+ fontFamily?: string;
219
+ /**
220
+ * Color theme applied to the terminal.
221
+ * @defaultValue {@link TerminalThemes.dark.default}
222
+ */
223
+ theme?: ITheme;
224
+ }
225
+ /** Holds the xterm {@link Terminal} and its associated {@link FitAddon}. */
226
+ interface TerminalInstance {
227
+ /** The underlying xterm Terminal instance. */
228
+ terminal: Terminal;
229
+ /** The FitAddon used to resize the terminal to match its container element. */
230
+ fitAddon: FitAddon;
231
+ }
232
+ /**
233
+ * React hook that creates and manages a read-only xterm terminal rendered
234
+ * inside a `<div>` element.
235
+ *
236
+ * The terminal is configured for display-only use: stdin is disabled, the
237
+ * cursor is hidden, and the scrollback buffer is removed. Custom CSS overrides
238
+ * are injected into `document.head` to make the terminal behave as an inline
239
+ * block that expands to fill its container width.
240
+ *
241
+ * The terminal is disposed and the injected styles are removed when the
242
+ * component unmounts or when `fontSize` / `fontFamily` change.
243
+ *
244
+ * @param options Display configuration for the terminal.
245
+ * @returns An object containing:
246
+ * - `terminalRef` – a React ref that must be attached to the container `<div>`.
247
+ * - `instance` – the {@link TerminalInstance} once the terminal is mounted, or `null`.
248
+ */
249
+ declare function useTerminal(options?: UseTerminalOptions): {
250
+ terminalRef: _$react.RefObject<HTMLDivElement | null>;
251
+ instance: TerminalInstance | null;
252
+ };
253
+ //#endregion
254
+ //#region src/hooks/use-shell.d.ts
255
+ /** Options for the {@link useShell} hook. */
256
+ interface UseShellOptions extends ShellOptions {
257
+ /**
258
+ * Interval in milliseconds at which the command is automatically re-executed.
259
+ * Set to `0` to disable auto-refresh.
260
+ * @defaultValue 30000
261
+ */
262
+ refreshInterval?: number;
263
+ /**
264
+ * Whether to write the command's stdout to the linked terminal.
265
+ * @defaultValue true
266
+ */
267
+ showStdout?: boolean;
268
+ /**
269
+ * Whether to write the command's stderr to the linked terminal.
270
+ * @defaultValue false
271
+ */
272
+ showStderr?: boolean;
273
+ /**
274
+ * Optional terminal instance returned by {@link useTerminal}.
275
+ * When provided, command output is rendered directly into the terminal and
276
+ * the terminal dimensions are used as the pseudo-terminal size.
277
+ */
278
+ terminal?: TerminalInstance | null;
279
+ }
280
+ /**
281
+ * React hook that executes a pre-declared Fluxlay shell command and
282
+ * optionally renders its output into an xterm terminal.
283
+ *
284
+ * The command runs once on mount and is re-executed whenever `commandId`
285
+ * changes or the `refreshInterval` elapses.
286
+ *
287
+ * @param commandId The ID of the command declared in `fluxlay.yaml`.
288
+ * @param options Configuration options for execution and display behaviour.
289
+ * @returns An object containing:
290
+ * - `execute` – manually triggers the command.
291
+ * - `isRunning` – `true` while the command is in progress.
292
+ * - `error` – error message string when the last execution failed, otherwise `null`.
293
+ * - `result` – the {@link ShellResult} of the last completed execution, or `null`.
294
+ */
295
+ declare function useShell(commandId: string, options?: UseShellOptions): {
296
+ execute: () => Promise<void>;
297
+ isRunning: boolean;
298
+ error: string | null;
299
+ result: ShellResult | null;
300
+ };
301
+ //#endregion
302
+ //#region src/hooks/use-system-monitor.d.ts
303
+ /** Polling interval options for each system monitor category (in milliseconds). */
304
+ interface SystemMonitorOptions {
305
+ /** CPU usage polling interval in ms. */
306
+ cpuIntervalMs?: number;
307
+ /** Memory usage polling interval in ms. */
308
+ memoryIntervalMs?: number;
309
+ /** Network throughput polling interval in ms. */
310
+ networkIntervalMs?: number;
311
+ /** Disk I/O polling interval in ms. */
312
+ diskIoIntervalMs?: number;
313
+ /** Disk space polling interval in ms. */
314
+ diskSpaceIntervalMs?: number;
315
+ /** Battery status polling interval in ms. */
316
+ batteryIntervalMs?: number;
317
+ /** Process count polling interval in ms. */
318
+ processIntervalMs?: number;
319
+ /** Load average polling interval in ms. */
320
+ loadAverageIntervalMs?: number;
321
+ }
322
+ /**
323
+ * React hook that subscribes to system hardware information streamed
324
+ * from the Fluxlay backend.
325
+ *
326
+ * Returns real-time system metrics including CPU usage, memory usage,
327
+ * battery status, and network throughput — useful for building
328
+ * system-reactive wallpapers (e.g. cyberpunk HUDs, hardware monitors).
329
+ *
330
+ * @param options - Optional polling interval configuration for each category.
331
+ * @returns The current system monitor info.
332
+ */
333
+ declare function useSystemMonitor(options?: SystemMonitorOptions): SystemMonitorInfo;
334
+ //#endregion
335
+ //#region src/themes/index.d.ts
336
+ /**
337
+ * Collection of pre-built xterm color themes.
338
+ *
339
+ * Pass any of these values to the `theme` option of {@link useTerminal}.
340
+ *
341
+ * @example
342
+ * ```tsx
343
+ * const { terminalRef, instance } = useTerminal({
344
+ * theme: TerminalThemes.dracula,
345
+ * });
346
+ * ```
347
+ */
348
+ declare const TerminalThemes: {
349
+ /** Dark themes with a transparent background. */readonly dark: {
350
+ /** Default dark theme using Tailwind color palette. */readonly default: _$_xterm_xterm0.ITheme; /** Modern dark theme using Slate/Rose color palette. */
351
+ readonly modern: _$_xterm_xterm0.ITheme;
352
+ }; /** Light themes. */
353
+ readonly light: {
354
+ /** Default light theme. */readonly default: _$_xterm_xterm0.ITheme; /** Modern light theme. */
355
+ readonly modern: _$_xterm_xterm0.ITheme;
356
+ }; /** Nord theme — an arctic, north-bluish color palette. */
357
+ readonly nord: _$_xterm_xterm0.ITheme; /** Dracula theme — a dark theme with vivid accent colors. */
358
+ readonly dracula: _$_xterm_xterm0.ITheme; /** Gruvbox themes — a retro groove color scheme. */
359
+ readonly gruvbox: {
360
+ /** Gruvbox dark variant. */readonly dark: _$_xterm_xterm0.ITheme; /** Gruvbox light variant. */
361
+ readonly light: _$_xterm_xterm0.ITheme;
362
+ }; /** Solarized themes — a precision color scheme with reduced brightness. */
363
+ readonly solarized: {
364
+ /** Solarized dark variant. */readonly dark: _$_xterm_xterm0.ITheme; /** Solarized light variant. */
365
+ readonly light: _$_xterm_xterm0.ITheme;
366
+ }; /** One Dark theme — based on Atom's One Dark syntax theme. */
367
+ readonly oneDark: _$_xterm_xterm0.ITheme; /** Catppuccin themes — a soothing pastel color scheme. */
368
+ readonly catppuccin: {
369
+ /** Catppuccin Latte — the light variant. */readonly latte: _$_xterm_xterm0.ITheme; /** Catppuccin Frappé — a cool medium-dark variant. */
370
+ readonly frappe: _$_xterm_xterm0.ITheme; /** Catppuccin Macchiato — a warm medium-dark variant. */
371
+ readonly macchiato: _$_xterm_xterm0.ITheme; /** Catppuccin Mocha — the darkest variant. */
372
+ readonly mocha: _$_xterm_xterm0.ITheme;
373
+ }; /** Monokai Pro theme — a refined dark theme inspired by Monokai. */
374
+ readonly monokaiPro: _$_xterm_xterm0.ITheme; /** Tokyo Night theme — a dark theme inspired by Tokyo city lights. */
375
+ readonly tokyoNight: _$_xterm_xterm0.ITheme; /** Night Owl theme — optimized for late-night coding with low brightness. */
376
+ readonly nightOwl: _$_xterm_xterm0.ITheme; /** Everforest themes — a green-tinted theme inspired by forests. */
377
+ readonly everforest: {
378
+ /** Everforest dark variant. */readonly dark: _$_xterm_xterm0.ITheme; /** Everforest light variant. */
379
+ readonly light: _$_xterm_xterm0.ITheme;
380
+ };
381
+ };
382
+ //#endregion
383
+ export { AudioOptions, MediaMetadataOptions, ShellOptions, type ShellResult, SystemMonitorOptions, TerminalInstance, TerminalThemes, UseShellOptions, UseTerminalOptions, runShell, useAudio, useMediaMetadata, useMousePosition, useProperties, useShell, useSystemMonitor, useTerminal };
package/dist/index.mjs ADDED
@@ -0,0 +1,32 @@
1
+ import{useCallback as e,useEffect as t,useRef as n,useState as r}from"react";import{FitAddon as i}from"@xterm/addon-fit";import{Terminal as a}from"@xterm/xterm";import"@xterm/xterm/css/xterm.css";var o=class{get baseUrl(){return`http://127.0.0.1:${new URLSearchParams(window.location.search).get(`fluxlay_port`)||`1421`}/v1`}pendingInvokes=new Map;async invoke(e,t){let n=new URLSearchParams(window.location.search).get(`window_label`)||`main`,r=`${e}:${n}:${JSON.stringify(t)}`;if(this.pendingInvokes.has(r))return this.pendingInvokes.get(r);let i=(async()=>{try{let r=await fetch(`${this.baseUrl}/${e}?window_label=${n}`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!r.ok)throw Error(`Failed to invoke ${e}: ${r.statusText}`);return await r.json()}finally{this.pendingInvokes.delete(r)}})();return this.pendingInvokes.set(r,i),i}subscribe(e,t,n){let r=new AbortController,i=new URLSearchParams(window.location.search).get(`window_label`)||`main`,a=new URLSearchParams({window_label:i,...n}),o=`${this.baseUrl}/${e}?${a.toString()}`;return(async()=>{try{let n=await fetch(o,{signal:r.signal});if(!n.ok||!n.body)throw Error(`Failed to subscribe to ${e}: ${n.statusText}`);let i=n.body.getReader(),a=new TextDecoder,s=``;for(;;){let{done:e,value:n}=await i.read();if(e)break;s+=a.decode(n,{stream:!0});let r=s.split(`
2
+ `);s=r.pop()||``;for(let e of r){let n=e.trim();if(n)try{t(JSON.parse(n))}catch(e){console.error(`Failed to parse NDJSON line:`,e)}}}}catch(t){t.name!==`AbortError`&&console.error(`Error in subscription to ${e}:`,t)}})(),()=>{r.abort()}}};const s=new o;function c(e){let[n,i]=r({rms:0,peak:0,spectrum:[]}),a=e?.numBands;return t(()=>{let e={};a!==void 0&&(e.num_bands=String(a));let t=s.subscribe(`audio-stream`,e=>i(e),e);return()=>{t()}},[a]),n}const l=new o;function u(e){let[n,i]=r({title:null,artist:null,album:null,artwork:null,duration:null,elapsedTime:null,playbackRate:null,isPlaying:!1}),a=e?.intervalMs;return t(()=>{let e={};a!==void 0&&(e.interval_ms=String(a));let t=l.subscribe(`media-metadata-stream`,e=>i(e),e);return()=>{t()}},[a]),n}const d=new o;function f(){let[e,n]=r({x:0,y:0});return t(()=>{let e=new URLSearchParams(window.location.search).get(`window_label`)||`main`,t=d.subscribe(`mouse-stream`,e=>{n({x:e.x,y:-e.y})},{window_label:e});return()=>{t()}},[]),e}const p=new o;function m(){let[e,n]=r({});return t(()=>{p.invoke(`properties`,{}).then(n);let e=p.subscribe(`properties-stream`,e=>n(e));return()=>{e()}},[]),e}const h=new o;async function g(e,t){return await h.invoke(`run-script`,{scriptId:e,columns:t?.columns,lines:t?.lines})}function _(i,a={}){let{showStdout:o=!0,showStderr:s=!1,refreshInterval:c=3e4,terminal:l}=a,[u,d]=r(!1),[f,p]=r(null),[m,h]=r(null),_=n(a);t(()=>{_.current=a},[a]);let v=e(async()=>{if(!u){d(!0),p(null);try{let e=_.current,t=e.columns,n=e.lines;l&&(l.fitAddon.fit(),t=l.terminal.cols,n=l.terminal.rows);let r=await g(i,{...e,columns:t,lines:n});h(r),r.success||p(`Command failed with status ${r.statusCode}: ${r.stderr}`)}catch(e){p(String(e))}finally{d(!1)}}},[i,l]);return t(()=>{if(!l||!m)return;let{terminal:e}=l;if(e.reset(),m.success){let t=``;o&&(t+=m.stdout),s&&(t+=m.stderr);let n=t.trimEnd();if(n){e.write(n);let t=n.split(`
3
+ `).length;e.resize(e.cols,Math.max(1,t))}else e.resize(e.cols,1)}else{let t=`Command failed with status ${m.statusCode}: ${m.stderr}`;e.write(`\x1b[31m${t.trimEnd()}\x1b[0m`),e.resize(e.cols,1)}},[l,m,o,s]),t(()=>{v()},[i]),t(()=>{if(!c)return;let e=setInterval(v,c);return()=>clearInterval(e)},[v,c]),{execute:v,isRunning:u,error:f,result:m}}const v=new o;function y(e){let[n,i]=r({cpuUsage:0,cpuPerCore:[],cpuFrequencyMhz:[],memoryTotal:0,memoryUsed:0,memoryUsage:0,swapTotal:0,swapUsed:0,swapUsage:0,batteryLevel:null,batteryCharging:null,networkRxBytesPerSec:0,networkTxBytesPerSec:0,diskReadBytesPerSec:0,diskWriteBytesPerSec:0,processCount:0,uptimeSecs:0,loadAverage:[0,0,0],disks:[],hostname:``,osName:``,cpuBrand:``,physicalCoreCount:0,logicalCoreCount:0,cpuArch:``,kernelVersion:``}),a=e?.cpuIntervalMs,o=e?.memoryIntervalMs,s=e?.networkIntervalMs,c=e?.diskIoIntervalMs,l=e?.diskSpaceIntervalMs,u=e?.batteryIntervalMs,d=e?.processIntervalMs,f=e?.loadAverageIntervalMs;return t(()=>{let e={};a!==void 0&&(e.cpu_interval_ms=String(a)),o!==void 0&&(e.memory_interval_ms=String(o)),s!==void 0&&(e.network_interval_ms=String(s)),c!==void 0&&(e.disk_io_interval_ms=String(c)),l!==void 0&&(e.disk_space_interval_ms=String(l)),u!==void 0&&(e.battery_interval_ms=String(u)),d!==void 0&&(e.process_interval_ms=String(d)),f!==void 0&&(e.load_average_interval_ms=String(f));let t=v.subscribe(`system-monitor-stream`,e=>i(e),e);return()=>{t()}},[a,o,s,c,l,u,d,f]),n}const b={dark:{default:{background:`#00000000`,foreground:`#ffffff`,cursor:`#00000000`,black:`#000000`,red:`#ef4444`,green:`#22c55e`,yellow:`#f59e0b`,blue:`#3b82f6`,magenta:`#a855f7`,cyan:`#06b6d4`,white:`#ffffff`,brightBlack:`#71717a`,brightRed:`#f87171`,brightGreen:`#4ade80`,brightYellow:`#fbbf24`,brightBlue:`#60a5fa`,brightMagenta:`#c084fc`,brightCyan:`#22d3ee`,brightWhite:`#ffffff`},modern:{background:`#00000000`,foreground:`#e2e8f0`,cursor:`#00000000`,black:`#1e293b`,red:`#f43f5e`,green:`#10b981`,yellow:`#f59e0b`,blue:`#3b82f6`,magenta:`#8b5cf6`,cyan:`#06b6d4`,white:`#f1f5f9`,brightBlack:`#475569`,brightRed:`#fb7185`,brightGreen:`#34d399`,brightYellow:`#fbbf24`,brightBlue:`#60a5fa`,brightMagenta:`#a78bfa`,brightCyan:`#22d3ee`,brightWhite:`#ffffff`}},light:{default:{background:`#00000000`,foreground:`#18181b`,cursor:`#00000000`,black:`#000000`,red:`#ef4444`,green:`#22c55e`,yellow:`#f59e0b`,blue:`#3b82f6`,magenta:`#a855f7`,cyan:`#06b6d4`,white:`#ffffff`,brightBlack:`#71717a`,brightRed:`#f87171`,brightGreen:`#4ade80`,brightYellow:`#fbbf24`,brightBlue:`#60a5fa`,brightMagenta:`#c084fc`,brightCyan:`#22d3ee`,brightWhite:`#ffffff`},modern:{background:`#00000000`,foreground:`#334155`,cursor:`#00000000`,black:`#0f172a`,red:`#dc2626`,green:`#16a34a`,yellow:`#d97706`,blue:`#2563eb`,magenta:`#7c3aed`,cyan:`#0891b2`,white:`#f8fafc`,brightBlack:`#64748b`,brightRed:`#ef4444`,brightGreen:`#22c55e`,brightYellow:`#f59e0b`,brightBlue:`#3b82f6`,brightMagenta:`#8b5cf6`,brightCyan:`#06b6d4`,brightWhite:`#ffffff`}},nord:{background:`#2E3440`,foreground:`#D8DEE9`,cursor:`#D8DEE9`,black:`#3B4252`,red:`#BF616A`,green:`#A3BE8C`,yellow:`#EBCB8B`,blue:`#81A1C1`,magenta:`#B48EAD`,cyan:`#88C0D0`,white:`#E5E9F0`,brightBlack:`#4C566A`,brightRed:`#BF616A`,brightGreen:`#A3BE8C`,brightYellow:`#EBCB8B`,brightBlue:`#81A1C1`,brightMagenta:`#B48EAD`,brightCyan:`#8FBCBB`,brightWhite:`#ECEFF4`},dracula:{background:`#282a36`,foreground:`#f8f8f2`,cursor:`#f8f8f2`,black:`#21222c`,red:`#ff5555`,green:`#50fa7b`,yellow:`#f1fa8c`,blue:`#bd93f9`,magenta:`#ff79c6`,cyan:`#8be9fd`,white:`#f8f8f2`,brightBlack:`#6272a4`,brightRed:`#ff6e6e`,brightGreen:`#69ff94`,brightYellow:`#ffffa5`,brightBlue:`#d6acff`,brightMagenta:`#ff92df`,brightCyan:`#a4ffff`,brightWhite:`#ffffff`},gruvbox:{dark:{background:`#282828`,foreground:`#ebdbb2`,cursor:`#ebdbb2`,black:`#282828`,red:`#cc241d`,green:`#98971a`,yellow:`#d79921`,blue:`#458588`,magenta:`#b16286`,cyan:`#689d6a`,white:`#a89984`,brightBlack:`#928374`,brightRed:`#fb4934`,brightGreen:`#b8bb26`,brightYellow:`#fabd2f`,brightBlue:`#83a598`,brightMagenta:`#d3869b`,brightCyan:`#8ec07c`,brightWhite:`#ebdbb2`},light:{background:`#fbf1c7`,foreground:`#3c3836`,cursor:`#3c3836`,black:`#fbf1c7`,red:`#cc241d`,green:`#98971a`,yellow:`#d79921`,blue:`#458588`,magenta:`#b16286`,cyan:`#689d6a`,white:`#7c6f64`,brightBlack:`#928374`,brightRed:`#9d0006`,brightGreen:`#79740e`,brightYellow:`#b57614`,brightBlue:`#076678`,brightMagenta:`#8f3f71`,brightCyan:`#427b58`,brightWhite:`#3c3836`}},solarized:{dark:{background:`#002b36`,foreground:`#839496`,cursor:`#93a1a1`,black:`#073642`,red:`#dc322f`,green:`#859900`,yellow:`#b58900`,blue:`#268bd2`,magenta:`#d33682`,cyan:`#2aa198`,white:`#eee8d5`,brightBlack:`#002b36`,brightRed:`#cb4b16`,brightGreen:`#586e75`,brightYellow:`#657b83`,brightBlue:`#839496`,brightMagenta:`#6c71c4`,brightCyan:`#93a1a1`,brightWhite:`#fdf6e3`},light:{background:`#fdf6e3`,foreground:`#657b83`,cursor:`#586e75`,black:`#073642`,red:`#dc322f`,green:`#859900`,yellow:`#b58900`,blue:`#268bd2`,magenta:`#d33682`,cyan:`#2aa198`,white:`#eee8d5`,brightBlack:`#002b36`,brightRed:`#cb4b16`,brightGreen:`#586e75`,brightYellow:`#657b83`,brightBlue:`#839496`,brightMagenta:`#6c71c4`,brightCyan:`#93a1a1`,brightWhite:`#fdf6e3`}},oneDark:{background:`#282c34`,foreground:`#abb2bf`,cursor:`#528bff`,black:`#282c34`,red:`#e06c75`,green:`#98c379`,yellow:`#e5c07b`,blue:`#61afef`,magenta:`#c678dd`,cyan:`#56b6c2`,white:`#abb2bf`,brightBlack:`#5c6370`,brightRed:`#e06c75`,brightGreen:`#98c379`,brightYellow:`#e5c07b`,brightBlue:`#61afef`,brightMagenta:`#c678dd`,brightCyan:`#56b6c2`,brightWhite:`#ffffff`},catppuccin:{latte:{background:`#eff1f5`,foreground:`#4c4f69`,cursor:`#dc8a78`,black:`#5c5f77`,red:`#d20f39`,green:`#40a02b`,yellow:`#df8e1d`,blue:`#1e66f5`,magenta:`#ea76cb`,cyan:`#179299`,white:`#acb0be`,brightBlack:`#6c6f85`,brightRed:`#d20f39`,brightGreen:`#40a02b`,brightYellow:`#df8e1d`,brightBlue:`#1e66f5`,brightMagenta:`#ea76cb`,brightCyan:`#179299`,brightWhite:`#bcc0cc`},frappe:{background:`#303446`,foreground:`#c6d0f5`,cursor:`#f2d5cf`,black:`#51576d`,red:`#e78284`,green:`#a6d189`,yellow:`#e5c890`,blue:`#8caaee`,magenta:`#f4b8e4`,cyan:`#81c8be`,white:`#b5bfe2`,brightBlack:`#626880`,brightRed:`#e78284`,brightGreen:`#a6d189`,brightYellow:`#e5c890`,brightBlue:`#8caaee`,brightMagenta:`#f4b8e4`,brightCyan:`#81c8be`,brightWhite:`#a5adce`},macchiato:{background:`#24273a`,foreground:`#cad3f5`,cursor:`#f4dbd6`,black:`#494d64`,red:`#ed8796`,green:`#a6da95`,yellow:`#eed49f`,blue:`#8aadf4`,magenta:`#f5bde6`,cyan:`#8bd5ca`,white:`#b8c0e0`,brightBlack:`#5b6078`,brightRed:`#ed8796`,brightGreen:`#a6da95`,brightYellow:`#eed49f`,brightBlue:`#8aadf4`,brightMagenta:`#f5bde6`,brightCyan:`#8bd5ca`,brightWhite:`#a5adcb`},mocha:{background:`#1e1e2e`,foreground:`#cdd6f4`,cursor:`#f5e0dc`,black:`#45475a`,red:`#f38ba8`,green:`#a6e3a1`,yellow:`#f9e2af`,blue:`#89b4fa`,magenta:`#f5c2e7`,cyan:`#94e2d5`,white:`#bac2de`,brightBlack:`#585b70`,brightRed:`#f38ba8`,brightGreen:`#a6e3a1`,brightYellow:`#f9e2af`,brightBlue:`#89b4fa`,brightMagenta:`#f5c2e7`,brightCyan:`#94e2d5`,brightWhite:`#a6adc8`}},monokaiPro:{background:`#2D2A2E`,foreground:`#FCFCFA`,cursor:`#FCFCFA`,black:`#403E41`,red:`#FF6188`,green:`#A9DC76`,yellow:`#FFD866`,blue:`#FC9867`,magenta:`#AB9DF2`,cyan:`#78DCE8`,white:`#FCFCFA`,brightBlack:`#727072`,brightRed:`#FF6188`,brightGreen:`#A9DC76`,brightYellow:`#FFD866`,brightBlue:`#FC9867`,brightMagenta:`#AB9DF2`,brightCyan:`#78DCE8`,brightWhite:`#FCFCFA`},tokyoNight:{background:`#1a1b26`,foreground:`#a9b1d6`,cursor:`#c0caf5`,black:`#32344a`,red:`#f7768e`,green:`#9ece6a`,yellow:`#e0af68`,blue:`#7aa2f7`,magenta:`#ad8ee6`,cyan:`#449dab`,white:`#787c99`,brightBlack:`#444b6a`,brightRed:`#ff7a93`,brightGreen:`#b9f27c`,brightYellow:`#ff9e64`,brightBlue:`#7da6ff`,brightMagenta:`#bb9af7`,brightCyan:`#0db9d7`,brightWhite:`#acb0d0`},nightOwl:{background:`#011627`,foreground:`#d6deeb`,cursor:`#80a4c2`,black:`#011627`,red:`#ef5350`,green:`#22da6e`,yellow:`#addb67`,blue:`#82aaff`,magenta:`#c792ea`,cyan:`#21c7a8`,white:`#ffffff`,brightBlack:`#575656`,brightRed:`#ef5350`,brightGreen:`#22da6e`,brightYellow:`#ffeb95`,brightBlue:`#82aaff`,brightMagenta:`#c792ea`,brightCyan:`#7fdbca`,brightWhite:`#ffffff`},everforest:{dark:{background:`#2b3339`,foreground:`#d3c6aa`,cursor:`#d3c6aa`,black:`#4b565c`,red:`#e67e80`,green:`#a7c080`,yellow:`#dbbc7f`,blue:`#7fbbb3`,magenta:`#d699b6`,cyan:`#83c092`,white:`#d3c6aa`,brightBlack:`#4b565c`,brightRed:`#e67e80`,brightGreen:`#a7c080`,brightYellow:`#dbbc7f`,brightBlue:`#7fbbb3`,brightMagenta:`#d699b6`,brightCyan:`#83c092`,brightWhite:`#d3c6aa`},light:{background:`#fdf6e3`,foreground:`#5c6a72`,cursor:`#5c6a72`,black:`#fdf6e3`,red:`#f85552`,green:`#8da101`,yellow:`#dfa000`,blue:`#3a94c5`,magenta:`#df69ba`,cyan:`#35a77c`,white:`#dfddc8`,brightBlack:`#5c6a72`,brightRed:`#f85552`,brightGreen:`#8da101`,brightYellow:`#dfa000`,brightBlue:`#3a94c5`,brightMagenta:`#df69ba`,brightCyan:`#35a77c`,brightWhite:`#5c6a72`}}};function x(e={}){let{fontSize:o=12,fontFamily:s=`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace`,theme:c=b.dark.default}=e,l=n(null),[u,d]=r(null);return t(()=>{if(!l.current)return;let e=document.createElement(`style`);e.textContent=`
4
+ .xterm-char-measure-element {
5
+ position: absolute !important;
6
+ top: 0 !important;
7
+ left: -9999px !important;
8
+ visibility: hidden !important;
9
+ pointer-events: none !important;
10
+ }
11
+ .xterm-helper-textarea {
12
+ position: absolute !important;
13
+ opacity: 0 !important;
14
+ left: -9999px !important;
15
+ pointer-events: none !important;
16
+ }
17
+ .xterm-viewport {
18
+ display: none !important;
19
+ }
20
+ .xterm-screen {
21
+ display: block !important;
22
+ width: 100% !important;
23
+ height: auto !important;
24
+ }
25
+ .xterm-rows {
26
+ line-height: normal !important;
27
+ user-select: text !important; /* Allow native HTML text selection. */
28
+ }
29
+ .xterm-selection {
30
+ display: none !important; /* Hide xterm's own selection overlay. */
31
+ }
32
+ `,document.head.appendChild(e);let t=new a({fontSize:o,fontFamily:s,disableStdin:!0,cursorBlink:!1,convertEol:!0,scrollback:0,theme:c}),n=new i;return t.loadAddon(n),t.open(l.current),t.write(`\x1B[?25l`),d({terminal:t,fitAddon:n}),()=>{document.head.contains(e)&&document.head.removeChild(e),t.dispose(),d(null)}},[o,s]),{terminalRef:l,instance:u}}export{b as TerminalThemes,g as runShell,c as useAudio,u as useMediaMetadata,f as useMousePosition,m as useProperties,_ as useShell,y as useSystemMonitor,x as useTerminal};
package/package.json CHANGED
@@ -1,47 +1,43 @@
1
1
  {
2
2
  "name": "@fluxlay/react",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "SDK for building Fluxlay wallpapers with React",
5
- "license": "SEE LICENSE IN LICENSE.txt",
6
- "homepage": "https://fluxlay.com",
7
5
  "keywords": [
8
- "fluxlay",
9
- "wallpaper",
10
6
  "desktop",
7
+ "fluxlay",
11
8
  "react",
12
- "sdk"
9
+ "sdk",
10
+ "wallpaper"
13
11
  ],
14
- "type": "module",
15
- "main": "./dist/index.js",
16
- "types": "./dist/index.d.ts",
17
- "style": "./dist/sdk.css",
12
+ "homepage": "https://fluxlay.com",
13
+ "license": "SEE LICENSE IN LICENSE.txt",
18
14
  "files": [
19
15
  "dist"
20
16
  ],
17
+ "type": "module",
18
+ "main": "./dist/index.mjs",
19
+ "types": "./dist/index.d.mts",
21
20
  "exports": {
22
21
  ".": {
23
- "types": "./dist/index.d.ts",
24
- "default": "./dist/index.js"
25
- },
26
- "./dist/sdk.css": "./dist/sdk.css"
22
+ "types": "./dist/index.d.mts",
23
+ "default": "./dist/index.mjs"
24
+ }
27
25
  },
28
26
  "dependencies": {
29
27
  "@xterm/addon-fit": "^0.11.0",
30
28
  "@xterm/xterm": "^6.0.0"
31
29
  },
32
- "peerDependencies": {
33
- "react": "^19.0.0"
34
- },
35
30
  "devDependencies": {
36
31
  "@types/react": "^19.2.14",
37
32
  "react": "^19.2.4",
38
- "typescript": "^5.9.3",
39
- "vite": "^8.0.0",
40
- "vite-plugin-dts": "^4.5.4"
33
+ "tsdown": "^0.21.7",
34
+ "typescript": "^5.9.3"
35
+ },
36
+ "peerDependencies": {
37
+ "react": "^19.0.0"
41
38
  },
42
39
  "scripts": {
43
- "build": "vite build",
44
- "check": "biome check --write",
45
- "typecheck": "tsc --noEmit"
40
+ "build": "tsdown",
41
+ "check": "oxlint --type-aware --type-check --fix && oxfmt --write ."
46
42
  }
47
43
  }