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
@@ -43,22 +43,21 @@ function Month({ from, to }) {
43
43
  }
44
44
  ```
45
45
 
46
- `<Calendar>` is the grid from
47
- [`@react-x11/components`](ecosystem.md); the `'YYYY-MM-DD'` keys are the one
48
- contract between the two packages, which is why `byDay` is here and the grid
49
- is there. Nothing here draws anything.
46
+ `<Calendar>` is the grid from [`@react-x11/components`](ecosystem.md); the
47
+ `'YYYY-MM-DD'` keys of `byDay` are the contract between the two. Nothing here
48
+ draws anything.
50
49
 
51
50
  ## The ladder
52
51
 
53
- The [file dialog](filedialog.md)'s shape again, chosen in order and never by
54
- naming a backend:
52
+ Chosen in order, like the [file dialog](filedialog.md)'s, never by naming a
53
+ backend:
55
54
 
56
- | | | |
57
- | --- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
58
- | 1 | **EventKit through the bridge** | The [cocoa backend](macos.md), where the app the tree renders through carries `calendars` (`@windowkit/appkit` >= 0.8). One `EKEventStore` for every account, recurrences expanded by the framework, and one notification for any change. |
59
- | 2 | **EventKit through `osascript`** | A Mac with no bridge — every XQuartz install, and a cocoa app over an older bridge. A long-lived `osascript -l JavaScript` child holds the same store and answers JSON lines. Same framework, slower transport. |
60
- | 3 | **EDS over the session bus** | `org.gnome.evolution.dataserver.Sources5` / `Calendar8` — the store every GNOME calendar UI reads, and the one GNOME Online Accounts feeds. Recurrences are expanded here, with `ical.js`. |
61
- | 4 | **nothing** | `desktopCalendar()` answers `null` and the hook says `'unavailable'`. An ordinary answer about a machine, not a failure. |
55
+ | | | |
56
+ | --- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
57
+ | 1 | **EventKit through the bridge** | The [cocoa backend](macos.md) with `@windowkit/appkit` >= 0.8. One `EKEventStore` for every account, recurrences expanded by the framework, and one notification for any change. |
58
+ | 2 | **EventKit through `osascript`** | A Mac with no bridge — every XQuartz install, and a cocoa app over an older bridge. A long-lived `osascript -l JavaScript` child holds the same store. Same framework, slower transport. |
59
+ | 3 | **EDS over the session bus** | `org.gnome.evolution.dataserver.Sources5` / `Calendar8` — the store every GNOME calendar UI reads, and the one GNOME Online Accounts feeds. Recurrences are expanded here, with `ical.js`. |
60
+ | 4 | **nothing** | `desktopCalendar()` answers `null` and the hook says `'unavailable'`. An ordinary answer about a machine, not a failure. |
62
61
 
63
62
  ```ts
64
63
  await calendarBackend(); // 'cocoa' | 'osascript' | 'eds' | null
@@ -67,9 +66,9 @@ await calendarBackend(); // 'cocoa' | 'osascript' | 'eds' | null
67
66
  `calendarBackend()` reads nothing, spawns nothing and prompts nothing, so it
68
67
  is safe on a settings screen that wants to say where the events come from.
69
68
 
70
- **Rung 2 outranks rung 3 on a Mac**, which is deliberate: EventKit is that
71
- machine's real store, and an Evolution Data Server installed beside it would
72
- be a second, emptier one.
69
+ **Rung 2 outranks rung 3 on a Mac**: EventKit is that machine's real store,
70
+ and an Evolution Data Server installed beside it would be a second, emptier
71
+ one.
73
72
 
74
73
  ## The imperative half
75
74
 
@@ -87,14 +86,14 @@ try {
87
86
  }
88
87
  ```
89
88
 
90
- `close()` matters on every rung: it stops the views EDS handed out, drops
91
- this handle's share of the `osascript` child, and releases the bus reference.
92
- `useDesktopCalendarEvents` does it for you.
89
+ Call `close()` on every rung; it releases what the rung holds (EDS views, this
90
+ handle's share of the `osascript` child, the bus reference). `useDesktopCalendarEvents` does it for
91
+ you.
93
92
 
94
93
  `{ required: true }` turns the `null` into a typed `NoCalendarServiceError`
95
94
  for a caller who would rather branch in a `catch`, and `{ backend }` pins one
96
- rung and fails rather than falling past it — which is what a test and a "why
97
- is this slow" investigation both want.
95
+ rung and fails rather than falling past it — for a test, or a "why is this
96
+ slow" investigation.
98
97
 
99
98
  ## One shape, whichever rung answered
100
99
 
@@ -122,20 +121,13 @@ interface DesktopEvent {
122
121
  }
123
122
  ```
