react-x11 2.52.0 → 2.53.0

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 (112) hide show
  1. package/README.md +10 -10
  2. package/docs/README.md +160 -314
  3. package/docs/accessibility.md +176 -229
  4. package/docs/appearance.md +77 -176
  5. package/docs/click-to-component.md +18 -51
  6. package/docs/clipboard.md +40 -59
  7. package/docs/components.md +518 -1036
  8. package/docs/dbus.md +61 -133
  9. package/docs/debugging.md +152 -245
  10. package/docs/desktop-calendar.md +51 -88
  11. package/docs/desktop.md +222 -347
  12. package/docs/devtools.md +50 -167
  13. package/docs/drag-and-drop.md +126 -204
  14. package/docs/ecosystem/animation.md +91 -125
  15. package/docs/ecosystem/data-fetching.md +38 -53
  16. package/docs/ecosystem/dev-tooling.md +159 -202
  17. package/docs/ecosystem/forms.md +61 -97
  18. package/docs/ecosystem/headless.md +64 -89
  19. package/docs/ecosystem/i18n.md +18 -21
  20. package/docs/ecosystem/icons.md +93 -126
  21. package/docs/ecosystem/layout.md +42 -52
  22. package/docs/ecosystem/routing.md +18 -29
  23. package/docs/ecosystem/state.md +71 -88
  24. package/docs/ecosystem/testing.md +131 -157
  25. package/docs/ecosystem/theming.md +119 -165
  26. package/docs/ecosystem.md +145 -179
  27. package/docs/elements.md +1091 -1774
  28. package/docs/embedding.md +83 -132
  29. package/docs/events.md +412 -695
  30. package/docs/extending.md +784 -1326
  31. package/docs/eyedropper.md +63 -122
  32. package/docs/filedialog.md +71 -107
  33. package/docs/frame.md +195 -339
  34. package/docs/gl.md +65 -62
  35. package/docs/globalmenu.md +63 -146
  36. package/docs/macos.md +531 -3234
  37. package/docs/notifications.md +33 -47
  38. package/docs/packaging.md +166 -309
  39. package/docs/permissions.md +9 -14
  40. package/docs/react-features.md +81 -106
  41. package/docs/remote.md +32 -76
  42. package/docs/scale.md +72 -186
  43. package/docs/styling.md +329 -547
  44. package/docs/system.md +200 -280
  45. package/docs/testing.md +63 -83
  46. package/docs/typescript.md +6 -48
  47. package/docs/uri-schemes.md +67 -107
  48. package/docs/wayland-backend.md +200 -459
  49. package/docs/windows-integrations.md +75 -131
  50. package/docs/windows.md +343 -1367
  51. package/package.json +3 -2
  52. package/src/Reconciler.js +2 -2
  53. package/src/a11y.js +1 -1
  54. package/src/backend/context2d.js +3 -3
  55. package/src/bootstrap.js +1 -1
  56. package/src/cocoa/app.js +6 -6
  57. package/src/cocoa/bezels.js +1 -1
  58. package/src/cocoa/fonts.js +1 -1
  59. package/src/cocoa/globalmenu.js +1 -1
  60. package/src/cocoa/keymap.js +1 -1
  61. package/src/cocoa/panewindow.js +1 -1
  62. package/src/cocoa/player.js +1 -1
  63. package/src/cocoa/presenter.js +2 -2
  64. package/src/cocoa/promotion.js +1 -1
  65. package/src/cocoa/relaunch.js +1 -1
  66. package/src/cocoa/threaded.js +1 -1
  67. package/src/cocoa/video.js +1 -1
  68. package/src/cocoa/window.js +4 -4
  69. package/src/components/Menu.js +7 -2
  70. package/src/components/Switch.js +1 -1
  71. package/src/components/native.js +1 -1
  72. package/src/dnd.js +2 -2
  73. package/src/glnodes.js +1 -1
  74. package/src/grid.js +1 -1
  75. package/src/layouts.js +1 -1
  76. package/src/nodes/animation.js +1 -1
  77. package/src/nodes/invalidate.js +1 -1
  78. package/src/nodes/layouthost.js +1 -1
  79. package/src/nodes/video.js +19 -8
  80. package/src/nodes/window/droptarget.js +1 -1
  81. package/src/pacing.js +1 -1
  82. package/src/refresh/index.js +2 -1
  83. package/src/types/video.d.ts +5 -2
  84. package/src/videobackend.js +28 -0
  85. package/src/videoframes.js +29 -16
  86. package/src/wayland/app.js +27 -0
  87. package/src/wayland/video.js +376 -0
  88. package/src/win32/a11y.js +1 -1
  89. package/src/win32/app.js +2 -2
  90. package/src/win32/fonts.js +1 -1
  91. package/src/win32/glarea.js +4 -4
  92. package/src/win32/overlay.js +1 -1
  93. package/src/win32/panewindow.js +3 -3
  94. package/src/win32/shell.js +1 -1
  95. package/src/win32/window.js +2 -2
  96. package/src/windowid.js +1 -1
  97. package/src/xvideo.js +189 -0
  98. package/docs/architecture/accessibility.md +0 -470
  99. package/docs/architecture/animation.md +0 -707
  100. package/docs/architecture/container-queries.md +0 -525
  101. package/docs/architecture/custom-layout.md +0 -334
  102. package/docs/architecture/drag-and-drop.md +0 -941
  103. package/docs/architecture/element-layer-contents.md +0 -622
  104. package/docs/architecture/frame-pacing.md +0 -255
  105. package/docs/architecture/grid-layout.md +0 -358
  106. package/docs/architecture/protocol-efficiency.md +0 -357
  107. package/docs/architecture/video.md +0 -1149
  108. package/docs/architecture/windowed-regions.md +0 -854
  109. package/docs/glx.md +0 -137
  110. package/docs/wayland.md +0 -545
  111. package/docs/windows-embedding.md +0 -271
  112. package/docs/windows-gl.md +0 -221
