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
package/docs/ecosystem.md CHANGED
@@ -1,29 +1,25 @@
1
1
  # Ecosystem
2
2
 
3
- react-x11 is a React renderer with no DOM: there is no `document`, no
4
- `window` global, no CSSOM, and the host elements are `<box>`/`<text>`/`<svg>`
5
- rather than `<div>`/`<span>`. So any package that only touches React —
6
- hooks, context, state, reconciliation — works unchanged, and any package
7
- that reaches for `document`, `window`, `HTMLElement`, CSS, or renders a
8
- `<div>` does not.
9
-
10
- That one rule decides every verdict below. Each of them was established by
11
- running the library against react-x11 1.2.0, not by reading its
12
- documentation — the two exceptions are React DevTools and Fast Refresh,
13
- which are already wired into this repo, so their pages document the working
14
- setup rather than re-deriving it.
3
+ react-x11 is a React renderer with no DOM: no `document`, no `window`
4
+ global, no CSSOM, and the host elements are `<box>`/`<text>`/`<svg>`, not
5
+ `<div>`/`<span>`. A package that only touches React — hooks, context, state,
6
+ reconciliation — works unchanged; one that reaches for `document`, `window`,
7
+ `HTMLElement`, CSS, or renders a `<div>` does not.
8
+
9
+ That rule decides every verdict below. Each was established by running the
10
+ library against react-x11 1.2.0, not by reading its documentation; React
11
+ DevTools and Fast Refresh, which react-x11 wires up itself, are documented as
12
+ working setups instead.
15
13
 
16
14
  ## The 30-second test
17
15
 
18
- Before installing anything, ask the four questions in order. Each one has a
19
- command.
16
+ Before installing anything, ask four questions in order. Each has a command.
20
17
 
21
18
  1. **Does it import?** `node --input-type=module -e "import('the-package')"`.
22
19
  A package that hard-requires `react-dom`, or whose `exports` map has only
