@gjsify/gtk-host 0.41.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +454 -6
  2. package/lib/esm/adapters/react.js +1 -0
  3. package/lib/esm/adapters/solid.js +1 -0
  4. package/lib/esm/adapters/vue.js +1 -0
  5. package/lib/esm/attrs.js +0 -0
  6. package/lib/esm/conformance/diagnostics.js +2 -2
  7. package/lib/esm/conformance/index.js +2 -2
  8. package/lib/esm/descriptors/index.js +1 -1
  9. package/lib/esm/errors.js +1 -1
  10. package/lib/esm/generated/props.js +0 -0
  11. package/lib/esm/generated/widgets.js +1 -0
  12. package/lib/esm/host.js +1 -1
  13. package/lib/esm/index.js +1 -1
  14. package/lib/esm/jsx-runtime.js +1 -0
  15. package/lib/esm/policies.js +1 -1
  16. package/lib/esm/probe.js +1 -0
  17. package/lib/esm/props.js +1 -1
  18. package/lib/esm/react-jsx-runtime.js +1 -0
  19. package/lib/esm/registry.js +1 -1
  20. package/lib/esm/signals.js +1 -1
  21. package/lib/esm/tags.js +2 -0
  22. package/lib/esm/vue-components.js +0 -0
  23. package/lib/types/adapters/react.d.ts +175 -0
  24. package/lib/types/adapters/react.spec.d.ts +2 -0
  25. package/lib/types/adapters/solid.d.ts +78 -0
  26. package/lib/types/adapters/solid.spec.d.ts +2 -0
  27. package/lib/types/adapters/vue.d.ts +24 -0
  28. package/lib/types/adapters/vue.spec.d.ts +2 -0
  29. package/lib/types/attrs.d.ts +102 -0
  30. package/lib/types/buildable.spec.d.ts +2 -0
  31. package/lib/types/conformance/diagnostics.d.ts +14 -0
  32. package/lib/types/conformance/index.d.ts +24 -1
  33. package/lib/types/conformance/vectors.d.mts +34 -0
  34. package/lib/types/descriptors/index.d.ts +52 -1
  35. package/lib/types/errors.d.ts +21 -0
  36. package/lib/types/generated/props.d.ts +5505 -0
  37. package/lib/types/generated/surface-data.d.mts +22 -0
  38. package/lib/types/generated/widgets.d.ts +3 -0
  39. package/lib/types/generated.spec.d.ts +4 -0
  40. package/lib/types/generator/emit-types.d.mts +54 -0
  41. package/lib/types/generator/emit.d.mts +50 -0
  42. package/lib/types/generator/gir.d.mts +156 -0
  43. package/lib/types/generator/main.d.mts +23 -0
  44. package/lib/types/generator/mini.fixture.d.mts +30 -0
  45. package/lib/types/generator/surface.d.mts +62 -0
  46. package/lib/types/generator/tsmap.d.mts +73 -0
  47. package/lib/types/generator.spec.d.ts +2 -0
  48. package/lib/types/host.d.ts +102 -1
  49. package/lib/types/index.d.ts +6 -3
  50. package/lib/types/jsx-runtime.d.ts +70 -0
  51. package/lib/types/policies.d.ts +58 -0
  52. package/lib/types/probe.d.ts +58 -0
  53. package/lib/types/props.d.ts +49 -2
  54. package/lib/types/react-jsx-runtime.d.ts +108 -0
  55. package/lib/types/registry.d.ts +1 -1
  56. package/lib/types/signals.d.ts +16 -1
  57. package/lib/types/tags.d.ts +25 -0
  58. package/lib/types/testing/gate.d.mts +2 -0
  59. package/lib/types/types.d.ts +56 -3
  60. package/lib/types/vue-components.d.ts +46 -0
  61. package/package.json +77 -7
package/README.md CHANGED
@@ -28,7 +28,9 @@ NativeScript carries five framework flavours over one host, and the adapters are
28
28
  small because the host exists: its Solid adapter is **91 lines**, its React
29
29
  adapter **505** — and both hold *zero* lines of widget knowledge. Under GTK4 the
30
30
  shared share is larger still: GTK4 deleted `GtkContainer`, so there is no generic
31
- `add`, and `Gtk.Buildable.add_child` is introspected as a vfunc only. Every
31
+ `add`. `Gtk.Buildable.add_child` is introspected as a vfunc only — the `vfunc_`
32
+ form is callable and correct, so it is an escape hatch, just not a safe default
33
+ (a childless widget accepts a child in silence). Every
32
34
  container's adoption rule has to be written down somewhere. Written once, it is a
33
35
  table; written per adapter, it is the same table three times — which is what
34
36
  stalled `react-gtk`, `react-native-gtk4` and `svelte-gjs`.
@@ -125,6 +127,17 @@ Construct-only properties cannot be patched; GObject accepts the write and keeps
125
127
  the old value. Changing one **rebuilds** the widget in place, preserving position,
126
128
  properties and listeners.
127
129
 
130
+ **`undefined` and `null` both mean REMOVED**, and the value that lands is what
131
+ CONSTRUCTION leaves behind rather than the ParamSpec default — the two disagree in
132
+ 104 places. `null` counts because every other op already read it that way
133
+ (`slot: null` is no slot, `layout: null` is no position, `onClicked: null`
134
+ unbinds), and because the alternative was three adapters each translating DOM's
135
+ `null` into the host's `undefined`: Vue did, React did it only for a key that
136
+ vanished and not for an authored `label={null}`, and Solid did not at all, so
137
+ `null` reached `set_property` verbatim — a throw for a `gint`, and a `null`
138
+ recorded for the next rebuild to replay. Nothing is lost by folding them: every
139
+ GObject type that CAN hold NULL has NULL as its construction default anyway.
140
+
128
141
  ## Conformance
129
142
 
130
143
  `@gjsify/gtk-host/conformance` exports the checks that keep the table honest and
@@ -132,9 +145,444 @@ the readers every vector asserts through:
132
145
 
133
146
  - `descriptorProblems()` — every method and text sink a descriptor names must
134
147
  exist on that GType in the *installed* GTK.