@@ -1,23 +1,21 @@
1
1
  # State management
2
2
 
3
- Every store here is renderer-agnostic: they subscribe through React's own
4
- `useSyncExternalStore` and never touch a host environment. The out-of-React
5
- surface matters more in a desktop app than on the web — an X event callback,
6
- an ntk timer or a D-Bus signal handler can write to the store directly, and
7
- every subscribed component under every `<window>` re-renders.
3
+ Every store here subscribes through React's own `useSyncExternalStore` and
4
+ never touches a host environment. Their out-of-React surface matters more in
5
+ a desktop app than on the web: an X event callback, an ntk timer or a D-Bus
6
+ signal handler can write to the store directly, and every subscribed
7
+ component under every `<window>` re-renders.
8
8
 
9
- Versions below are what was tested; anything newer in the same major is
10
- expected to behave the same.
9
+ Versions are the ones tested; newer releases in the same major are expected
10
+ to behave the same.
11
11
 
12
12
  ## zustand {#zustand}
13
13
 
14
14
  **Out of the box.** zustand@5.0.14.
15
15
 
16
- A small unopinionated store: `create((set) => ({...}))` returns a hook that
17
- components call with a selector. Subscription goes through
18
- `useSyncExternalStore` imported from `react` itself, and the store is usable
19
- outside React via `useStore.getState()` / `useStore.subscribe()`. The
20
- default recommendation for app state: zero DOM, zero adapter.
16
+ A small store: `create((set) => ({...}))` returns a hook that components
17
+ call with a selector, and `useStore.getState()` / `useStore.subscribe()`
18
+ work outside React. The default recommendation for app state.
21
19
 
22
20
  ```jsx
23
21
  import React from 'react';
@@ -43,8 +41,7 @@ function App() {
43
41
  (await createRoot()).render(<App />);
44
42
  ```
45
43
 
46
- Because the store is module-level rather than tree-level, several windows
47
- share it for free.
44
+ The store is module-level, so several windows share it.
48
45
 
49
46
  - `zustand/middleware`'s `persist` defaults to `localStorage`; pass a
50
47
  `storage` backed by `node:fs` (`createJSONStorage(() => fileStorage)`).