124
123
 
125
- Three things the rungs had to agree on, and they are the whole of why this is
126
- one module rather than three:
127
-
128
- - **`end` is exclusive.** EventKit reports an all-day event as ending at
129
- 23:59:59 of its last day; iCalendar (so EDS) ends it at the next midnight.
130
- An app cannot branch on which store it happens to be reading, so the macOS
131
- rungs normalise on the way out and `byDay` may assume it.
132
- - **A change is "something moved", not a patch.** EDS names the objects that
133
- changed and EventKit's notification names nothing at all — and neither can
134
- say what a recurrence master edited three months away did to the range on
135
- screen. So `watch` reports a change and the only correct answer is to query
136
- again.
137
- - **"Not allowed to look" is not "no events".** Without the grant EventKit
138
- answers an empty list, which is a lie an app would draw.
124
+ - **`end` is exclusive** on every rung — an all-day event ends at the next
125
+ midnight (the macOS rungs normalise EventKit's 23:59:59), so `byDay` may
126
+ assume it.
127
+ - **A change is "something moved", not a patch.** `watch` reports that the
128
+ range changed; the only correct answer is to query again.
129
+ - **"Not allowed to look" is not "no events".** Without the grant a read
130
+ rejects; it never returns an empty list.
139
131
 
140
132
  ## `byDay`
141
133
 
@@ -160,14 +152,12 @@ await cal.openSettings(); // System Settings › Privacy & Security › Calenda
160
152
  ```
161
153
 
162
154
  **The first read asks.** `listCalendars()` and `eventsBetween()` raise the
163
- prompt when the status is `'prompt'`, the way the notification centre's first
164
- post asks — so a picker the user never opens never prompts, and
165
- `enabled: false` on the hook is how a button defers it. A refusal is a typed
166
- `CalendarAccessError` carrying the status, never an empty list.
155
+ prompt when the status is `'prompt'` — so a picker the user never opens never
156
+ prompts, and `enabled: false` on the hook is how a button defers it. A refusal
157
+ is a typed `CalendarAccessError` carrying the status, never an empty list.
167
158
 
168
159
  `'denied'` is the **user's** answer and `'unavailable'` is the **machine's**.
169
- They are separate words because only one of them has a switch behind it: show
170
- an Open Settings button on `'denied'` and on nothing else
160
+ Show an Open Settings button on `'denied'` and on nothing else
171
161
  ([permissions.md](permissions.md) has the same rule for `'unknown'`).
172
162
 
173
163
  `'write-only'` — macOS 14's partial grant — is a refusal to a reader, so it
@@ -176,26 +166,13 @@ tell the two apart.
176
166
 
177
167
  ### Attribution, and what raises the prompt
178
168
 
179
- **The grant does not belong to `osascript`.** It belongs to whatever owns the
180
- process tree. Measured on macOS 15.2 by raising the prompt for real through
181
- the second rung and reading `tccd`'s own record of it
182
- (`log show --predicate 'subsystem == "com.apple.TCC"'`), the attribution is
183
- three processes, not one:
184
-
185
- ```
186
- AUTHREQ_ATTRIBUTION: service=kTCCServiceCalendar
187
- responsible = the app that owns the tree (Terminal, iTerm, the IDE — here
188
- com.anthropic.claude-code)
189
- accessing = com.apple.osascript (/usr/bin/osascript — the child)
190
- requesting = com.apple.calaccessd (CalendarDaemon, doing the check)
191
- ```
192
-
193
- `responsible` is what TCC keys the decision on and what the dialog names, so:
169
+ macOS keys the grant on the process that owns the process tree, and the
170
+ dialog names that process:
194
171
 
195
- - The second rung's grant is **shared with everything that terminal or IDE
196
- runs** — not with every `osascript` on the Mac, and not with this app
197
- alone. Two react-x11 apps started from the same terminal share one answer;
198
- the same app launched from Finder asks again.
172
+ - The `osascript` rung's grant is **shared with everything that terminal or
173
+ IDE runs** — not with this app alone. Two react-x11 apps started from the
174
+ same terminal share one answer; the same app launched from Finder asks
175
+ again.
199
176
  - A bare `node` on the bridge rung lands in the same place: attributed to its
200
177
  responsible process, or to `node` itself where it has none.
201
178
  - **A bundled app is its own responsible process**, which is the only way to
@@ -204,15 +181,8 @@ AUTHREQ_ATTRIBUTION: service=kTCCServiceCalendar
204
181
  `NSCalendarsWriteOnlyAccessUsageDescription` where it asks for the narrower
205
182
  grant) or the request never prompts. See [packaging.md](packaging.md).
206
183
 
207
- Also measured on macOS 15.2, with the grant undecided:
208
-
209
- - `EKEventStore.authorizationStatusForEntityType` answers from an unbundled
210
- process with **no prompt** — a status read is always safe.
211
- - Creating the store never prompts either; only a request does.
212
- - Without the grant, `calendarsForEntityType` answers an **empty array** and
213
- `eventsMatchingPredicate` an empty one — no error. That is the whole reason
214
- the ladder checks the status first rather than reporting "no events".
215
- - The `osascript` child starts and answers its first line in ~130 ms.
184
+ Reading the status and opening the store never prompt; only a request (or the
185
+ first read) does.
216
186
 
217
187
  ## `useDesktopCalendarEvents()`
218
188
 
@@ -238,14 +208,13 @@ const {
238
208
  | `'denied'` | the user's answer. `openSettings()` is the way back |
239
209
  | `'unavailable'` | the machine's answer: no rung — or a request TCC would not even ask (above). Hide the feature rather than reporting it |
240
210
 
241
- `errors` is none of those: calendars that would not answer while others did.
242
- One unreachable CalDAV server must not blank a whole month of the user's own
243
- local calendar, so it is reported beside the events rather than instead of
244
- them. It is always empty on the macOS rungs, where there is one store.
211
+ `errors` is none of those: calendars that would not answer while others did
212
+ (one unreachable CalDAV server does not blank the user's local calendar). It
213
+ is always empty on the macOS rungs, where there is one store.
245
214
 
246
215
  **`from` and `to` are read by their timestamps, not their identity**, so
247
216
  `from={new Date(y, m, 1)}` inline in the render body is fine and does not
248
- re-query every paint. That is the mistake this hook is shaped to survive.
217
+ re-query every paint.
249
218
 
250
219
  ## What differs between the rungs
251
220
 
@@ -253,12 +222,11 @@ re-query every paint. That is the mistake this hook is shaped to survive.
253
222
  and `ical.js` expands them here. A malformed `RRULE` with no `UNTIL` is
254
223
  guarded at 2000 occurrences on that rung.
255
224
  - **`enabled`.** EDS reports whether the user switched a calendar off;
256
- EventKit has no such state — a calendar unchecked in Calendar.app is still
257
- in the store — so it is always `true` there.
225
+ EventKit has no such state (a calendar unchecked in Calendar.app is still in
226
+ the store), so it is always `true` there.
258
227
  - **The change signal.** EDS names the calendar, the kind (`ObjectsAdded`,
259
228
  `ObjectsModified`, `ObjectsRemoved`) and a count; EventKit's is one
260
- `'changed'` with a null calendar and no count, because its notification
261
- names nothing and a rung must not invent one.
229
+ `'changed'` with a null calendar and no count.
262
230
  - **The range.** EventKit's predicate spans at most four years, so a longer
263
231
  one is asked for in pieces and merged (an occurrence on a seam is reported
264
232
  once). EDS takes any range.
@@ -268,17 +236,12 @@ re-query every paint. That is the mistake this hook is shaped to survive.
268
236
 
269
237
  ## `ical.js`
270
238
 
271
- A regular dependency, loaded behind one lazy `import('ical.js')` with a
272
- static specifier: it is 268 KB of a 1.2 MB package, has no dependencies of
273
- its own, no native code and no install script (MPL-2.0, file-level copyleft).
274
- The `import()` keeps it off the startup path — an app that never opens a
275
- calendar never parses it — while a static specifier is something a bundler
276
- or a single-executable build can still follow, which the run-time-built
277
- specifier an optional dependency needs is not. Neither macOS rung loads it.
239
+ A regular dependency (MPL-2.0, no native code, no install script), loaded
240
+ lazily and only by the EDS rung, through a static `import('ical.js')` that a
241
+ bundler or single-executable build can follow.
278
242
 
279
243
  ## Writing
280
244
 
281
- Not yet — [#504](https://github.com/sidorares/react-x11/issues/504)'s third
282
- milestone. The bridge has `saveEvent`/`removeEvent` with the recurrence span
283
- (`@windowkit/appkit` >= 0.8) and EDS has `CreateObjects`/`ModifyObjects`/
284
- `RemoveObjects`, so the shape is known; what is here reads.
245
+ Not supported yet: this module reads.
246
+
247
+ Design notes: [design/desktop-calendar.md](../design/desktop-calendar.md).