135
- - `gtkChildren()` / `gtkChildTypes()` / `dumpTree()` — read the **real** widget
136
- tree. A renderer that asserts against its own bookkeeping agrees with itself
137
- while the window is wrong.
148
+ - `gtkChildren()` / `gtkChildTypes()` / `dumpTree()` / `findDescendant()` /
149
+ `descendants()` — read the **real** widget tree. A renderer that asserts against
150
+ its own bookkeeping agrees with itself while the window is wrong.
151
+ - `installDiagnosticsGate()` — GTK's failure mode is exit 0, so every vector counts
152
+ GLib warnings-or-worse and fails the test that produced one.
153
+
154
+ **One vector table runs through all three adapters.** `conformance/vectors.mts`
155
+ (a `.mts` file, so it never reaches the published bundle: it imports
156
+ `@gjsify/unit`, a devDependency) exports `runAdapterVectors(harness, gate)`, and
157
+ each adapter's spec supplies a `mount`/`patch`/`unmount` harness over its own
158
+ framework. It exists because a per-framework spec agrees with the framework it was
159
+ written against: measured over the three specs, `slot` and `layout` had ZERO hits
160
+ in any of them, and only React's ever created a text node — so `createText`,
161
+ `setText`, `replaceText`, `isTextNode`, `flushText` and the `text-not-accepted`
162
+ refusal went unexercised through two of the three adapters. Deleting `flushText`
163
+ from `host.ts` now reds twelve vectors across all three, where before it reds two,
164
+ in React alone.
165
+
166
+ **Self-verification for a showcase**, from the main barrel rather than from here:
167
+ `runHostProbeApp({ applicationId, build, assert, present })` owns the
168
+ `GJSIFY_HOST_PROBE`-vs-`activate` split, the diagnostics gate, the `check()`
169
+ recorder and the `PROBE: PASS|FAIL <json>` line, so a showcase writes only its own
170
+ assertions. The recorder checks ITSELF first — every assertion speaks through one
171
+ closure, so a `check` that drops its findings would turn the whole probe green with
172
+ nothing to say, and no showcase assertion could notice.
173
+
174
+ ## Adapters
175
+
176
+ Three of them today — `/solid`, `/vue`, `/react` — over one table.
177
+ `scripts/check-adapter-import-direction.mjs` holds all three to that mechanically:
178
+ an adapter fails the check if it reaches for `descriptors`, `policies` or
179
+ `registry`, names a widget in a string, uses one as a VALUE (`new Gtk.Box()`,
180
+ `instanceof`, `$gtype`, a call — a type annotation is fine and is what every
181
+ adapter writes), imports a typelib at runtime (`gi://…`), or names a placement
182
+ method. The last two landed with the violation they describe: the Vue adapter held
183
+ the one runtime `gi://` import and the one concrete widget class in the whole
184
+ adapter set, for `<KeepAlive>`'s off-screen storage. That is `createDetachedContainer()`
185
+ now — a host op, so the adapter has nothing left to know.
186
+
187
+ Everything an adapter needs beyond the fourteen ops is exported from the host, once:
188
+ `widgetOf(node)` (the `ref` seam — Solid and React each carried their own copy and
189
+ Vue carried none, so a Vue app's only route to a widget was `materialize()`, the
190
+ call `widgetOf`'s destroyed-node refusal exists to intercept), `isHostElement(value)`,
191
+ `describeValue(value)` for naming what arrived instead of a node, and
192
+ `withoutKeys(props, reserved)` for the reserved-prop filter whose SET is
193
+ per-framework and whose loop is not.
194
+
195
+ `@gjsify/gtk-host/solid` is the first, and it is the thesis made checkable: Solid
196
+ publishes a ten-method renderer contract, every one of them is a host op, and the
197
+ adapter is the mapping — no widget name, no insertion rule, no GTK knowledge.
198
+
199
+ ```ts
200
+ import { For, createComponent, createElement, insert, mount, setProp } from '@gjsify/gtk-host/solid';
201
+
202
+ const dispose = mount(() => {
203
+ const box = createElement('GtkBox');
204
+ insert(box, createComponent(For, { get each() { return items(); }, children: renderRow }));
205
+ return box;
206
+ }, myWindow);
207
+ ```
208
+
209
+ `adopt(container)` is the mount seam every adapter needs: it wraps a widget the
210
+ application owns as a host element, resolving its descriptor through the same
211
+ table as every other parent, and **records the children the container already
212
+ had** so placement offsets past them. Without that record the first insertion
213
+ resolves to GTK's "make first" and the rendered tree lands above the app's own
214
+ chrome.
215
+
216
+ Three things the adapter has to know that the contract does not say:
217
+
218
+ - **`removeNode` is a detach, never a teardown.** Solid uses one op for a
219
+ reconciliation move and for an unmount, and `<For>` moves the same nodes across a
220
+ reorder (measured: 3 of 3 widget objects reused). Destroying there would recreate
221
+ every row on every reorder.
222
+ - **The unmount signal is Solid's per-node scope, not `removeNode`** — but it may
223
+ only disconnect HANDLERS, never unlink. A node dropped by reconciliation is
224
+ unreachable from the root, so no later teardown can find its handlers, and GJS
225
+ blocks JS callbacks during GC. `onCleanup` fires exactly when a node is gone for
226
+ good and survives a reorder. Unlinking there breaks ordering, though: Solid
227
+ disposes these scopes BEFORE `insertExpression` runs, and `reconcileArrays` opens
228
+ with `getNextSibling(last)` — on an unlinked node that reads null, and every
229
+ trailing insertion appends at the end of the parent instead of before the marker.
230
+ A dynamic list with a static sibling after it rendered `head | foot | c`.
231
+ - **`solid-js/universal`'s `render` returns the disposer and nothing else** — the
232
+ DOM renderer additionally clears its container, the universal one has no
233
+ equivalent, so disposing tears down the reactive scopes and leaves the widgets
234
+ mounted (measured: a button kept firing). Tearing the subtree down is `mount`'s job.
235
+
236
+ Solid's control-flow components (`For`, `Index`, `Show`) are re-exported re-typed:
237
+ their runtime is renderer-agnostic, their types are pinned to the DOM's `Element`.
238
+
239
+ **`Dynamic` is the exception and is implemented here, not re-exported.** `For`,
240
+ `Index` and `Show` live in `solid-js`; `Dynamic` lives in `solid-js/web`, and that
241
+ package *is* the DOM renderer — its string branch is
242
+ `document.createElement(component)` followed by the DOM's own `spread`, so under a
243
+ universal renderer nothing arrives through the host ops at all. Measured with
244
+ `<Dynamic component="GtkLabel">` imported from `solid-js/web` into a GJS bundle:
245
+ container `["GtkBox"]`, the box's children just the static sibling, **no throw, no
246
+ GTK diagnostic, exit 0**. (Importing it also makes `--globals auto` inject
247
+ `document`, `HTMLCanvasElement` and `Path2D` and pull `gi://Gdk`, `GdkPixbuf`,
248
+ `Pango` and `PangoCairo`.) Import `Dynamic` from `@gjsify/gtk-host/solid`; the
249
+ adapter's version takes the same `component` — a registered tag name or a
250
+ component function — and **refuses anything else by name**, where Solid's own
251
+ `switch` falls through to `undefined`: `component={registry[key]}` with a key that
252
+ missed is indistinguishable from an empty branch, and rendering nothing on purpose
253
+ is `<Show>`'s job.
254
+
255
+ That silence had a second, more general cause, now closed at the seam:
256
+ `insertExpression`'s last branch is `insertNode(parent, value)` for **any**
257
+ non-array object, and the host wrote its `parent`/`prev`/`next` links onto it and
258
+ returned — the kind was neither `element` nor `text`, so nothing else happened. A
259
+ phantom in the shadow tree that never reaches GTK. `insertNode` now refuses a
260
+ value that is not one of the three node kinds, naming what it got and which
261
+ `solid-js/web` exports (`Dynamic`, `Portal`, `template`) are DOM-bound.
262
+
263
+ `@gjsify/gtk-host/vue` is the second, and it is what makes "framework-agnostic"
264
+ a measured claim rather than an ADR sentence: the same descriptor table and the
265
+ same placement engine satisfy Vue's `RendererOptions` (10 required + 4 optional)
266
+ and Solid's universal renderer (10) without either knowing about the other.
267
+
268
+ ```ts
269
+ import { mount } from '@gjsify/gtk-host/vue';
270
+ mount(defineComponent({ render: () => h('GtkBox', null, [h('GtkLabel', { label: 'hi' })]) }), myWindow);
271
+ ```
272
+
273
+ Where Vue differs from Solid, and it is all in what Vue asks for:
274
+
275
+ - **`createComment`.** Vue marks every `v-if` branch and fragment boundary with
276
+ one. That is why the host has anchors: they never enter the GTK tree, so an
277
+ empty branch cannot shift a sibling's index.
278
+ - **`createElement` receives the vnode props**, so construct-only values arrive at
279
+ construction instead of forcing a rebuild. Solid's `createElement(tag)` cannot.
280
+ The props are RAW though — `key`, `ref` and the `onVnode*` hooks are Vue's own
281
+ and are filtered out; passing them through produced
282
+ `<GtkLabel> has no property "key"` on the first keyed list.
283
+ - **`remove` is a TEARDOWN here, not a detach** — the opposite of the Solid
284
+ adapter, and measured both ways. Vue moves a node with `insert` alone, so
285
+ `remove` is only ever a real unmount: with it mapped to `destroy`, a keyed
286
+ reorder still reuses 3 of 3 widget objects and the handlers are gone after
287
+ `app.unmount()`. Solid uses one op for both and must therefore detach.
288
+ - **`<KeepAlive>` and `<Suspense>` get a detached scratch container.**
289
+ `KeepAliveImpl.setup` opens with `createElement("div")` for its off-screen
290
+ storage and `SuspenseImpl` does the same for its `hiddenContainer`. Forwarded as
291
+ a tag, `"div"` threw `unknown-tag` *inside `setup`* — and Vue routes that through
292
+ `callWithErrorHandling`, whose production arm is `console.error(err)` with no
293
+ rethrow. Measured under the defines below: `mount()` returned normally, the
294
+ container had **zero** children, GTK emitted no diagnostic, exit 0, and the only
295
+ trace was one line of `{"code":"unknown-tag","name":"GtkHostError"}`.
296
+
297
+ The adapter hands those calls an unparented box through `adopt`, which is the
298
+ faithful analogue of the DOM's detached `<div>`: deactivating really unparents
299
+ the subtree and really keeps it alive, so reactivating moves the *same* widgets
300
+ back. Measured end to end — a `<KeepAlive>`d component's widget object and its
301
+ own `ref` state both survive a toggle away and back.
302
+
303
+ **The discriminator is ARITY, and it had to be measured.** `mountElement` calls
304
+ `hostCreateElement(vnode.type, namespace, props && props.is, props)` — four
305
+ arguments, always; the two built-ins call `createElement("div")` with one.
306
+ Testing the later parameters for `undefined` cannot separate them, because
307
+ `ElementNamespace` *is* `'svg' | 'mathml' | undefined` and a plain GTK element
308
+ gets `undefined` there too. So a user's own `<div>` still arrives with four
309
+ arguments and is still refused by name — the scratch container is never a
310
+ silent yes for something a user wrote.
311
+ - **`cloneNode` and `insertStaticContent` throw.** They back Vue's static hoisting,
312
+ and the second one takes an HTML *string*. Compile with `hoistStatic: false` and
313
+ `transformHoist: null`; if that is ever lost, these throw at the first static
314
+ subtree instead of rendering something wrong.
315
+ - **`<Teleport :to="el">` takes a widget the application owns**, and the adapter
316
+ adopts it — once per widget, so every teleported child and both of Vue's own text
317
+ anchors see the same shadow tree. Adopting per `insert` call re-snapshots the
318
+ container's existing children each time and reorders the teleport: measured,
319
+ `['one','two','three']` landed as `['one','three','two']`. `adopt` is re-exported
320
+ from `@gjsify/gtk-host/vue` for the explicit spelling, `:to="adopt(el)"`.
321
+
322
+ The coercion is what makes that sentence TRUE. Vue returns a non-string target
323
+ verbatim (`resolveTarget`'s non-string branch is `return targetSelector`), so
324
+ "pass the target widget instead" — which this adapter's own error message and
325
+ this README used to say — handed the host a raw `Gtk.Box` as a parent: nothing
326
+ rendered, nothing threw, no diagnostic. The host now refuses a raw widget by
327
+ name (`not-a-host-parent`) as the backstop for every other route in.
328
+ - **A *string* teleport target throws.** Answering null looks gentler and is worse:
329
+ `TeleportImpl` mounts nothing for a falsy target and the warning is `__DEV__`-only,
330
+ which the production defines below strip — so it would render nothing, silently,
331
+ in exactly the configuration this adapter prescribes. Resolving a name would need
332
+ a registry of mounted roots; when a consumer needs it, that is the work.
333
+ - **A prop that disappears is reset, not nulled.** Vue signals removal with `null`;
334
+ the host's contract is `undefined` → the ParamSpec default. Forwarding the `null`
335
+ reached `set_property` verbatim, which throws for an int property — and
336
+ `el.props` had already recorded it for the next rebuild to replay.
337
+
338
+ **Build recipe.** `@vue/runtime-core` is DOM-free in fact — every `document`,
339
+ `navigator`, `location` and `HTMLElement` reference sits in a dev/HMR/devtools
340
+ path behind `typeof window !== 'undefined'` or `__DEV__`. But `--globals auto` is a
341
+ static analysis and injects a polyfill for each identifier it sees, which made the
342
+ bundle require `gi://Gdk`, `GdkPixbuf`, `Pango` and `PangoCairo` at load. Define
343
+ Vue's flags so dead-code elimination removes those branches:
344
+
345
+ ```
346
+ --define '__VUE_OPTIONS_API__=false'
347
+ --define '__VUE_PROD_DEVTOOLS__=false'
348
+ --define '__VUE_PROD_HYDRATION_MISMATCH_DETAILS__=false'
349
+ --define 'process.env.NODE_ENV="production"'
350
+ ```
351
+
352
+ A vector asserts `globalThis.document` is `undefined`, so losing the recipe fails
353
+ the suite rather than silently growing four typelib dependencies.
354
+
355
+ **`Suspense` is the one import the recipe cannot save**, so measure the bundle if
356
+ you use it. `SuspenseImpl` carries `hydrate: hydrateSuspense`, and that function
357
+ contains a literal `document.createElement("div")` which no define eliminates —
358
+ hydration is not dead code, it is simply never called here. Measured, same entry
359
+ plus one named import, `--app gjs` with the four defines above:
360
+
361
+ | import | bytes | typelibs | DOM |
362
+ |---|---|---|---|
363
+ | baseline (`createRenderer`) | 191 032 | `gi://GLib` | — |
364
+ | `+ Teleport` | 194 907 | `gi://GLib` | — |
365
+ | `+ KeepAlive` | 197 561 | `gi://GLib` | — |
366
+ | `+ Suspense` | 274 177 | `+ Gdk, GdkPixbuf, Gio, Pango, PangoCairo` | `HTMLCanvasElement`, `Path2D` |
367
+ | `+ Suspense`, `--exclude-globals document` | 196 614 | `gi://GLib` | — |
368
+
369
+ `--exclude-globals document` is the escape: `--globals auto` is a static scan, so
370
+ the identifier is what it reacts to, not whether the branch can run. Three more
371
+ built-ins measured clean alongside `Teleport` and `KeepAlive` — `BaseTransition`
372
+ (192–197 KB, `gi://GLib` only), `defineAsyncComponent` and `Fragment`. `Transition`
373
+ is not in this table because `@vue/runtime-core` does not export it at all
374
+ (`MISSING_EXPORT` from rolldown); it belongs to `runtime-dom`.
375
+
376
+ `@gjsify/gtk-host/react` is the third, and it is the one whose contract can be
377
+ READ instead of restated. `react-reconciler` is `module.exports = function
378
+ $$$reconciler($$$hostConfig) { … }` and its body opens by destructuring the whole
379
+ config, so a recording `Proxy` over the config reports exactly which members the
380
+ installed version asks for. Measured on **0.29.2**, production bundle: **76**
381
+ members read, **37** answered here, **39** switched off by three flags the config
382
+ does declare (`supportsPersistence: false`, `supportsHydration: false`,
383
+ `supportsTestSelectors` absent) plus `supportsMicrotasks`, and 4 more declared for
384
+ the development bundle, which reads 94. `react.spec.ts` asserts all three
385
+ directions, so a version bump that starts asking for something new fails a test
386
+ instead of reading `undefined` inside a commit.
387
+
388
+ ```ts
389
+ import { createRoot, flushSync } from '@gjsify/gtk-host/react';
390
+
391
+ const root = createRoot(myWindow);
392
+ root.render(createElement('GtkBox', null, createElement('GtkLabel', { label: 'hi' })));
393
+ ```
394
+
395
+ - **`render()` is synchronous, and that is a choice with a reason.** A
396
+ `ConcurrentRoot`'s updates are DEFAULT-lane, so they are handed to `scheduler`,
397
+ which under GJS is a GLib timer source — with no main loop running yet, an
398
+ unflushed first render leaves the container empty and says nothing. `render()`
399
+ therefore wraps `updateContainer` in `flushSync`, which sets the current update
400
+ priority to `DiscreteEventPriority` and makes everything scheduled inside it a
401
+ sync lane the same call then flushes.
402
+ - **A `setState` from a GTK signal handler is concurrent** and lands on the next
403
+ main-loop iteration, because `getCurrentEventPriority` returns the default lane
404
+ (there is no ambient DOM event to derive a priority from). `flushSync` is the
405
+ escape hatch. A vector pumps `GLib.MainContext.default()` and proves the
406
+ scheduled path works at all under GJS — it does, on gjs 1.88.1, with no
407
+ polyfill: `scheduler` feature-detects `performance`, `setImmediate`,
408
+ `MessageChannel` and `navigator` and falls back to `setTimeout`, which the GJS
409
+ prologue already provides.
410
+ - **React CLEARS the container before its first commit.** `updateHostRoot` sets
411
+ the `Snapshot` flag whenever the previous render produced no child — in the DOM
412
+ to discard leftover markup. Here the container is a widget the application built
413
+ and filled, so `clearContainer` destroys only the SHADOW children and never
414
+ `el.foreign`. A vector records the call, because surviving chrome alone would
415
+ also be explained by React never making it.
416
+ - **`removeChild` is a TEARDOWN, like Vue's `remove` and unlike Solid's
417
+ `removeNode`.** React moves a node with `insertBefore`/`appendChild` alone, so
418
+ `removeChild` is only ever a real unmount. The reorder vector holds both halves:
419
+ the same widget objects survive, and `removeChild` was never reached.
420
+ - **`getPublicInstance` IS `ref`,** and it returns the author's widget — never the
421
+ `GtkListBoxRow` the host wrapped it in.
422
+ - **`shouldSetTextContent` answers `false`, always.** `true` would leave the string
423
+ in `props.children` for the adapter to write, which is a widget-knowledge test in
424
+ an adapter; the host already routes a text node to the descriptor's `textSink` and
425
+ refuses text by tag name where there is none.
426
+ - **`<Suspense>`'s `hideTextInstance` empties the run's contribution** to its
427
+ parent's sink — a text run owns no widget — and nothing has to be remembered,
428
+ because `unhideTextInstance` is handed the text back.
429
+
430
+ **Build recipe**, and it is not optional:
431
+
432
+ ```
433
+ --define 'process.env.NODE_ENV="production"'
434
+ --exclude-globals navigator
435
+ ```
436
+
437
+ `react-reconciler/index.js` picks its bundle from `process.env.NODE_ENV`, and the
438
+ development one reaches for `document`, `HTMLCanvasElement` and `Path2D`, which
439
+ makes `--globals auto` inject the GTK-backed DOM registers and pull `gi://Gdk`,
440
+ `GdkPixbuf`, `Pango` and `PangoCairo` into a bundle that needs none of them. Even
441
+ the production `scheduler` carries `typeof navigator !== 'undefined' &&
442
+ navigator.scheduling`, dead code under GJS but still a free identifier the
443
+ detector answers with the same register. With both flags the bundle loads with no
444
+ `document` and no `navigator`, and a vector asserts exactly that.
445
+
446
+ `react` and `react-reconciler` are OPTIONAL peer dependencies, like `solid-js` and
447
+ `@vue/runtime-core`.
448
+
449
+ ## What ships
450
+
451
+ `files` negates two shapes the library build already excludes:
452
+ `!lib/types/**/*.d.mts` and `!lib/types/**/*.spec.d.ts`. `build:gjsify` globs
453
+ `src/**/*.{ts,js}` minus the specs, so a `.mts` file is this package's marker for
454
+ "test-only, never in the bundle" — but `build:types` compiles all of `src`, and the
455
+ tarball therefore carried 17 type declarations for runtime modules that are not in
456
+ it, `lib/types/testing/gate.d.mts` among them. Nothing could import one (the exports
457
+ map gates every subpath), so the cost was a package describing modules it does not
458
+ contain, and a reader who concludes `@gjsify/gtk-host/testing` exists.
459
+
460
+ ## The widget table, and the type surfaces
461
+
462
+ The table is **generated from the GIR** and committed. 164 concrete GtkWidget
463
+ descendants (Gtk 102, Adw 62), each with its GType name, its kebab tag and a lazy
464
+ `ctor`; 26 of them also carry a **curated** placement rule, and the generator may
465
+ only ever ADD a tag, never contradict one. A tag with no curated rule gets
466
+ `children: { kind: 'uncurated' }` — the widget can be created, given properties and
467
+ given handlers, while inserting a child raises an error naming the tag that needs a
468
+ policy. Guessing is not on offer: `add`, `append` and `set_child` all exist
469
+ somewhere in GTK, and calling the wrong one is a warning at exit 0.
470
+
471
+ Regenerating is a maintainer step, because the GIR files are not in this repo:
472
+
473
+ ```sh
474
+ GJSIFY_GIR_DIR=/path/to/girs npm run generate # then look at git diff
475
+ ```
476
+
477
+ A fresh clone needs no GIR to build, check, pack or test. What travels instead is
478
+ `generated.spec.ts`, which asks the *installed* GTK whether every generated name is
479
+ real: every offered property present as a writable ParamSpec, every offered signal
480
+ resolvable by `GObject.signal_lookup`, every enum nick resolvable through the
481
+ host's own `coerce()` path. A member the installed library lacks is accepted only
482
+ if the GIR says it arrived in a newer release — `GtkApplicationWindow::save-state`
483
+ is GTK 4.24 and the check runs on 4.22.4.
484
+
485
+ ### Solid / JSX
486
+
487
+ ```jsonc
488
+ {
489
+ "jsx": "preserve", // babel-preset-solid does the transform
490
+ "jsxImportSource": "@gjsify/gtk-host", // TypeScript appends /jsx-runtime
491
+ "noImplicitAny": true // load-bearing, see below
492
+ }
493
+ ```
494
+
495
+ ```tsx
496
+ <gtk-box orientation="vertical" spacing={8}>
497
+ <gtk-label label="Hello" />
498
+ <gtk-button label="Go" onClicked={() => count(count() + 1)} />
499
+ </gtk-box>
500
+ ```
501
+
502
+ Tags are kebab because a capitalised `JSX.IntrinsicElements` key is never
503
+ consulted — `<GtkBox/>` is `TS2304: Cannot find name 'GtkBox'`. This package ships
504
+ its **own** jsx-runtime rather than augmenting `solid-js`, which would leave all
505
+ 208 tags Solid pre-declares (HTML, SVG, MathML) type-checking clean on a GTK
506
+ renderer and rendering nothing.
507
+
508
+ Two things worth knowing:
509
+
510
+ - **`noImplicitAny: true` is not optional.** With `jsx: "preserve"`, no
511
+ `jsxImportSource` and `noImplicitAny` off, every JSX element is implicitly `any`
512
+ and `tsc` exits 0 having checked nothing.
513
+ - **An unknown *hyphenated* prop cannot be refused.** TypeScript exempts every
514
+ hyphen-containing JSX attribute from excess-property checking, so
515
+ `<gtk-box no-such={1}/>` is accepted. Both spellings are generated, so a declared
516
+ `can-focus={'yes'}` still fails on its VALUE — but prefer `canFocus`, which is
517
+ checked both ways.
518
+
519
+ ### Vue
520
+
521
+ ```ts
522
+ import '@gjsify/gtk-host/vue-components';
523
+ ```
524
+
525
+ ```jsonc
526
+ { "vueCompilerOptions": { "strictTemplates": true } }
527
+ ```
528
+
529
+ ```vue
530
+ <GtkBox orientation="vertical" :spacing="8">
531
+ <GtkButton label="Go" @clicked="go" />
532
+ </GtkBox>
533
+ ```
534
+
535
+ Keys are GType names, because Volar camelizes and capitalises a template tag before
536
+ looking it up — so one `GtkBox` key answers both `<GtkBox>` and `<gtk-box>`.
537
+ `strictTemplates: true` is **required**: without it an unknown prop, an unknown
538
+ event and an entirely unresolved tag are all silently accepted while wrong VALUE
539
+ types still error, so the surface looks alive and checks the wrong half.
540
+
541
+ **Set it in the BASE of your `extends` chain.** Measured on `vue-tsc@3.3.11`, all
542
+ four cells: the base tsconfig's value wins and the child's is ignored outright — a
543
+ strict base stays strict under a child that sets `false`, and a lax base stays lax
544
+ under a child that sets `true`. In a monorepo the shared base config therefore
545
+ decides this for every package and a per-package override does nothing. Confirm
546
+ with `vue-tsc --showConfig` rather than by reading the nearest tsconfig.
547
+
548
+ That camelize has no acronym knowledge (`gtk-gl-area` → `GtkGlArea`), so widgets
549
+ with two adjacent capitals get an extra kebab key. The generator finds them by
550
+ rule; today there is exactly one, `GtkGLArea`.
551
+
552
+ ### React / JSX
553
+
554
+ ```jsonc
555
+ {
556
+ "jsx": "react-jsx",
557
+ "jsxImportSource": "@gjsify/gtk-host/react", // TypeScript appends /jsx-runtime
558
+ "noImplicitAny": true
559
+ }
560
+ ```
561
+
562
+ A **separate subpath**, and the split is structural rather than stylistic.
563
+ `@gjsify/gtk-host/jsx-runtime` deliberately throws from `jsx()`/`jsxs()`, which is
564
+ right for the dialects it serves: Solid's reactivity lives in what
565
+ `babel-preset-solid` emits and Vue's in its SFC compiler, so an automatic runtime
566
+ reaching those functions means the pipeline was misconfigured and nothing would
567
+ render. React is the opposite case — its `jsx()` builds a plain, renderer-agnostic
568
+ element record and the host mapping happens later, in `react-reconciler` — so
569
+ `@gjsify/gtk-host/react/jsx-runtime` re-exports React's OWN factories and declares
570
+ its own `JSX` namespace over the same generated tag list. One module cannot both
571
+ refuse the automatic runtime and provide it; `jsxImportSource` picks.
572
+
573
+ Pointing `jsxImportSource` at `"react"` instead is the 208-tag trap: the element
574
+ list then comes from `@types/react`, and every HTML, SVG and MathML tag
575
+ type-checks clean on a GTK renderer and renders nothing.
576
+
577
+ Tags are kebab here too, for the same measured reason as the Solid surface. `ref`
578
+ takes React's `Ref<T>` (a callback *or* a `useRef` object), which is why it is not
579
+ the Solid surface's `ref` type.
138
580
 
139
- Adapters will run the same vectors, so "it works in Vue" and "it works in Solid"
140
- will mean the same thing. None is written yet — see `status/open-todos.md`.
581
+ **The export names are the framework's contract, not a style choice** — the same
582
+ lesson the Solid adapter paid for when its `setProp` was exported as
583
+ `setSolidProp` and `babel-plugin-jsx-dom-expressions` emitted
584
+ `import { setProp }` literally. TypeScript's automatic runtime emits `jsx`, `jsxs`
585
+ and `Fragment` from `<jsxImportSource>/jsx-runtime`, and `jsxDEV` from
586
+ `<jsxImportSource>/jsx-dev-runtime`; those four are exactly what this module
587
+ exports, so a rename here is a `MISSING_EXPORT` in a consumer's build rather than
588
+ a matter of taste.
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{withoutKeys as e}from"../props.js";import{adopt as t,createElement as n,createText as r,destroy as i,destroyChildren as a,insert as o,materialize as s,setElementText as c,setProp as l,setText as u,widgetOf as d}from"../host.js";import f from"react-reconciler";import{ConcurrentRoot as p,DefaultEventPriority as m}from"react-reconciler/constants.js";const h=new Set([`children`]),ownProps=t=>e(t,h);function diffProps(e,t){let n=null;for(let r of Object.keys(t))h.has(r)||t[r]!==e[r]&&(n??=[]).push([r,t[r],e[r]]);for(let r of Object.keys(e))h.has(r)||r in t||(n??=[]).push([r,void 0,e[r]]);return n}const visibilityTargetOf=e=>{let t=s(e);return e.wrapper??t},g={supportsMutation:!0,supportsPersistence:!1,supportsHydration:!1,isPrimaryRenderer:!0,noTimeout:-1,scheduleTimeout:setTimeout,cancelTimeout:clearTimeout,createInstance:(e,t)=>n(e,ownProps(t)),createTextInstance:e=>r(e),appendInitialChild:(e,t)=>{o(t,e,null)},finalizeInitialChildren:()=>!1,shouldSetTextContent:()=>!1,getRootHostContext:()=>null,getChildHostContext:e=>e,getPublicInstance:e=>s(e),prepareForCommit:()=>null,resetAfterCommit:()=>{},preparePortalMount:()=>{},getCurrentEventPriority:()=>m,appendChild:(e,t)=>{o(t,e,null)},appendChildToContainer:(e,t)=>{o(t,e,null)},insertBefore:(e,t,n)=>{o(t,e,n)},insertInContainerBefore:(e,t,n)=>{o(t,e,n)},removeChild:(e,t)=>{i(t)},removeChildFromContainer:(e,t)=>{i(t)},clearContainer:e=>{a(e)},prepareUpdate:(e,t,n,r)=>diffProps(n,r),commitUpdate:(e,t)=>{for(let[n,r,i]of t)l(e,n,r,i)},commitTextUpdate:(e,t,n)=>{u(e,n)},commitMount:()=>{throw Error(`@gjsify/gtk-host/react: commitMount was called, which means finalizeInitialChildren returned true. Nothing in this adapter asks for a post-mount callback yet.`)},resetTextContent:e=>{c(e,``)},hideInstance:e=>{visibilityTargetOf(e).set_visible(!1)},unhideInstance:e=>{visibilityTargetOf(e).set_visible(!0)},hideTextInstance:e=>{u(e,``)},unhideTextInstance:(e,t)=>{u(e,t)},getInstanceFromNode:()=>null,getInstanceFromScope:()=>null,prepareScopeUpdate:()=>{},beforeActiveInstanceBlur:()=>{},afterActiveInstanceBlur:()=>{},detachDeletedInstance:()=>{}},_=f(g),flushSync=e=>_.flushSync(e);function createRoot(e,n={}){let r=t(e),i=n.onRecoverableError??(e=>{console.error(`@gjsify/gtk-host/react: React recovered from an error`,e)}),a=_.createContainer(r,p,null,!1,null,``,i,null);return{container:r,render(e){_.flushSync(()=>{_.updateContainer(e,a,null,null)})},unmount(){_.flushSync(()=>{_.updateContainer(null,a,null,null)})}}}function mount(e,t,n={}){let r=createRoot(t,n);return r.render(e),r}export{t as adopt,createRoot,flushSync,g as gtkHostConfig,mount,d as widgetOf};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{adopt as e,createElement as t,createText as n,describeValue as r,destroyChildren as i,disconnectHandlers as a,firstChild as o,insert as s,isText as c,nextSibling as l,parentNode as u,remove as d,setProp as f,setText as p,widgetOf as m}from"../host.js";import{For as h,Index as g,Show as _,onCleanup as v,splitProps as y,untrack as b}from"solid-js";import{createRenderer as x}from"solid-js/universal";const S=new Set([`element`,`text`,`anchor`]);function assertHostNode(e){let t=e?.kind;if(!(typeof t==`string`&&S.has(t)))throw Error(`@gjsify/gtk-host/solid: insertNode got ${r(e)}, which is not a node of this renderer. Almost always this is a component from solid-js/web — the DOM renderer — reaching a universal one: its <Dynamic>, <Portal> and template() build DOM elements with document.createElement and spread onto them with the DOM's own spread, so nothing arrives through these host ops and the subtree renders NOTHING, silently. Import Dynamic, For, Index and Show from @gjsify/gtk-host/solid instead; solid-js's own control flow (For/Index/Show) is renderer-agnostic, everything under solid-js/web is not.`)}const{render:C,effect:w,memo:T,createComponent:E,createElement:D,createTextNode:O,insertNode:k,insert:A,spread:j,setProp:M,mergeProps:N,use:P}=x({createElement:e=>{let n=t(e);return v(()=>a(n)),n},createTextNode:e=>n(e),replaceText:(e,t)=>{p(e,t)},isTextNode:e=>c(e),setProperty:(e,t,n,r)=>{f(e,t,n,r)},insertNode:(e,t,n)=>{assertHostNode(t),s(t,e,n??null)},removeNode:(e,t)=>{d(t)},getParentNode:e=>u(e)??void 0,getFirstChild:e=>e.kind===`element`?o(e)??void 0:void 0,getNextSibling:e=>l(e)??void 0});function mount(t,n){let r=e(n),a=C(t,r);return()=>{a(),i(r)}}const F=h,I=g,L=_;function Dynamic(e){let[,t]=y(e,[`component`]);return T(()=>{let n=e.component;if(typeof n==`function`)return b(()=>n(t));if(typeof n==`string`){let e=D(n);return j(e,t,!1),e}throw Error(`@gjsify/gtk-host/solid: <Dynamic component={…}> needs a registered tag name or a component function, and got ${r(n)}. Solid's own DOM version returns undefined here and renders nothing at all — a lookup that missed is indistinguishable from an empty branch. Use <Show when={…}> to render nothing on purpose.`)},!1)}export{Dynamic,F as For,I as Index,L as Show,E as createComponent,D as createElement,O as createTextNode,w as effect,A as insert,k as insertNode,T as memo,N as mergeProps,mount,C as render,M as setProp,j as spread,P as use,m as widgetOf};
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import{withoutKeys as e}from"../props.js";import{adopt as t,createAnchor as n,createDetachedContainer as r,createElement as i,createText as a,destroy as o,insert as s,isHostElement as c,materialize as l,nextSibling as u,parentNode as d,setElementText as f,setProp as p,setText as m,widgetOf as h}from"../host.js";import{createRenderer as g}from"@vue/runtime-core";const _=new Set([`key`,`ref`,`ref_for`,`ref_key`,`onVnodeBeforeMount`,`onVnodeMounted`,`onVnodeBeforeUpdate`,`onVnodeUpdated`,`onVnodeBeforeUnmount`,`onVnodeUnmounted`]),withoutReservedProps=t=>e(t,_),v=new WeakMap;function asHostParent(e){if(c(e))return e;let n=e;if(typeof n!=`object`||!n)return e;let r=v.get(n);if(r)return r;let i=t(e);return v.set(n,i),i}const createElementOp=((...e)=>e.length===1?r():i(e[0],withoutReservedProps(e[3]))),{render:y,createApp:b}=g({createElement:createElementOp,createText:e=>a(e),createComment:e=>n(e),setText:(e,t)=>m(e,t),setElementText:(e,t)=>f(e,t),patchProp:(e,t,n,r)=>{_.has(t)||p(e,t,r,n)},insert:(e,t,n)=>s(e,asHostParent(t),n??null),remove:e=>o(e),parentNode:e=>d(e),nextSibling:e=>u(e),querySelector:e=>{throw Error(`@gjsify/gtk-host/vue: <Teleport to="${e}"> needs a string target resolved against a widget tree, which this adapter does not implement yet. Pass the target WIDGET instead (<Teleport :to="el">, el being a Gtk.Widget the application owns — this adapter adopts it for you), or pass adopt(el) if you want the host element yourself. A string target would render nothing at all under the production defines this adapter requires.`)},setScopeId:(e,t)=>{l(e).add_css_class?.(t)},cloneNode:e=>{throw Error(`@gjsify/gtk-host/vue: cloneNode is not available on GTK — a GObject does not clone. This is Vue's static-hoisting path: compile with hoistStatic: false and transformHoist: null. (node kind: ${e.kind})`)},insertStaticContent:()=>{throw Error(`@gjsify/gtk-host/vue: insertStaticContent takes an HTML string and GTK parses no HTML. This is Vue's stringifyStatic transform: compile with hoistStatic: false and transformHoist: null.`)}});function mount(e,n){let r=b(e);return r.mount(t(n)),r}export{t as adopt,b as createApp,mount,y as render,h as widgetOf};
File without changes
@@ -1,2 +1,2 @@
1
- import"../_virtual/_rolldown/runtime.js";import e from"gi://GLib";let t=null;function installDiagnosticsGate(){if(t)return t;let n=[],r=new TextDecoder,i=e.getenv(`G_MESSAGES_DEBUG`)!==null;return e.log_set_writer_func((t,a)=>{try{let o=a?.MESSAGE,s=o instanceof Uint8Array?r.decode(o):String(o??``),c=t&e.LogLevelFlags.LEVEL_MASK;c<=e.LogLevelFlags.LEVEL_WARNING&&n.push(s),(i||c<=e.LogLevelFlags.LEVEL_MESSAGE)&&printerr(s)}catch{printerr(`<gtk-host: a log message could not be decoded>`)}return e.LogWriterOutput.HANDLED}),t={seen:n,reset(){n.length=0},assertQuiet(e){if(n.length===0)return;let t=n.length,r=n.join(`
2
- `);throw n.length=0,Error(`${e?e+`: `:``}GTK reported ${t} diagnostic(s) that would have passed at exit 0:\n ${r}`)}},t}export{installDiagnosticsGate};
1
+ import"../_virtual/_rolldown/runtime.js";import e from"gi://GLib";let t=null;function describeLogRecord(e,t=new TextDecoder){let text=e=>e instanceof Uint8Array?t.decode(e):String(e),n=e,r=n?.MESSAGE;if(r!=null){let e=text(r);if(e!==``)return e}let i=n?Object.keys(n).filter(e=>e!==`MESSAGE`&&n[e]!==void 0&&n[e]!==null).map(e=>`${e}=${text(n[e])}`):[];return i.length>0?`<no MESSAGE field> ${i.join(` `)}`:`<a log record with no MESSAGE and no other field>`}function installDiagnosticsGate(){if(t)return t;let n=[],r=new TextDecoder,i=e.getenv(`G_MESSAGES_DEBUG`)!==null;return e.log_set_writer_func((t,a)=>{try{let o=describeLogRecord(a,r),s=t&e.LogLevelFlags.LEVEL_MASK;s<=e.LogLevelFlags.LEVEL_WARNING&&n.push(o),(i||s<=e.LogLevelFlags.LEVEL_MESSAGE)&&printerr(o)}catch{printerr(`<gtk-host: a log message could not be decoded>`)}return e.LogWriterOutput.HANDLED}),t={seen:n,reset(){n.length=0},assertQuiet(e){if(n.length===0)return;let t=n.length,r=n.join(`
2
+ `);throw n.length=0,Error(`${e?e+`: `:``}GTK reported ${t} diagnostic(s) that would have passed at exit 0:\n ${r}`)}},t}export{describeLogRecord,installDiagnosticsGate};
@@ -1,2 +1,2 @@
1
- import"../_virtual/_rolldown/runtime.js";import{installDiagnosticsGate as e}from"./diagnostics.js";import{BUILTIN_DESCRIPTORS as t}from"../descriptors/index.js";import{addressOf as n}from"../policies.js";import r from"gi://GObject";function methodsOf(e){switch(e.kind){case`none`:return[];case`single`:return[e.set];case`ordered`:return e.after?[e.append,e.after,e.remove]:[e.append,e.remove];case`indexed`:return[e.insert,e.remove];case`slotted`:return[...Object.values(e.slots),e.remove];case`keyed`:return[e.add,e.remove];case`coords`:return[e.attach,e.remove]}}function descriptorProblems(e=t){let n=[];for(let t of e){let e;try{e=t.ctor()}catch(e){n.push({gtype:t.gtype,problem:`ctor() threw: ${e.message}`});continue}let i=r.type_name(e.$gtype);i!==t.gtype&&n.push({gtype:t.gtype,problem:`ctor() is ${i}, not ${t.gtype}`});for(let r of methodsOf(t.children))typeof e.prototype[r]!=`function`&&n.push({gtype:t.gtype,problem:`declares children.${r}(), which ${i} does not have`});if(t.textSink){let a=e.list_properties().find(e=>e.get_name()===t.textSink);a?(a.flags&r.ParamFlags.WRITABLE)===0?n.push({gtype:t.gtype,problem:`declares a READ-ONLY textSink "${t.textSink}"`}):r.type_is_a(a.value_type,r.TYPE_STRING)||n.push({gtype:t.gtype,problem:`declares textSink "${t.textSink}", which is ${r.type_name(a.value_type)}, not a string`}):n.push({gtype:t.gtype,problem:`declares textSink "${t.textSink}", which ${i} does not have`})}n.push(...policyProblems(t,e,i))}return n}function policyProblems(e,t,n){let r=[],i=t.prototype,a=e.children,requireGetter=(t,a)=>{let o=t.replace(/^set_/,`get_`);typeof i[o]!=`function`&&r.push({gtype:e.gtype,problem:`${a} uses ${t}() but ${n} has no ${o}(), so removal cannot check whether this child is still the one in place`})};if(a.kind===`single`&&requireGetter(a.set,`children.set`),a.kind===`slotted`){for(let[e,t]of Object.entries(a.slots))t.startsWith(`set_`)&&requireGetter(t,`slot "${e}"`);a.defaultSlot in a.slots||r.push({gtype:e.gtype,problem:`defaultSlot "${a.defaultSlot}" is not one of ${Object.keys(a.slots).join(`, `)}`})}if(a.kind===`ordered`&&a.reorder===`native`&&!a.after&&r.push({gtype:e.gtype,problem:`claims reorder: 'native' with no "after" method — reorderMode() would tell an adapter the wrong thing`}),a.kind===`keyed`){let t=i[a.add],o=a.titled?3:1;typeof t==`function`&&t.length!==o&&r.push({gtype:e.gtype,problem:`titled: ${a.titled} implies ${a.add}() takes ${o} argument(s), but ${n}'s takes ${t.length}`})}return r}function gtkChildren(e){let t=[],n=e;if(typeof n.get_first_child!=`function`)return t;for(let e=n.get_first_child();e;e=e.get_next_sibling())t.push(e);return t}const gtkChildTypes=e=>gtkChildren(e).map(e=>r.type_name(e.constructor.$gtype));function addressesOf(e){let t=[];for(let r=e.first;r;r=r.next)r.kind===`element`&&r.widget&&t.push(n(r));return t}function dumpTree(e,t=0){let n=r.type_name(e.constructor.$gtype),i=[`${` `.repeat(t)}${n}`];for(let n of gtkChildren(e))i.push(dumpTree(n,t+1));return i.join(`
2
- `)}export{addressesOf,descriptorProblems,dumpTree,gtkChildTypes,gtkChildren,e as installDiagnosticsGate,methodsOf};
1
+ import"../_virtual/_rolldown/runtime.js";import{addressOf as e,unhandledPolicy as t}from"../policies.js";import{describeLogRecord as n,installDiagnosticsGate as r}from"./diagnostics.js";import{BUILTIN_DESCRIPTORS as i}from"../descriptors/index.js";import a from"gi://GObject";function methodsOf(e){switch(e.kind){case`none`:case`uncurated`:return[];case`single`:return[e.set];case`ordered`:return e.after?[e.append,e.after,e.remove]:[e.append,e.remove];case`indexed`:return[e.insert,e.remove];case`slotted`:return[...Object.values(e.slots),e.remove];case`keyed`:return[e.add,e.remove];case`coords`:return[e.attach,e.remove];default:return t(e)}}function descriptorProblems(e=i){let t=[];for(let n of e){let e;try{e=n.ctor()}catch(e){t.push({gtype:n.gtype,problem:`ctor() threw: ${e.message}`});continue}let r=a.type_name(e.$gtype);r!==n.gtype&&t.push({gtype:n.gtype,problem:`ctor() is ${r}, not ${n.gtype}`});for(let i of methodsOf(n.children))typeof e.prototype[i]!=`function`&&t.push({gtype:n.gtype,problem:`declares children.${i}(), which ${r} does not have`});if(n.textSink){let i=e.list_properties().find(e=>e.get_name()===n.textSink);i?(i.flags&a.ParamFlags.WRITABLE)===0?t.push({gtype:n.gtype,problem:`declares a READ-ONLY textSink "${n.textSink}"`}):a.type_is_a(i.value_type,a.TYPE_STRING)||t.push({gtype:n.gtype,problem:`declares textSink "${n.textSink}", which is ${a.type_name(i.value_type)}, not a string`}):t.push({gtype:n.gtype,problem:`declares textSink "${n.textSink}", which ${r} does not have`})}t.push(...policyProblems(n,e,r))}return t}function policyProblems(e,t,n){let r=[],i=t.prototype,a=e.children,requireGetter=(t,a)=>{let o=t.replace(/^set_/,`get_`);typeof i[o]!=`function`&&r.push({gtype:e.gtype,problem:`${a} uses ${t}() but ${n} has no ${o}(), so removal cannot check whether this child is still the one in place`})};if(a.kind===`single`&&requireGetter(a.set,`children.set`),a.kind===`slotted`){for(let[e,t]of Object.entries(a.slots))t.startsWith(`set_`)&&requireGetter(t,`slot "${e}"`);a.defaultSlot in a.slots||r.push({gtype:e.gtype,problem:`defaultSlot "${a.defaultSlot}" is not one of ${Object.keys(a.slots).join(`, `)}`})}if(a.kind===`ordered`&&a.reorder===`native`&&!a.after&&r.push({gtype:e.gtype,problem:`claims reorder: 'native' with no "after" method — reorderMode() would tell an adapter the wrong thing`}),a.kind===`keyed`){let t=i[a.add],o=a.titled?3:1;typeof t==`function`&&t.length!==o&&r.push({gtype:e.gtype,problem:`titled: ${a.titled} implies ${a.add}() takes ${o} argument(s), but ${n}'s takes ${t.length}`})}return r}function gtkChildren(e){let t=[],n=e;if(typeof n.get_first_child!=`function`)return t;for(let e=n.get_first_child();e;e=e.get_next_sibling())t.push(e);return t}const gtkChildTypes=e=>gtkChildren(e).map(e=>a.type_name(e.constructor.$gtype));function addressesOf(t){let n=[];for(let r=t.first;r;r=r.next)r.kind===`element`&&r.widget&&n.push(e(r));return n}function findDescendant(e,t){let n=[e];for(;n.length>0;){let r=n.shift();if(r!==e&&t(r))return r;n.push(...gtkChildren(r))}return null}function descendants(e){let t=[e];for(let n of gtkChildren(e))t.push(...descendants(n));return t}function dumpTree(e,t=0){let n=a.type_name(e.constructor.$gtype),r=[`${` `.repeat(t)}${n}`];for(let n of gtkChildren(e))r.push(dumpTree(n,t+1));return r.join(`
2
+ `)}export{addressesOf,descendants,n as describeLogRecord,descriptorProblems,dumpTree,findDescendant,gtkChildTypes,gtkChildren,r as installDiagnosticsGate,methodsOf};
@@ -1 +1 @@
1
- import"../_virtual/_rolldown/runtime.js";import{registerWidgets as e}from"../registry.js";import{ADW_DESCRIPTORS as t}from"./adw.js";import{GTK_DESCRIPTORS as n}from"./gtk.js";const r=[...n,...t];function registerBuiltinWidgets(){e(r)}export{t as ADW_DESCRIPTORS,r as BUILTIN_DESCRIPTORS,n as GTK_DESCRIPTORS,registerBuiltinWidgets};
1
+ import"../_virtual/_rolldown/runtime.js";import{registerWidgets as e}from"../registry.js";import{GENERATED_PROVENANCE as t,GENERATED_WIDGETS as n}from"../generated/widgets.js";import{ADW_DESCRIPTORS as r}from"./adw.js";import{GTK_DESCRIPTORS as i}from"./gtk.js";const a=[...i,...r],o={AdwLayoutSlot:[`id`]};function mergeGenerated(e,t){let n=[...e],r=new Set(e.map(e=>e.gtype));for(let e of t){if(r.has(e.gtype))continue;let t=o[e.gtype];n.push({gtype:e.gtype,ctor:e.ctor,children:{kind:`uncurated`},...t?{requiresProps:t}:{}})}return n}const s=mergeGenerated(a,n);function registerBuiltinWidgets(){e(s)}const tableProvenance=()=>({gir:t,curated:a.length,generated:n.length,total:s.length});export{r as ADW_DESCRIPTORS,s as BUILTIN_DESCRIPTORS,a as CURATED_DESCRIPTORS,t as GENERATED_PROVENANCE,n as GENERATED_WIDGETS,i as GTK_DESCRIPTORS,o as REQUIRED_CONSTRUCT_PROPS,mergeGenerated,registerBuiltinWidgets,tableProvenance};
package/lib/esm/errors.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";var GtkHostError=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`GtkHostError`}};const e={unknownTag:e=>new GtkHostError(`unknown-tag`,`No descriptor registered for <${e}>. Register one with registerWidget({ gtype: '${e}', … }) or use a raw GType tag that is present in the installed typelib.`),unknownProp:(e,t)=>new GtkHostError(`unknown-prop`,`<${e}> has no property "${t}". Check the spelling against the installed GTK (camelCase and kebab-case both resolve), or bind it as a signal with on${t[0]?.toUpperCase()}${t.slice(1)}.`),readOnlyProp:(e,t)=>new GtkHostError(`read-only-prop`,`<${e}>.${t} is read-only in the installed GTK. Writing it is a silent no-op in GObject, so this host refuses it instead of dropping the value.`),badEnum:(e,t,n,r)=>new GtkHostError(`bad-enum`,`<${e}>.${t} expects ${r}, and "${n}" is not one of its values. Note that GObject accepts the wrong string SILENTLY — the property would have kept its old value.`),unknownSignal:(e,t,n)=>new GtkHostError(`unknown-signal`,`<${e}> emits no signal "${n}" (bound as ${t}). Check the spelling against the installed GTK, or use the escape hatch on:<raw-signal-name> if the name is irregular.`),signalTaken:(e,t,n,r)=>new GtkHostError(`signal-taken`,`<${e}> already binds "${r}" through ${n}, so ${t} would silently replace it — GObject has one handler per connect, and this host keeps one per signal name. Use one spelling, or combine the two callbacks yourself.`),badString:(e,t,n)=>new GtkHostError(`bad-string`,`<${e}>.${t} is a string property and got a ${n}. Numbers and booleans are stringified; anything else has no unambiguous spelling, and GObject would have thrown from inside the next rebuild.`),badBoolean:(e,t,n)=>new GtkHostError(`bad-boolean`,`<${e}>.${t} is a boolean and got the string "${n}". JS truthiness would make "false" mean TRUE — the exact silent-wrong-value this host exists to refuse. Pass a real boolean.`),badFlags:(e,t,n,r)=>new GtkHostError(`bad-flags`,`<${e}>.${t} expects the flags type ${r}, and a string ("${n}") cannot be resolved to one. Pass the numeric value (bitwise-or the members). GObject would have dropped the string silently.`),unresolvableEnum:e=>new GtkHostError(`unresolvable-enum`,`Cannot resolve the enum type ${e} to a GI namespace. Pass the numeric value instead, or extend ENUM_NAMESPACES in props.ts.`),textNotAccepted:(e,t)=>new GtkHostError(`text-not-accepted`,`<${e}> has no text sink, so the text ${JSON.stringify(t.slice(0,32))} has nowhere to go. Wrap it in a widget that takes text (<GtkLabel>), or set the property directly.`),unclaimedChild:(e,t)=>new GtkHostError(`unclaimed-child`,`<${e}> declares children: { kind: 'none' }, so it cannot adopt <${t}>. Fix one of three things: give the parent a child policy, wrap the child in a container, or set the child on a property (e.g. a "child" or "content" property).`),unknownSlot:(e,t,n)=>new GtkHostError(`unknown-slot`,`<${e}> has no slot "${t}". Known slots: ${n.join(`, `)}.`),rejectedChild:(e,t,n)=>new GtkHostError(`rejected-child`,`<${e}> refused <${t}>: ${n}. The container accepts only certain child types (e.g. AdwPreferencesPage takes AdwPreferencesGroup); the descriptor cannot know that, GTK does.`),notAWidget:e=>new GtkHostError(`not-a-widget`,`<${e}> is not a Gtk.Widget, so it cannot be placed as a child. Non-widget GObjects (controllers, filters, models) attach to a property, not to a parent.`)};export{GtkHostError,e as err};
1
+ import"./_virtual/_rolldown/runtime.js";var GtkHostError=class extends Error{constructor(e,t){super(t),this.code=e,this.name=`GtkHostError`}};const e={unknownTag:e=>new GtkHostError(`unknown-tag`,`No descriptor registered for <${e}>. Register one with registerWidget({ gtype: '${e}', … }). Being a real GType in the installed typelib is not enough on its own.`),missingConstructProp:(e,t)=>new GtkHostError(`missing-construct-prop`,`<${e}> cannot be constructed without ${t}. In the installed library this is not an exception but a g_error(): the process ABORTS (SIGABRT, exit 134, core dump) with no catch and no diagnostic, so the host refuses here while a refusal is still reportable. Author ${t} on the element.`),unknownProp:(e,t)=>new GtkHostError(`unknown-prop`,`<${e}> has no property "${t}". Check the spelling against the installed GTK (camelCase and kebab-case both resolve), or bind it as a signal with on${t[0]?.toUpperCase()}${t.slice(1)}.`),readOnlyProp:(e,t)=>new GtkHostError(`read-only-prop`,`<${e}>.${t} is read-only in the installed GTK. Writing it is a silent no-op in GObject, so this host refuses it instead of dropping the value.`),badEnum:(e,t,n,r)=>new GtkHostError(`bad-enum`,`<${e}>.${t} expects ${r}, and "${n}" is not one of its values. Note that GObject accepts the wrong string SILENTLY — the property would have kept its old value.`),unknownSignal:(e,t,n)=>new GtkHostError(`unknown-signal`,`<${e}> emits no signal "${n}" (bound as ${t}). Check the spelling against the installed GTK, or use the escape hatch on:<raw-signal-name> if the name is irregular.`),signalTaken:(e,t,n,r)=>new GtkHostError(`signal-taken`,`<${e}> already binds "${r}" through ${n}, so ${t} would silently replace it — GObject has one handler per connect, and this host keeps one per signal name. Use one spelling, or combine the two callbacks yourself.`),eventModifier:(e,t)=>new GtkHostError(`event-modifier`,`${e} carries the DOM listener modifier ".${t}", which has no GObject meaning: a signal is emitted on one object and does not propagate through a tree, so there is no capture phase and nothing to be passive about. Drop the modifier (${e.slice(0,e.length-t.length)}); for GTK4's own propagation phases set "propagation-phase" on a Gtk.EventController instead.`),badString:(e,t,n)=>new GtkHostError(`bad-string`,`<${e}>.${t} is a string property and got a ${n}. Numbers and booleans are stringified; anything else has no unambiguous spelling, and GObject would have thrown from inside the next rebuild.`),badBoolean:(e,t,n)=>new GtkHostError(`bad-boolean`,`<${e}>.${t} is a boolean and got the string "${n}". JS truthiness would make "false" mean TRUE — the exact silent-wrong-value this host exists to refuse. Pass a real boolean.`),badFlags:(e,t,n,r)=>new GtkHostError(`bad-flags`,`<${e}>.${t} expects the flags type ${r}, and a string ("${n}") cannot be resolved to one. Pass the numeric value (bitwise-or the members). GObject would have dropped the string silently.`),unresolvableEnum:e=>new GtkHostError(`unresolvable-enum`,`Cannot resolve the enum type ${e} to a GI namespace. Pass the numeric value instead, or extend ENUM_NAMESPACES in props.ts.`),textNotAccepted:(e,t)=>new GtkHostError(`text-not-accepted`,`<${e}> has no text sink, so the text ${JSON.stringify(t.slice(0,32))} has nowhere to go. Wrap it in a widget that takes text (<GtkLabel>), or set the property directly.`),unclaimedChild:(e,t)=>new GtkHostError(`unclaimed-child`,`<${e}> declares children: { kind: 'none' }, so it cannot adopt <${t}>. Fix one of three things: give the parent a child policy, wrap the child in a container, or set the child on a property (e.g. a "child" or "content" property).`),unknownSlot:(e,t,n)=>new GtkHostError(`unknown-slot`,`<${e}> has no slot "${t}". Known slots: ${n.join(`, `)}.`),rejectedChild:(e,t,n)=>new GtkHostError(`rejected-child`,`<${e}> refused <${t}>: ${n}. The container accepts only certain child types (e.g. AdwPreferencesPage takes AdwPreferencesGroup); the descriptor cannot know that, GTK does.`),uncuratedPlacement:(e,t)=>new GtkHostError(`uncurated-placement`,`<${e}> comes from the GENERATED table, which knows the tag but not how the widget adopts a child, so it cannot take <${t}>. Guessing is the one thing that is not available here: \`add\`, \`append\` and \`set_child\` all exist somewhere in GTK and calling the wrong one is a warning at exit 0. Add a curated policy for ${e} in descriptors/, or mount into a container that has one.`),siblingCycle:e=>new GtkHostError(`sibling-cycle`,`The child list of <${e}> does not terminate. A renderer linked a node to itself or into a loop; the host refuses to walk it rather than spin. This is a host or adapter bug, not an application one — please report it with the reordering that produced it.`),notAWidget:e=>new GtkHostError(`not-a-widget`,`<${e}> is not a Gtk.Widget, so it cannot be placed as a child. Non-widget GObjects (controllers, filters, models) attach to a property, not to a parent.`),occupiedSlot:(e,t,n)=>new GtkHostError(`occupied-slot`,`<${e}> already holds a child the application put there, and ${n}() takes only ONE — placing <${t}> would unparent it. GTK does that silently: no throw, no warning, exit 0, and the application's own widget is simply gone. Mount into a container of your own inside <${e}>, or clear the existing child first (${n}(null)) if replacing it is the intent.`),notAnElement:e=>new GtkHostError(`not-an-element`,`Only an element node owns a widget, and this node is a ${e}. A text node's content lives in its PARENT's text sink and an anchor owns nothing at all — neither has a widget to hand back. Ask the parent element instead.`),destroyedNode:e=>new GtkHostError(`destroyed-node`,`<${e}> was destroyed, so its widget is gone. Asking again would MATERIALISE a fresh, propertyless, unparented widget — \`destroy\` clears props and layout precisely so a destroyed element cannot look re-materialisable — and a caller holding that widget would be looking at nothing on screen.`),notAHostParent:e=>new GtkHostError(`not-a-host-parent`,`insert() needs a host element as the parent and got ${e}. A raw widget cannot be one: the shadow tree lives in the host's own fields, so writing them onto a GObject wrapper renders nothing and reports nothing — Vue's <Teleport to="someWidget"> hands the widget through verbatim and landed exactly here. Wrap it with adopt(widget) first, which is what mountRoot() does.`)};export{GtkHostError,e as err};
File without changes
@@ -0,0 +1 @@
1
+ import"../_virtual/_rolldown/runtime.js";import e from"gi://Gtk?version=4.0";import t from"gi://Adw?version=1";const n=`Gtk-4.0 Adw-1`,r=[{gtype:`AdwAboutDialog`,tag:`adw-about-dialog`,ctor:()=>t.AboutDialog},{gtype:`AdwAboutWindow`,tag:`adw-about-window`,ctor:()=>t.AboutWindow},{gtype:`AdwActionRow`,tag:`adw-action-row`,ctor:()=>t.ActionRow},{gtype:`AdwAlertDialog`,tag:`adw-alert-dialog`,ctor:()=>t.AlertDialog},{gtype:`AdwApplicationWindow`,tag:`adw-application-window`,ctor:()=>t.ApplicationWindow},{gtype:`AdwAvatar`,tag:`adw-avatar`,ctor:()=>t.Avatar},{gtype:`AdwBanner`,tag:`adw-banner`,ctor:()=>t.Banner},{gtype:`AdwBin`,tag:`adw-bin`,ctor:()=>t.Bin},{gtype:`AdwBottomSheet`,tag:`adw-bottom-sheet`,ctor:()=>t.BottomSheet},{gtype:`AdwBreakpointBin`,tag:`adw-breakpoint-bin`,ctor:()=>t.BreakpointBin},{gtype:`AdwButtonContent`,tag:`adw-button-content`,ctor:()=>t.ButtonContent},{gtype:`AdwButtonRow`,tag:`adw-button-row`,ctor:()=>t.ButtonRow},{gtype:`AdwCarousel`,tag:`adw-carousel`,ctor:()=>t.Carousel},{gtype:`AdwCarouselIndicatorDots`,tag:`adw-carousel-indicator-dots`,ctor:()=>t.CarouselIndicatorDots},{gtype:`AdwCarouselIndicatorLines`,tag:`adw-carousel-indicator-lines`,ctor:()=>t.CarouselIndicatorLines},{gtype:`AdwClamp`,tag:`adw-clamp`,ctor:()=>t.Clamp},{gtype:`AdwClampScrollable`,tag:`adw-clamp-scrollable`,ctor:()=>t.ClampScrollable},{gtype:`AdwComboRow`,tag:`adw-combo-row`,ctor:()=>t.ComboRow},{gtype:`AdwDialog`,tag:`adw-dialog`,ctor:()=>t.Dialog},{gtype:`AdwEntryRow`,tag:`adw-entry-row`,ctor:()=>t.EntryRow},{gtype:`AdwExpanderRow`,tag:`adw-expander-row`,ctor:()=>t.ExpanderRow},{gtype:`AdwFlap`,tag:`adw-flap`,ctor:()=>t.Flap},{gtype:`AdwHeaderBar`,tag:`adw-header-bar`,ctor:()=>t.HeaderBar},{gtype:`AdwInlineViewSwitcher`,tag:`adw-inline-view-switcher`,ctor:()=>t.InlineViewSwitcher},{gtype:`AdwLayoutSlot`,tag:`adw-layout-slot`,ctor:()=>t.LayoutSlot},{gtype:`AdwLeaflet`,tag:`adw-leaflet`,ctor:()=>t.Leaflet},{gtype:`AdwMessageDialog`,tag:`adw-message-dialog`,ctor:()=>t.MessageDialog},{gtype:`AdwMultiLayoutView`,tag:`adw-multi-layout-view`,ctor:()=>t.MultiLayoutView},{gtype:`AdwNavigationPage`,tag:`adw-navigation-page`,ctor:()=>t.NavigationPage},{gtype:`AdwNavigationSplitView`,tag:`adw-navigation-split-view`,ctor:()=>t.NavigationSplitView},{gtype:`AdwNavigationView`,tag:`adw-navigation-view`,ctor:()=>t.NavigationView},{gtype:`AdwOverlaySplitView`,tag:`adw-overlay-split-view`,ctor:()=>t.OverlaySplitView},{gtype:`AdwPasswordEntryRow`,tag:`adw-password-entry-row`,ctor:()=>t.PasswordEntryRow},{gtype:`AdwPreferencesDialog`,tag:`adw-preferences-dialog`,ctor:()=>t.PreferencesDialog},{gtype:`AdwPreferencesGroup`,tag:`adw-preferences-group`,ctor:()=>t.PreferencesGroup},{gtype:`AdwPreferencesPage`,tag:`adw-preferences-page`,ctor:()=>t.PreferencesPage},{gtype:`AdwPreferencesRow`,tag:`adw-preferences-row`,ctor:()=>t.PreferencesRow},{gtype:`AdwPreferencesWindow`,tag:`adw-preferences-window`,ctor:()=>t.PreferencesWindow},{gtype:`AdwShortcutLabel`,tag:`adw-shortcut-label`,ctor:()=>t.ShortcutLabel},{gtype:`AdwShortcutsDialog`,tag:`adw-shortcuts-dialog`,ctor:()=>t.ShortcutsDialog},{gtype:`AdwSidebar`,tag:`adw-sidebar`,ctor:()=>t.Sidebar},{gtype:`AdwSpinRow`,tag:`adw-spin-row`,ctor:()=>t.SpinRow},{gtype:`AdwSpinner`,tag:`adw-spinner`,ctor:()=>t.Spinner},{gtype:`AdwSplitButton`,tag:`adw-split-button`,ctor:()=>t.SplitButton},{gtype:`AdwSqueezer`,tag:`adw-squeezer`,ctor:()=>t.Squeezer},{gtype:`AdwStatusPage`,tag:`adw-status-page`,ctor:()=>t.StatusPage},{gtype:`AdwSwitchRow`,tag:`adw-switch-row`,ctor:()=>t.SwitchRow},{gtype:`AdwTabBar`,tag:`adw-tab-bar`,ctor:()=>t.TabBar},{gtype:`AdwTabButton`,tag:`adw-tab-button`,ctor:()=>t.TabButton},{gtype:`AdwTabOverview`,tag:`adw-tab-overview`,ctor:()=>t.TabOverview},{gtype:`AdwTabView`,tag:`adw-tab-view`,ctor:()=>t.TabView},{gtype:`AdwToastOverlay`,tag:`adw-toast-overlay`,ctor:()=>t.ToastOverlay},{gtype:`AdwToggleGroup`,tag:`adw-toggle-group`,ctor:()=>t.ToggleGroup},{gtype:`AdwToolbarView`,tag:`adw-toolbar-view`,ctor:()=>t.ToolbarView},{gtype:`AdwViewStack`,tag:`adw-view-stack`,ctor:()=>t.ViewStack},{gtype:`AdwViewSwitcher`,tag:`adw-view-switcher`,ctor:()=>t.ViewSwitcher},{gtype:`AdwViewSwitcherBar`,tag:`adw-view-switcher-bar`,ctor:()=>t.ViewSwitcherBar},{gtype:`AdwViewSwitcherSidebar`,tag:`adw-view-switcher-sidebar`,ctor:()=>t.ViewSwitcherSidebar},{gtype:`AdwViewSwitcherTitle`,tag:`adw-view-switcher-title`,ctor:()=>t.ViewSwitcherTitle},{gtype:`AdwWindow`,tag:`adw-window`,ctor:()=>t.Window},{gtype:`AdwWindowTitle`,tag:`adw-window-title`,ctor:()=>t.WindowTitle},{gtype:`AdwWrapBox`,tag:`adw-wrap-box`,ctor:()=>t.WrapBox},{gtype:`GtkAboutDialog`,tag:`gtk-about-dialog`,ctor:()=>e.AboutDialog},{gtype:`GtkActionBar`,tag:`gtk-action-bar`,ctor:()=>e.ActionBar},{gtype:`GtkAppChooserButton`,tag:`gtk-app-chooser-button`,ctor:()=>e.AppChooserButton},{gtype:`GtkAppChooserDialog`,tag:`gtk-app-chooser-dialog`,ctor:()=>e.AppChooserDialog},{gtype:`GtkAppChooserWidget`,tag:`gtk-app-chooser-widget`,ctor:()=>e.AppChooserWidget},{gtype:`GtkApplicationWindow`,tag:`gtk-application-window`,ctor:()=>e.ApplicationWindow},{gtype:`GtkAspectFrame`,tag:`gtk-aspect-frame`,ctor:()=>e.AspectFrame},{gtype:`GtkAssistant`,tag:`gtk-assistant`,ctor:()=>e.Assistant},{gtype:`GtkBox`,tag:`gtk-box`,ctor:()=>e.Box},{gtype:`GtkButton`,tag:`gtk-button`,ctor:()=>e.Button},{gtype:`GtkCalendar`,tag:`gtk-calendar`,ctor:()=>e.Calendar},{gtype:`GtkCellView`,tag:`gtk-cell-view`,ctor:()=>e.CellView},{gtype:`GtkCenterBox`,tag:`gtk-center-box`,ctor:()=>e.CenterBox},{gtype:`GtkCheckButton`,tag:`gtk-check-button`,ctor:()=>e.CheckButton},{gtype:`GtkColorButton`,tag:`gtk-color-button`,ctor:()=>e.ColorButton},{gtype:`GtkColorChooserDialog`,tag:`gtk-color-chooser-dialog`,ctor:()=>e.ColorChooserDialog},{gtype:`GtkColorChooserWidget`,tag:`gtk-color-chooser-widget`,ctor:()=>e.ColorChooserWidget},{gtype:`GtkColorDialogButton`,tag:`gtk-color-dialog-button`,ctor:()=>e.ColorDialogButton},{gtype:`GtkColumnView`,tag:`gtk-column-view`,ctor:()=>e.ColumnView},{gtype:`GtkComboBox`,tag:`gtk-combo-box`,ctor:()=>e.ComboBox},{gtype:`GtkComboBoxText`,tag:`gtk-combo-box-text`,ctor:()=>e.ComboBoxText},{gtype:`GtkDialog`,tag:`gtk-dialog`,ctor:()=>e.Dialog},{gtype:`GtkDragIcon`,tag:`gtk-drag-icon`,ctor:()=>e.DragIcon},{gtype:`GtkDrawingArea`,tag:`gtk-drawing-area`,ctor:()=>e.DrawingArea},{gtype:`GtkDropDown`,tag:`gtk-drop-down`,ctor:()=>e.DropDown},{gtype:`GtkEditableLabel`,tag:`gtk-editable-label`,ctor:()=>e.EditableLabel},{gtype:`GtkEmojiChooser`,tag:`gtk-emoji-chooser`,ctor:()=>e.EmojiChooser},{gtype:`GtkEntry`,tag:`gtk-entry`,ctor:()=>e.Entry},{gtype:`GtkExpander`,tag:`gtk-expander`,ctor:()=>e.Expander},{gtype:`GtkFileChooserDialog`,tag:`gtk-file-chooser-dialog`,ctor:()=>e.FileChooserDialog},{gtype:`GtkFileChooserWidget`,tag:`gtk-file-chooser-widget`,ctor:()=>e.FileChooserWidget},{gtype:`GtkFixed`,tag:`gtk-fixed`,ctor:()=>e.Fixed},{gtype:`GtkFlowBox`,tag:`gtk-flow-box`,ctor:()=>e.FlowBox},{gtype:`GtkFlowBoxChild`,tag:`gtk-flow-box-child`,ctor:()=>e.FlowBoxChild},{gtype:`GtkFontButton`,tag:`gtk-font-button`,ctor:()=>e.FontButton},{gtype:`GtkFontChooserDialog`,tag:`gtk-font-chooser-dialog`,ctor:()=>e.FontChooserDialog},{gtype:`GtkFontChooserWidget`,tag:`gtk-font-chooser-widget`,ctor:()=>e.FontChooserWidget},{gtype:`GtkFontDialogButton`,tag:`gtk-font-dialog-button`,ctor:()=>e.FontDialogButton},{gtype:`GtkFrame`,tag:`gtk-frame`,ctor:()=>e.Frame},{gtype:`GtkGLArea`,tag:`gtk-gl-area`,ctor:()=>e.GLArea},{gtype:`GtkGraphicsOffload`,tag:`gtk-graphics-offload`,ctor:()=>e.GraphicsOffload},{gtype:`GtkGrid`,tag:`gtk-grid`,ctor:()=>e.Grid},{gtype:`GtkGridView`,tag:`gtk-grid-view`,ctor:()=>e.GridView},{gtype:`GtkHeaderBar`,tag:`gtk-header-bar`,ctor:()=>e.HeaderBar},{gtype:`GtkIconView`,tag:`gtk-icon-view`,ctor:()=>e.IconView},{gtype:`GtkImage`,tag:`gtk-image`,ctor:()=>e.Image},{gtype:`GtkInfoBar`,tag:`gtk-info-bar`,ctor:()=>e.InfoBar},{gtype:`GtkInscription`,tag:`gtk-inscription`,ctor:()=>e.Inscription},{gtype:`GtkLabel`,tag:`gtk-label`,ctor:()=>e.Label},{gtype:`GtkLevelBar`,tag:`gtk-level-bar`,ctor:()=>e.LevelBar},{gtype:`GtkLinkButton`,tag:`gtk-link-button`,ctor:()=>e.LinkButton},{gtype:`GtkListBox`,tag:`gtk-list-box`,ctor:()=>e.ListBox},{gtype:`GtkListBoxRow`,tag:`gtk-list-box-row`,ctor:()=>e.ListBoxRow},{gtype:`GtkListView`,tag:`gtk-list-view`,ctor:()=>e.ListView},{gtype:`GtkLockButton`,tag:`gtk-lock-button`,ctor:()=>e.LockButton},{gtype:`GtkMediaControls`,tag:`gtk-media-controls`,ctor:()=>e.MediaControls},{gtype:`GtkMenuButton`,tag:`gtk-menu-button`,ctor:()=>e.MenuButton},{gtype:`GtkMessageDialog`,tag:`gtk-message-dialog`,ctor:()=>e.MessageDialog},{gtype:`GtkNotebook`,tag:`gtk-notebook`,ctor:()=>e.Notebook},{gtype:`GtkOverlay`,tag:`gtk-overlay`,ctor:()=>e.Overlay},{gtype:`GtkPageSetupUnixDialog`,tag:`gtk-page-setup-unix-dialog`,ctor:()=>e.PageSetupUnixDialog},{gtype:`GtkPaned`,tag:`gtk-paned`,ctor:()=>e.Paned},{gtype:`GtkPasswordEntry`,tag:`gtk-password-entry`,ctor:()=>e.PasswordEntry},{gtype:`GtkPicture`,tag:`gtk-picture`,ctor:()=>e.Picture},{gtype:`GtkPopover`,tag:`gtk-popover`,ctor:()=>e.Popover},{gtype:`GtkPopoverBin`,tag:`gtk-popover-bin`,ctor:()=>e.PopoverBin},{gtype:`GtkPopoverMenu`,tag:`gtk-popover-menu`,ctor:()=>e.PopoverMenu},{gtype:`GtkPopoverMenuBar`,tag:`gtk-popover-menu-bar`,ctor:()=>e.PopoverMenuBar},{gtype:`GtkPrintUnixDialog`,tag:`gtk-print-unix-dialog`,ctor:()=>e.PrintUnixDialog},{gtype:`GtkProgressBar`,tag:`gtk-progress-bar`,ctor:()=>e.ProgressBar},{gtype:`GtkRange`,tag:`gtk-range`,ctor:()=>e.Range},{gtype:`GtkRevealer`,tag:`gtk-revealer`,ctor:()=>e.Revealer},{gtype:`GtkScale`,tag:`gtk-scale`,ctor:()=>e.Scale},{gtype:`GtkScaleButton`,tag:`gtk-scale-button`,ctor:()=>e.ScaleButton},{gtype:`GtkScrollbar`,tag:`gtk-scrollbar`,ctor:()=>e.Scrollbar},{gtype:`GtkScrolledWindow`,tag:`gtk-scrolled-window`,ctor:()=>e.ScrolledWindow},{gtype:`GtkSearchBar`,tag:`gtk-search-bar`,ctor:()=>e.SearchBar},{gtype:`GtkSearchEntry`,tag:`gtk-search-entry`,ctor:()=>e.SearchEntry},{gtype:`GtkSeparator`,tag:`gtk-separator`,ctor:()=>e.Separator},{gtype:`GtkShortcutLabel`,tag:`gtk-shortcut-label`,ctor:()=>e.ShortcutLabel},{gtype:`GtkShortcutsGroup`,tag:`gtk-shortcuts-group`,ctor:()=>e.ShortcutsGroup},{gtype:`GtkShortcutsSection`,tag:`gtk-shortcuts-section`,ctor:()=>e.ShortcutsSection},{gtype:`GtkShortcutsShortcut`,tag:`gtk-shortcuts-shortcut`,ctor:()=>e.ShortcutsShortcut},{gtype:`GtkShortcutsWindow`,tag:`gtk-shortcuts-window`,ctor:()=>e.ShortcutsWindow},{gtype:`GtkSpinButton`,tag:`gtk-spin-button`,ctor:()=>e.SpinButton},{gtype:`GtkSpinner`,tag:`gtk-spinner`,ctor:()=>e.Spinner},{gtype:`GtkStack`,tag:`gtk-stack`,ctor:()=>e.Stack},{gtype:`GtkStackSidebar`,tag:`gtk-stack-sidebar`,ctor:()=>e.StackSidebar},{gtype:`GtkStackSwitcher`,tag:`gtk-stack-switcher`,ctor:()=>e.StackSwitcher},{gtype:`GtkStatusbar`,tag:`gtk-statusbar`,ctor:()=>e.Statusbar},{gtype:`GtkSwitch`,tag:`gtk-switch`,ctor:()=>e.Switch},{gtype:`GtkText`,tag:`gtk-text`,ctor:()=>e.Text},{gtype:`GtkTextView`,tag:`gtk-text-view`,ctor:()=>e.TextView},{gtype:`GtkToggleButton`,tag:`gtk-toggle-button`,ctor:()=>e.ToggleButton},{gtype:`GtkTreeExpander`,tag:`gtk-tree-expander`,ctor:()=>e.TreeExpander},{gtype:`GtkTreeView`,tag:`gtk-tree-view`,ctor:()=>e.TreeView},{gtype:`GtkVideo`,tag:`gtk-video`,ctor:()=>e.Video},{gtype:`GtkViewport`,tag:`gtk-viewport`,ctor:()=>e.Viewport},{gtype:`GtkVolumeButton`,tag:`gtk-volume-button`,ctor:()=>e.VolumeButton},{gtype:`GtkWindow`,tag:`gtk-window`,ctor:()=>e.Window},{gtype:`GtkWindowControls`,tag:`gtk-window-controls`,ctor:()=>e.WindowControls},{gtype:`GtkWindowHandle`,tag:`gtk-window-handle`,ctor:()=>e.WindowHandle}];export{n as GENERATED_PROVENANCE,r as GENERATED_WIDGETS};