@@ -55,15 +52,12 @@ share it for free.
55
52
 
56
53
  **Out of the box.** jotai@2.20.2.
57
54
 
58
- Bottom-up atomic state: `atom(initial)` defines a unit of state,
59
- `useAtom`/`useAtomValue`/`useSetAtom` read and write it, and derived atoms
60
- recompute from their dependencies. Atoms are pure and the React bindings
61
- import only `react`.
62
-
63
- The explicit-store pattern is the right one for a desktop app: create the
64
- store at startup, hand it to the tree, and let X event handlers or
65
- background work call `store.set(...)`. One store shared by several
66
- `<window>` trees keeps them in sync automatically.
55
+ Atomic state: `atom(initial)` defines a unit, `useAtom`/`useAtomValue`/
56
+ `useSetAtom` read and write it, and derived atoms recompute from their
57
+ dependencies. In a desktop app use an explicit store: create it at startup,
58
+ hand it to `<Provider>`, and let X event handlers or background work call
59
+ `store.set(...)`. One store shared by several `<window>` trees keeps them in
60
+ sync.
67
61
 
68
62
  ```jsx
69
63
  import React from 'react';
@@ -93,21 +87,18 @@ setInterval(() => store.set(countAtom, (n) => n + 1), 1000);
93
87
 
94
88
  - `jotai/utils`' `atomWithStorage` defaults to `localStorage`; supply a
95
89
  custom storage (sync or async).
96
- - Async atoms suspend; wrap consumers in `<React.Suspense>` — react-x11
97
- renders fallbacks like any React 19 host — or use `loadable()`.
90
+ - Async atoms suspend; wrap consumers in `<React.Suspense>` (react-x11
91
+ renders fallbacks like any React 19 host) or use `loadable()`.
98
92
 
99
93
  ## valtio {#valtio}
100
94
 
101
95
  **Out of the box.** valtio@2.3.2.
102
96
 
103
97
  Proxy-based state: `proxy(obj)` returns an object you mutate directly;
104
- `useSnapshot(state)` returns an immutable snapshot and tracks which
105
- properties were read, re-rendering only when those change.
106
-
107
- Mutation-from-anywhere maps well onto X event handlers and ntk callbacks.
108
- `subscribe(state, cb)` is handy for pushing state into non-React things —
109
- writing a selection to the X clipboard, updating a window title
110
- imperatively.
98
+ `useSnapshot(state)` returns an immutable snapshot and re-renders only when
99
+ the properties read change. Mutation from anywhere suits X event handlers
100
+ and ntk callbacks; `subscribe(state, cb)` pushes state into non-React things
101
+ — a selection onto the clipboard, a window title set imperatively.
111
102
 
112
103
  ```jsx
113
104
  import React from 'react';
