react-native-gtkx 0.4.0-alpha.2 → 0.4.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.
- package/README.md +35 -96
- package/dist/adw/index.js +3 -2
- package/dist/adw/index.js.map +1 -1
- package/dist/apis/host.gtkx.js.map +1 -1
- package/dist/components/modal.d.ts +1 -1
- package/dist/components/modal.js +16 -8
- package/dist/components/modal.js.map +1 -1
- package/dist/dnd/gtk-controllers.js +1 -1
- package/dist/dnd/gtk-controllers.js.map +1 -1
- package/dist/gtk/index.js +4 -3
- package/dist/gtk/index.js.map +1 -1
- package/dist/gtkx/bridge/adw.js +1 -1
- package/dist/gtkx/bridge/adw.js.map +1 -1
- package/dist/gtkx/bridge/core.d.ts +1 -2
- package/dist/gtkx/bridge/core.js +2 -5
- package/dist/gtkx/bridge/core.js.map +1 -1
- package/dist/gtkx/bridge/geometry.js +1 -1
- package/dist/gtkx/bridge/geometry.js.map +1 -1
- package/dist/gtkx/bridge/layout-manager.js +18 -5
- package/dist/gtkx/bridge/layout-manager.js.map +1 -1
- package/dist/gtkx/bridge/slot-portal.js.map +1 -1
- package/dist/gtkx/bridge/svg-node.js +13 -6
- package/dist/gtkx/bridge/svg-node.js.map +1 -1
- package/dist/gtkx/bridge/view-box.js +19 -10
- package/dist/gtkx/bridge/view-box.js.map +1 -1
- package/dist/gtkx/bridge/widgets.generated.adw.js +1 -1
- package/dist/gtkx/bridge/widgets.generated.adw.js.map +1 -1
- package/dist/mcp/bin.js +1 -1
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/data/generated.d.ts +860 -531
- package/dist/mcp/data/generated.js +952 -538
- package/dist/mcp/data/generated.js.map +1 -1
- package/dist/mcp/resolve.d.ts +2 -2
- package/dist/mcp/resolve.js +2 -2
- package/dist/mcp/resolve.js.map +1 -1
- package/dist/mcp/server.js +2 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/runner/host-dev.js +5 -0
- package/dist/runner/host-dev.js.map +1 -1
- package/dist/runner/host.js +15 -0
- package/dist/runner/host.js.map +1 -1
- package/dist/runner/index.d.ts +27 -0
- package/dist/runner/index.js +206 -1
- package/dist/runner/index.js.map +1 -1
- package/dist/sea/assemble.d.ts +9 -0
- package/dist/sea/assemble.js +16 -3
- package/dist/sea/assemble.js.map +1 -1
- package/dist/sea/bundle.d.ts +37 -2
- package/dist/sea/bundle.js +77 -5
- package/dist/sea/bundle.js.map +1 -1
- package/dist/sea/native-shim.js +4 -3
- package/dist/sea/native-shim.js.map +1 -1
- package/dist/testing/index.js +28 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/vite/index.js +3 -3
- package/dist/vite/index.js.map +1 -1
- package/dist/vitest/index.d.ts +2 -2
- package/dist/vitest/index.js +1 -1
- package/dist/vitest/index.js.map +1 -1
- package/package.json +9 -9
- package/dist/gtkx/bridge/use-signal.d.ts +0 -2
- package/dist/gtkx/bridge/use-signal.js +0 -41
- package/dist/gtkx/bridge/use-signal.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
<h1 align="center">react-native-gtkx</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center"><b>React Native for the Linux desktop.</b><br/>
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
The <code>react-native</code> API, rendered as real GTK4/Adwaita widgets — no WebView,<br/>
|
|
9
|
+
no canvas, no bridge. Linux is a React Native out-of-tree platform here:<br/>
|
|
10
|
+
<code>npx react-native run-linux</code>, next to <code>run-ios</code> and <code>run-android</code>.</p>
|
|
10
11
|
|
|
11
12
|
<p align="center">
|
|
12
13
|
<a href="https://github.com/itsmepetrov/react-native-gtkx/actions/workflows/ci.yml"><img src="https://github.com/itsmepetrov/react-native-gtkx/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
|
|
@@ -14,110 +15,48 @@ applications on real GTK4/Adwaita widgets, with no WebView and no canvas renderi
|
|
|
14
15
|
<a href="https://github.com/itsmepetrov/react-native-gtkx/releases"><img src="https://img.shields.io/github/v/release/itsmepetrov/react-native-gtkx?label=deb%20packages" alt="releases" /></a>
|
|
15
16
|
</p>
|
|
16
17
|
|
|
17
|
-
Under the hood: [gtkx](https://github.com/gtkx-org/gtkx) (a React reconciler for GTK4
|
|
18
|
+
Under the hood: [gtkx](https://github.com/gtkx-org/gtkx) (a React reconciler for GTK4, with an in-process FFI into libgtk) and [Yoga](https://yogalayout.dev) — the same flexbox engine React Native itself uses. Navigation runs on real Adwaita widgets: react-navigation's stack and drawer are backed by an actual `Adw.NavigationView`/`Adw.NavigationSplitView`, so the back button, the slide transition, Escape, the back gesture and the back-history menu are the platform's, not a JS re-implementation. Past the portable surface, `react-native-gtkx/gtk` and `/adw` hand you every GTK/Adwaita widget directly — including a navigation stack that needs no router at all.
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
<table align="center">
|
|
21
|
+
<tr>
|
|
22
|
+
<td><img src="https://raw.githubusercontent.com/itsmepetrov/react-native-gtkx/main/docs/shots/hn-list.png" alt="Hacker News list — react-native-gtkx"/></td>
|
|
23
|
+
<td><img src="https://raw.githubusercontent.com/itsmepetrov/react-native-gtkx/main/docs/shots/hn-story.png" alt="story screen with comments"/></td>
|
|
24
|
+
</tr>
|
|
25
|
+
</table>
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
<p align="center"><i><code>examples/hn-app</code>, live in native GTK windows: a Hacker News reader on the standard React Native Metro toolchain. Tapping a card pushes a real <code>Adw.NavigationView</code> page — the back button, the slide and the preserved list position come from the platform, not from JS. The search field sits <b>inside</b> the HeaderBar (real RN content in native chrome) and queries the HN API; comments load as you scroll. The data layer is plain Node <code>fetch</code> — on this platform "native modules" are just Node.</i></p>
|
|
23
28
|
|
|
24
29
|
And the portability proof — `examples/profile` renders ONE source file with both renderers, not a single `@gtkx/*` import in it:
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- [x] Windowed lists: virtualization (10k rows), sticky headers, SectionList, scrollToIndex, viewability, inverted (RN chat semantics), refresh parity
|
|
43
|
-
- [x] Linux as an RN **out-of-tree platform**: the standard Metro/Babel toolchain, `react-native.config.js` declared by the dependency, `npx react-native run-linux`, compiled package distribution (attw-checked) — see `examples/rn-app` (a cli-init app with ios + android + linux)
|
|
44
|
-
- [x] **Fast Refresh on both toolchains**: `run-linux --dev` (Metro dev server + HMR in the GTK host, state preserved) and `gtkx dev` (vite)
|
|
45
|
-
- [x] **Navigation on real Adwaita widgets**: react-navigation navigators backed by `Adw.NavigationView` and `Adw.NavigationSplitView` — see below
|
|
46
|
-
|
|
47
|
-
Verified live: `examples/hn-app` (a Hacker News reader on the Metro path), `examples/gallery` (the whole surface, 33 sections), and `examples/tasks-app` (a full GNOME task manager — a port of the [gtkx tutorial](https://gtkx.dev/tutorial/)'s Tasks app, and the platform's most demanding app so far) — 1,800 tests (unit + component tests under headless Wayland).
|
|
48
|
-
|
|
49
|
-
## Navigation is native, not redrawn
|
|
50
|
-
|
|
51
|
-
```tsx
|
|
52
|
-
import { NavigationContainer } from "@react-navigation/native"
|
|
53
|
-
import { createStackNavigator } from "react-native-gtkx/navigation"
|
|
31
|
+
<table align="center">
|
|
32
|
+
<tr>
|
|
33
|
+
<th>react-native-gtkx (GTK4)</th>
|
|
34
|
+
<th>react-native-web (browser)</th>
|
|
35
|
+
</tr>
|
|
36
|
+
<tr>
|
|
37
|
+
<td><img src="https://raw.githubusercontent.com/itsmepetrov/react-native-gtkx/main/docs/shots/profile.png" width="400" alt="profile — GTK"/></td>
|
|
38
|
+
<td><img src="https://raw.githubusercontent.com/itsmepetrov/react-native-gtkx/main/docs/shots/profile-web.png" width="400" alt="profile — web"/></td>
|
|
39
|
+
</tr>
|
|
40
|
+
</table>
|
|
41
|
+
|
|
42
|
+
## Quickstart
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx degit itsmepetrov/react-native-gtkx/template my-app && cd my-app
|
|
46
|
+
npm install && npm run dev # a window, with Fast Refresh
|
|
54
47
|
```
|
|
55
48
|
|
|
56
|
-
|
|
57
|
-
react-navigation state stays the source of truth. The consequence: the back
|
|
58
|
-
button, the slide transition, Escape, the back gesture and the back-history
|
|
59
|
-
menu are the platform's, not a JS re-implementation — and a native pop is
|
|
60
|
-
reported back into react-navigation state instead of fighting it. Screen
|
|
61
|
-
options map onto the real chrome (`title`, `headerShown`, `gestureEnabled`
|
|
62
|
-
→ the page's `can-pop`, which is also what makes `usePreventRemove` work),
|
|
63
|
-
`headerLeft`/`headerRight` accept ordinary React Native content rendered
|
|
64
|
-
_inside_ the HeaderBar, and `createSidebarNavigator` gives the desktop
|
|
65
|
-
answer to a drawer: a persistent `Adw.NavigationSplitView` sidebar
|
|
66
|
-
(`examples/gallery` runs on it).
|
|
67
|
-
|
|
68
|
-
**No other out-of-tree React Native platform does this.** react-native-screens
|
|
69
|
-
lists Windows support, but it is an old-architecture stub that does not build
|
|
70
|
-
against modern react-native-windows — Microsoft's own showcase app falls back
|
|
71
|
-
to the JS drawer; react-native-macos is not supported by it at all, because
|
|
72
|
-
AppKit has no navigation-stack primitive to bind to. GTK4/libadwaita does have
|
|
73
|
-
one, so the model here is the iOS `native-stack` one:
|
|
74
|
-
[docs/research/navigation-extensibility.md](https://github.com/itsmepetrov/react-native-gtkx/blob/main/docs/research/navigation-extensibility.md)
|
|
75
|
-
lays out the split, what an app can reach, and what is meaningless on a
|
|
76
|
-
desktop.
|
|
77
|
-
|
|
78
|
-
Underneath it, [`react-native-gtkx/gtk` and `react-native-gtkx/adw`](https://github.com/itsmepetrov/react-native-gtkx/blob/main/docs/platform-layer.md) exposes the
|
|
79
|
-
widgets themselves — including a navigation stack that needs no router at
|
|
80
|
-
all, and GTK widgets that take a React Native `style` for position and
|
|
81
|
-
appearance. react-navigation is a convenience here, not the ceiling.
|
|
82
|
-
|
|
83
|
-
## Performance architecture
|
|
84
|
-
|
|
85
|
-
There is no "bridge tax" here. React Native's historic bottleneck — JSON
|
|
86
|
-
batches serialized between the JS and native threads — does not exist in this
|
|
87
|
-
architecture: gtkx binds GTK through an in-process FFI (NAPI-RS), so a widget
|
|
88
|
-
call is a synchronous C call on the same thread, with numbers and pointers
|
|
89
|
-
marshalled directly. That is the same direction React Native itself took with
|
|
90
|
-
JSI/Fabric, where Yoga and view commits run through direct synchronous calls.
|
|
91
|
-
|
|
92
|
-
Layout math runs in Yoga compiled to WASM (near-native speed): a 500-node
|
|
93
|
-
reflow measures at 0.13–0.17 ms. The GTK side is driven by our own
|
|
94
|
-
GtkLayoutManager subclass; a full measure+allocate pass over a 50-child
|
|
95
|
-
container costs ~0.21 ms including every FFI hop. Animation frames bypass
|
|
96
|
-
layout entirely — an Animated value write is a WeakMap store plus one queued
|
|
97
|
-
GTK allocation. Two orders of magnitude of headroom against a 60 fps frame
|
|
98
|
-
budget, measured, not estimated (see docs/research/yoga-gtk-spike.md and
|
|
99
|
-
docs/research/layout-manager.md).
|
|
100
|
-
|
|
101
|
-
Those are this layer's own costs, and a scrolling-list study measured what
|
|
102
|
-
share of a real frame they are: 0.6 ms of a 44.5 ms frame at full screen,
|
|
103
|
-
where the rest is software rasterization on a GPU-less test VM. Windowed,
|
|
104
|
-
a `FlatList` is indistinguishable from a native `GtkScrolledWindow`. Read
|
|
105
|
-
that as "the compatibility layer is not what costs frames on that rig"
|
|
106
|
-
rather than as an absolute — the same study retracted an earlier headline
|
|
107
|
-
number that had compared two different window sizes
|
|
108
|
-
(docs/research/scroll-performance.md).
|
|
49
|
+
Adding Linux to an app that already ships iOS/Android is `npm install react-native-gtkx`, a one-line Metro config wrap, and `npx react-native run-linux` — see [installation](https://github.com/itsmepetrov/react-native-gtkx/blob/main/docs/guide/installation.md).
|
|
109
50
|
|
|
110
51
|
## Documentation
|
|
111
52
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
- [
|
|
115
|
-
- [
|
|
116
|
-
- [
|
|
117
|
-
- [
|
|
118
|
-
- [
|
|
119
|
-
- [What we need from gtkx](https://github.com/itsmepetrov/react-native-gtkx/blob/main/docs/upstream-gtkx.md) — the standing upstream agenda (bugs with repros, API asks, workarounds we want to delete);
|
|
120
|
-
- [CONTRIBUTING](https://github.com/itsmepetrov/react-native-gtkx/blob/main/CONTRIBUTING.md) — developing the library (from macOS — via the UTM VM).
|
|
53
|
+
The full docs, including screenshots per component and a searchable reference, are published at [itsmepetrov.github.io/react-native-gtkx](https://itsmepetrov.github.io/react-native-gtkx/) (source in this repo's `docs/` tree):
|
|
54
|
+
|
|
55
|
+
- [Guide](https://itsmepetrov.github.io/react-native-gtkx/docs/guide/installation) — [installation](https://itsmepetrov.github.io/react-native-gtkx/docs/guide/installation), [your first app](https://itsmepetrov.github.io/react-native-gtkx/docs/guide/first-app), [Metro vs. vite toolchains](https://itsmepetrov.github.io/react-native-gtkx/docs/guide/toolchains), the [plain-GTK profile](https://itsmepetrov.github.io/react-native-gtkx/docs/guide/plain-gtk), [packaging](https://itsmepetrov.github.io/react-native-gtkx/docs/guide/packaging) (debs, standalone).
|
|
56
|
+
- [Reference](https://itsmepetrov.github.io/react-native-gtkx/docs/reference) — every component and API, each with its GTK/Adw badge and its differences from React Native.
|
|
57
|
+
- [Architecture](https://itsmepetrov.github.io/react-native-gtkx/docs/architecture/overview) — [overview](https://itsmepetrov.github.io/react-native-gtkx/docs/architecture/overview) (the reconciler-to-gtkx path, the widget surface), [layout and styling](https://itsmepetrov.github.io/react-native-gtkx/docs/architecture/layout-and-styling) (the Yoga shadow tree, the style split), [gestures](https://itsmepetrov.github.io/react-native-gtkx/docs/architecture/gestures), and [window/navigation/settings integration](https://itsmepetrov.github.io/react-native-gtkx/docs/architecture/integration).
|
|
58
|
+
- [gtkx upstream agenda](https://github.com/itsmepetrov/react-native-gtkx/blob/main/docs/upstream-gtkx.md) — the standing agenda for gtkx itself.
|
|
59
|
+
- [CONTRIBUTING](https://github.com/itsmepetrov/react-native-gtkx/blob/main/CONTRIBUTING.md) — developing the library from macOS, via a Linux VM.
|
|
121
60
|
|
|
122
61
|
## Requirements
|
|
123
62
|
|
package/dist/adw/index.js
CHANGED
|
@@ -49,8 +49,9 @@ export { Adw } from "../gtkx/bridge/adw-namespace";
|
|
|
49
49
|
// (the `breakpoints` prop of AdwApplicationWindow/AdwBreakpointBin/AdwDialog
|
|
50
50
|
// takes one of these as a child) and the two leaf elements a
|
|
51
51
|
// AdwShortcutsDialog's AdwShortcutsSection is built from. See
|
|
52
|
-
// docs/
|
|
53
|
-
//
|
|
52
|
+
// docs/architecture/overview.md, "The widget surface: wrapped, raw, and
|
|
53
|
+
// auxiliary", and docs/architecture/layout-and-styling.md, "Two ways to
|
|
54
|
+
// react to size" — createSidebarNavigator's own collapse
|
|
54
55
|
// (src/navigation/sidebar.tsx) pairs AdwBreakpoint with AdwBreakpointBin
|
|
55
56
|
// (a real widget, wrapped above) to scope a breakpoint to a subtree.
|
|
56
57
|
const { AdwBreakpoint, AdwShortcutsItem, AdwShortcutsSection, AdwToggle } = requireAdwJsx("react-native-gtkx/adw");
|
package/dist/adw/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adw/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,iEAAiE;AACjE,8DAA8D;AAC9D,yFAAyF;AACzF,4BAA4B;AAC5B,EAAE;AACF,0EAA0E;AAC1E,4EAA4E;AAC5E,EAAE;AACF,wEAAwE;AACxE,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,sEAAsE;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,2EAA2E;AAC3E,4DAA4D;AAC5D,EAAE;AACF,wEAAwE;AACxE,6EAA6E;AAC7E,yEAAyE;AACzE,mEAAmE;AACnE,6EAA6E;AAC7E,6EAA6E;AAC7E,oEAAoE;AACpE,0DAA0D;AAC1D,cAAc,qBAAqB,CAAA;AAEnC,2EAA2E;AAC3E,yEAAyE;AACzE,0EAA0E;AAC1E,2EAA2E;AAC3E,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAC1E,qEAAqE;AACrE,0EAA0E;AAC1E,sEAAsE;AACtE,2EAA2E;AAC3E,0EAA0E;AAC1E,sEAAsE;AACtE,sEAAsE;AACtE,2EAA2E;AAC3E,wEAAwE;AACxE,oCAAoC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,8BAA8B,CAAA;AAElD,oEAAoE;AACpE,0EAA0E;AAC1E,6EAA6E;AAC7E,6DAA6D;AAC7D,8DAA8D;AAC9D,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adw/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,iEAAiE;AACjE,8DAA8D;AAC9D,yFAAyF;AACzF,4BAA4B;AAC5B,EAAE;AACF,0EAA0E;AAC1E,4EAA4E;AAC5E,EAAE;AACF,wEAAwE;AACxE,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,sEAAsE;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,2EAA2E;AAC3E,4DAA4D;AAC5D,EAAE;AACF,wEAAwE;AACxE,6EAA6E;AAC7E,yEAAyE;AACzE,mEAAmE;AACnE,6EAA6E;AAC7E,6EAA6E;AAC7E,oEAAoE;AACpE,0DAA0D;AAC1D,cAAc,qBAAqB,CAAA;AAEnC,2EAA2E;AAC3E,yEAAyE;AACzE,0EAA0E;AAC1E,2EAA2E;AAC3E,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAC1E,qEAAqE;AACrE,0EAA0E;AAC1E,sEAAsE;AACtE,2EAA2E;AAC3E,0EAA0E;AAC1E,sEAAsE;AACtE,sEAAsE;AACtE,2EAA2E;AAC3E,wEAAwE;AACxE,oCAAoC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,8BAA8B,CAAA;AAElD,oEAAoE;AACpE,0EAA0E;AAC1E,6EAA6E;AAC7E,6DAA6D;AAC7D,8DAA8D;AAC9D,wEAAwE;AACxE,wEAAwE;AACxE,yDAAyD;AACzD,yEAAyE;AACzE,qEAAqE;AACrE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,SAAS,EAAE,GACvE,aAAa,CAAC,uBAAuB,CAAC,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,SAAS,EAAE,CAAA","sourcesContent":["// react-native-gtkx/adw — libadwaita widgets as React components.\n//\n// The Adwaita half of the platform layer; its GTK counterpart is\n// react-native-gtkx/gtk, and what we wrote ourselves lives in\n// react-native-gtkx/common (NavigationStack, SlotContent, wrapReactNative). Nothing here\n// imports react-navigation.\n//\n// NAMING, one rule across both subpaths: a name carrying a `Gtk` or `Adw`\n// prefix IS that widget, as gtkx binds it. A name without a prefix is ours.\n//\n// The layering mirrors the React Native ecosystem: react-native-screens\n// exposes primitives, @react-navigation/native-stack binds them to a router.\n// Here, this subpath exposes primitives and react-native-gtkx/navigation\n// binds them to react-navigation. You can skip the binding entirely — drive\n// NavigationStack from useState, from your own router, from anything.\nimport { requireAdwJsx } from \"../gtkx/bridge/adw\"\n\n// The raw widgets, exactly as gtkx binds them — every GObject property and\n// signal, including ones added after this file was written.\n//\n// AdwNavigationView and AdwNavigationPage are the imperative originals:\n// NavigationStack above is a declarative alternative, NOT a replacement, and\n// a standard widget must never become unreachable because we wrapped it.\n// The full Adwaita widget surface lives in a generated file: every\n// Adw.Widget subclass gtkx binds, wrapped so React Native drives it. The raw\n// AdwNavigationView and AdwNavigationPage are in there too — NavigationStack\n// in react-native-gtkx/common is a declarative alternative, never a\n// replacement, and a standard widget must stay reachable.\nexport * from \"./widgets.generated\"\n\n// This whole subpath REQUIRES Adw-1 (see .claude/epics/adw-optional/001.md\n// and docs/api.md) — a bare re-export of an actual namespace import (see\n// gtkx/bridge/adw-namespace.ts), so `Adw` keeps working exactly as it did\n// before this epic: both a value (`Adw.Toast.new(title)`, `Adw.ColorScheme\n// .FORCE_DARK`) and a namespace in type position (`Ref<Adw.ToastOverlay |\n// null>`), in ONE import, from real apps (examples/tasks-app/tasks-nav's\n// toast.tsx and window.tsx, examples/gallery's adwaita-stack.tsx) as well\n// as ours. That duality does not survive being synthesized through a\n// function call (tried: adw.ts's requireAdwGi() — the value comes through\n// fine, but \"Cannot find namespace 'Adw'\" everywhere it was used as a\n// type), which is why this is a re-export of a plain, eager, static import\n// rather than routed through the lazy probe every other Adw value in this\n// package goes through. Importing react-native-gtkx/adw without Adw-1\n// throws at import time regardless — just as a build failure one line\n// down (adw-namespace.ts's own `@gtkx/gi/adw` import, unresolvable without\n// it) instead of a thrown Error, which is an equally loud refusal for a\n// subpath that always requires Adw.\nexport { Adw } from \"../gtkx/bridge/adw-namespace\"\n\n// Auxiliary JSX elements that are not Adw.Widget subclasses, so the\n// generated widget surface above never sees them: a responsive breakpoint\n// (the `breakpoints` prop of AdwApplicationWindow/AdwBreakpointBin/AdwDialog\n// takes one of these as a child) and the two leaf elements a\n// AdwShortcutsDialog's AdwShortcutsSection is built from. See\n// docs/architecture/overview.md, \"The widget surface: wrapped, raw, and\n// auxiliary\", and docs/architecture/layout-and-styling.md, \"Two ways to\n// react to size\" — createSidebarNavigator's own collapse\n// (src/navigation/sidebar.tsx) pairs AdwBreakpoint with AdwBreakpointBin\n// (a real widget, wrapped above) to scope a breakpoint to a subtree.\nconst { AdwBreakpoint, AdwShortcutsItem, AdwShortcutsSection, AdwToggle } =\n requireAdwJsx(\"react-native-gtkx/adw\")\nexport { AdwBreakpoint, AdwShortcutsItem, AdwShortcutsSection, AdwToggle }\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.gtkx.js","sourceRoot":"","sources":["../../src/apis/host.gtkx.ts"],"names":[],"mappings":"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","sourcesContent":["// Production host adapter: the ONLY module under src/apis/ allowed to import\n// the gtkx bridge. Everything GTK-specific lives here; the API modules stay\n// pure and receive this object (or a mock in unit tests) via injection.\n\nimport type { SubscriptionHandle } from \"../contracts\"\nimport {\n adwAvailable,\n colorScheme,\n requireAdwGi,\n styleManager,\n} from \"../gtkx/bridge/adw\"\nimport {\n getPlainColorScheme,\n onPlainColorSchemeChange,\n setPlainColorScheme,\n} from \"../gtkx/bridge/color-scheme-portal\"\nimport { Gdk, Gio, Gtk, quit, toNumber } from \"../gtkx/bridge/index\"\nimport type {\n ColorSchemeName,\n Host,\n HostAlertRequest,\n ScaledSize,\n} from \"./host\"\n\nconst FALLBACK_METRICS: ScaledSize = {\n width: 0,\n height: 0,\n scale: 1,\n fontScale: 1,\n}\n\nconst getApplication = (): Gtk.Application | null =>\n Gio.Application.getDefault() as unknown as Gtk.Application | null\n\nconst getActiveAppWindow = (): Gtk.Window | null => {\n const app = getApplication()\n if (!app || typeof app.getActiveWindow !== \"function\") {\n return null\n }\n return app.getActiveWindow() ?? null\n}\n\nconst windowAt = (model: Gio.ListModel, index: number): Gtk.Window | null =>\n model.getItem(index) as unknown as Gtk.Window | null\n\n// The application's active window if any, otherwise the first toplevel. The\n// toplevel fallback covers the test harness, where windows exist without a\n// GtkApplication (`Gio.Application.getDefault()` is null there).\n// RN's Dimensions(\"window\") means the MAIN window: transient toplevels\n// (Modal → modal GtkWindow, dialogs) must never be resolved as \"the window\" —\n// an open modal becomes the active window and would shrink the app viewport\n// to the modal size.\nconst isMainWindow = (window: Gtk.Window): boolean =>\n window.getTransientFor() === null\n\nconst resolveWindow = (): Gtk.Window | null => {\n const active = getActiveAppWindow()\n if (active && isMainWindow(active)) {\n return active\n }\n const toplevels = Gtk.Window.getToplevels()\n const count = toNumber(toplevels.getNItems())\n let first: Gtk.Window | null = null\n for (let index = 0; index < count; index += 1) {\n const window = windowAt(toplevels, index)\n if (!window || !isMainWindow(window)) {\n continue\n }\n if (window.isActive()) {\n return window\n }\n first = first ?? window\n }\n return first\n}\n\nconst isAnyWindowActive = (): boolean => {\n const toplevels = Gtk.Window.getToplevels()\n const count = toNumber(toplevels.getNItems())\n for (let index = 0; index < count; index += 1) {\n if (windowAt(toplevels, index)?.isActive()) {\n return true\n }\n }\n return false\n}\n\nconst windowMetrics = (): ScaledSize => {\n const window = resolveWindow()\n if (!window) {\n return FALLBACK_METRICS\n }\n // RN's Dimensions(\"window\") is the app viewport: the window CHILD's\n // allocation (the content area under the headerbar), not the window widget\n // size. Falls back to the window size before the first allocation.\n const child = window.getChild()\n const childAllocation = child?.getAllocation()\n const allocatedWidth =\n childAllocation && childAllocation.width > 0\n ? toNumber(childAllocation.width)\n : toNumber(window.getWidth())\n const allocatedHeight =\n childAllocation && childAllocation.height > 0\n ? toNumber(childAllocation.height)\n : toNumber(window.getHeight())\n // Before the first allocation everything reports 0 — fall back to\n // the requested default size (which GTK4 also keeps updated on resize).\n const width =\n allocatedWidth > 0\n ? allocatedWidth\n : Math.max(toNumber(window.defaultWidth ?? 0), 0)\n const height =\n allocatedHeight > 0\n ? allocatedHeight\n : Math.max(toNumber(window.defaultHeight ?? 0), 0)\n return {\n width,\n height,\n scale: toNumber(window.getScaleFactor()),\n fontScale: 1,\n }\n}\n\nconst screenMetrics = (): ScaledSize => {\n const display = Gdk.Display.getDefault()\n if (!display) {\n return windowMetrics()\n }\n const monitors = display.getMonitors()\n if (toNumber(monitors.getNItems()) === 0) {\n return windowMetrics()\n }\n const monitor = monitors.getItem(0) as unknown as Gdk.Monitor | null\n if (!monitor) {\n return windowMetrics()\n }\n const geometry = monitor.getGeometry()\n return {\n width: toNumber(geometry.width),\n height: toNumber(geometry.height),\n scale: toNumber(monitor.getScaleFactor()),\n fontScale: 1,\n }\n}\n\n// GtkNative.getSurface is an interface method merged onto Gtk.Window at\n// runtime via mixins; accessed defensively to stay typecheckable either way.\nconst surfaceOf = (window: Gtk.Window): Gdk.Surface | null => {\n const native = window as unknown as { getSurface?: () => Gdk.Surface | null }\n return typeof native.getSurface === \"function\"\n ? (native.getSurface() ?? null)\n : null\n}\n\n// Tracks the \"current\" window across creation/destruction/focus moves:\n// listens on the given signals of the resolved window (and, when requested,\n// its GdkSurface) plus the toplevel list model, re-resolving and re-attaching\n// whenever the tracked window may have changed. Modules dedupe, so\n// over-notifying is fine.\n//\n// Why the surface: notify::default-width fires when setDefaultSize() is\n// called, i.e. before the compositor actually resizes the surface — the\n// allocated size (what Dimensions reports) only changes when the surface\n// does. And GdkSurface notify::width/height fires at configure time, still\n// before the widget allocation pass, so the \"layout\" signal is also needed:\n// it is emitted during the frame's layout phase and — because GTK's own\n// relayout handler is connected first — our handler observes the updated\n// allocation. The module dedupes, so early/no-op emissions cost nothing.\nconst watchWindow = (\n windowSignals: readonly string[],\n surfaceSignals: readonly string[],\n notify: () => void,\n): SubscriptionHandle => {\n let window: Gtk.Window | null = null\n let surface: Gdk.Surface | null = null\n\n const attachWindow = (): void => {\n if (!window) {\n return\n }\n for (const signal of windowSignals) {\n window.on(signal, onSignal)\n }\n }\n\n const detachWindow = (): void => {\n if (!window) {\n return\n }\n for (const signal of windowSignals) {\n window.off(signal, onSignal)\n }\n }\n\n const attachSurface = (): void => {\n if (!surface) {\n return\n }\n for (const signal of surfaceSignals) {\n surface.on(signal, onSignal)\n }\n }\n\n const detachSurface = (): void => {\n if (!surface) {\n return\n }\n for (const signal of surfaceSignals) {\n surface.off(signal, onSignal)\n }\n }\n\n const syncTargets = (): void => {\n const nextWindow = resolveWindow()\n if (nextWindow !== window) {\n detachWindow()\n window = nextWindow\n attachWindow()\n }\n const nextSurface =\n window && surfaceSignals.length > 0 ? surfaceOf(window) : null\n if (nextSurface !== surface) {\n detachSurface()\n surface = nextSurface\n attachSurface()\n }\n }\n\n const onSignal = (): void => {\n syncTargets()\n notify()\n }\n\n const toplevels = Gtk.Window.getToplevels()\n const onToplevelsChanged = (): void => {\n syncTargets()\n notify()\n }\n toplevels.on(\"items-changed\", onToplevelsChanged)\n syncTargets()\n\n return {\n remove: () => {\n detachWindow()\n detachSurface()\n window = null\n surface = null\n toplevels.off(\"items-changed\", onToplevelsChanged)\n },\n }\n}\n\n// realize/map re-run target resolution so the surface listeners attach as\n// soon as the surface exists.\nconst WINDOW_SIZE_SIGNALS = [\n \"notify::default-width\",\n \"notify::default-height\",\n \"realize\",\n \"map\",\n] as const\n\nconst SURFACE_SIZE_SIGNALS = [\n \"notify::width\",\n \"notify::height\",\n \"layout\",\n] as const\n\nconst WINDOW_ACTIVE_SIGNALS = [\"notify::is-active\"] as const\n\nconst gtkVersion = (): string =>\n `${toNumber(Gtk.getMajorVersion())}.${toNumber(Gtk.getMinorVersion())}.${toNumber(Gtk.getMicroVersion())}`\n\n// AdwStyleManager is the only thing that decides the palette here, and it is\n// enough on its own — appearance.test.tsx asserts that a real widget's\n// computed foreground flips with it. This used to also write the classic\n// GtkSettings:gtk-application-prefer-dark-theme, guarding against Adwaita\n// not restyling a GtkApplication (we do not use AdwApplication). Under\n// libadwaita that write is inert: adw_init() takes the color scheme over,\n// answers the setting with \"unsupported ... use AdwStyleManager:color-scheme\n// instead\" and keeps its own value, so all the duplicate ever produced was a\n// warning per call — seven per test run.\nconst setColorSchemeAdw = (scheme: ColorSchemeName | null): void => {\n const manager = styleManager()\n const { ColorScheme } = requireAdwGi(\"Appearance\")\n if (scheme === \"dark\") {\n manager.setColorScheme(ColorScheme.FORCE_DARK)\n } else if (scheme === \"light\") {\n manager.setColorScheme(ColorScheme.FORCE_LIGHT)\n } else {\n manager.setColorScheme(ColorScheme.DEFAULT)\n }\n}\n\nconst onColorSchemeChangeAdw = (notify: () => void): SubscriptionHandle => {\n const manager = styleManager()\n const listener = (): void => notify()\n manager.on(\"notify::dark\", listener)\n return { remove: () => manager.off(\"notify::dark\", listener) }\n}\n\n// Without Adw-1 (adwAvailable() === false): the org.freedesktop.appearance\n// portal, falling back to Gtk.Settings — see gtkx/bridge/color-scheme-portal.ts\n// for the two-tier mechanism and .claude/epics/adw-optional/004.md for why.\nconst setColorScheme = (scheme: ColorSchemeName | null): void =>\n adwAvailable() ? setColorSchemeAdw(scheme) : setPlainColorScheme(scheme)\n\nconst onColorSchemeChange = (notify: () => void): SubscriptionHandle =>\n adwAvailable()\n ? onColorSchemeChangeAdw(notify)\n : onPlainColorSchemeChange(notify)\n\nconst showAlertAdw = async (\n request: HostAlertRequest,\n): Promise<string | null> => {\n const { AlertDialog, ResponseAppearance } = requireAdwGi(\"Alert\")\n const dialog = new AlertDialog()\n dialog.setHeading(request.title)\n if (request.message !== undefined && request.message.length > 0) {\n dialog.setBody(request.message)\n }\n let closeResponse: string | null = null\n for (const button of request.buttons) {\n dialog.addResponse(button.id, button.label)\n if (button.style === \"destructive\") {\n dialog.setResponseAppearance(button.id, ResponseAppearance.DESTRUCTIVE)\n }\n if (button.isPreferred) {\n dialog.setResponseAppearance(button.id, ResponseAppearance.SUGGESTED)\n dialog.setDefaultResponse(button.id)\n }\n if (button.style === \"cancel\") {\n closeResponse = button.id\n }\n }\n if (closeResponse !== null) {\n // Esc / close maps onto the cancel button, like RN's cancel semantics.\n dialog.setCloseResponse(closeResponse)\n } else if (!request.cancelable) {\n // No cancel button and not cancelable: block Esc-dismissal. Responses\n // still close the dialog (they bypass the can-close guard).\n dialog.setCanClose(false)\n }\n const response = await dialog.choose(resolveWindow())\n // Anything that is not one of our buttons (e.g. the built-in \"close\"\n // response) is a dismissal.\n return request.buttons.some((button) => button.id === response)\n ? response\n : null\n}\n\n// Without Adw-1: Gtk.AlertDialog (GTK >= 4.10) — index-based rather than\n// Adw's string response ids, so the button's position in request.buttons IS\n// its Gtk.AlertDialog index; no id bookkeeping needed. What is LOST: Adw's\n// ResponseAppearance (DESTRUCTIVE/SUGGESTED) has no Gtk.AlertDialog\n// equivalent at all — every button renders the same, undocumented-away in\n// docs/api.md's Alert row rather than silently dropped. Default/cancel\n// mapping is preserved via defaultButton/cancelButton, same idea as Adw's\n// defaultResponse/closeResponse above.\nconst showAlertPlain = async (\n request: HostAlertRequest,\n): Promise<string | null> => {\n const dialog = new Gtk.AlertDialog({\n message: request.title,\n detail: request.message ?? \"\",\n buttons: request.buttons.map((button) => button.label),\n modal: true,\n })\n const preferredIndex = request.buttons.findIndex(\n (button) => button.isPreferred,\n )\n if (preferredIndex >= 0) {\n dialog.setDefaultButton(preferredIndex)\n }\n const cancelIndex = request.buttons.findIndex(\n (button) => button.style === \"cancel\",\n )\n if (cancelIndex >= 0) {\n // Esc maps onto the cancel button, same as the Adw path's closeResponse.\n dialog.setCancelButton(cancelIndex)\n } else if (!request.cancelable && process.env.NODE_ENV !== \"production\") {\n // Unlike Adw.AlertDialog.setCanClose(false), Gtk.AlertDialog has no way\n // to block Esc/window-close dismissal outright — with no cancel button\n // set, GTK closes the dialog anyway and rejects choose() with\n // Gtk.DialogError.DISMISSED (caught below, mapped to the same null\n // dismissal cancelable: true would produce). Documented in docs/api.md;\n // an app that truly needs to block dismissal should add a cancel\n // button on both profiles rather than relying on cancelable: false alone.\n console.warn(\n '[react-native-gtkx] Alert.alert was called with cancelable: false and no \"cancel\" ' +\n \"style button. The plain-GTK profile's Gtk.AlertDialog fallback cannot block \" +\n \"Esc/window-close dismissal the way Adw.AlertDialog does — the dialog stays \" +\n \"dismissable. Add a cancel-style button for identical behavior on both profiles.\",\n )\n }\n try {\n const index = await dialog.choose(resolveWindow())\n return request.buttons[index]?.id ?? null\n } catch {\n // Dismissed (Esc / window-close) with no valid cancel button — the\n // plain-profile equivalent of the Adw path's unmatched \"close\" response.\n return null\n }\n}\n\nconst showAlert = async (request: HostAlertRequest): Promise<string | null> =>\n adwAvailable() ? showAlertAdw(request) : showAlertPlain(request)\n\nconst launchUri = async (uri: string): Promise<void> => {\n const launcher = new Gtk.UriLauncher({ uri })\n // Promisified by the gi codegen; rejects with the GError on failure.\n await launcher.launch(resolveWindow())\n}\n\n// The default widget direction is GTK's read of the locale text direction.\nconst isRTL = (): boolean => {\n try {\n return Gtk.Widget.getDefaultDirection() === Gtk.TextDirection.RTL\n } catch {\n return false\n }\n}\n\nexport const gtkxHost: Host = {\n gtkVersion,\n getWindowMetrics: windowMetrics,\n getScreenMetrics: screenMetrics,\n onMetricsChange: (notify) =>\n watchWindow(WINDOW_SIZE_SIGNALS, SURFACE_SIZE_SIGNALS, notify),\n getColorScheme: () =>\n adwAvailable() ? colorScheme() : getPlainColorScheme(),\n setColorScheme,\n onColorSchemeChange,\n isActive: isAnyWindowActive,\n onActiveChange: (notify) => watchWindow(WINDOW_ACTIVE_SIGNALS, [], notify),\n showAlert,\n launchUri,\n isRTL,\n exitApp: () => quit(),\n}\n"]}
|
|
1
|
+
{"version":3,"file":"host.gtkx.js","sourceRoot":"","sources":["../../src/apis/host.gtkx.ts"],"names":[],"mappings":"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","sourcesContent":["// Production host adapter: the ONLY module under src/apis/ allowed to import\n// the gtkx bridge. Everything GTK-specific lives here; the API modules stay\n// pure and receive this object (or a mock in unit tests) via injection.\n\nimport type { SubscriptionHandle } from \"../contracts\"\nimport {\n adwAvailable,\n colorScheme,\n requireAdwGi,\n styleManager,\n} from \"../gtkx/bridge/adw\"\nimport {\n getPlainColorScheme,\n onPlainColorSchemeChange,\n setPlainColorScheme,\n} from \"../gtkx/bridge/color-scheme-portal\"\nimport { Gdk, Gio, Gtk, quit, toNumber } from \"../gtkx/bridge/index\"\nimport type {\n ColorSchemeName,\n Host,\n HostAlertRequest,\n ScaledSize,\n} from \"./host\"\n\nconst FALLBACK_METRICS: ScaledSize = {\n width: 0,\n height: 0,\n scale: 1,\n fontScale: 1,\n}\n\nconst getApplication = (): Gtk.Application | null =>\n Gio.Application.getDefault() as unknown as Gtk.Application | null\n\nconst getActiveAppWindow = (): Gtk.Window | null => {\n const app = getApplication()\n if (!app || typeof app.getActiveWindow !== \"function\") {\n return null\n }\n return app.getActiveWindow() ?? null\n}\n\nconst windowAt = (model: Gio.ListModel, index: number): Gtk.Window | null =>\n model.getItem(index) as unknown as Gtk.Window | null\n\n// The application's active window if any, otherwise the first toplevel. The\n// toplevel fallback covers the test harness, where windows exist without a\n// GtkApplication (`Gio.Application.getDefault()` is null there).\n// RN's Dimensions(\"window\") means the MAIN window: transient toplevels\n// (Modal → modal GtkWindow, dialogs) must never be resolved as \"the window\" —\n// an open modal becomes the active window and would shrink the app viewport\n// to the modal size.\nconst isMainWindow = (window: Gtk.Window): boolean =>\n window.getTransientFor() === null\n\nconst resolveWindow = (): Gtk.Window | null => {\n const active = getActiveAppWindow()\n if (active && isMainWindow(active)) {\n return active\n }\n const toplevels = Gtk.Window.getToplevels()\n const count = toNumber(toplevels.getNItems())\n let first: Gtk.Window | null = null\n for (let index = 0; index < count; index += 1) {\n const window = windowAt(toplevels, index)\n if (!window || !isMainWindow(window)) {\n continue\n }\n if (window.isActive()) {\n return window\n }\n first = first ?? window\n }\n return first\n}\n\nconst isAnyWindowActive = (): boolean => {\n const toplevels = Gtk.Window.getToplevels()\n const count = toNumber(toplevels.getNItems())\n for (let index = 0; index < count; index += 1) {\n if (windowAt(toplevels, index)?.isActive()) {\n return true\n }\n }\n return false\n}\n\nconst windowMetrics = (): ScaledSize => {\n const window = resolveWindow()\n if (!window) {\n return FALLBACK_METRICS\n }\n // RN's Dimensions(\"window\") is the app viewport: the window CHILD's\n // allocation (the content area under the headerbar), not the window widget\n // size. Falls back to the window size before the first allocation.\n const child = window.getChild()\n const childAllocation = child?.getAllocation()\n const allocatedWidth =\n childAllocation && childAllocation.width > 0\n ? toNumber(childAllocation.width)\n : toNumber(window.getWidth())\n const allocatedHeight =\n childAllocation && childAllocation.height > 0\n ? toNumber(childAllocation.height)\n : toNumber(window.getHeight())\n // Before the first allocation everything reports 0 — fall back to\n // the requested default size (which GTK4 also keeps updated on resize).\n const width =\n allocatedWidth > 0\n ? allocatedWidth\n : Math.max(toNumber(window.defaultWidth ?? 0), 0)\n const height =\n allocatedHeight > 0\n ? allocatedHeight\n : Math.max(toNumber(window.defaultHeight ?? 0), 0)\n return {\n width,\n height,\n scale: toNumber(window.getScaleFactor()),\n fontScale: 1,\n }\n}\n\nconst screenMetrics = (): ScaledSize => {\n const display = Gdk.Display.getDefault()\n if (!display) {\n return windowMetrics()\n }\n const monitors = display.getMonitors()\n if (toNumber(monitors.getNItems()) === 0) {\n return windowMetrics()\n }\n const monitor = monitors.getItem(0) as unknown as Gdk.Monitor | null\n if (!monitor) {\n return windowMetrics()\n }\n const geometry = monitor.getGeometry()\n return {\n width: toNumber(geometry.width),\n height: toNumber(geometry.height),\n scale: toNumber(monitor.getScaleFactor()),\n fontScale: 1,\n }\n}\n\n// GtkNative.getSurface is an interface method merged onto Gtk.Window at\n// runtime via mixins; accessed defensively to stay typecheckable either way.\nconst surfaceOf = (window: Gtk.Window): Gdk.Surface | null => {\n const native = window as unknown as { getSurface?: () => Gdk.Surface | null }\n return typeof native.getSurface === \"function\"\n ? (native.getSurface() ?? null)\n : null\n}\n\n// Tracks the \"current\" window across creation/destruction/focus moves:\n// listens on the given signals of the resolved window (and, when requested,\n// its GdkSurface) plus the toplevel list model, re-resolving and re-attaching\n// whenever the tracked window may have changed. Modules dedupe, so\n// over-notifying is fine.\n//\n// Why the surface: notify::default-width fires when setDefaultSize() is\n// called, i.e. before the compositor actually resizes the surface — the\n// allocated size (what Dimensions reports) only changes when the surface\n// does. And GdkSurface notify::width/height fires at configure time, still\n// before the widget allocation pass, so the \"layout\" signal is also needed:\n// it is emitted during the frame's layout phase and — because GTK's own\n// relayout handler is connected first — our handler observes the updated\n// allocation. The module dedupes, so early/no-op emissions cost nothing.\nconst watchWindow = (\n windowSignals: readonly (keyof Gtk.WindowSignals)[],\n surfaceSignals: readonly (keyof Gdk.SurfaceSignals)[],\n notify: () => void,\n): SubscriptionHandle => {\n let window: Gtk.Window | null = null\n let surface: Gdk.Surface | null = null\n\n const attachWindow = (): void => {\n if (!window) {\n return\n }\n for (const signal of windowSignals) {\n window.on(signal, onSignal)\n }\n }\n\n const detachWindow = (): void => {\n if (!window) {\n return\n }\n for (const signal of windowSignals) {\n window.off(signal, onSignal)\n }\n }\n\n const attachSurface = (): void => {\n if (!surface) {\n return\n }\n for (const signal of surfaceSignals) {\n surface.on(signal, onSignal)\n }\n }\n\n const detachSurface = (): void => {\n if (!surface) {\n return\n }\n for (const signal of surfaceSignals) {\n surface.off(signal, onSignal)\n }\n }\n\n const syncTargets = (): void => {\n const nextWindow = resolveWindow()\n if (nextWindow !== window) {\n detachWindow()\n window = nextWindow\n attachWindow()\n }\n const nextSurface =\n window && surfaceSignals.length > 0 ? surfaceOf(window) : null\n if (nextSurface !== surface) {\n detachSurface()\n surface = nextSurface\n attachSurface()\n }\n }\n\n const onSignal = (): void => {\n syncTargets()\n notify()\n }\n\n const toplevels = Gtk.Window.getToplevels()\n const onToplevelsChanged = (): void => {\n syncTargets()\n notify()\n }\n toplevels.on(\"items-changed\", onToplevelsChanged)\n syncTargets()\n\n return {\n remove: () => {\n detachWindow()\n detachSurface()\n window = null\n surface = null\n toplevels.off(\"items-changed\", onToplevelsChanged)\n },\n }\n}\n\n// realize/map re-run target resolution so the surface listeners attach as\n// soon as the surface exists.\nconst WINDOW_SIZE_SIGNALS = [\n \"notify::default-width\",\n \"notify::default-height\",\n \"realize\",\n \"map\",\n] as const\n\nconst SURFACE_SIZE_SIGNALS = [\n \"notify::width\",\n \"notify::height\",\n \"layout\",\n] as const\n\nconst WINDOW_ACTIVE_SIGNALS = [\"notify::is-active\"] as const\n\nconst gtkVersion = (): string =>\n `${toNumber(Gtk.getMajorVersion())}.${toNumber(Gtk.getMinorVersion())}.${toNumber(Gtk.getMicroVersion())}`\n\n// AdwStyleManager is the only thing that decides the palette here, and it is\n// enough on its own — appearance.test.tsx asserts that a real widget's\n// computed foreground flips with it. This used to also write the classic\n// GtkSettings:gtk-application-prefer-dark-theme, guarding against Adwaita\n// not restyling a GtkApplication (we do not use AdwApplication). Under\n// libadwaita that write is inert: adw_init() takes the color scheme over,\n// answers the setting with \"unsupported ... use AdwStyleManager:color-scheme\n// instead\" and keeps its own value, so all the duplicate ever produced was a\n// warning per call — seven per test run.\nconst setColorSchemeAdw = (scheme: ColorSchemeName | null): void => {\n const manager = styleManager()\n const { ColorScheme } = requireAdwGi(\"Appearance\")\n if (scheme === \"dark\") {\n manager.setColorScheme(ColorScheme.FORCE_DARK)\n } else if (scheme === \"light\") {\n manager.setColorScheme(ColorScheme.FORCE_LIGHT)\n } else {\n manager.setColorScheme(ColorScheme.DEFAULT)\n }\n}\n\nconst onColorSchemeChangeAdw = (notify: () => void): SubscriptionHandle => {\n const manager = styleManager()\n const listener = (): void => notify()\n manager.on(\"notify::dark\", listener)\n return { remove: () => manager.off(\"notify::dark\", listener) }\n}\n\n// Without Adw-1 (adwAvailable() === false): the org.freedesktop.appearance\n// portal, falling back to Gtk.Settings — see gtkx/bridge/color-scheme-portal.ts\n// for the two-tier mechanism and .claude/epics/adw-optional/004.md for why.\nconst setColorScheme = (scheme: ColorSchemeName | null): void =>\n adwAvailable() ? setColorSchemeAdw(scheme) : setPlainColorScheme(scheme)\n\nconst onColorSchemeChange = (notify: () => void): SubscriptionHandle =>\n adwAvailable()\n ? onColorSchemeChangeAdw(notify)\n : onPlainColorSchemeChange(notify)\n\nconst showAlertAdw = async (\n request: HostAlertRequest,\n): Promise<string | null> => {\n const { AlertDialog, ResponseAppearance } = requireAdwGi(\"Alert\")\n const dialog = new AlertDialog()\n dialog.setHeading(request.title)\n if (request.message !== undefined && request.message.length > 0) {\n dialog.setBody(request.message)\n }\n let closeResponse: string | null = null\n for (const button of request.buttons) {\n dialog.addResponse(button.id, button.label)\n if (button.style === \"destructive\") {\n dialog.setResponseAppearance(button.id, ResponseAppearance.DESTRUCTIVE)\n }\n if (button.isPreferred) {\n dialog.setResponseAppearance(button.id, ResponseAppearance.SUGGESTED)\n dialog.setDefaultResponse(button.id)\n }\n if (button.style === \"cancel\") {\n closeResponse = button.id\n }\n }\n if (closeResponse !== null) {\n // Esc / close maps onto the cancel button, like RN's cancel semantics.\n dialog.setCloseResponse(closeResponse)\n } else if (!request.cancelable) {\n // No cancel button and not cancelable: block Esc-dismissal. Responses\n // still close the dialog (they bypass the can-close guard).\n dialog.setCanClose(false)\n }\n const response = await dialog.choose(resolveWindow())\n // Anything that is not one of our buttons (e.g. the built-in \"close\"\n // response) is a dismissal.\n return request.buttons.some((button) => button.id === response)\n ? response\n : null\n}\n\n// Without Adw-1: Gtk.AlertDialog (GTK >= 4.10) — index-based rather than\n// Adw's string response ids, so the button's position in request.buttons IS\n// its Gtk.AlertDialog index; no id bookkeeping needed. What is LOST: Adw's\n// ResponseAppearance (DESTRUCTIVE/SUGGESTED) has no Gtk.AlertDialog\n// equivalent at all — every button renders the same, undocumented-away in\n// docs/api.md's Alert row rather than silently dropped. Default/cancel\n// mapping is preserved via defaultButton/cancelButton, same idea as Adw's\n// defaultResponse/closeResponse above.\nconst showAlertPlain = async (\n request: HostAlertRequest,\n): Promise<string | null> => {\n const dialog = new Gtk.AlertDialog({\n message: request.title,\n detail: request.message ?? \"\",\n buttons: request.buttons.map((button) => button.label),\n modal: true,\n })\n const preferredIndex = request.buttons.findIndex(\n (button) => button.isPreferred,\n )\n if (preferredIndex >= 0) {\n dialog.setDefaultButton(preferredIndex)\n }\n const cancelIndex = request.buttons.findIndex(\n (button) => button.style === \"cancel\",\n )\n if (cancelIndex >= 0) {\n // Esc maps onto the cancel button, same as the Adw path's closeResponse.\n dialog.setCancelButton(cancelIndex)\n } else if (!request.cancelable && process.env.NODE_ENV !== \"production\") {\n // Unlike Adw.AlertDialog.setCanClose(false), Gtk.AlertDialog has no way\n // to block Esc/window-close dismissal outright — with no cancel button\n // set, GTK closes the dialog anyway and rejects choose() with\n // Gtk.DialogError.DISMISSED (caught below, mapped to the same null\n // dismissal cancelable: true would produce). Documented in docs/api.md;\n // an app that truly needs to block dismissal should add a cancel\n // button on both profiles rather than relying on cancelable: false alone.\n console.warn(\n '[react-native-gtkx] Alert.alert was called with cancelable: false and no \"cancel\" ' +\n \"style button. The plain-GTK profile's Gtk.AlertDialog fallback cannot block \" +\n \"Esc/window-close dismissal the way Adw.AlertDialog does — the dialog stays \" +\n \"dismissable. Add a cancel-style button for identical behavior on both profiles.\",\n )\n }\n try {\n const index = await dialog.choose(resolveWindow())\n return request.buttons[index]?.id ?? null\n } catch {\n // Dismissed (Esc / window-close) with no valid cancel button — the\n // plain-profile equivalent of the Adw path's unmatched \"close\" response.\n return null\n }\n}\n\nconst showAlert = async (request: HostAlertRequest): Promise<string | null> =>\n adwAvailable() ? showAlertAdw(request) : showAlertPlain(request)\n\nconst launchUri = async (uri: string): Promise<void> => {\n const launcher = new Gtk.UriLauncher({ uri })\n // Promisified by the gi codegen; rejects with the GError on failure.\n await launcher.launch(resolveWindow())\n}\n\n// The default widget direction is GTK's read of the locale text direction.\nconst isRTL = (): boolean => {\n try {\n return Gtk.Widget.getDefaultDirection() === Gtk.TextDirection.RTL\n } catch {\n return false\n }\n}\n\nexport const gtkxHost: Host = {\n gtkVersion,\n getWindowMetrics: windowMetrics,\n getScreenMetrics: screenMetrics,\n onMetricsChange: (notify) =>\n watchWindow(WINDOW_SIZE_SIGNALS, SURFACE_SIZE_SIGNALS, notify),\n getColorScheme: () =>\n adwAvailable() ? colorScheme() : getPlainColorScheme(),\n setColorScheme,\n onColorSchemeChange,\n isActive: isAnyWindowActive,\n onActiveChange: (notify) => watchWindow(WINDOW_ACTIVE_SIGNALS, [], notify),\n showAlert,\n launchUri,\n isRTL,\n exitApp: () => quit(),\n}\n"]}
|
|
@@ -9,4 +9,4 @@ export type ModalProps = {
|
|
|
9
9
|
height?: number;
|
|
10
10
|
children?: ReactNode;
|
|
11
11
|
};
|
|
12
|
-
export declare const Modal: ({ visible, onRequestClose, title, width, height, children, }: ModalProps) => React.
|
|
12
|
+
export declare const Modal: ({ visible, onRequestClose, title, width, height, children, }: ModalProps) => React.JSX.Element | null;
|
package/dist/components/modal.js
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { GtkWindow } from "../gtkx/bridge/index";
|
|
3
3
|
import { Root } from "./root";
|
|
4
|
-
// RN Modal → a
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// RN Modal → a GtkWindow with a regular RN tree inside. Through gtkx 1.0
|
|
5
|
+
// this used to wrap the window in our own `createPortal(..., application)`
|
|
6
|
+
// and pass an explicit `transientFor` read via `useParentWindow()`. Neither
|
|
7
|
+
// is needed any more: gtkx 1.0's own GtkWindow JSX component is
|
|
8
|
+
// createWindowComponent(createElementComponent("GtkWindow"))
|
|
9
|
+
// (node_modules/.gtkx/jsx/gtk/gtk.js), which already composes
|
|
10
|
+
// createPortaledComponent (self-portals to @gtkx/react's rootElement,
|
|
11
|
+
// unconditionally, regardless of where it is rendered in the tree) and
|
|
12
|
+
// withDefaultTransientFor (defaults transientFor from ParentWindowContext —
|
|
13
|
+
// the exact context useParentWindow() read — whenever the prop is left
|
|
14
|
+
// undefined). Removing our own portal/transientFor was probed both ways
|
|
15
|
+
// (gallery's Modal section, before/after: same position, same blocked
|
|
16
|
+
// parent, same close/reopen behavior) before landing — see 003-notes.md.
|
|
7
17
|
export const Modal = ({ visible = false, onRequestClose, title = "", width = 480, height = 400, children, }) => {
|
|
8
|
-
const application = useApplication();
|
|
9
|
-
const parentWindow = useParentWindow();
|
|
10
18
|
if (!visible) {
|
|
11
19
|
return null;
|
|
12
20
|
}
|
|
13
|
-
return
|
|
21
|
+
return (_jsx(GtkWindow, { title: title, modal: true, defaultWidth: width, defaultHeight: height, onCloseRequest: () => {
|
|
14
22
|
onRequestClose?.();
|
|
15
23
|
return true;
|
|
16
|
-
}, children: _jsx(Root, { width: width, height: height, followAllocation: true, children: children }) })
|
|
24
|
+
}, children: _jsx(Root, { width: width, height: height, followAllocation: true, children: children }) }));
|
|
17
25
|
};
|
|
18
26
|
//# sourceMappingURL=modal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.js","sourceRoot":"","sources":["../../src/components/modal.tsx"],"names":[],"mappings":";AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"modal.js","sourceRoot":"","sources":["../../src/components/modal.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAe7B,yEAAyE;AACzE,2EAA2E;AAC3E,4EAA4E;AAC5E,gEAAgE;AAChE,6DAA6D;AAC7D,8DAA8D;AAC9D,sEAAsE;AACtE,uEAAuE;AACvE,4EAA4E;AAC5E,uEAAuE;AACvE,wEAAwE;AACxE,sEAAsE;AACtE,yEAAyE;AACzE,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EACpB,OAAO,GAAG,KAAK,EACf,cAAc,EACd,KAAK,GAAG,EAAE,EACV,KAAK,GAAG,GAAG,EACX,MAAM,GAAG,GAAG,EACZ,QAAQ,GACG,EAAE,EAAE;IACf,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,CACL,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,KAAK,QACL,YAAY,EAAE,KAAK,EACnB,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,GAAG,EAAE;YACnB,cAAc,EAAE,EAAE,CAAA;YAClB,OAAO,IAAI,CAAA;QACb,CAAC,YAED,KAAC,IAAI,IACH,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,gBAAgB,kBAEf,QAAQ,GACJ,GACG,CACb,CAAA;AACH,CAAC,CAAA","sourcesContent":["import { type ReactNode } from \"react\"\nimport { GtkWindow } from \"../gtkx/bridge/index\"\nimport { Root } from \"./root\"\n\nexport type ModalProps = {\n visible?: boolean\n onRequestClose?: () => void\n title?: string\n // Desktop mapping: RN modals become modal windows; transparent/animationType\n // have no GTK equivalent and are accepted as no-ops for API parity.\n transparent?: boolean\n animationType?: \"none\" | \"slide\" | \"fade\"\n width?: number\n height?: number\n children?: ReactNode\n}\n\n// RN Modal → a GtkWindow with a regular RN tree inside. Through gtkx 1.0\n// this used to wrap the window in our own `createPortal(..., application)`\n// and pass an explicit `transientFor` read via `useParentWindow()`. Neither\n// is needed any more: gtkx 1.0's own GtkWindow JSX component is\n// createWindowComponent(createElementComponent(\"GtkWindow\"))\n// (node_modules/.gtkx/jsx/gtk/gtk.js), which already composes\n// createPortaledComponent (self-portals to @gtkx/react's rootElement,\n// unconditionally, regardless of where it is rendered in the tree) and\n// withDefaultTransientFor (defaults transientFor from ParentWindowContext —\n// the exact context useParentWindow() read — whenever the prop is left\n// undefined). Removing our own portal/transientFor was probed both ways\n// (gallery's Modal section, before/after: same position, same blocked\n// parent, same close/reopen behavior) before landing — see 003-notes.md.\nexport const Modal = ({\n visible = false,\n onRequestClose,\n title = \"\",\n width = 480,\n height = 400,\n children,\n}: ModalProps) => {\n if (!visible) {\n return null\n }\n\n return (\n <GtkWindow\n title={title}\n modal\n defaultWidth={width}\n defaultHeight={height}\n onCloseRequest={() => {\n onRequestClose?.()\n return true\n }}\n >\n <Root\n width={width}\n height={height}\n followAllocation\n >\n {children}\n </Root>\n </GtkWindow>\n )\n}\n"]}
|
|
@@ -6,7 +6,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
6
6
|
// Both go through `Controllers` from react-native-gtkx/gtk — the same public
|
|
7
7
|
// door an app would use. Nothing here is reachable only from inside the
|
|
8
8
|
// platform, which is the property `List`/`ListRow` already established
|
|
9
|
-
// (docs/
|
|
9
|
+
// (docs/architecture/overview.md).
|
|
10
10
|
import { useRef } from "react";
|
|
11
11
|
import { Controllers } from "../gtk/controllers";
|
|
12
12
|
import { beginDragLayer, Gdk, GObject, Gtk, GtkDragSource, GtkDropTarget, } from "../gtkx/bridge/index";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gtk-controllers.js","sourceRoot":"","sources":["../../src/dnd/gtk-controllers.tsx"],"names":[],"mappings":"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","sourcesContent":["// The two GTK controllers everything in this module is built from, wrapped\n// once so `Draggable`, `Droppable` and `SortableItem` do not each re-derive\n// the drag-icon and payload details.\n//\n// Both go through `Controllers` from react-native-gtkx/gtk — the same public\n// door an app would use. Nothing here is reachable only from inside the\n// platform, which is the property `List`/`ListRow` already established\n// (docs/platform-layer.md).\nimport { useRef, type ReactNode } from \"react\"\nimport { Controllers } from \"../gtk/controllers\"\nimport {\n beginDragLayer,\n Gdk,\n GObject,\n Gtk,\n GtkDragSource,\n GtkDropTarget,\n type DragLayerHandle,\n} from \"../gtkx/bridge/index\"\nimport { decodePayload, encodePayload, type DragPayload } from \"./payload\"\n\nexport type DragSourceControllersProps = {\n payload: DragPayload\n /** Reports the grab point in the source widget's own coordinates, which is\n * where the drag icon's hotspot goes and where `tx`/`ty` start from. The\n * widget itself rides along too — `Sortable`/`SortableGrid` use it to\n * convert this point into their own container's coordinates with\n * `computePointIn` (see sortable.tsx/grid.tsx), the origin their reorder\n * tracking measures every subsequent motion event against. `null` only\n * when GDK could not resolve a widget for the drag source itself, which\n * should not happen in practice. */\n onGrab?: (x: number, y: number, widget: Gtk.Widget | null) => void\n onDragBegin?: () => void\n /** `dropped` is what GDK's own `drag-end` reports: whether a target took\n * it. `drag-cancel` reports the negative case separately, so both are\n * folded into one callback here. */\n onDragEnd?: (dropped: boolean) => void\n}\n\n/**\n * A `GtkDragSource` on the enclosing React Native component's widget.\n *\n * The drag icon is a `Gtk.WidgetPaintable` of that widget, offset by where\n * inside it the drag began — so the thing appears to lift off under the\n * cursor rather than jump to it. That is the visual no JS drag can produce,\n * and the reason this module is built on GDK at all.\n *\n * A second, window-level copy of the same picture rides alongside it for as\n * long as the drag stays over this window — `gtkx/bridge/drag-layer.ts` has\n * the reason: `setIcon`'s own icon is a compositor surface, unclipped by any\n * `overflow: hidden` ancestor but also outside this process's own widget\n * tree, so nothing in it can prove that escape happened. The window-level\n * copy is the same escape, provable.\n */\nexport const DragSourceControllers = ({\n payload,\n onGrab,\n onDragBegin,\n onDragEnd,\n}: DragSourceControllersProps): ReactNode => {\n // GDK emits `drag-cancel` AND then `drag-end` for a refused drop, so the\n // cancel is recorded and read by the end handler rather than reported\n // twice.\n const cancelled = useRef(false)\n // Set in `onPrepare`, consumed in `onDragBegin` — the window-level layer\n // only starts once GDK confirms the drag is really happening, but the\n // widget and grab point it needs are only ever handed to `onPrepare`.\n const grab = useRef<{ widget: Gtk.Widget; x: number; y: number } | null>(null)\n const dragLayer = useRef<DragLayerHandle | null>(null)\n\n return (\n <Controllers>\n <GtkDragSource\n actions={Gdk.DragAction.MOVE}\n onPrepare={(x, y, self) => {\n const widget = self.getWidget()\n if (widget) {\n self.setIcon(\n Gtk.WidgetPaintable.new(widget),\n Math.round(x),\n Math.round(y),\n )\n grab.current = { widget, x, y }\n }\n onGrab?.(x, y, widget)\n return Gdk.ContentProvider.newForValue(\n GObject.buildValue(GObject.TYPE_STRING, (value) =>\n value.setString(encodePayload(payload)),\n ),\n )\n }}\n onDragBegin={() => {\n cancelled.current = false\n if (grab.current) {\n dragLayer.current = beginDragLayer(\n grab.current.widget,\n grab.current.x,\n grab.current.y,\n )\n }\n onDragBegin?.()\n }}\n onDragCancel={() => {\n cancelled.current = true\n // false: let GTK play its own \"snap back\" animation, which is the\n // platform's way of saying the drop was refused.\n return false\n }}\n onDragEnd={() => {\n dragLayer.current?.end()\n dragLayer.current = null\n onDragEnd?.(!cancelled.current)\n }}\n />\n </Controllers>\n )\n}\n\nexport type DropTargetControllersProps = {\n /** Return false to refuse — GDK then shows the no-drop cursor, which is\n * better feedback than upstream's silent skip. */\n accepts: (payload: DragPayload) => boolean\n onDrop: (payload: DragPayload, x: number, y: number) => void\n onEnter?: (payload: DragPayload) => void\n onMotion?: (payload: DragPayload, x: number, y: number) => void\n onLeave?: () => void\n}\n\n/**\n * A `GtkDropTarget` on the enclosing React Native component's widget,\n * accepting the string payload this module encodes.\n *\n * The payload is decoded before `accepts` is consulted, so a string dragged\n * in from a text editor is refused rather than mistaken for a draggable.\n */\nexport const DropTargetControllers = ({\n accepts,\n onDrop,\n onEnter,\n onMotion,\n onLeave,\n}: DropTargetControllersProps): ReactNode => {\n // The payload of the drag currently overhead, sampled on `::enter` and kept\n // for `::motion` (which is not handed the target).\n const hovering = useRef<DragPayload | null>(null)\n\n return (\n <Controllers>\n <GtkDropTarget\n actions={Gdk.DragAction.MOVE}\n types={[GObject.TYPE_STRING]}\n // Without this `gtk_drop_target_get_value()` returns NULL until the\n // drop itself, so `::enter` could not tell one drag from another and\n // every zone would light up for every payload. Preloading is exactly\n // the property GTK provides for reading the data during the drag; the\n // cost it warns about (fetching data from another process on hover)\n // does not apply, because the payload is a short string this process\n // wrote.\n preload\n onEnter={(_x, _y, self) => {\n const payload = payloadOf(self)\n hovering.current = payload\n // A payload that is not readable yet is NOT refused: refusing in\n // `::enter` ends the drag for this target permanently, while\n // accepting and re-checking at drop time is recoverable. Only a\n // payload we can read AND reject is turned away.\n if (payload && !accepts(payload)) {\n return Gdk.DragAction.NONE\n }\n if (payload) {\n onEnter?.(payload)\n }\n return Gdk.DragAction.MOVE\n }}\n onMotion={(x, y) => {\n const payload = hovering.current\n if (payload && !accepts(payload)) {\n return Gdk.DragAction.NONE\n }\n if (payload) {\n onMotion?.(payload, x, y)\n }\n return Gdk.DragAction.MOVE\n }}\n onLeave={() => {\n hovering.current = null\n onLeave?.()\n }}\n onDrop={(value, x, y) => {\n hovering.current = null\n const payload = decodePayload(value.getString())\n if (!payload || !accepts(payload)) {\n return false\n }\n onDrop(payload, x, y)\n return true\n }}\n />\n </Controllers>\n )\n}\n\n/**\n * The payload of the drag currently over a drop target, readable during the\n * drag because the target above sets `preload`.\n */\nconst payloadOf = (target: Gtk.DropTarget): DragPayload | null => {\n const value = target.getValue()\n if (!value) {\n return null\n }\n return decodePayload(value.getString())\n}\n"]}
|
|
1
|
+
{"version":3,"file":"gtk-controllers.js","sourceRoot":"","sources":["../../src/dnd/gtk-controllers.tsx"],"names":[],"mappings":"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","sourcesContent":["// The two GTK controllers everything in this module is built from, wrapped\n// once so `Draggable`, `Droppable` and `SortableItem` do not each re-derive\n// the drag-icon and payload details.\n//\n// Both go through `Controllers` from react-native-gtkx/gtk — the same public\n// door an app would use. Nothing here is reachable only from inside the\n// platform, which is the property `List`/`ListRow` already established\n// (docs/architecture/overview.md).\nimport { useRef, type ReactNode } from \"react\"\nimport { Controllers } from \"../gtk/controllers\"\nimport {\n beginDragLayer,\n Gdk,\n GObject,\n Gtk,\n GtkDragSource,\n GtkDropTarget,\n type DragLayerHandle,\n} from \"../gtkx/bridge/index\"\nimport { decodePayload, encodePayload, type DragPayload } from \"./payload\"\n\nexport type DragSourceControllersProps = {\n payload: DragPayload\n /** Reports the grab point in the source widget's own coordinates, which is\n * where the drag icon's hotspot goes and where `tx`/`ty` start from. The\n * widget itself rides along too — `Sortable`/`SortableGrid` use it to\n * convert this point into their own container's coordinates with\n * `computePointIn` (see sortable.tsx/grid.tsx), the origin their reorder\n * tracking measures every subsequent motion event against. `null` only\n * when GDK could not resolve a widget for the drag source itself, which\n * should not happen in practice. */\n onGrab?: (x: number, y: number, widget: Gtk.Widget | null) => void\n onDragBegin?: () => void\n /** `dropped` is what GDK's own `drag-end` reports: whether a target took\n * it. `drag-cancel` reports the negative case separately, so both are\n * folded into one callback here. */\n onDragEnd?: (dropped: boolean) => void\n}\n\n/**\n * A `GtkDragSource` on the enclosing React Native component's widget.\n *\n * The drag icon is a `Gtk.WidgetPaintable` of that widget, offset by where\n * inside it the drag began — so the thing appears to lift off under the\n * cursor rather than jump to it. That is the visual no JS drag can produce,\n * and the reason this module is built on GDK at all.\n *\n * A second, window-level copy of the same picture rides alongside it for as\n * long as the drag stays over this window — `gtkx/bridge/drag-layer.ts` has\n * the reason: `setIcon`'s own icon is a compositor surface, unclipped by any\n * `overflow: hidden` ancestor but also outside this process's own widget\n * tree, so nothing in it can prove that escape happened. The window-level\n * copy is the same escape, provable.\n */\nexport const DragSourceControllers = ({\n payload,\n onGrab,\n onDragBegin,\n onDragEnd,\n}: DragSourceControllersProps): ReactNode => {\n // GDK emits `drag-cancel` AND then `drag-end` for a refused drop, so the\n // cancel is recorded and read by the end handler rather than reported\n // twice.\n const cancelled = useRef(false)\n // Set in `onPrepare`, consumed in `onDragBegin` — the window-level layer\n // only starts once GDK confirms the drag is really happening, but the\n // widget and grab point it needs are only ever handed to `onPrepare`.\n const grab = useRef<{ widget: Gtk.Widget; x: number; y: number } | null>(null)\n const dragLayer = useRef<DragLayerHandle | null>(null)\n\n return (\n <Controllers>\n <GtkDragSource\n actions={Gdk.DragAction.MOVE}\n onPrepare={(x, y, self) => {\n const widget = self.getWidget()\n if (widget) {\n self.setIcon(\n Gtk.WidgetPaintable.new(widget),\n Math.round(x),\n Math.round(y),\n )\n grab.current = { widget, x, y }\n }\n onGrab?.(x, y, widget)\n return Gdk.ContentProvider.newForValue(\n GObject.buildValue(GObject.TYPE_STRING, (value) =>\n value.setString(encodePayload(payload)),\n ),\n )\n }}\n onDragBegin={() => {\n cancelled.current = false\n if (grab.current) {\n dragLayer.current = beginDragLayer(\n grab.current.widget,\n grab.current.x,\n grab.current.y,\n )\n }\n onDragBegin?.()\n }}\n onDragCancel={() => {\n cancelled.current = true\n // false: let GTK play its own \"snap back\" animation, which is the\n // platform's way of saying the drop was refused.\n return false\n }}\n onDragEnd={() => {\n dragLayer.current?.end()\n dragLayer.current = null\n onDragEnd?.(!cancelled.current)\n }}\n />\n </Controllers>\n )\n}\n\nexport type DropTargetControllersProps = {\n /** Return false to refuse — GDK then shows the no-drop cursor, which is\n * better feedback than upstream's silent skip. */\n accepts: (payload: DragPayload) => boolean\n onDrop: (payload: DragPayload, x: number, y: number) => void\n onEnter?: (payload: DragPayload) => void\n onMotion?: (payload: DragPayload, x: number, y: number) => void\n onLeave?: () => void\n}\n\n/**\n * A `GtkDropTarget` on the enclosing React Native component's widget,\n * accepting the string payload this module encodes.\n *\n * The payload is decoded before `accepts` is consulted, so a string dragged\n * in from a text editor is refused rather than mistaken for a draggable.\n */\nexport const DropTargetControllers = ({\n accepts,\n onDrop,\n onEnter,\n onMotion,\n onLeave,\n}: DropTargetControllersProps): ReactNode => {\n // The payload of the drag currently overhead, sampled on `::enter` and kept\n // for `::motion` (which is not handed the target).\n const hovering = useRef<DragPayload | null>(null)\n\n return (\n <Controllers>\n <GtkDropTarget\n actions={Gdk.DragAction.MOVE}\n types={[GObject.TYPE_STRING]}\n // Without this `gtk_drop_target_get_value()` returns NULL until the\n // drop itself, so `::enter` could not tell one drag from another and\n // every zone would light up for every payload. Preloading is exactly\n // the property GTK provides for reading the data during the drag; the\n // cost it warns about (fetching data from another process on hover)\n // does not apply, because the payload is a short string this process\n // wrote.\n preload\n onEnter={(_x, _y, self) => {\n const payload = payloadOf(self)\n hovering.current = payload\n // A payload that is not readable yet is NOT refused: refusing in\n // `::enter` ends the drag for this target permanently, while\n // accepting and re-checking at drop time is recoverable. Only a\n // payload we can read AND reject is turned away.\n if (payload && !accepts(payload)) {\n return Gdk.DragAction.NONE\n }\n if (payload) {\n onEnter?.(payload)\n }\n return Gdk.DragAction.MOVE\n }}\n onMotion={(x, y) => {\n const payload = hovering.current\n if (payload && !accepts(payload)) {\n return Gdk.DragAction.NONE\n }\n if (payload) {\n onMotion?.(payload, x, y)\n }\n return Gdk.DragAction.MOVE\n }}\n onLeave={() => {\n hovering.current = null\n onLeave?.()\n }}\n onDrop={(value, x, y) => {\n hovering.current = null\n const payload = decodePayload(value.getString())\n if (!payload || !accepts(payload)) {\n return false\n }\n onDrop(payload, x, y)\n return true\n }}\n />\n </Controllers>\n )\n}\n\n/**\n * The payload of the drag currently over a drop target, readable during the\n * drag because the target above sets `preload`.\n */\nconst payloadOf = (target: Gtk.DropTarget): DragPayload | null => {\n const value = target.getValue()\n if (!value) {\n return null\n }\n return decodePayload(value.getString())\n}\n"]}
|
package/dist/gtk/index.js
CHANGED
|
@@ -13,7 +13,8 @@ export { Gdk, Gio, GLib, GObject, Gtk, Pango } from "../gtkx/bridge/index";
|
|
|
13
13
|
// `Gtk.Application`/`Gtk.ApplicationWindow`), a text buffer and an
|
|
14
14
|
// adjustment (the model objects `GtkTextView`/`GtkSpinRow`-style widgets
|
|
15
15
|
// bind to), keyboard shortcuts, and the two drag-and-drop controllers. See
|
|
16
|
-
// docs/
|
|
16
|
+
// docs/architecture/overview.md, "The widget surface: wrapped, raw, and
|
|
17
|
+
// auxiliary".
|
|
17
18
|
export { GMenu, GtkAdjustment, GtkDragSource, GtkDropControllerMotion, GtkDropTarget, GtkShortcut, GtkShortcutController, GtkTextBuffer, } from "../gtkx/bridge/index";
|
|
18
19
|
// Window and application actions declared inside the app tree instead of
|
|
19
20
|
// around it (the AppRegistry options they replace cannot see app context —
|
|
@@ -31,7 +32,7 @@ export { Controllers } from "./controllers";
|
|
|
31
32
|
// GSettings: reads and writes backed by a compiled `.gschema.xml` schema.
|
|
32
33
|
// `useSetting`/`useBindSetting` come straight from @gtkx/react; loading a
|
|
33
34
|
// `.gschema.xml` file into the `SettingsSchema` object they expect is a
|
|
34
|
-
// build-time concern (see docs/
|
|
35
|
+
// build-time concern (see docs/architecture/integration.md, "GSettings").
|
|
35
36
|
export { useBindSetting, useSetting, } from "../gtkx/bridge/index";
|
|
36
37
|
// @gtkx/css — a real GTK CSS class from a tagged template, the same
|
|
37
38
|
// mechanism the style prop's visual half uses under the hood. Re-exported
|
|
@@ -40,7 +41,7 @@ export { useBindSetting, useSetting, } from "../gtkx/bridge/index";
|
|
|
40
41
|
// surface, not just Gtk.Widget subclasses. `GObject` above is exported
|
|
41
42
|
// mainly for `GObject.Value` — constructing a boxed value is required by
|
|
42
43
|
// APIs like `Adw.Breakpoint.addSetter`, which reject a bare JS primitive
|
|
43
|
-
// (see docs/
|
|
44
|
+
// (see docs/architecture/layout-and-styling.md, "Two ways to react to size").
|
|
44
45
|
export { css, cx, injectGlobal } from "../gtkx/bridge/index";
|
|
45
46
|
// The window and application AppRegistry itself sits on: useParentWindow
|
|
46
47
|
// reaches the Gtk.Window ancestor (for anything not modeled by a prop —
|
package/dist/gtk/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gtk/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,8DAA8D;AAC9D,yCAAyC;AACzC,0EAA0E;AAC1E,cAAc,qBAAqB,CAAA;AAEnC,4EAA4E;AAC5E,8EAA8E;AAC9E,mCAAmC;AACnC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAE1E,oEAAoE;AACpE,0EAA0E;AAC1E,oEAAoE;AACpE,mEAAmE;AACnE,yEAAyE;AACzE,2EAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gtk/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,8DAA8D;AAC9D,yCAAyC;AACzC,0EAA0E;AAC1E,cAAc,qBAAqB,CAAA;AAEnC,4EAA4E;AAC5E,8EAA8E;AAC9E,mCAAmC;AACnC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAE1E,oEAAoE;AACpE,0EAA0E;AAC1E,oEAAoE;AACpE,mEAAmE;AACnE,yEAAyE;AACzE,2EAA2E;AAC3E,wEAAwE;AACxE,cAAc;AACd,OAAO,EACL,KAAK,EACL,aAAa,EACb,aAAa,EACb,uBAAuB,EACvB,aAAa,EACb,WAAW,EACX,qBAAqB,EACrB,aAAa,GACd,MAAM,sBAAsB,CAAA;AAE7B,yEAAyE;AACzE,2EAA2E;AAC3E,qEAAqE;AACrE,yEAAyE;AACzE,oEAAoE;AACpE,aAAa;AACb,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,iBAAiB,GAKlB,MAAM,kBAAkB,CAAA;AAEzB,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,yEAAyE;AACzE,uCAAuC;AACvC,OAAO,EAAE,WAAW,EAAyB,MAAM,eAAe,CAAA;AAElE,0EAA0E;AAC1E,0EAA0E;AAC1E,wEAAwE;AACxE,0EAA0E;AAC1E,OAAO,EACL,cAAc,EACd,UAAU,GAIX,MAAM,sBAAsB,CAAA;AAE7B,oEAAoE;AACpE,0EAA0E;AAC1E,sEAAsE;AACtE,0EAA0E;AAC1E,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,8EAA8E;AAC9E,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAE5D,yEAAyE;AACzE,wEAAwE;AACxE,uEAAuE;AACvE,6DAA6D;AAC7D,yEAAyE;AACzE,mEAAmE;AACnE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA","sourcesContent":["// The full GTK widget surface lives in a generated file: every Gtk.Widget\n// subclass gtkx binds, wrapped so React Native drives it. See\n// scripts/generate-widget-surface.ts and\n// scripts/widget-surface/classification.json for how the list is derived.\nexport * from \"./widgets.generated\"\n\n// The GTK namespaces themselves, exported as values because they carry both\n// the enums you need at runtime — `hscrollbarPolicy={Gtk.PolicyType.NEVER}` —\n// and the types you need for refs.\nexport { Gdk, Gio, GLib, GObject, Gtk, Pango } from \"../gtkx/bridge/index\"\n\n// Auxiliary JSX elements that are not Gtk.Widget subclasses, so the\n// generated widget surface above never sees them — real building blocks a\n// non-trivial app still needs: actions and menus (Gio, used through\n// `Gtk.Application`/`Gtk.ApplicationWindow`), a text buffer and an\n// adjustment (the model objects `GtkTextView`/`GtkSpinRow`-style widgets\n// bind to), keyboard shortcuts, and the two drag-and-drop controllers. See\n// docs/architecture/overview.md, \"The widget surface: wrapped, raw, and\n// auxiliary\".\nexport {\n GMenu,\n GtkAdjustment,\n GtkDragSource,\n GtkDropControllerMotion,\n GtkDropTarget,\n GtkShortcut,\n GtkShortcutController,\n GtkTextBuffer,\n} from \"../gtkx/bridge/index\"\n\n// Window and application actions declared inside the app tree instead of\n// around it (the AppRegistry options they replace cannot see app context —\n// see window-actions.tsx). GSimpleAction comes from here rather than\n// straight from the bridge because inside these components it arbitrates\n// duplicate action names; on every other path it is gtkx's element,\n// unchanged.\nexport {\n ApplicationActions,\n GSimpleAction,\n WindowActions,\n WindowControllers,\n type ApplicationActionsProps,\n type GSimpleActionProps,\n type WindowActionsProps,\n type WindowControllersProps,\n} from \"./window-actions\"\n\n// The same idea one level down: event controllers attached to the widget of\n// the enclosing React Native component, so a row written in View/Pressable\n// can still carry GTK drag-and-drop. The door onto GTK behaviour that no RN\n// prop expresses — deliberately an element in THIS subpath rather than a\n// prop on `View`, see controllers.tsx.\nexport { Controllers, type ControllersProps } from \"./controllers\"\n\n// GSettings: reads and writes backed by a compiled `.gschema.xml` schema.\n// `useSetting`/`useBindSetting` come straight from @gtkx/react; loading a\n// `.gschema.xml` file into the `SettingsSchema` object they expect is a\n// build-time concern (see docs/architecture/integration.md, \"GSettings\").\nexport {\n useBindSetting,\n useSetting,\n type SettingsSchema,\n type SettingsSchemaKeys,\n type SettingValue,\n} from \"../gtkx/bridge/index\"\n\n// @gtkx/css — a real GTK CSS class from a tagged template, the same\n// mechanism the style prop's visual half uses under the hood. Re-exported\n// here rather than left to a direct @gtkx/css dependency for the same\n// reason the namespaces above are: one subpath for the whole gtkx toolkit\n// surface, not just Gtk.Widget subclasses. `GObject` above is exported\n// mainly for `GObject.Value` — constructing a boxed value is required by\n// APIs like `Adw.Breakpoint.addSetter`, which reject a bare JS primitive\n// (see docs/architecture/layout-and-styling.md, \"Two ways to react to size\").\nexport { css, cx, injectGlobal } from \"../gtkx/bridge/index\"\n\n// The window and application AppRegistry itself sits on: useParentWindow\n// reaches the Gtk.Window ancestor (for anything not modeled by a prop —\n// e.g. binding a GSettings key to its own defaultWidth/defaultHeight),\n// useApplication reaches the Adw.Application (e.g. to send a\n// Gio.Notification), quit tears the whole app down programmatically (the\n// same function AppRegistry wires to a window's own close button).\nexport { quit, useApplication, useParentWindow } from \"../gtkx/bridge/index\"\n"]}
|
package/dist/gtkx/bridge/adw.js
CHANGED
|
@@ -61,7 +61,7 @@ else {
|
|
|
61
61
|
*/
|
|
62
62
|
export const adwAvailable = () => cached !== null && cached !== undefined;
|
|
63
63
|
const NOT_AVAILABLE = ' requires "Adw-1" in this app\'s gtkx.config.ts `libraries` — see ' +
|
|
64
|
-
"docs/
|
|
64
|
+
"docs/guide/plain-gtk.md for what needs Adw unconditionally " +
|
|
65
65
|
"and what falls back without it.";
|
|
66
66
|
/** The repo's loud named throw for a feature that reached for Adw and found
|
|
67
67
|
* none. Every Adw-dependent call site in the seam funnels through this, but
|