23
- browser conditions, fails here — see
24
- [import time](#install-and-import-time) below. Caveat: if anything else in
25
- your tree already pulled `react-dom` in, this test passes and the problem
26
- moves to the [silent](#silent-failures) column. Run
20
+ browser conditions, fails here ([import time](#install-and-import-time)).
21
+ If something else in your tree already pulled in `react-dom`, this passes
22
+ and the problem moves to the [silent](#silent-failures) column — run
27
23
  `npm ls react-dom` before you trust a pass.
28
24
  2. **Does it render host elements?** Grep the shipped code for tag names:
29
25
 
@@ -32,8 +28,8 @@ command.
32
28
  node_modules/the-package --include='*.js' --include='*.mjs' | sort -u
33
29
  ```
34
30
 
35
- Anything that emits DOM tags cannot render here, no matter how headless
36
- the README says it is. This one is a reliable verdict: zustand and
31
+ Anything that emits DOM tags cannot render here, however headless the
32
+ README says it is. This one is a reliable verdict: zustand and
37
33
  `@tanstack/react-table` print nothing; recharts, react-select and Headless
38
34
  UI print a list.
39
35
 
@@ -44,32 +40,31 @@ command.
44
40
  node_modules/the-package --include='*.js' --include='*.mjs'
45
41
  ```
46
42
 
47
- This one is a pointer, not a verdict — _read the hits_. A minified UMD
48
- bundle and an `isSSR = typeof window === "undefined"` default both match
49
- harmlessly. What you are looking for is an environment probe whose result
50
- gates a feature, because that is the silent-failure shape: the library
51
- decides it is doing SSR and quietly turns things off. Check the transitive
52
- core package too — `@tanstack/query-core`, not just
53
- `@tanstack/react-query`, which has no hits of its own.
54
-
55
- 4. **Does it expect DOM-shaped events?** Since 2.0.0 the answer is usually
56
- fine: `<textinput onChange>` hands over a synthetic event with
57
- `target.value`, `target.name` and a writable `target.value`, so
58
- `event.target.value` reads the way it does in the DOM. What to check
59
- instead is the **opposite** direction — a library whose field contract is
60
- value-in/value-out (`field.handleChange(value)`) now needs one unwrap per
43
+ A pointer, not a verdict — _read the hits_. A minified UMD bundle or an
44
+ `isSSR = typeof window === "undefined"` default matches harmlessly. Look
45
+ for an environment probe whose result gates a feature: that is the
46
+ silent-failure shape, where the library decides it is doing SSR and
47
+ quietly turns things off. Check the transitive core too —
48
+ `@tanstack/query-core`, not just `@tanstack/react-query`, which has no
49
+ hits of its own.
50
+
51
+ 4. **Does it expect DOM-shaped events?** Usually fine: `<textinput onChange>`
52
+ passes a synthetic event with `target.value` (writable) and `target.name`,
53
+ so `event.target.value` reads as it does in the DOM. Check the
54
+ **opposite** direction: a library whose field contract is
55
+ value-in/value-out (`field.handleChange(value)`) needs one unwrap per
61
56
  field, and a bare `onChange={field.handleChange}` stores the event object
62
57
  with no error. Grep your own code for `onChange={` on a `<textinput>`.
63
58
 
64
- A library that passes all four is almost always a drop-in. A library that
65
- fails 2 or 3 usually has a headless core published separately — that is the
66
- pattern behind half the adapters on this page.
59
+ A library that passes all four is almost always a drop-in. One that fails 2
60
+ or 3 usually has a headless core published separately — the pattern behind
61
+ half the adapters on this page.
67
62
 
68
63
  ## What works
69
64
 
70
- Fifty-three packages and two Node built-ins, across 12 categories. **Out of
71
- the box** means install and use; **adapter** means a small amount of glue,
72
- written out in full on the category page.
65
+ Fifty-five packages and two Node built-ins, across 12 categories. **Out of
66
+ the box** means install and use; **adapter** means a little glue, written
67
+ out in full on the category page.
73
68
 
74
69
  ### State management
75
70
 
@@ -92,11 +87,13 @@ written out in full on the category page.
92
87
 
93
88
  ### Forms and validation
94
89
 
95
- | Package | Integration | |
96
- | ---------------------- | ---------------------------------------------- | ------------------------------------------- |
97
- | `@tanstack/react-form` | out of the box | [forms](ecosystem/forms.md#tanstack-form) |
98
- | `zod` | out of the box | [forms](ecosystem/forms.md#zod) |
99
- | `react-hook-form` | adapter — use `<Controller>`, not `register()` | [forms](ecosystem/forms.md#react-hook-form) |
90
+ | Package | Integration | |
91
+ | ---------------------- | ---------------------------------------------------------- | ------------------------------------------- |
92
+ | `@tanstack/react-form` | out of the box | [forms](ecosystem/forms.md#tanstack-form) |
93
+ | `zod` | out of the box | [forms](ecosystem/forms.md#zod) |
94
+ | `react-hook-form` | out of the box — `register()` or `<Controller>` | [forms](ecosystem/forms.md#react-hook-form) |
95
+ | `formik` | out of the box — no `<Form>`; `<Field>` with a render prop | [forms](ecosystem/forms.md#formik) |
96
+ | `downshift` | out of the box — `getInputProps()` on a `<textinput>` | [forms](ecosystem/forms.md) |
100
97
 
101
98
  ### Icons
102
99
 
@@ -188,21 +185,18 @@ written out in full on the category page.
188
185
 
189
186
  ## What does not work
190
187
 
191
- Everything below was reproduced against react-x11 1.2.0. The error text is
192
- verbatim — if you got here by searching for one of these strings, this is
193
- the right page.
194
-
195
- Failures come in four flavours, and they cost very different amounts of
196
- time:
188
+ Everything below was reproduced against react-x11 1.2.0, and the error text
189
+ is verbatim — if you searched for one of these strings, this is the right
190
+ page. Failures come in four flavours, by cost:
197
191
 
198
192
  - **Install and import time** — loud, immediate, cheap.
199
- - **Render time** — loud, immediate, and the message usually names the
193
+ - **Render time** — loud, immediate; the message usually names the
200
194
  offending element.
201
195
  - **First interaction** — the tree mounts clean and breaks on the first
202
- keystroke. Expensive, because the stack trace points at the library, not
203
- at the renderer.
204
- - **Silent** — no error, ever. The most expensive class by a wide margin;
205
- read that table even if nothing is broken yet.
196
+ keystroke, with a stack trace that points at the library, not the
197
+ renderer.
198
+ - **Silent** — no error, ever. By far the most expensive; read that table
199
+ even if nothing is broken yet.
206
200
 
207
201
  ### Install and import time
208
202
 
@@ -213,13 +207,12 @@ time:
213
207
  | `@tanstack/react-virtual` | `Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'react-dom' imported from node_modules/@tanstack/react-virtual/dist/esm/index.js` | `@tanstack/virtual-core` — [layout](ecosystem/layout.md#tanstack-virtual) |
214
208
  | `styled-components` | `TypeError: styled.div is not a function` | `createStyles`/`ThemeProvider` + a palette package — [theming](ecosystem/theming.md) |
215
209
  | `react-scan` | `Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './auto' is not defined by "exports" in node_modules/react-scan/package.json imported from …` | React's own `<Profiler>`, or why-did-you-render — [dev tooling](ecosystem/dev-tooling.md#why-did-you-render) |
216
- | `@testing-library/react` (no `react-dom`) | `Error: Cannot find module 'react-dom/test-utils'` | `node:test` or `vitest` — [testing](ecosystem/testing.md) |
210
+ | `@testing-library/react` (no `react-dom`) | `Error: Cannot find module 'react-dom/test-utils'` | `react-x11/test` on `node:test` or `vitest` — [testing](testing.md) |
217
211
  | `jest` (no ESM config) | `Jest encountered an unexpected token` … `SyntaxError: Cannot use import statement outside a module` | `node:test`/`vitest`, or Jest in ESM mode — [testing](ecosystem/testing.md#jest) |
218
212
  | `jest` (transformed to CJS) | `SyntaxError: Cannot use 'import.meta' outside a module` | as above |
219
213
 
220
- `styled-components` deserves a note because the error is actively
221
- misleading. It fires at module-evaluation time, mentions neither react-x11
222
- nor the DOM, and sends people hunting for a version mismatch:
214
+ The `styled-components` error is misleading: it fires at module evaluation,
215
+ mentions neither react-x11 nor the DOM, and looks like a version mismatch.
223
216
 
224
217
  ```js
225
218
  import styled from 'styled-components';
@@ -228,13 +221,12 @@ const Panel = styled.div`
228
221
  `; // throws right here
229
222
  ```
230
223
 
231
- Under plain Node ESM — which is how react-x11 apps run, with no bundler —
232
- the default import resolves to the CJS module namespace, so `styled` is an
233
- object with `ServerStyleSheet` and friends on it, and no `.div`. Working
234
- around the interop with `const styled = sc.default ?? sc` only moves you to
235
- `react-x11: unknown element type <div>`. See the
236
- [silent failures](#silent-failures) table for what happens if you then try
237
- `styled('box')`.
224
+ Under plain Node ESM (how react-x11 apps run, with no bundler) the default
225
+ import resolves to the CJS module namespace — an object with
226
+ `ServerStyleSheet` and friends, and no `.div`. Fixing the interop with
227
+ `const styled = sc.default ?? sc` only moves you to
228
+ `react-x11: unknown element type <div>`; `styled('box')` is in
229
+ [silent failures](#silent-failures).
238
230
 
239
231
  The two Jest entries are the same dead end from two directions. Full text:
240
232
 
@@ -247,49 +239,45 @@ Jest encountered an unexpected token
247
239
  SyntaxError: Cannot use 'import.meta' outside a module
248
240
  ```
249
241
 
250
- `react-x11/src/Reconciler.js` and `src/DevToolsIntegration.js` both call
251
- `createRequire(import.meta.url)`, which cannot be down-compiled to CJS. Jest
252
- _can_ run react-x11 tests, but only in real ESM mode — see
253
- [testing](ecosystem/testing.md#jest). `node:test` and `vitest` need no
254
- transform at all.
242
+ react-x11 calls `createRequire(import.meta.url)`, which cannot be
243
+ down-compiled to CJS, so Jest runs react-x11 tests only in real ESM mode —
244
+ see [testing](ecosystem/testing.md#jest).
255
245
 
256
246
  ### Render time
257
247
 
258
248
  The renderer's own errors are prefixed `react-x11:` and name the element it
259
- could not create. This is the most common failure by far, and the tag it
260
- names tells you which library layer broke.
261
-
262
- | Package | Error | Use instead |
263
- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
264
- | `framer-motion` | `react-x11: uncaught error Error: react-x11: unknown element type <div>. Supported: <window>, <popup>, <box>, <text>, <image>, <canvas>, <textinput>, <textarea>, <svg>, <glarea>.` | popmotion, `@tweenjs/tween.js`, d3-ease + d3-interpolate — [animation](ecosystem/animation.md) |
265
- | `framer-motion` (value layer) | `ReferenceError: HTMLElement is not defined` | popmotion — [animation](ecosystem/animation.md#popmotion) |
266
- | `recharts` | `react-x11: uncaught error Error: react-x11: unknown element type <div>. …` | d3-scale + d3-shape into the `<svg>` host — [below](#charting) |
267
- | `formik` (`<Form>` with a `<Field>`) | `react-x11: uncaught error Error: react-x11: unknown element type <input>. …` | `@tanstack/react-form` — [forms](ecosystem/forms.md#tanstack-form) |
268
- | `formik` (`<Form>` alone) | `react-x11: uncaught error Error: react-x11: unknown element type <form>. …` | as above |
269
- | `@headlessui/react` (`Switch`) | `react-x11: uncaught error Error: react-x11: unknown element type <button>. …` | react-x11's built-in widgets — [components](components.md) |
270
- | `@headlessui/react` (`Dialog`) | `react-x11: uncaught error Error: react-x11: unknown element type <span>. …` | react-x11's built-in `Dialog` |
271
- | `@radix-ui/react-dialog` | `react-x11: uncaught error Error: react-x11: unknown element type <button>. …` | react-x11's built-in `Dialog` |
272
- | `react-select` | `react-x11: uncaught error Error: react-x11: unknown element type <style>. …` | react-x11's built-in `Select` |
273
- | `@emotion/styled` | `react-x11: uncaught error Error: react-x11: unknown element type <style>. …` | `createStyles` + `ThemeProvider` — [styling](styling.md) |
274
- | `react-dropzone` | `react-x11: uncaught error Error: react-x11: unknown element type <input>. …` | built-in `useDropTarget` / `<box dropAccept onDrop>` — [drag and drop](drag-and-drop.md) |
275
- | `react-router-dom` (`BrowserRouter`) | `react-x11: uncaught error ReferenceError: document is not defined` at `getUrlBasedHistory` | `MemoryRouter` — [routing](ecosystem/routing.md#react-router) |
276
- | `react-router-dom` (`<Link>`) | `react-x11: uncaught error Error: react-x11: unknown element type <a>. …` | `useNavigate()` on a `<box onClick>` |
277
- | `lucide-react` | `react-x11: uncaught error Error: react-x11: <svg width=…> is a style property — pass it in style: <svg style={{ width: … }} />` | `@iconify-json/lucide`, or `lucide` — [icons](ecosystem/icons.md) |
278
- | `@tabler/icons-react` | `react-x11: uncaught error Error: react-x11: <svg width=…> is a style property — pass it in style: <svg style={{ width: … }} />` | `@iconify-json/tabler`, or `@tabler/icons` — [icons](ecosystem/icons.md#tabler-icons) |
279
- | `@phosphor-icons/react` | `react-x11: uncaught error Error: react-x11: <svg width=…> is a style property — pass it in style: <svg style={{ width: … }} />` | `@iconify-json/ph`, or `@phosphor-icons/core` — [icons](ecosystem/icons.md#phosphor-icons) |
280
- | `@testing-library/react` | `ReferenceError: document is not defined` at `render (node_modules/@testing-library/react/dist/pure.js:256:5)` | `node:test`/`vitest` against the node tree — [testing](ecosystem/testing.md) |
281
- | `@testing-library/dom` (`within`) | `TypeError: Expected container to be an Element, a Document or a DocumentFragment but got WindowNode.` | walk `node.children`/`node.props` — [testing](ecosystem/testing.md) |
282
- | `@testing-library/dom` (`screen`) | `TypeError: For queries bound to document.body a global document has to be available... Learn more: https://testing-library.com/s/screen-global-error` | nothing — there is no accessibility tree behind react-x11 today |
283
- | `@testing-library/user-event` | `TypeError: Cannot read properties of undefined (reading 'Symbol(Node prepared with document state workarounds)')` | emit raw ntk events on the window — [testing](ecosystem/testing.md#driving-events) |
284
- | `jest-image-snapshot` | `TypeError: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Object` | `getImageData` + `pngjs` + `pixelmatch` — [testing](ecosystem/testing.md#pixelmatch) |
285
- | `react-x11` test selectors | `Error: Test selector API is not supported by this renderer.` | nothing — `supportsTestSelectors` is `false` |
286
-
287
- Four of those need the detail, because the obvious workaround does not
288
- work.
289
-
290
- **framer-motion cannot be rescued by dropping to its value layer.** The
291
- `motion.div` failure is the expected one; the interesting one is what
292
- happens when you reach past it:
249
+ could not create. By far the most common failure; the tag tells you which
250
+ library layer broke.
251
+
252
+ | Package | Error | Use instead |
253
+ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
254
+ | `framer-motion` | `react-x11: uncaught error Error: react-x11: unknown element type <div>. Supported: <window>, <popup>, <box>, <text>, <image>, <canvas>, <textinput>, <textarea>, <svg>, <glarea>.` | popmotion, `@tweenjs/tween.js`, d3-ease + d3-interpolate — [animation](ecosystem/animation.md) |
255
+ | `framer-motion` (value layer) | `ReferenceError: HTMLElement is not defined` | popmotion — [animation](ecosystem/animation.md#popmotion) |
256
+ | `recharts` | `react-x11: uncaught error Error: react-x11: unknown element type <div>. …` | d3-scale + d3-shape into the `<svg>` host — [below](#charting) |
257
+ | `formik` (`<Form>` with a `<Field>`) | `react-x11: uncaught error Error: react-x11: unknown element type <input>. …` | a `<Field>` render prop onto a `<textinput>` — [forms](ecosystem/forms.md#formik) |
258
+ | `formik` (`<Form>` alone) | `react-x11: uncaught error Error: react-x11: unknown element type <form>. …` | no `<Form>`; call `submitForm()` from a `Button` |
259
+ | `@headlessui/react` (`Switch`) | `react-x11: uncaught error Error: react-x11: unknown element type <button>. …` | react-x11's built-in widgets — [components](components.md) |
260
+ | `@headlessui/react` (`Dialog`) | `react-x11: uncaught error Error: react-x11: unknown element type <span>. …` | react-x11's built-in `Dialog` |
261
+ | `@radix-ui/react-dialog` | `react-x11: uncaught error Error: react-x11: unknown element type <button>. …` | react-x11's built-in `Dialog` |
262
+ | `react-select` | `react-x11: uncaught error Error: react-x11: unknown element type <style>. …` | react-x11's built-in `Select` |
263
+ | `@emotion/styled` | `react-x11: uncaught error Error: react-x11: unknown element type <style>. …` | `createStyles` + `ThemeProvider` — [styling](styling.md) |
264
+ | `react-dropzone` | `react-x11: uncaught error Error: react-x11: unknown element type <input>. …` | built-in `useDropTarget` / `<box dropAccept onDrop>` — [drag and drop](drag-and-drop.md) |
265
+ | `react-router-dom` (`BrowserRouter`) | `react-x11: uncaught error ReferenceError: document is not defined` at `getUrlBasedHistory` | `MemoryRouter` — [routing](ecosystem/routing.md#react-router) |
266
+ | `react-router-dom` (`<Link>`) | `react-x11: uncaught error Error: react-x11: unknown element type <a>. …` | `useNavigate()` on a `<box onClick>` |
267
+ | `lucide-react` | `react-x11: uncaught error Error: react-x11: <svg width=…> is a style property — pass it in style: <svg style={{ width: … }} />` | `@iconify-json/lucide`, or `lucide` — [icons](ecosystem/icons.md) |
268
+ | `@tabler/icons-react` | `react-x11: uncaught error Error: react-x11: <svg width=…> is a style property — pass it in style: <svg style={{ width: … }} />` | `@iconify-json/tabler`, or `@tabler/icons` — [icons](ecosystem/icons.md#tabler-icons) |
269
+ | `@phosphor-icons/react` | `react-x11: uncaught error Error: react-x11: <svg width=…> is a style property — pass it in style: <svg style={{ width: … }} />` | `@iconify-json/ph`, or `@phosphor-icons/core` — [icons](ecosystem/icons.md#phosphor-icons) |
270
+ | `@testing-library/react` | `ReferenceError: document is not defined` at `render (node_modules/@testing-library/react/dist/pure.js:256:5)` | `renderX11` from `react-x11/test` — [testing](testing.md) |
271
+ | `@testing-library/dom` (`within`) | `TypeError: Expected container to be an Element, a Document or a DocumentFragment but got WindowNode.` | `within` from `react-x11/test` — [testing](testing.md) |
272
+ | `@testing-library/dom` (`screen`) | `TypeError: For queries bound to document.body a global document has to be available... Learn more: https://testing-library.com/s/screen-global-error` | `screen` from `react-x11/test` — [testing](testing.md) |
273
+ | `@testing-library/user-event` | `TypeError: Cannot read properties of undefined (reading 'Symbol(Node prepared with document state workarounds)')` | `userEvent` from `react-x11/test`, or raw ntk events — [testing](ecosystem/testing.md#driving-events) |
274
+ | `jest-image-snapshot` | `TypeError: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Object` | `getImageData` + `pngjs` + `pixelmatch` — [testing](ecosystem/testing.md#pixelmatch) |
275
+ | `react-x11` test selectors | `Error: Test selector API is not supported by this renderer.` | nothing — `supportsTestSelectors` is `false` |
276
+
277
+ Four of those need detail, because the obvious workaround fails.
278
+
279
+ **framer-motion cannot be rescued by dropping to its value layer.** Reaching
280
+ past `motion.div` fails too:
293
281
 
294
282
  ```js
295
283
  import { animate, motionValue } from 'framer-motion';
@@ -299,17 +287,16 @@ animate(mv, 100, { duration: 0.1 });
299
287
  // ReferenceError: HTMLElement is not defined
300
288
  ```
301
289
 
302
- `motion-dom` feature-detects the Web Animations API by testing
290
+ `motion-dom` feature-detects the Web Animations API with
303
291
  `subject instanceof HTMLElement`, so `animate()` on a plain `motionValue`
304
- still throws once keyframes resolve — asynchronously, from
305
- `motion-dom/src/animation/waapi/supports/waapi.ts`. Use popmotion's
306
- `animate()` instead: same author lineage, no DOM assumption.
292
+ still throws, asynchronously, once keyframes resolve (from
293
+ `motion-dom/src/animation/waapi/supports/waapi.ts`). Use popmotion's
294
+ `animate()` instead.
307
295
 
308
296
  **The Radix escape hatch is worse than the error.**
309
297
  `<Dialog.Portal><Dialog.Content /></Dialog.Portal>` produces no error and no
310
- output at all — Radix's `Portal` is SSR-guarded, finds no `document`, and
311
- renders nothing, so the dialog silently never appears. Every Radix primitive
312
- has that shape. (`@radix-ui/colors`, by contrast, is pure data and is
298
+ output: `Portal` is SSR-guarded, finds no `document`, and renders nothing.
299
+ Every Radix primitive has that shape. (`@radix-ui/colors` is pure data and
313
300
  [recommended](ecosystem/theming.md#radix-colors).)
314
301
 
315
302
  **react-dropzone fails twice.** Deleting the `<input>` does not rescue it:
@@ -317,19 +304,17 @@ with only `<box {...getRootProps()} />` you get past the reconciler and then
317
304
  hit `react-x11: uncaught error ReferenceError: window is not defined`,
318
305
  thrown from react-dropzone's own mount effect.
319
306
 
320
- **The three `*-react` icon packages produce a byte-identical error**, and it
321
- is not "unknown element type" — react-x11 has a real `<svg>` host, so the
322
- icon gets further than every other DOM library here and then dies on the
323
- flat `width`/`height` props those wrappers set unconditionally. There is no
324
- prop you can pass to avoid it. `@heroicons/react` is the
325
- [exception](ecosystem/icons.md#heroicons-react): it sizes with a class name
326
- rather than flat attributes, so it renders.
307
+ **The three `*-react` icon packages produce a byte-identical error**, not
308
+ "unknown element type": react-x11 has a real `<svg>` host, so the icon gets
309
+ further and dies on the flat `width`/`height` props those wrappers always
310
+ set. No prop avoids it. `@heroicons/react` is the
311
+ [exception](ecosystem/icons.md#heroicons-react): it sizes with a class name,
312
+ so it renders.
327
313
 
328
- Two more index notes for searchers:
314
+ Index notes for searchers:
329
315
 
330
- - `react-select` reports `<style>`, not `<div>`. It is built on Emotion, and
331
- the first host it emits is Emotion's injected style tag — so this is the
332
- CSS-in-JS failure rather than the component failure.
316
+ - `react-select` reports `<style>`, not `<div>`: it is built on Emotion, and
317
+ the first host it emits is Emotion's injected style tag.
333
318
  - `formik` reports `<input>` when your `<Form>` has a `<Field>` in it and
334
319
  `<form>` when it does not, because the reconciler completes children
335
320
  first.
@@ -339,9 +324,8 @@ Two more index notes for searchers:
339
324
 
340
325
  #### Charting, without recharts {#charting}
341
326
 
342
- There is no charting entry in the compatibility table, but the substitute
343
- for `recharts` is small: compute with `d3-scale` + `d3-shape` and emit the
344
- path into react-x11's own `<svg>` host.
327
+ The substitute for `recharts` is small: compute with `d3-scale` +
328
+ `d3-shape` and emit the path into react-x11's own `<svg>` host.
345
329
 
346
330
  ```jsx
347
331
  import { scaleLinear } from 'd3-scale';
@@ -370,30 +354,24 @@ better one for dense plots.
370
354
 
371
355
  ### First interaction
372
356
 
373
- These mount without a single error message. The first sign of trouble is a
374
- keystroke.
375
-
376
- **Two entries left this table in 2.0.0.** `downshift` (a TypeError on the
377
- first keystroke) and `formik`'s `getFieldProps` spread (silent, no error,
378
- the field simply never updated) both had one cause: `<textinput>` called
379
- `onChange(newString)` rather than `onChange(event)`. It now passes a
380
- synthetic event, and both work — see
381
- [forms](ecosystem/forms.md). They are recorded here because the symptoms are
382
- what a 1.x user searches for.
357
+ These mount without an error; the first sign of trouble is a keystroke.
383
358
 
384
- Nothing currently fails on first interaction. Two shapes to know about
385
- anyway, because they are the ones this class of bug takes here:
359
+ Nothing currently fails here. `downshift` (a TypeError on the first
360
+ keystroke) and `formik`'s `getFieldProps` spread (the field silently never
361
+ updated) did on 1.x, when `<textinput>` called `onChange(newString)`; it now
362
+ passes a synthetic event and both work ([forms](ecosystem/forms.md)). The
363
+ two shapes this class of bug takes:
386
364
 
387
365
  - A handler that reads `event.nativeEvent.<something>` **unguarded** works
388
366
  for a keystroke and throws for a paste or an undo, where there is no X
389
367
  event to report. downshift reads
390
- `event.nativeEvent.preventDownshiftDefault` this way; it is safe only
391
- because it also checks `hasOwnProperty('nativeEvent')` first and the
392
- property is always present.
368
+ `event.nativeEvent.preventDownshiftDefault` this way, and is safe only
369
+ because it checks `hasOwnProperty('nativeEvent')` first and the property
370
+ is always present.
393
371
  - A library that writes through a ref — `ref.value = ''` — needs the node to
394
- have a value **setter**. `<textinput>` does; most nodes do not, and the
395
- failure is a TypeError thrown from inside the commit phase, which takes the
396
- render down rather than one handler.
372
+ have a value **setter**. `<textinput>` has one; most nodes do not, and the
373
+ TypeError is thrown inside the commit phase, taking the render down rather
374
+ than one handler.
397
375
 
398
376
  ### Silent failures
399
377
 
@@ -408,34 +386,23 @@ No error is ever printed. Read this table before you spend an afternoon.
408
386
  | `styled-components` (`styled('box')`) | renders with no error and hands the box a single `className` prop, which react-x11 ignores — the CSS goes nowhere | `createStyles` + `ThemeProvider` |
409
387
  | `tailwindcss/colors` (raw values) | v4 ships `oklch()` strings; ntk's parser returns null and paints nothing | convert with `culori` — [theming](ecosystem/theming.md#tailwind-colors) |
410
388
 
411
- The swr one is the most expensive, so here it is in full. `useSWR` fetches
412
- on mount, caches and dedupes correctly. What never happens is focus
413
- revalidation, because swr computes its environment once at import:
414
-
415
- ```js
416
- // swr/dist/_internal/config-context-*.mjs
417
- const IS_SERVER = !isWindowDefined || isLegacyDeno;
418
- ```
389
+ The swr one is the most expensive. `useSWR` fetches, caches and dedupes,
390
+ but swr decides once at import that a process with no global `window` is a
391
+ server and registers no focus or reconnect listeners — not even a custom
392
+ `initFocus` passed through `<SWRConfig value={{ provider, initFocus }}>`,
393
+ the documented React Native escape hatch. Details and the workaround:
394
+ [data fetching](ecosystem/data-fetching.md#swr).
419
395
 
420
- In Node there is no global `window`, so `initCache`'s `if (!IS_SERVER)`
421
- branch never runs and neither `initFocus` nor `initReconnect` is ever
422
- called — swr registers zero listeners. The documented React Native escape
423
- hatch does not help either: a custom `initFocus` passed through
424
- `<SWRConfig value={{ provider, initFocus }}>` is never called, because the
425
- guard sits above it. The workaround, and its one gotcha, are on the
426
- [data fetching](ecosystem/data-fetching.md#swr) page.
427
-
428
- The `@tanstack/react-virtual` entry is subtle in a different way. `react-dom`
429
- is a _required_ peer, so a default `npm i @tanstack/react-virtual` installs
430
- it and the import-time error above never appears. `react-dom@19`'s
431
- `flushSync()` called outside any react-dom root runs the callback and does
432
- not throw — so nothing warns you that the synchronous flush the virtualizer
433
- depends on is happening in the wrong renderer.
396
+ `@tanstack/react-virtual` is subtle differently. `react-dom` is a _required_
397
+ peer, so a default `npm i @tanstack/react-virtual` installs it and the
398
+ import-time error never appears; `react-dom@19`'s `flushSync()` outside any
399
+ react-dom root runs the callback without throwing, so nothing warns you that
400
+ the virtualizer's synchronous flush happens in the wrong renderer.
434
401
 
435
402
  ## Adding a library that is not listed
436
403
 
437
404
  Run the [30-second test](#the-30-second-test) first; it settles most cases
438
- without an install. If it passes, the fastest real check is a render:
405
+ without an install. If it passes, render it:
439
406
 
440
407
  ```jsx
441
408
  // probe.jsx — needs a display: run under $DISPLAY, or `xvfb-run -a`
@@ -451,23 +418,22 @@ import { TheThing } from 'the-package';
451
418
  );
452
419
  ```
453
420
 
454
- Four outcomes, and each one tells you where to look:
421
+ Four outcomes:
455
422
 
456
423
  - **`react-x11: unknown element type <…>`** — the library renders DOM hosts.
457
424
  Look for a headless core published as a separate package; that is what
458
425
  rescued TanStack Virtual, Floating UI and react-spring.
459
- - **`react-x11: <… width=…> is a style property`** — it got as far as a real
460
- react-x11 host and then passed a flat style prop. Usually fixable by
461
- wrapping the component rather than replacing it.
426
+ - **`react-x11: <… width=…> is a style property`** — it reached a real
427
+ react-x11 host and passed a flat style prop. Usually fixable by wrapping
428
+ the component rather than replacing it.
462
429
  - **`ReferenceError: document is not defined`** (or `window`, or
463
- `HTMLElement`) — a DOM global at module or mount time. Check whether the
464
- library has a documented environment-override seam, the way
465
- `@tanstack/react-query`'s `environmentManager` does.
466
- - **It renders.** Then type into it, click it, and resize the window. The
430
+ `HTMLElement`) — a DOM global at module or mount time. Look for a
431
+ documented environment-override seam, like `@tanstack/react-query`'s
432
+ `environmentManager`.
433
+ - **It renders.** Then type into it, click it, and resize the window; the
467
434
  event-shape and silent classes only show up here.
468
435
 
469
- If you establish a result — either direction — open an issue on
436
+ If you establish a result either way, open an issue on
470
437
  [the react-x11 repository](https://github.com/sidorares/react-x11/issues)
471
438
  with the package name, its exact version, the code you ran, and the verbatim
472
- output. Negative results are as useful as positive ones on this page; most
473
- of what is above started as somebody's wasted afternoon.
439
+ output. Negative results are as useful as positive ones.