@@ -136,24 +127,21 @@ function App() {
136
127
  (await createRoot()).render(<App />);
137
128
  ```
138
129
 
139
- - Valtio 2 no longer deep-clones snapshots the way v1 did in dev; read the
140
- v2 migration notes if you are coming from v1 examples.
141
- - `valtio/utils`' `devtools()` targets the Redux DevTools browser extension.
142
- It is a no-op without one, and there is nothing to connect to under X11.
130
+ - Valtio 2 no longer deep-clones snapshots in dev the way v1 did; read the
131
+ v2 migration notes if you port v1 examples.
132
+ - `valtio/utils`' `devtools()` targets the Redux DevTools browser extension
133
+ and is a no-op here.
143
134
 
144
135
  ## XState {#xstate}
145
136
 
146
137
  **Out of the box.** xstate@5.32.5, @xstate/react@6.1.0.
147
138
 
148
- `createMachine` describes states, events, guards and actions; `createActor`
149
- interprets one; `@xstate/react` provides `useMachine`, `useActor`,
150
- `useActorRef` and `useSelector`. The interpreter has no environment coupling
151
- and the React bindings subscribe via `useSyncExternalStore`.
152
-
153
- Desktop chrome is where statecharts earn their keep: drag-resize state,
154
- modal and focus flows, a connection lifecycle (`connecting → connected →
155
- retrying`), long-running jobs with cancellation. An actor started at app
156
- level can outlive any single `<window>` and drive several of them.
139
+ `createMachine` describes states, events, guards and actions;
140
+ `createActor` interprets one; `@xstate/react` provides `useMachine`,
141
+ `useActor`, `useActorRef` and `useSelector`. Statecharts suit desktop
142
+ chrome: drag-resize, modal and focus flows, a connection lifecycle
143
+ (`connecting → connected → retrying`), cancellable jobs. An actor started at
144
+ app level can outlive any single `<window>` and drive several.
157
145
 
158
146
  ```jsx
159
147
  import React from 'react';
@@ -188,22 +176,20 @@ function App() {
188
176
  (await createRoot()).render(<App />);
189
177
  ```
190
178
 
191
- - `useMachine(machine)` inside a component works too and gives you a
192
- component-scoped actor; the external-actor pattern above is better for
193
- machines shared across windows.
194
- - `@statelyai/inspect` connects over WebSocket to Stately's editor. The
195
- transport works from Node; the iframe inspector expects a browser.
179
+ - `useMachine(machine)` inside a component gives a component-scoped actor;
180
+ the external actor above is better for machines shared across windows.
181
+ - `@statelyai/inspect` connects over WebSocket to Stately's editor, which
182
+ works from Node; the iframe inspector expects a browser.
196
183
 
197
184
  ## Redux {#redux}
198
185
 
199
186
  **Out of the box — pin `react-redux@>=9`.** react-redux@9.3.0,
200
187
  @reduxjs/toolkit@2.12.0, redux@5.0.1.
201
188
 
202
- react-redux 9 dropped the `react-dom`/`react-native` imports it used for
203
- `unstable_batchedUpdates` and subscribes through React's own
204
- `useSyncExternalStore`, so it is renderer-agnostic and needs no shim here.
205
- redux core and RTK are pure JS throughout, listener and observable
206
- middleware included.
189
+ react-redux 9 no longer imports `react-dom`/`react-native` for
190
+ `unstable_batchedUpdates` and subscribes through `useSyncExternalStore`, so
191
+ it needs no shim. redux core and RTK, listener and observable middleware
192
+ included, are pure JS.
207
193
 
208
194
  ```jsx
209
195
  import React from 'react';
@@ -242,18 +228,17 @@ function Counter() {
242
228
  ```
243
229
 
244
230
  - **The version pin is the one thing you must know.** react-redux 8 imports
245
- `react-dom` unconditionally, and the failure is a module-resolution error
246
- at startup, not a runtime warning. Both of its failure modes — the npm
247
- `ERESOLVE` on React 19 and the `Cannot find module 'react-dom'` behind
248
- `--legacy-peer-deps` — are in the
231
+ `react-dom` unconditionally: npm refuses it with `ERESOLVE` on React 19,
232
+ and behind `--legacy-peer-deps` the app fails at startup with
233
+ `Cannot find module 'react-dom'`. Both are in the
249
234
  [negative-results register](../ecosystem.md#install-and-import-time).
250
235
  - RTK's `devTools: true` (the default) looks for the Redux DevTools
251
- extension global; harmless when absent. `@redux-devtools/cli` is a remote
252
- devtools server if you want inspection.
236
+ extension global and is harmless when absent; `@redux-devtools/cli` is a
237
+ remote devtools server if you want inspection.
253
238
  - RTK Query works, but `setupListeners()` wires
254
- `window.addEventListener('focus'|'online')`, which are absent under Node.
255
- Pass a custom handler to `setupListeners(dispatch, customHandler)` wired
256
- to `<window onFocus>`, the same way as the
239
+ `window.addEventListener('focus'|'online')`, absent under Node. Pass
240
+ `setupListeners(dispatch, customHandler)` a handler wired to
241
+ `<window onFocus>`, as in the
257
242
  [TanStack Query adapter](data-fetching.md#tanstack-query).
258
243
 
259
244
  ## Immer {#immer}
@@ -261,10 +246,10 @@ function Counter() {
261
246
  **Out of the box.** immer@11.1.15.
262
247
 
263
248
  `produce(base, recipe)` runs a mutating recipe against a Proxy draft and
264
- returns a structurally-shared immutable result. Curried `produce(recipe)` is
265
- a drop-in `setState` updater. Pure JS, no environment assumptions — and it
266
- is already inside `@reduxjs/toolkit`'s `createSlice` reducers and available
267
- as zustand middleware (`zustand/middleware/immer`).
249
+ returns a structurally-shared immutable result; curried `produce(recipe)` is
250
+ a drop-in `setState` updater. It is already inside `@reduxjs/toolkit`'s
251
+ `createSlice` reducers and available as zustand middleware
252
+ (`zustand/middleware/immer`).
268
253
 
269
254
  ```jsx
270
255
  import React from 'react';
@@ -298,30 +283,28 @@ function App() {
298
283
  (await createRoot()).render(<App />);
299
284
  ```
300
285
 
301
- Nothing to adapt. Useful directly with `useState`/`useReducer` for the
302
- nested state desktop apps accumulate — tree views, multi-pane layouts.
286
+ Useful directly with `useState`/`useReducer` for the nested state desktop
287
+ apps accumulate — tree views, multi-pane layouts.
303
288
 
304
289
  ## MobX {#mobx}
305
290
 
306
291
  **Adapter — no code, but `react-dom` must be installed.** mobx@6.16.1,
307
292
  mobx-react-lite@4.1.1.
308
293
 
309
- Observable state via `makeAutoObservable`/`observable`, with
310
- `mobx-react-lite`'s `observer()` HOC re-rendering components when the
311
- observables they dereference change. mobx core is pure JS.
294
+ Observable state via `makeAutoObservable`/`observable`; `mobx-react-lite`'s
295
+ `observer()` re-renders a component when the observables it dereferences
296
+ change. mobx core is pure JS.
312
297
 
313
- The wrinkle: **every build of mobx-react-lite unconditionally does
298
+ **Every build of mobx-react-lite does
314
299
  `import { unstable_batchedUpdates } from "react-dom"`** at module load, to
315
- install React's batcher as mobx's reaction scheduler. In a react-x11 app
316
- react-dom is not otherwise present, so the import fails at startup with
317
- `Cannot find module 'react-dom'`.
300
+ install React's batcher as mobx's reaction scheduler. Without react-dom the
301
+ app fails at startup with `Cannot find module 'react-dom'`.
318
302
 
319
- The fix is `npm install react-dom`. Its top-level entry is Node-safe (it is
320
- the same entry SSR uses), react-x11 never renders through it, and React 19's
321
- `unstable_batchedUpdates` is a thin wrapper that batches correctly for any
322
- renderer. With react-dom present, `observer` subscribes through
323
- `use-sync-external-store` and mutations from X event handlers or timers
324
- re-render the tree.
303
+ The fix is `npm install react-dom`. Its top-level entry is Node-safe (the
304
+ one SSR uses), react-x11 never renders through it, and React 19's
305
+ `unstable_batchedUpdates` batches correctly for any renderer. With it
306
+ present, `observer` subscribes through `use-sync-external-store` and
307
+ mutations from X event handlers or timers re-render the tree.
325
308
 
326
309
  ```jsx
327
310
  // prerequisite: npm install react-dom (satisfies mobx-react-lite's import;
@@ -353,9 +336,9 @@ const App = observer(function App() {
353
336
  (await createRoot()).render(<App />);
354
337
  ```
355
338
 
356
- - Without react-dom the app fails at import time, not render time; the error
357
- names mobx-react-lite in its require stack.
358
- - `mobx-react` (the bigger sibling) layers on mobx-react-lite, so the same
359
- note applies. Prefer `-lite`.
360
- - Do not import from `react-dom` yourself. It is a compatibility shim here,
339
+ - Without react-dom the failure is at import time, not render time, and the
340
+ require stack names mobx-react-lite.
341
+ - `mobx-react` layers on mobx-react-lite, so the same applies. Prefer
342
+ `-lite`.
343
+ - Do not import from `react-dom` yourself; it is a compatibility shim here,
361
344
  nothing more.