@gtkx/testing 0.21.0 → 1.0.0-rc.2
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 +137 -34
- package/dist/act.d.ts +19 -0
- package/dist/act.d.ts.map +1 -0
- package/dist/act.js +56 -0
- package/dist/act.js.map +1 -0
- package/dist/bound-queries.d.ts +33 -0
- package/dist/bound-queries.d.ts.map +1 -0
- package/dist/bound-queries.js +2 -0
- package/dist/bound-queries.js.map +1 -0
- package/dist/build-queries.d.ts +16 -0
- package/dist/build-queries.d.ts.map +1 -0
- package/dist/build-queries.js +115 -0
- package/dist/build-queries.js.map +1 -0
- package/dist/cleanup-registry.d.ts +5 -0
- package/dist/cleanup-registry.d.ts.map +1 -0
- package/dist/cleanup-registry.js +21 -0
- package/dist/cleanup-registry.js.map +1 -0
- package/dist/config.d.ts +20 -52
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -46
- package/dist/config.js.map +1 -1
- package/dist/editable.d.ts +8 -0
- package/dist/editable.d.ts.map +1 -0
- package/dist/editable.js +26 -0
- package/dist/editable.js.map +1 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +135 -0
- package/dist/errors.js.map +1 -0
- package/dist/fire-event.d.ts +8 -25
- package/dist/fire-event.d.ts.map +1 -1
- package/dist/fire-event.js +11 -30
- package/dist/fire-event.js.map +1 -1
- package/dist/frame-sync.d.ts +4 -0
- package/dist/frame-sync.d.ts.map +1 -0
- package/dist/frame-sync.js +37 -0
- package/dist/frame-sync.js.map +1 -0
- package/dist/index.d.ts +17 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/matchers.d.ts +59 -0
- package/dist/matchers.d.ts.map +1 -0
- package/dist/matchers.js +117 -0
- package/dist/matchers.js.map +1 -0
- package/dist/pretty-widget.d.ts +24 -26
- package/dist/pretty-widget.d.ts.map +1 -1
- package/dist/pretty-widget.js +111 -117
- package/dist/pretty-widget.js.map +1 -1
- package/dist/queries.d.ts +190 -180
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +291 -320
- package/dist/queries.js.map +1 -1
- package/dist/register-test-hooks.d.ts +2 -0
- package/dist/register-test-hooks.d.ts.map +1 -0
- package/dist/register-test-hooks.js +16 -0
- package/dist/register-test-hooks.js.map +1 -0
- package/dist/render-hook.d.ts +15 -35
- package/dist/render-hook.d.ts.map +1 -1
- package/dist/render-hook.js +9 -45
- package/dist/render-hook.js.map +1 -1
- package/dist/render.d.ts +13 -42
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +138 -121
- package/dist/render.js.map +1 -1
- package/dist/role-helpers.d.ts +19 -53
- package/dist/role-helpers.d.ts.map +1 -1
- package/dist/role-helpers.js +48 -63
- package/dist/role-helpers.js.map +1 -1
- package/dist/screen.d.ts +7 -63
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +24 -110
- package/dist/screen.js.map +1 -1
- package/dist/screenshot.d.ts +21 -23
- package/dist/screenshot.d.ts.map +1 -1
- package/dist/screenshot.js +98 -50
- package/dist/screenshot.js.map +1 -1
- package/dist/suggestions.d.ts +27 -0
- package/dist/suggestions.d.ts.map +1 -0
- package/dist/suggestions.js +61 -0
- package/dist/suggestions.js.map +1 -0
- package/dist/traversal.d.ts +12 -10
- package/dist/traversal.d.ts.map +1 -1
- package/dist/traversal.js +36 -15
- package/dist/traversal.js.map +1 -1
- package/dist/types.d.ts +115 -169
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/user-event/adjustment.d.ts +10 -0
- package/dist/user-event/adjustment.d.ts.map +1 -0
- package/dist/user-event/adjustment.js +35 -0
- package/dist/user-event/adjustment.js.map +1 -0
- package/dist/user-event/click.d.ts +8 -0
- package/dist/user-event/click.d.ts.map +1 -0
- package/dist/user-event/click.js +73 -0
- package/dist/user-event/click.js.map +1 -0
- package/dist/user-event/controller.d.ts +8 -0
- package/dist/user-event/controller.d.ts.map +1 -0
- package/dist/user-event/controller.js +31 -0
- package/dist/user-event/controller.js.map +1 -0
- package/dist/user-event/dispatch.d.ts +7 -0
- package/dist/user-event/dispatch.d.ts.map +1 -0
- package/dist/user-event/dispatch.js +11 -0
- package/dist/user-event/dispatch.js.map +1 -0
- package/dist/user-event/event-wrapper.d.ts +4 -0
- package/dist/user-event/event-wrapper.d.ts.map +1 -0
- package/dist/user-event/event-wrapper.js +59 -0
- package/dist/user-event/event-wrapper.js.map +1 -0
- package/dist/user-event/gesture.d.ts +35 -0
- package/dist/user-event/gesture.d.ts.map +1 -0
- package/dist/user-event/gesture.js +138 -0
- package/dist/user-event/gesture.js.map +1 -0
- package/dist/user-event/index.d.ts +51 -0
- package/dist/user-event/index.d.ts.map +1 -0
- package/dist/user-event/index.js +42 -0
- package/dist/user-event/index.js.map +1 -0
- package/dist/user-event/keyboard.d.ts +10 -0
- package/dist/user-event/keyboard.d.ts.map +1 -0
- package/dist/user-event/keyboard.js +204 -0
- package/dist/user-event/keyboard.js.map +1 -0
- package/dist/user-event/pointer.d.ts +10 -0
- package/dist/user-event/pointer.d.ts.map +1 -0
- package/dist/user-event/pointer.js +30 -0
- package/dist/user-event/pointer.js.map +1 -0
- package/dist/user-event/selection.d.ts +5 -0
- package/dist/user-event/selection.d.ts.map +1 -0
- package/dist/user-event/selection.js +105 -0
- package/dist/user-event/selection.js.map +1 -0
- package/dist/user-event/state.d.ts +7 -0
- package/dist/user-event/state.d.ts.map +1 -0
- package/dist/user-event/state.js +3 -0
- package/dist/user-event/state.js.map +1 -0
- package/dist/user-event/text.d.ts +18 -0
- package/dist/user-event/text.d.ts.map +1 -0
- package/dist/user-event/text.js +113 -0
- package/dist/user-event/text.js.map +1 -0
- package/dist/wait-for.d.ts +16 -36
- package/dist/wait-for.d.ts.map +1 -1
- package/dist/wait-for.js +74 -70
- package/dist/wait-for.js.map +1 -1
- package/dist/widget-accessible-properties.d.ts +34 -0
- package/dist/widget-accessible-properties.d.ts.map +1 -0
- package/dist/widget-accessible-properties.js +260 -0
- package/dist/widget-accessible-properties.js.map +1 -0
- package/dist/within.d.ts +10 -26
- package/dist/within.d.ts.map +1 -1
- package/dist/within.js +16 -25
- package/dist/within.js.map +1 -1
- package/package.json +23 -12
- package/src/act.ts +77 -0
- package/src/bound-queries.ts +37 -0
- package/src/build-queries.ts +226 -0
- package/src/cleanup-registry.ts +27 -0
- package/src/config.ts +35 -62
- package/src/editable.ts +37 -0
- package/src/errors.ts +191 -0
- package/src/fire-event.ts +13 -38
- package/src/frame-sync.ts +51 -0
- package/src/index.ts +58 -15
- package/src/matchers.ts +251 -0
- package/src/pretty-widget.ts +163 -130
- package/src/queries.ts +485 -396
- package/src/register-test-hooks.ts +19 -0
- package/src/render-hook.tsx +38 -45
- package/src/render.tsx +192 -155
- package/src/role-helpers.ts +65 -72
- package/src/screen.ts +26 -114
- package/src/screenshot.ts +128 -56
- package/src/suggestions.ts +106 -0
- package/src/traversal.ts +56 -22
- package/src/types.ts +144 -172
- package/src/user-event/adjustment.ts +62 -0
- package/src/user-event/click.ts +99 -0
- package/src/user-event/controller.ts +58 -0
- package/src/user-event/dispatch.ts +25 -0
- package/src/user-event/event-wrapper.ts +80 -0
- package/src/user-event/gesture.ts +239 -0
- package/src/user-event/index.ts +81 -0
- package/src/user-event/keyboard.ts +290 -0
- package/src/user-event/pointer.ts +46 -0
- package/src/user-event/selection.ts +159 -0
- package/src/user-event/state.ts +8 -0
- package/src/user-event/text.ts +172 -0
- package/src/wait-for.ts +117 -78
- package/src/widget-accessible-properties.ts +388 -0
- package/src/within.ts +29 -27
- package/dist/bind-queries.d.ts +0 -14
- package/dist/bind-queries.d.ts.map +0 -1
- package/dist/bind-queries.js +0 -29
- package/dist/bind-queries.js.map +0 -1
- package/dist/error-builder.d.ts +0 -28
- package/dist/error-builder.d.ts.map +0 -1
- package/dist/error-builder.js +0 -81
- package/dist/error-builder.js.map +0 -1
- package/dist/timing.d.ts +0 -18
- package/dist/timing.d.ts.map +0 -1
- package/dist/timing.js +0 -18
- package/dist/timing.js.map +0 -1
- package/dist/user-event.d.ts +0 -138
- package/dist/user-event.d.ts.map +0 -1
- package/dist/user-event.js +0 -411
- package/dist/user-event.js.map +0 -1
- package/dist/widget-text.d.ts +0 -69
- package/dist/widget-text.d.ts.map +0 -1
- package/dist/widget-text.js +0 -177
- package/dist/widget-text.js.map +0 -1
- package/dist/widget.d.ts +0 -3
- package/dist/widget.d.ts.map +0 -1
- package/dist/widget.js +0 -13
- package/dist/widget.js.map +0 -1
- package/src/bind-queries.ts +0 -52
- package/src/error-builder.ts +0 -102
- package/src/timing.ts +0 -17
- package/src/user-event.ts +0 -492
- package/src/widget-text.ts +0 -202
- package/src/widget.ts +0 -15
package/README.md
CHANGED
|
@@ -1,70 +1,173 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
|
|
2
|
+
<img src="https://raw.githubusercontent.com/gtkx-org/gtkx/main/logo.svg" alt="GTKX" width="100" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">GTKX</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
|
|
8
|
+
The React framework for Linux.<br />
|
|
9
|
+
Build GTK4 and Adwaita apps in TypeScript, with React components and hooks driving GNOME's own widgets. What you ship is a GNOME app.
|
|
9
10
|
</p>
|
|
10
11
|
|
|
11
12
|
<p align="center">
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
<a href="https://www.npmjs.com/package/create-gtkx"><img src="https://img.shields.io/npm/v/create-gtkx?color=cb3837&logo=npm&label=create-gtkx" alt="npm version" /></a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/create-gtkx"><img src="https://img.shields.io/npm/dm/create-gtkx?color=cb3837&logo=npm&label=downloads" alt="npm downloads" /></a>
|
|
15
|
+
<img src="https://img.shields.io/badge/node-%E2%89%A524-339933?logo=node.js&logoColor=white" alt="Node >= 24" />
|
|
16
|
+
<a href="https://github.com/gtkx-org/gtkx/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MPL--2.0-blue.svg" alt="License: MPL-2.0" /></a>
|
|
17
|
+
<a href="https://github.com/gtkx-org/gtkx/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/gtkx-org/gtkx/ci.yml?branch=main&logo=github&label=CI" alt="CI status" /></a>
|
|
18
|
+
<img src="https://img.shields.io/badge/TypeScript-strict-3178c6?logo=typescript&logoColor=white" alt="TypeScript" />
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<a href="https://gtkx.dev">Homepage</a> ·
|
|
23
|
+
<a href="https://gtkx.dev/guide/why-gtkx">Documentation</a> ·
|
|
24
|
+
<a href="https://github.com/gtkx-org/gtkx/tree/main/examples">Examples</a> ·
|
|
25
|
+
<a href="https://github.com/gtkx-org/gtkx/blob/main/CONTRIBUTING.md">Contributing</a>
|
|
16
26
|
</p>
|
|
17
27
|
|
|
18
28
|
---
|
|
19
29
|
|
|
30
|
+
GTKX generates fully typed bindings for the entire GTK4 and Adwaita surface directly from GObject-Introspection. On top of those bindings you get the React programming model: components and hooks driving GObject instances, with Fast Refresh while you develop.
|
|
31
|
+
|
|
20
32
|
<p align="center">
|
|
21
|
-
|
|
33
|
+
<img src="https://raw.githubusercontent.com/gtkx-org/gtkx/main/examples/tutorial/assets/screenshot.png" alt="The Tasks app: an Adwaita window with a sidebar of smart views and colored lists on the left, and a boxed task list on the right." />
|
|
22
34
|
</p>
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
<p align="center">
|
|
37
|
+
<em>The Tasks app you build in the <a href="https://gtkx.dev/tutorial/">tutorial</a>.</em>
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
## Demo
|
|
41
|
+
|
|
42
|
+
The intrinsic elements in this snippet render GTK4 widgets, and ordinary React hooks and events drive them:
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
46
|
+
import { GtkApplication, GtkApplicationWindow, GtkBox, GtkButton, GtkLabel } from "@gtkx/jsx/gtk";
|
|
47
|
+
import { createRoot, quit } from "@gtkx/react";
|
|
48
|
+
import { useState } from "react";
|
|
49
|
+
|
|
50
|
+
const Counter = () => {
|
|
51
|
+
const [count, setCount] = useState(0);
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<GtkApplicationWindow
|
|
55
|
+
title="Hello GTKX"
|
|
56
|
+
defaultWidth={400}
|
|
57
|
+
defaultHeight={300}
|
|
58
|
+
onCloseRequest={quit}
|
|
59
|
+
>
|
|
60
|
+
<GtkBox
|
|
61
|
+
orientation={Gtk.Orientation.VERTICAL}
|
|
62
|
+
spacing={20}
|
|
63
|
+
marginTop={40}
|
|
64
|
+
marginBottom={40}
|
|
65
|
+
marginStart={40}
|
|
66
|
+
marginEnd={40}
|
|
67
|
+
valign={Gtk.Align.CENTER}
|
|
68
|
+
halign={Gtk.Align.CENTER}
|
|
69
|
+
>
|
|
70
|
+
<GtkLabel cssClasses={["title-1"]}>Welcome to GTKX!</GtkLabel>
|
|
71
|
+
<GtkLabel cssClasses={["title-2"]}>{`Count: ${count}`}</GtkLabel>
|
|
72
|
+
<GtkButton
|
|
73
|
+
label="Increment"
|
|
74
|
+
onClicked={() => setCount((c) => c + 1)}
|
|
75
|
+
cssClasses={["suggested-action", "pill"]}
|
|
76
|
+
/>
|
|
77
|
+
</GtkBox>
|
|
78
|
+
</GtkApplicationWindow>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const App = () => (
|
|
83
|
+
<GtkApplication>
|
|
84
|
+
<Counter />
|
|
85
|
+
</GtkApplication>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
createRoot().render(<App />);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
This is the [`hello-world`](https://github.com/gtkx-org/gtkx/tree/main/examples/hello-world) example, with `app.tsx` and `index.tsx` combined into a single snippet. `@gtkx/gi` and `@gtkx/jsx` are per-project bindings generated by the CLI, not packages you install from npm.
|
|
92
|
+
|
|
93
|
+
## Why GTKX
|
|
94
|
+
|
|
95
|
+
### A declarative layer for the GNOME stack
|
|
96
|
+
|
|
97
|
+
GTK4 is mature, and GtkBuilder XML can lay out a static interface, but nothing re-renders that interface when your application state changes, and nothing hot-reloads it as you work. GTKX adds that missing layer, and the tooling around it, on top of the stack you already know:
|
|
98
|
+
|
|
99
|
+
- a React reconciler that exposes every GObject as a JSX element,
|
|
100
|
+
- a CLI for scaffolding, development, and production builds,
|
|
101
|
+
- a dev server with Fast Refresh that patches your running UI in place,
|
|
102
|
+
- CSS-in-JS styling and high-level list, grid, and dialog components,
|
|
103
|
+
- a Testing Library-style API for querying and driving your widgets in tests,
|
|
104
|
+
- and a Model Context Protocol (MCP) server that exposes your live app to AI agents.
|
|
105
|
+
|
|
106
|
+
### The full GNOME API surface
|
|
107
|
+
|
|
108
|
+
React Native and similar frameworks hide the native toolkit so one API can run everywhere. GTKX exposes it: GTK4, Adwaita, and any other GObject-Introspection library on your system. Linux-only by design.
|
|
109
|
+
|
|
110
|
+
### Why Node.js, and why generated bindings
|
|
111
|
+
|
|
112
|
+
GTKX runs on Node.js, which puts native modules, the npm ecosystem, and the tooling built for Node.js APIs within reach. GJS is GNOME's own runtime, built on SpiderMonkey rather than V8; node-gtk runs on Node.js but is lightly maintained, on the older nan/V8 ABI rather than N-API, and still centered on GTK3. The [why-gtkx guide](https://gtkx.dev/guide/why-gtkx) covers the comparison in full.
|
|
25
113
|
|
|
26
|
-
GTKX
|
|
114
|
+
GTKX generates the TypeScript types and the native FFI calls from the same GObject-Introspection data, so the types cannot drift from the calls they back. Codegen covers the whole GTK4 and Adwaita surface.
|
|
27
115
|
|
|
28
|
-
|
|
116
|
+
At runtime, the native Rust core calls straight into the system GTK4, Adwaita, and GLib libraries through libffi, without loading libgirepository at all.
|
|
29
117
|
|
|
30
|
-
|
|
31
|
-
- **Fully native Node.js environment** - Runs on vanilla Node.js, with the help of a Neon native module
|
|
32
|
-
- **TypeScript first** — Full type safety with auto-generated bindings
|
|
33
|
-
- **Rich GLib support** — Provides bindings for most modern GLib/GObject libraries, including Adwaita
|
|
34
|
-
- **HMR** — Fast refresh during development powered by Vite
|
|
35
|
-
- **CSS-in-JS styling** — Easy styling with GTK CSS powered by Emotion
|
|
36
|
-
- **Testing library** — Testing Library-inspired API for testing components and E2E
|
|
118
|
+
## Quick start
|
|
37
119
|
|
|
38
|
-
|
|
120
|
+
GTKX is Linux-only and needs Node.js 24 or later. See [Requirements](#requirements).
|
|
39
121
|
|
|
40
|
-
|
|
41
|
-
|
|
122
|
+
Scaffold a new app with the `create-gtkx` initializer:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
npm create gtkx@rc
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The same command works with other package managers: `pnpm create gtkx@rc` or `yarn create gtkx@rc`.
|
|
129
|
+
|
|
130
|
+
Then run your new app:
|
|
131
|
+
|
|
132
|
+
```sh
|
|
42
133
|
cd my-app
|
|
43
134
|
npm run dev
|
|
44
135
|
```
|
|
45
136
|
|
|
46
|
-
|
|
137
|
+
To go further, follow the [tutorial](https://gtkx.dev/tutorial/).
|
|
47
138
|
|
|
48
|
-
|
|
139
|
+
## Documentation
|
|
49
140
|
|
|
50
|
-
|
|
51
|
-
- **[gtk-demo](./examples/gtk-demo)** — Full replica of the official GTK demo app
|
|
52
|
-
- **[tutorial](./examples/tutorial)** — Notes app from the tutorial with GSettings and Adwaita
|
|
53
|
-
- **[browser](./examples/browser)** — Simple browser using WebKitWebView
|
|
141
|
+
The documentation at **[gtkx.dev](https://gtkx.dev)** includes a step-by-step tutorial that builds a complete GNOME app, from scaffolding to packaging and shipping, plus guides and a full API reference.
|
|
54
142
|
|
|
55
|
-
|
|
143
|
+
**[Read the docs →](https://gtkx.dev/guide/why-gtkx)**
|
|
56
144
|
|
|
57
|
-
|
|
145
|
+
## Requirements
|
|
58
146
|
|
|
59
|
-
|
|
147
|
+
GTKX is Linux-only. You need:
|
|
60
148
|
|
|
61
|
-
|
|
149
|
+
- Linux with the GTK4 (4.20 or later), Adwaita (1.8 or later), and GLib development libraries
|
|
150
|
+
- Node.js 24 or later
|
|
62
151
|
|
|
63
|
-
|
|
152
|
+
The `@gtkx/native` addon ships prebuilt for x64 and arm64 glibc Linux; other targets need to build it from the GTKX repository, which requires a Rust toolchain.
|
|
153
|
+
|
|
154
|
+
## Examples
|
|
155
|
+
|
|
156
|
+
Explore the [example apps](https://github.com/gtkx-org/gtkx/tree/main/examples):
|
|
157
|
+
|
|
158
|
+
- [`hello-world`](https://github.com/gtkx-org/gtkx/tree/main/examples/hello-world): the counter above.
|
|
159
|
+
- [`gtk-demo`](https://github.com/gtkx-org/gtkx/tree/main/examples/gtk-demo): a React port of the official GTK4 widget showcase, covering lists, dialogs, gestures, CSS, and OpenGL.
|
|
160
|
+
- [`browser`](https://github.com/gtkx-org/gtkx/tree/main/examples/browser): a WebKitWebView-based web browser.
|
|
161
|
+
- [`tutorial`](https://github.com/gtkx-org/gtkx/tree/main/examples/tutorial): the Tasks app the documentation builds.
|
|
162
|
+
|
|
163
|
+
## Status
|
|
164
|
+
|
|
165
|
+
GTKX 1.0 is at the release candidate stage.
|
|
166
|
+
|
|
167
|
+
## Contributing
|
|
64
168
|
|
|
65
|
-
- [
|
|
66
|
-
- [Issue Tracker](https://github.com/gtkx-org/gtkx/issues) — Bug reports and feature requests
|
|
169
|
+
Contributions are welcome. See [CONTRIBUTING.md](https://github.com/gtkx-org/gtkx/blob/main/CONTRIBUTING.md), the [Code of Conduct](https://github.com/gtkx-org/gtkx/blob/main/CODE_OF_CONDUCT.md), and the [security policy](https://github.com/gtkx-org/gtkx/blob/main/SECURITY.md). Building the repo needs Node.js 24 or later, pnpm, and a Rust toolchain.
|
|
67
170
|
|
|
68
171
|
## License
|
|
69
172
|
|
|
70
|
-
[MPL-2.0](
|
|
173
|
+
GTKX is licensed under [MPL-2.0](https://github.com/gtkx-org/gtkx/blob/main/LICENSE).
|
package/dist/act.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
var IS_REACT_ACT_ENVIRONMENT: boolean | undefined;
|
|
3
|
+
}
|
|
4
|
+
type ActCallback<T> = () => T | PromiseLike<T>;
|
|
5
|
+
type ActImplementation = <T>(callback: ActCallback<T>) => PromiseLike<T>;
|
|
6
|
+
/**
|
|
7
|
+
* Runs a callback inside React's act environment, flushing pending state
|
|
8
|
+
* updates and effects, and resolves once the work has settled.
|
|
9
|
+
*
|
|
10
|
+
* @param callback Work to run within the act environment.
|
|
11
|
+
* @returns A promise that resolves with the callback's result after updates flush.
|
|
12
|
+
*/
|
|
13
|
+
declare const act: ActImplementation;
|
|
14
|
+
declare const getIsReactActEnvironment: () => boolean | undefined;
|
|
15
|
+
declare const setIsReactActEnvironment: (value: boolean | undefined) => void;
|
|
16
|
+
declare const runWithActEnvironment: <T>(isForced: boolean, fn: () => T | PromiseLike<T>) => Promise<T>;
|
|
17
|
+
declare const runInAct: (callback: () => unknown) => Promise<void>;
|
|
18
|
+
export { act, getIsReactActEnvironment, setIsReactActEnvironment, runWithActEnvironment, runInAct };
|
|
19
|
+
//# sourceMappingURL=act.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACX,IAAI,wBAAwB,EAAE,OAAO,GAAG,SAAS,CAAC;CACrD;AAED,KAAK,WAAW,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAC/C,KAAK,iBAAiB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;AAGzE;;;;;;GAMG;AACH,QAAA,MAAM,GAAG,EAAE,iBAA+D,CAAC;AAU3E,QAAA,MAAM,wBAAwB,QAAO,OAAO,GAAG,SAAqD,CAAC;AAErG,QAAA,MAAM,wBAAwB,GAAI,OAAO,OAAO,GAAG,SAAS,KAAG,IAE9D,CAAC;AAaF,QAAA,MAAM,qBAAqB,GAAI,CAAC,EAAE,UAAU,OAAO,EAAE,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,CAAC,CAkB5F,CAAC;AAUF,QAAA,MAAM,QAAQ,GAAU,UAAU,MAAM,OAAO,KAAG,OAAO,CAAC,IAAI,CAE7D,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC"}
|
package/dist/act.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { act as reactAct } from "react";
|
|
2
|
+
const actImplementation = reactAct;
|
|
3
|
+
/**
|
|
4
|
+
* Runs a callback inside React's act environment, flushing pending state
|
|
5
|
+
* updates and effects, and resolves once the work has settled.
|
|
6
|
+
*
|
|
7
|
+
* @param callback Work to run within the act environment.
|
|
8
|
+
* @returns A promise that resolves with the callback's result after updates flush.
|
|
9
|
+
*/
|
|
10
|
+
const act = withGlobalActEnvironment(actImplementation);
|
|
11
|
+
const getGlobalThis = () => {
|
|
12
|
+
if (typeof globalThis !== "undefined") {
|
|
13
|
+
return globalThis;
|
|
14
|
+
}
|
|
15
|
+
throw new Error("unable to locate global object");
|
|
16
|
+
};
|
|
17
|
+
const getIsReactActEnvironment = () => getGlobalThis().IS_REACT_ACT_ENVIRONMENT;
|
|
18
|
+
const setIsReactActEnvironment = (value) => {
|
|
19
|
+
getGlobalThis().IS_REACT_ACT_ENVIRONMENT = value;
|
|
20
|
+
};
|
|
21
|
+
const isThenable = (value) => value !== null && typeof value === "object" && typeof value.then === "function";
|
|
22
|
+
const restoreAfter = async (result, previous) => {
|
|
23
|
+
try {
|
|
24
|
+
return await result;
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
setIsReactActEnvironment(previous);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const runWithActEnvironment = (isForced, fn) => {
|
|
31
|
+
const previousActEnvironment = getIsReactActEnvironment();
|
|
32
|
+
setIsReactActEnvironment(isForced);
|
|
33
|
+
try {
|
|
34
|
+
const result = fn();
|
|
35
|
+
if (isThenable(result)) {
|
|
36
|
+
return restoreAfter(result, previousActEnvironment);
|
|
37
|
+
}
|
|
38
|
+
setIsReactActEnvironment(previousActEnvironment);
|
|
39
|
+
return Promise.resolve(result);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
setIsReactActEnvironment(previousActEnvironment);
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
function withGlobalActEnvironment(actImplementation) {
|
|
47
|
+
return (callback) => {
|
|
48
|
+
const settled = runWithActEnvironment(true, () => actImplementation(() => callback()));
|
|
49
|
+
return Promise.resolve(settled);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const runInAct = async (callback) => {
|
|
53
|
+
await act(() => callback());
|
|
54
|
+
};
|
|
55
|
+
export { act, getIsReactActEnvironment, setIsReactActEnvironment, runWithActEnvironment, runInAct };
|
|
56
|
+
//# sourceMappingURL=act.js.map
|
package/dist/act.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"act.js","sourceRoot":"","sources":["../src/act.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,QAAQ,EAAE,MAAM,OAAO,CAAC;AASxC,MAAM,iBAAiB,GAAsB,QAAQ,CAAC;AACtD;;;;;;GAMG;AACH,MAAM,GAAG,GAAsB,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;AAE3E,MAAM,aAAa,GAAG,GAAsB,EAAE;IAC1C,IAAI,OAAO,UAAU,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,GAAwB,EAAE,CAAC,aAAa,EAAE,CAAC,wBAAwB,CAAC;AAErG,MAAM,wBAAwB,GAAG,CAAC,KAA0B,EAAQ,EAAE;IAClE,aAAa,EAAE,CAAC,wBAAwB,GAAG,KAAK,CAAC;AACrD,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAI,KAAc,EAA2B,EAAE,CAC9D,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAAwB,CAAC,IAAI,KAAK,UAAU,CAAC;AAExG,MAAM,YAAY,GAAG,KAAK,EAAK,MAAsB,EAAE,QAA6B,EAAc,EAAE;IAChG,IAAI,CAAC;QACD,OAAO,MAAM,MAAM,CAAC;IACxB,CAAC;YAAS,CAAC;QACP,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAI,QAAiB,EAAE,EAA4B,EAAc,EAAE;IAC7F,MAAM,sBAAsB,GAAG,wBAAwB,EAAE,CAAC;IAC1D,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,CAAC;QACD,MAAM,MAAM,GAAuB,EAAE,EAAE,CAAC;QAExC,IAAI,UAAU,CAAI,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,YAAY,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;QACxD,CAAC;QAED,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QAEjD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,wBAAwB,CAAC,sBAAsB,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC,CAAC;AAEF,SAAS,wBAAwB,CAAC,iBAAoC;IAClE,OAAO,CAAI,QAAwB,EAAkB,EAAE;QACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEvF,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAuB,EAAiB,EAAE;IAC9D,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,OAAO,EAAE,GAAG,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,CAAC","sourcesContent":["import { act as reactAct } from \"react\";\n\ndeclare global {\n var IS_REACT_ACT_ENVIRONMENT: boolean | undefined;\n}\n\ntype ActCallback<T> = () => T | PromiseLike<T>;\ntype ActImplementation = <T>(callback: ActCallback<T>) => PromiseLike<T>;\n\nconst actImplementation: ActImplementation = reactAct;\n/**\n * Runs a callback inside React's act environment, flushing pending state\n * updates and effects, and resolves once the work has settled.\n *\n * @param callback Work to run within the act environment.\n * @returns A promise that resolves with the callback's result after updates flush.\n */\nconst act: ActImplementation = withGlobalActEnvironment(actImplementation);\n\nconst getGlobalThis = (): typeof globalThis => {\n if (typeof globalThis !== \"undefined\") {\n return globalThis;\n }\n\n throw new Error(\"unable to locate global object\");\n};\n\nconst getIsReactActEnvironment = (): boolean | undefined => getGlobalThis().IS_REACT_ACT_ENVIRONMENT;\n\nconst setIsReactActEnvironment = (value: boolean | undefined): void => {\n getGlobalThis().IS_REACT_ACT_ENVIRONMENT = value;\n};\n\nconst isThenable = <T>(value: unknown): value is PromiseLike<T> =>\n value !== null && typeof value === \"object\" && typeof (value as PromiseLike<T>).then === \"function\";\n\nconst restoreAfter = async <T>(result: PromiseLike<T>, previous: boolean | undefined): Promise<T> => {\n try {\n return await result;\n } finally {\n setIsReactActEnvironment(previous);\n }\n};\n\nconst runWithActEnvironment = <T>(isForced: boolean, fn: () => T | PromiseLike<T>): Promise<T> => {\n const previousActEnvironment = getIsReactActEnvironment();\n setIsReactActEnvironment(isForced);\n\n try {\n const result: T | PromiseLike<T> = fn();\n\n if (isThenable<T>(result)) {\n return restoreAfter(result, previousActEnvironment);\n }\n\n setIsReactActEnvironment(previousActEnvironment);\n\n return Promise.resolve(result);\n } catch (error) {\n setIsReactActEnvironment(previousActEnvironment);\n throw error;\n }\n};\n\nfunction withGlobalActEnvironment(actImplementation: ActImplementation): ActImplementation {\n return <T>(callback: ActCallback<T>): PromiseLike<T> => {\n const settled = runWithActEnvironment(true, () => actImplementation(() => callback()));\n\n return Promise.resolve(settled);\n };\n}\n\nconst runInAct = async (callback: () => unknown): Promise<void> => {\n await act(() => callback());\n};\n\nexport { act, getIsReactActEnvironment, setIsReactActEnvironment, runWithActEnvironment, runInAct };\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import type { builtinQueries } from "./queries.js";
|
|
4
|
+
import type { Container } from "./traversal.js";
|
|
5
|
+
import type { BoundCustomQueries, DebugUtilities, QueryMap } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* The set of built-in queries (getBy, findBy, queryBy, and their All variants)
|
|
8
|
+
* bound to a specific container.
|
|
9
|
+
*/
|
|
10
|
+
type BoundQueries = BoundCustomQueries<typeof builtinQueries>;
|
|
11
|
+
/**
|
|
12
|
+
* The global screen object's shape: built-in queries scoped to the current
|
|
13
|
+
* toplevels, plus debug utilities.
|
|
14
|
+
*/
|
|
15
|
+
type Screen = BoundQueries & DebugUtilities;
|
|
16
|
+
/**
|
|
17
|
+
* The result of a render call: queries scoped to the rendered tree, debug
|
|
18
|
+
* utilities, and controls for updating or tearing down the render.
|
|
19
|
+
*
|
|
20
|
+
* @typeParam Q Custom queries provided at render time, merged with the built-in ones.
|
|
21
|
+
*/
|
|
22
|
+
type RenderResult<Q extends QueryMap = Record<never, never>> = BoundQueries & BoundCustomQueries<Q> & DebugUtilities & {
|
|
23
|
+
/** The top-level widget the element was rendered into. */
|
|
24
|
+
container: Gtk.Widget;
|
|
25
|
+
/** The root the queries are scoped to (defaults to all toplevels). */
|
|
26
|
+
baseElement: Container;
|
|
27
|
+
/** Unmounts the rendered tree and disposes its resources. */
|
|
28
|
+
unmount: () => Promise<void>;
|
|
29
|
+
/** Re-renders the tree with a new element, reusing the same root. */
|
|
30
|
+
rerender: (element: ReactNode) => Promise<void>;
|
|
31
|
+
};
|
|
32
|
+
export { type BoundQueries, type Screen, type RenderResult };
|
|
33
|
+
//# sourceMappingURL=bound-queries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bound-queries.d.ts","sourceRoot":"","sources":["../src/bound-queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE/E;;;GAGG;AACH,KAAK,YAAY,GAAG,kBAAkB,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D;;;GAGG;AACH,KAAK,MAAM,GAAG,YAAY,GAAG,cAAc,CAAC;AAE5C;;;;;GAKG;AACH,KAAK,YAAY,CAAC,CAAC,SAAS,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,YAAY,GACvE,kBAAkB,CAAC,CAAC,CAAC,GACrB,cAAc,GAAG;IACb,0DAA0D;IAC1D,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC;IACtB,sEAAsE;IACtE,WAAW,EAAE,SAAS,CAAC;IACvB,6DAA6D;IAC7D,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,qEAAqE;IACrE,QAAQ,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAAC;AAEN,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,MAAM,EAAE,KAAK,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bound-queries.js","sourceRoot":"","sources":["../src/bound-queries.ts"],"names":[],"mappings":"AAoCA,OAAO,EAAqD,CAAC","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport type { ReactNode } from \"react\";\nimport type { builtinQueries } from \"./queries.js\";\nimport type { Container } from \"./traversal.js\";\nimport type { BoundCustomQueries, DebugUtilities, QueryMap } from \"./types.js\";\n\n/**\n * The set of built-in queries (getBy, findBy, queryBy, and their All variants)\n * bound to a specific container.\n */\ntype BoundQueries = BoundCustomQueries<typeof builtinQueries>;\n/**\n * The global screen object's shape: built-in queries scoped to the current\n * toplevels, plus debug utilities.\n */\ntype Screen = BoundQueries & DebugUtilities;\n\n/**\n * The result of a render call: queries scoped to the rendered tree, debug\n * utilities, and controls for updating or tearing down the render.\n *\n * @typeParam Q Custom queries provided at render time, merged with the built-in ones.\n */\ntype RenderResult<Q extends QueryMap = Record<never, never>> = BoundQueries &\n BoundCustomQueries<Q> &\n DebugUtilities & {\n /** The top-level widget the element was rendered into. */\n container: Gtk.Widget;\n /** The root the queries are scoped to (defaults to all toplevels). */\n baseElement: Container;\n /** Unmounts the rendered tree and disposes its resources. */\n unmount: () => Promise<void>;\n /** Re-renders the tree with a new element, reusing the same root. */\n rerender: (element: ReactNode) => Promise<void>;\n };\n\nexport { type BoundQueries, type Screen, type RenderResult };\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
import type { Container } from "./traversal.js";
|
|
3
|
+
import { type Method } from "./suggestions.js";
|
|
4
|
+
type QueryAllBy<Args extends unknown[]> = (container: Container, ...args: Args) => Gtk.Widget[];
|
|
5
|
+
type MultipleErrorBuilder<Args extends unknown[]> = (container: Container, matches: Gtk.Widget[], ...args: Args) => Error;
|
|
6
|
+
type MissingErrorBuilder<Args extends unknown[]> = (container: Container, ...args: Args) => Error;
|
|
7
|
+
type BuiltQueries<Args extends unknown[]> = {
|
|
8
|
+
queryBy: (container: Container, ...args: Args) => Gtk.Widget | null;
|
|
9
|
+
getAllBy: QueryAllBy<Args>;
|
|
10
|
+
getBy: (container: Container, ...args: Args) => Gtk.Widget;
|
|
11
|
+
findAllBy: (container: Container, ...args: Args) => Promise<Gtk.Widget[]>;
|
|
12
|
+
findBy: (container: Container, ...args: Args) => Promise<Gtk.Widget>;
|
|
13
|
+
};
|
|
14
|
+
declare const buildQueries: <Args extends unknown[]>(queryName: Method, queryAllBy: QueryAllBy<Args>, getMultipleError: MultipleErrorBuilder<Args>, getMissingError: MissingErrorBuilder<Args>) => BuiltQueries<Args>;
|
|
15
|
+
export { buildQueries, type QueryAllBy, type BuiltQueries };
|
|
16
|
+
//# sourceMappingURL=build-queries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-queries.d.ts","sourceRoot":"","sources":["../src/build-queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAIhD,OAAO,EAAqB,KAAK,MAAM,EAAgB,MAAM,kBAAkB,CAAC;AAGhF,KAAK,UAAU,CAAC,IAAI,SAAS,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;AAEhG,KAAK,oBAAoB,CAAC,IAAI,SAAS,OAAO,EAAE,IAAI,CAChD,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,EACrB,GAAG,IAAI,EAAE,IAAI,KACZ,KAAK,CAAC;AAEX,KAAK,mBAAmB,CAAC,IAAI,SAAS,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,KAAK,CAAC;AAElG,KAAK,YAAY,CAAC,IAAI,SAAS,OAAO,EAAE,IAAI;IACxC,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;IACpE,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC;IAC3D,SAAS,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1E,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;CACxE,CAAC;AA4JF,QAAA,MAAM,YAAY,GAAI,IAAI,SAAS,OAAO,EAAE,EACxC,WAAW,MAAM,EACjB,YAAY,UAAU,CAAC,IAAI,CAAC,EAC5B,kBAAkB,oBAAoB,CAAC,IAAI,CAAC,EAC5C,iBAAiB,mBAAmB,CAAC,IAAI,CAAC,KAC3C,YAAY,CAAC,IAAI,CAsCnB,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { getConfig } from "./config.js";
|
|
2
|
+
import { runWithExpensiveErrorDiagnosticsDisabled, suggestionError } from "./errors.js";
|
|
3
|
+
import { getSuggestedQuery } from "./suggestions.js";
|
|
4
|
+
import { waitFor } from "./wait-for.js";
|
|
5
|
+
const extractWaitForOptions = (args) => {
|
|
6
|
+
const last = args.at(-1);
|
|
7
|
+
if (last && typeof last === "object" && !(last instanceof RegExp)) {
|
|
8
|
+
const { timeout, interval, onTimeout } = last;
|
|
9
|
+
return { timeout, interval, onTimeout };
|
|
10
|
+
}
|
|
11
|
+
return {};
|
|
12
|
+
};
|
|
13
|
+
const extractSuggestOption = (args) => {
|
|
14
|
+
const last = args.at(-1);
|
|
15
|
+
if (last && typeof last === "object" && !(last instanceof RegExp)) {
|
|
16
|
+
return last.suggest;
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
};
|
|
20
|
+
const maybeThrowSuggestion = (options) => {
|
|
21
|
+
const { container, match, queryName, variant, suggest } = options;
|
|
22
|
+
const shouldSuggest = suggest ?? getConfig().throwSuggestions;
|
|
23
|
+
if (!shouldSuggest) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const suggestion = getSuggestedQuery(match, variant);
|
|
27
|
+
if (suggestion && suggestion.queryName !== queryName) {
|
|
28
|
+
throw suggestionError(suggestion.toString(), container);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const reRunForDiagnostics = (query, container, args, fallback) => {
|
|
32
|
+
try {
|
|
33
|
+
query(container, ...args);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (error instanceof Error) {
|
|
37
|
+
return error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return fallback;
|
|
41
|
+
};
|
|
42
|
+
const findOptions = (query, container, args) => {
|
|
43
|
+
const userOptions = extractWaitForOptions(args);
|
|
44
|
+
const onTimeout = userOptions.onTimeout ?? ((fallback) => reRunForDiagnostics(query, container, args, fallback));
|
|
45
|
+
return {
|
|
46
|
+
stackTraceError: new Error("STACK_TRACE_MESSAGE"),
|
|
47
|
+
onTimeout,
|
|
48
|
+
timeout: userOptions.timeout,
|
|
49
|
+
interval: userOptions.interval,
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
const singleFrom = (allQuery, getMultipleError) => (container, ...args) => {
|
|
53
|
+
const matches = allQuery(container, ...args);
|
|
54
|
+
if (matches.length > 1) {
|
|
55
|
+
throw getMultipleError(container, matches, ...args);
|
|
56
|
+
}
|
|
57
|
+
return matches[0] ?? null;
|
|
58
|
+
};
|
|
59
|
+
const allOrThrow = (allQuery, getMissingError) => (container, ...args) => {
|
|
60
|
+
const matches = allQuery(container, ...args);
|
|
61
|
+
if (matches.length === 0) {
|
|
62
|
+
throw getMissingError(container, ...args);
|
|
63
|
+
}
|
|
64
|
+
return matches;
|
|
65
|
+
};
|
|
66
|
+
const wrapSingleWithSuggestion = (query, queryName, variant) => (container, ...args) => {
|
|
67
|
+
const match = query(container, ...args);
|
|
68
|
+
if (match) {
|
|
69
|
+
maybeThrowSuggestion({ container, match, queryName, variant, suggest: extractSuggestOption(args) });
|
|
70
|
+
}
|
|
71
|
+
return match;
|
|
72
|
+
};
|
|
73
|
+
const wrapAllWithSuggestion = (query, queryName, variant) => (container, ...args) => {
|
|
74
|
+
const matches = query(container, ...args);
|
|
75
|
+
const [first] = matches;
|
|
76
|
+
if (first !== undefined) {
|
|
77
|
+
maybeThrowSuggestion({
|
|
78
|
+
container,
|
|
79
|
+
match: first,
|
|
80
|
+
queryName,
|
|
81
|
+
variant,
|
|
82
|
+
suggest: extractSuggestOption(args),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return matches;
|
|
86
|
+
};
|
|
87
|
+
const requireSingle = (query, getMissingError) => (container, ...args) => {
|
|
88
|
+
const match = query(container, ...args);
|
|
89
|
+
if (match === null) {
|
|
90
|
+
throw getMissingError(container, ...args);
|
|
91
|
+
}
|
|
92
|
+
return match;
|
|
93
|
+
};
|
|
94
|
+
const buildQueries = (queryName, queryAllBy, getMultipleError, getMissingError) => {
|
|
95
|
+
const getAllBy = allOrThrow(queryAllBy, getMissingError);
|
|
96
|
+
const getBy = requireSingle(singleFrom(getAllBy, getMultipleError), getMissingError);
|
|
97
|
+
const queryByWithSuggestion = wrapSingleWithSuggestion(singleFrom(queryAllBy, getMultipleError), queryName, "query");
|
|
98
|
+
const getAllByWithSuggestion = wrapAllWithSuggestion(getAllBy, queryName, "getAll");
|
|
99
|
+
const getByWithSuggestion = (container, ...args) => {
|
|
100
|
+
const match = getBy(container, ...args);
|
|
101
|
+
maybeThrowSuggestion({ container, match, queryName, variant: "get", suggest: extractSuggestOption(args) });
|
|
102
|
+
return match;
|
|
103
|
+
};
|
|
104
|
+
const findAllBy = (container, ...args) => waitFor(() => runWithExpensiveErrorDiagnosticsDisabled(() => getAllByWithSuggestion(container, ...args)), findOptions(getAllByWithSuggestion, container, args));
|
|
105
|
+
const findBy = (container, ...args) => waitFor(() => runWithExpensiveErrorDiagnosticsDisabled(() => getByWithSuggestion(container, ...args)), findOptions(getByWithSuggestion, container, args));
|
|
106
|
+
return {
|
|
107
|
+
queryBy: queryByWithSuggestion,
|
|
108
|
+
getAllBy: getAllByWithSuggestion,
|
|
109
|
+
getBy: getByWithSuggestion,
|
|
110
|
+
findAllBy,
|
|
111
|
+
findBy,
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
export { buildQueries };
|
|
115
|
+
//# sourceMappingURL=build-queries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-queries.js","sourceRoot":"","sources":["../src/build-queries.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport type { Container } from \"./traversal.js\";\nimport type { MatcherOptions, WaitForOptions } from \"./types.js\";\nimport { getConfig } from \"./config.js\";\nimport { runWithExpensiveErrorDiagnosticsDisabled, suggestionError } from \"./errors.js\";\nimport { getSuggestedQuery, type Method, type Variant } from \"./suggestions.js\";\nimport { waitFor } from \"./wait-for.js\";\n\ntype QueryAllBy<Args extends unknown[]> = (container: Container, ...args: Args) => Gtk.Widget[];\n\ntype MultipleErrorBuilder<Args extends unknown[]> = (\n container: Container,\n matches: Gtk.Widget[],\n ...args: Args\n) => Error;\n\ntype MissingErrorBuilder<Args extends unknown[]> = (container: Container, ...args: Args) => Error;\n\ntype BuiltQueries<Args extends unknown[]> = {\n queryBy: (container: Container, ...args: Args) => Gtk.Widget | null;\n getAllBy: QueryAllBy<Args>;\n getBy: (container: Container, ...args: Args) => Gtk.Widget;\n findAllBy: (container: Container, ...args: Args) => Promise<Gtk.Widget[]>;\n findBy: (container: Container, ...args: Args) => Promise<Gtk.Widget>;\n};\n\ntype FindQuery<Args extends unknown[]> = (container: Container, ...args: Args) => unknown;\ntype SingleQuery<Args extends unknown[]> = (container: Container, ...args: Args) => Gtk.Widget | null;\n\nconst extractWaitForOptions = (args: unknown[]): WaitForOptions => {\n const last = args.at(-1);\n\n if (last && typeof last === \"object\" && !(last instanceof RegExp)) {\n const { timeout, interval, onTimeout } = last as WaitForOptions;\n\n return { timeout, interval, onTimeout };\n }\n\n return {};\n};\n\nconst extractSuggestOption = (args: unknown[]): boolean | undefined => {\n const last = args.at(-1);\n\n if (last && typeof last === \"object\" && !(last instanceof RegExp)) {\n return (last as MatcherOptions).suggest;\n }\n\n return undefined;\n};\n\nconst maybeThrowSuggestion = (options: {\n container: Container;\n match: Gtk.Widget;\n queryName: Method;\n variant: Variant;\n suggest: boolean | undefined;\n}): void => {\n const { container, match, queryName, variant, suggest } = options;\n const shouldSuggest = suggest ?? getConfig().throwSuggestions;\n\n if (!shouldSuggest) {\n return;\n }\n\n const suggestion = getSuggestedQuery(match, variant);\n\n if (suggestion && suggestion.queryName !== queryName) {\n throw suggestionError(suggestion.toString(), container);\n }\n};\n\nconst reRunForDiagnostics = <Args extends unknown[]>(\n query: FindQuery<Args>,\n container: Container,\n args: Args,\n fallback: Error,\n): Error => {\n try {\n query(container, ...args);\n } catch (error) {\n if (error instanceof Error) {\n return error;\n }\n }\n\n return fallback;\n};\n\nconst findOptions = <Args extends unknown[]>(\n query: FindQuery<Args>,\n container: Container,\n args: Args,\n): WaitForOptions => {\n const userOptions = extractWaitForOptions(args);\n\n const onTimeout =\n userOptions.onTimeout ?? ((fallback: Error) => reRunForDiagnostics(query, container, args, fallback));\n\n return {\n stackTraceError: new Error(\"STACK_TRACE_MESSAGE\"),\n onTimeout,\n timeout: userOptions.timeout,\n interval: userOptions.interval,\n };\n};\n\nconst singleFrom =\n <Args extends unknown[]>(\n allQuery: QueryAllBy<Args>,\n getMultipleError: MultipleErrorBuilder<Args>,\n ): SingleQuery<Args> =>\n (container, ...args) => {\n const matches = allQuery(container, ...args);\n\n if (matches.length > 1) {\n throw getMultipleError(container, matches, ...args);\n }\n\n return matches[0] ?? null;\n };\n\nconst allOrThrow =\n <Args extends unknown[]>(\n allQuery: QueryAllBy<Args>,\n getMissingError: MissingErrorBuilder<Args>,\n ): QueryAllBy<Args> =>\n (container, ...args) => {\n const matches = allQuery(container, ...args);\n\n if (matches.length === 0) {\n throw getMissingError(container, ...args);\n }\n\n return matches;\n };\n\nconst wrapSingleWithSuggestion =\n <Args extends unknown[]>(query: SingleQuery<Args>, queryName: Method, variant: Variant): SingleQuery<Args> =>\n (container, ...args) => {\n const match = query(container, ...args);\n\n if (match) {\n maybeThrowSuggestion({ container, match, queryName, variant, suggest: extractSuggestOption(args) });\n }\n\n return match;\n };\n\nconst wrapAllWithSuggestion =\n <Args extends unknown[]>(query: QueryAllBy<Args>, queryName: Method, variant: Variant): QueryAllBy<Args> =>\n (container, ...args) => {\n const matches = query(container, ...args);\n const [first] = matches;\n\n if (first !== undefined) {\n maybeThrowSuggestion({\n container,\n match: first,\n queryName,\n variant,\n suggest: extractSuggestOption(args),\n });\n }\n\n return matches;\n };\n\nconst requireSingle =\n <Args extends unknown[]>(query: SingleQuery<Args>, getMissingError: MissingErrorBuilder<Args>) =>\n (container: Container, ...args: Args): Gtk.Widget => {\n const match = query(container, ...args);\n\n if (match === null) {\n throw getMissingError(container, ...args);\n }\n\n return match;\n };\n\nconst buildQueries = <Args extends unknown[]>(\n queryName: Method,\n queryAllBy: QueryAllBy<Args>,\n getMultipleError: MultipleErrorBuilder<Args>,\n getMissingError: MissingErrorBuilder<Args>,\n): BuiltQueries<Args> => {\n const getAllBy = allOrThrow(queryAllBy, getMissingError);\n const getBy = requireSingle(singleFrom(getAllBy, getMultipleError), getMissingError);\n\n const queryByWithSuggestion = wrapSingleWithSuggestion(\n singleFrom(queryAllBy, getMultipleError),\n queryName,\n \"query\",\n );\n\n const getAllByWithSuggestion = wrapAllWithSuggestion(getAllBy, queryName, \"getAll\");\n\n const getByWithSuggestion: (container: Container, ...args: Args) => Gtk.Widget = (container, ...args) => {\n const match = getBy(container, ...args);\n maybeThrowSuggestion({ container, match, queryName, variant: \"get\", suggest: extractSuggestOption(args) });\n\n return match;\n };\n\n const findAllBy = (container: Container, ...args: Args): Promise<Gtk.Widget[]> =>\n waitFor(\n () => runWithExpensiveErrorDiagnosticsDisabled(() => getAllByWithSuggestion(container, ...args)),\n findOptions(getAllByWithSuggestion, container, args),\n );\n\n const findBy = (container: Container, ...args: Args): Promise<Gtk.Widget> =>\n waitFor(\n () => runWithExpensiveErrorDiagnosticsDisabled(() => getByWithSuggestion(container, ...args)),\n findOptions(getByWithSuggestion, container, args),\n );\n\n return {\n queryBy: queryByWithSuggestion,\n getAllBy: getAllByWithSuggestion,\n getBy: getByWithSuggestion,\n findAllBy,\n findBy,\n };\n};\n\nexport { buildQueries, type QueryAllBy, type BuiltQueries };\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
type CleanupFunction = () => void | Promise<void>;
|
|
2
|
+
declare const addToCleanupQueue: (fn: CleanupFunction) => void;
|
|
3
|
+
declare const runCleanup: () => Promise<void>;
|
|
4
|
+
export { addToCleanupQueue, runCleanup, type CleanupFunction };
|
|
5
|
+
//# sourceMappingURL=cleanup-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup-registry.d.ts","sourceRoot":"","sources":["../src/cleanup-registry.ts"],"names":[],"mappings":"AAAA,KAAK,eAAe,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAIlD,QAAA,MAAM,iBAAiB,GAAI,IAAI,eAAe,KAAG,IAEhD,CAAC;AAEF,QAAA,MAAM,UAAU,QAAa,OAAO,CAAC,IAAI,CAgBxC,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const cleanupQueue = new Set();
|
|
2
|
+
const addToCleanupQueue = (fn) => {
|
|
3
|
+
cleanupQueue.add(fn);
|
|
4
|
+
};
|
|
5
|
+
const runCleanup = async () => {
|
|
6
|
+
const failures = [];
|
|
7
|
+
for (const fn of cleanupQueue) {
|
|
8
|
+
try {
|
|
9
|
+
await fn();
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
failures.push(error);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
cleanupQueue.clear();
|
|
16
|
+
if (failures.length > 0) {
|
|
17
|
+
throw new AggregateError(failures, "Cleanup failed");
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export { addToCleanupQueue, runCleanup };
|
|
21
|
+
//# sourceMappingURL=cleanup-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup-registry.js","sourceRoot":"","sources":["../src/cleanup-registry.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAyB,IAAI,GAAG,EAAE,CAAC;AAErD,MAAM,iBAAiB,GAAG,CAAC,EAAmB,EAAQ,EAAE;IACpD,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,KAAK,IAAmB,EAAE;IACzC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;QAC5B,IAAI,CAAC;YACD,MAAM,EAAE,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACL,CAAC;IAED,YAAY,CAAC,KAAK,EAAE,CAAC;IAErB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,cAAc,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IACzD,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAwB,CAAC","sourcesContent":["type CleanupFunction = () => void | Promise<void>;\n\nconst cleanupQueue: Set<CleanupFunction> = new Set();\n\nconst addToCleanupQueue = (fn: CleanupFunction): void => {\n cleanupQueue.add(fn);\n};\n\nconst runCleanup = async (): Promise<void> => {\n const failures: unknown[] = [];\n\n for (const fn of cleanupQueue) {\n try {\n await fn();\n } catch (error) {\n failures.push(error);\n }\n }\n\n cleanupQueue.clear();\n\n if (failures.length > 0) {\n throw new AggregateError(failures, \"Cleanup failed\");\n }\n};\n\nexport { addToCleanupQueue, runCleanup, type CleanupFunction };\n"]}
|