@gjsify/gtk-host 0.48.0 → 0.49.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 (38) hide show
  1. package/README.md +108 -6
  2. package/lib/esm/adjustment.js +1 -0
  3. package/lib/esm/conformance/diagnostics.js +1 -1
  4. package/lib/esm/conformance/index.js +1 -1
  5. package/lib/esm/descriptors/adw.js +1 -1
  6. package/lib/esm/descriptors/gtk.js +1 -1
  7. package/lib/esm/descriptors/index.js +1 -1
  8. package/lib/esm/errors.js +1 -1
  9. package/lib/esm/font-families.js +1 -0
  10. package/lib/esm/fonts.js +1 -1
  11. package/lib/esm/host.js +1 -1
  12. package/lib/esm/index.js +1 -1
  13. package/lib/esm/list-model.js +1 -0
  14. package/lib/esm/menu.js +1 -1
  15. package/lib/esm/policies.js +1 -1
  16. package/lib/esm/props.js +1 -1
  17. package/lib/types/adjustment.d.ts +28 -0
  18. package/lib/types/attrs.d.ts +49 -1
  19. package/lib/types/conformance/index.d.ts +14 -4
  20. package/lib/types/descriptors/gtk.d.ts +32 -1
  21. package/lib/types/errors.d.ts +34 -2
  22. package/lib/types/font-families.d.ts +40 -0
  23. package/lib/types/font-families.spec.d.ts +2 -0
  24. package/lib/types/fonts.d.ts +45 -1
  25. package/lib/types/generated/enum-values.d.mts +38 -0
  26. package/lib/types/generated/methods.d.mts +46 -0
  27. package/lib/types/jsx-runtime.d.ts +2 -2
  28. package/lib/types/list-model.d.ts +38 -0
  29. package/lib/types/list-model.spec.d.ts +2 -0
  30. package/lib/types/placement.spec.d.ts +2 -0
  31. package/lib/types/policies.d.ts +177 -1
  32. package/lib/types/react-jsx-runtime.d.ts +2 -2
  33. package/lib/types/shared-trees.spec.d.ts +2 -0
  34. package/lib/types/testing/refusal.d.mts +2 -0
  35. package/lib/types/types.d.ts +99 -2
  36. package/lib/types/vue-components.d.ts +2 -2
  37. package/package.json +7 -5
  38. /package/lib/types/{portal.spec.d.ts → adjustment.spec.d.ts} +0 -0
@@ -1,2 +1,33 @@
1
- import type { WidgetDescriptor } from '../types.js';
1
+ import type { NodePlacement, WidgetDescriptor } from '../types.js';
2
+ /**
3
+ * The placement every `Gtk.Root` shares — ADR 0054.
4
+ *
5
+ * `present` and `destroy` are measured on GTK 4.22.4; the measurements that pick
6
+ * `destroy` over `close` (a vetoed `close-request` leaves the window up) and that
7
+ * make the retraction terminal are on `NodePlacement`'s toplevel arm in `types.ts`.
8
+ *
9
+ * SHARED WITH `adw.ts`, which imports it: a toplevel is a fact about the TYPE, and
10
+ * `Gtk.Root`'s presentable implementations are split across the two libraries by
11
+ * nothing but who owns the class (measured with `GObject.type_is_a`). They are
12
+ * NAMED rather than inherited for the reason the dialog family is: registration is
13
+ * exact, so `lookupWidget('GtkMessageDialog')` answers the GENERATED row and an
14
+ * inherited placement would never be looked up. `is declared by every registered
15
+ * Gtk.Root` in `placement.spec.ts` is what keeps the list complete, and it holds
16
+ * the count so no comment has to.
17
+ *
18
+ * `GtkDragIcon` is the one `Gtk.Root` deliberately absent: measured, it has no
19
+ * `present`, no `close` and no `destroy` — GTK creates one for a drag operation and
20
+ * nothing else ever shows one. It is refused at the insert by `refuseUnparentable`
21
+ * instead, which is the honest answer for a root that cannot present itself, and
22
+ * the spec NAMES it so a second such class is a decision rather than a bumped
23
+ * number.
24
+ *
25
+ * CHILDREN STAY UNCURATED on every row that had no policy before this. A window
26
+ * takes `set_child`, but `GtkDialog` and its five chooser subclasses put children
27
+ * into a content area (`get_content_area`) that `set_child` would REPLACE, and
28
+ * `GtkAssistant` addresses pages by index — the `AdwAlertDialog` trap one axis
29
+ * over. Guessing here buys a warning at exit 0; the tags are creatable,
30
+ * propertyable and presentable, and a child in one is a named refusal.
31
+ */
32
+ export declare const TOPLEVEL: NodePlacement;
2
33
  export declare const GTK_DESCRIPTORS: readonly WidgetDescriptor[];
@@ -21,6 +21,20 @@ export declare const err: {
21
21
  readOnlyProp: (tag: string, prop: string) => GtkHostError;
22
22
  noAccessor: (tag: string, prop: string, accessor: string) => GtkHostError;
23
23
  badDetailedAction: (label: string, detailed: string, why: string) => GtkHostError;
24
+ badListModel: (tag: string, prop: string, got: string) => GtkHostError;
25
+ /**
26
+ * A list-shaped property the portable list model cannot satisfy.
27
+ *
28
+ * `Gtk.ListView:model` is a `Gtk.SelectionModel`, which IS a `Gio.ListModel` — so a
29
+ * branch keyed on the ParamSpec's list-ness alone would build a `Gtk.StringList` for
30
+ * it, and GObject's answer to that is SILENCE (measured, GTK 4.22.4): `set_property`
31
+ * transforms an object of the wrong type into NULL and logs nothing, so the view is
32
+ * empty at exit 0 and not even the diagnostics gate reports it. The second test in
33
+ * `coerce` asks whether the property can HOLD what the branch builds; where it
34
+ * cannot, this names the type GTK wants.
35
+ */
36
+ listModelMismatch: (tag: string, prop: string, gtypeName: string) => GtkHostError;
37
+ badAdjustment: (tag: string, prop: string, got: string) => GtkHostError;
24
38
  badEnum: (tag: string, prop: string, nick: string, gtypeName: string) => GtkHostError;
25
39
  unknownSignal: (tag: string, prop: string, signal: string) => GtkHostError;
26
40
  signalTaken: (tag: string, prop: string, other: string, signal: string) => GtkHostError;
@@ -61,14 +75,32 @@ export declare const err: {
61
75
  notAWidget: (tag: string) => GtkHostError;
62
76
  occupiedSlot: (parentTag: string, childTag: string, setter: string) => GtkHostError;
63
77
  /**
64
- * A portal descriptor naming a method the installed class does not have.
78
+ * A placement naming a method the installed class does not have.
65
79
  *
66
80
  * `descriptorProblems()` rejects this shape up front, so a BUILT-IN descriptor
67
81
  * can never reach here — an application-registered one is checked by nobody,
68
82
  * and the alternative is `TypeError: widget[placement.present] is not a
69
83
  * function` thrown from inside an insert, naming neither the tag nor the axis.
70
84
  */
71
- portalMethodMissing: (tag: string, method: string, role: "present" | "close") => GtkHostError;
85
+ placementMethodMissing: (tag: string, kind: string, method: string, role: "present" | "close") => GtkHostError;
86
+ /**
87
+ * A child GTK will not take, refused BEFORE the parent's adder is called.
88
+ *
89
+ * THE ONLY REFUSAL IN THIS FILE THAT EXISTS TO PREVENT A PROCESS ABORT rather
90
+ * than a wrong window. `adw_dialog_root()` answers a parented dialog with
91
+ * `g_error()` — SIGABRT, exit 134, a core dump — which no `try` catches and no
92
+ * diagnostics gate counts, so a message can only be produced while there is
93
+ * still a process to produce it (ADR 0054). Its neighbour is the opposite and
94
+ * just as wrong: a `GtkRoot` appended to a rooted box is accepted at exit 0
95
+ * with nothing logged, leaving a toplevel with a parent.
96
+ *
97
+ * The class is asked STRUCTURALLY and never by name — `Gtk.Root` for a
98
+ * toplevel, a `present()` that takes a parent for a portal — so a consumer's
99
+ * own subclass is refused exactly like a shipped one. A widget that trips the
100
+ * oracle and really is a child says so with an explicit
101
+ * `placement: { kind: 'parented' }`.
102
+ */
103
+ unparentableChild: (parentTag: string, childTag: string, kind: string, why: string) => GtkHostError;
72
104
  notAnElement: (kind: string) => GtkHostError;
73
105
  destroyedNode: (tag: string) => GtkHostError;
74
106
  notAHostParent: (got: string) => GtkHostError;
@@ -0,0 +1,40 @@
1
+ /** How a declared family name was found among the families a font map holds. */
2
+ export type FontFamilyMatchKind = 'exact' | 'optical' | 'ambiguous' | 'absent';
3
+ /** What a declared family name resolves to on a given font map. */
4
+ export interface FontFamilyMatch {
5
+ /** The name the application wrote. */
6
+ readonly declared: string;
7
+ /**
8
+ * The family name to put in a `Pango.FontDescription` or a `font-family` declaration, or
9
+ * `undefined` when there is no answer this module may give (`absent`, `ambiguous`).
10
+ */
11
+ readonly family: string | undefined;
12
+ readonly kind: FontFamilyMatchKind;
13
+ /**
14
+ * Every family on the map that is a plausible reading of `declared`. One entry for `exact`
15
+ * and `optical`, several for `ambiguous`, none for `absent` — so a caller resolving an
16
+ * ambiguity has the candidates in hand and does not have to re-derive them.
17
+ */
18
+ readonly candidates: readonly string[];
19
+ }
20
+ /**
21
+ * Resolve one declared family name against the families a font map holds.
22
+ *
23
+ * Both directions of the divergence, because it is one fact read from either side: an application
24
+ * written against the fontconfig name (`Merriweather`) meets `Merriweather 18pt` on Windows, and
25
+ * one written against the Windows name meets `Merriweather` everywhere else. Neither is more
26
+ * correct than the other, and an application that hardcodes either has to keep working on the
27
+ * other platform — which is the whole complaint.
28
+ */
29
+ export declare function matchFontFamily(declared: string, families: readonly string[]): FontFamilyMatch;
30
+ /** {@link matchFontFamily} over a list, in the order declared. */
31
+ export declare function matchFontFamilies(declared: readonly string[], families: readonly string[]): readonly FontFamilyMatch[];
32
+ /**
33
+ * One line saying what happened to a declared family, for a caller that wants to print it.
34
+ *
35
+ * Exported because the wording is the point: a report that says "not found" leaves the reader
36
+ * to guess whether the file failed, the map declined it, or the name simply differs here — and
37
+ * those have three different repairs. The `optical` line is the one that earns its keep, because
38
+ * a rename is exactly what does NOT look like a problem when the window renders.
39
+ */
40
+ export declare function describeFontFamilyMatch(match: FontFamilyMatch): string;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -1,6 +1,20 @@
1
+ import { type FontFamilyMatch } from './font-families.js';
1
2
  import { type ResolveFontDirOptions } from './font-dir.js';
3
+ export { describeFontFamilyMatch, matchFontFamilies, matchFontFamily, type FontFamilyMatch, type FontFamilyMatchKind, } from './font-families.js';
2
4
  /** Everything {@link resolveFontDir} takes except the environment, which {@link initFonts} reads. */
3
- export type InitFontsOptions = Omit<ResolveFontDirOptions, 'env'>;
5
+ export interface InitFontsOptions extends Omit<ResolveFontDirOptions, 'env'> {
6
+ /**
7
+ * The family names this application will ASK FOR — checked against the map once registration
8
+ * is done, and reported in {@link InitFontsResult.matches}.
9
+ *
10
+ * Optional, and the reason to pass it is that nothing downstream can. A `font-family`
11
+ * declaration cannot know which file was supposed to back it, and `list_families()` alone
12
+ * cannot say which of 84 names arrived from the staged directory; this call is the one moment
13
+ * that has both. Every name that does not resolve is WARNED about here, which is the only
14
+ * place a missing family is ever loud — Pango substitutes silently and the window renders.
15
+ */
16
+ readonly expectedFamilies?: readonly string[];
17
+ }
4
18
  /** A face the font map would not take, and why. */
5
19
  export interface FontFaceFailure {
6
20
  readonly path: string;
@@ -16,6 +30,36 @@ export interface InitFontsResult {
16
30
  readonly declined: readonly string[];
17
31
  /** Faces that failed for any other reason. Each was warned about; none threw. */
18
32
  readonly failed: readonly FontFaceFailure[];
33
+ /**
34
+ * The family names the default font map GAINED across this call, sorted.
35
+ *
36
+ * THE FIELD #1542 IS ABOUT, and the reason it is a diff rather than a list: a caller can act
37
+ * only on a family NAME, the name is not derivable from the file, and no caller can take this
38
+ * measurement afterwards — `list_families()` alone cannot say which of 84 names arrived from
39
+ * the staged directory. Only the call that registered them is in a position to know.
40
+ *
41
+ * NOT a file → family map, and that is a limit rather than a shortcut: Pango exposes no link
42
+ * from a registered file back to the family it produced, and attributing families by
43
+ * registering one file at a time would credit a family to whichever of its faces happened to
44
+ * be registered first — five staged faces of two families would report three files as having
45
+ * contributed nothing, which reads exactly like three failures.
46
+ *
47
+ * EMPTY IS NOT FAILURE, on two live paths: a map that declines runtime registration (macOS,
48
+ * where a shipped `.app` has already activated the directory through
49
+ * `ATSApplicationFontsPath` before any code runs) gains nothing here and is CORRECT, and a
50
+ * face whose family the map already holds adds no new name. {@link matches} is what tells
51
+ * those apart from nothing having worked, because it asks what the map holds NOW.
52
+ */
53
+ readonly families: readonly string[];
54
+ /**
55
+ * What each of {@link InitFontsOptions.expectedFamilies} resolves to on the map, in the order
56
+ * declared. Empty when the caller declared none.
57
+ *
58
+ * This is the answer to the darwin row of #1542, where `declined: 5` is consistent BOTH with
59
+ * everything working and with nothing working: the only thing that separates the two is what
60
+ * the map holds afterwards, which is what a match reads.
61
+ */
62
+ readonly matches: readonly FontFamilyMatch[];
19
63
  }
20
64
  /**
21
65
  * Did the font map decline runtime registration outright?
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The libraries these numbers were read from, in the vocabulary's own provenance
3
+ * grammar so one parser reads both lines.
4
+ *
5
+ * A value, not only a header comment: `generated.spec.ts` compares it with the
6
+ * running library to decide whether a disagreement is a defect or a version gap.
7
+ */
8
+ export declare const VALUES_PROVENANCE = "Adw-1/1.9.3 Gtk-4.0/4.22.4 Pango-1.0/1.57.1";
9
+ /** `<enum GType>.<nick>` -> the integer the library registers for it. */
10
+ export declare const ENUM_VALUES: Readonly<Record<string, number>>;
11
+ /**
12
+ * `<enum GType>.<alias nick>` -> the nick of the same enum it shares a value with.
13
+ *
14
+ * Two names, one member. Both names keep an entry in `ENUM_VALUES` carrying the same
15
+ * number — nothing is lost — and this table says which of them a number should be
16
+ * spelled back as. `GTK_ALIGN_BASELINE` is here because GTK 4.12 deprecated it in
17
+ * favour of `GTK_ALIGN_BASELINE_FILL` and gave the new name the same value instead of
18
+ * adding a member; the typelib's own deprecation flag is what picks the direction.
19
+ */
20
+ export declare const ENUM_ALIASES: Readonly<Record<string, string>>;
21
+ /**
22
+ * Every enum nick the installed typelib marks deprecated.
23
+ *
24
+ * The input to `ENUM_ALIASES`' direction, kept as its own fact so the choice is
25
+ * checkable rather than a convention about ordering.
26
+ */
27
+ export declare const ENUM_DEPRECATED: readonly string[];
28
+ /**
29
+ * `<enum GType>.<nick>` -> the installed library that has no such member.
30
+ *
31
+ * The declared remainder, and the only reason one exists: the vocabulary can describe
32
+ * a library NEWER than the one installed (ADR 0029 § Amendment), so a nick can be real
33
+ * and have no number here yet. Every nick in `ENUM_NICKS` is in `ENUM_VALUES` or in
34
+ * this table — a nick in neither is a silent drop and the gate fails on it. The value
35
+ * is the library and version that was asked, so the entry says WHICH host produced the
36
+ * gap rather than only that there is one; regenerating on a newer one empties it.
37
+ */
38
+ export declare const ENUM_VALUES_UNAVAILABLE: Readonly<Record<string, string>>;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The libraries these names were read from, in the vocabulary's own provenance grammar
3
+ * so one parser reads both lines.
4
+ *
5
+ * A value, not only a header comment: `generated.spec.ts` compares it with the running
6
+ * library to decide whether a missing method is a defect or a version gap.
7
+ */
8
+ export declare const METHODS_PROVENANCE = "Adw-1/1.9.3 Gtk-4.0/4.22.4";
9
+ /**
10
+ * GType -> the instance methods that type declares ITSELF, in typelib order.
11
+ *
12
+ * Every widget of the runtime table has a row, and so does every ancestor and interface
13
+ * `ANCESTRY` names, so a union over a chain never stops short. Inherited methods are not
14
+ * repeated: `AdwActionRow` lists `add_prefix` and not `add_css_class`.
15
+ */
16
+ export declare const OWN_METHODS: Readonly<Record<string, readonly string[]>>;
17
+ /**
18
+ * Widget GType -> every ancestor and interface a GJS instance of it carries methods
19
+ * from, transitively, nearest first — the parent chain to `GObject`, then the
20
+ * interfaces of each link and their prerequisites.
21
+ *
22
+ * Only the runtime table's widgets have a row; a base or an interface has methods in
23
+ * `OWN_METHODS` and no chain of its own here.
24
+ */
25
+ export declare const ANCESTRY: Readonly<Record<string, readonly string[]>>;
26
+ /**
27
+ * What GJS installs on `GObject.Object.prototype` beyond the typelib — measured by
28
+ * subtraction on the generating host, never authored.
29
+ *
30
+ * These are the verbs every GJS snippet writes and no `.gir` declares: `connect`,
31
+ * `disconnect`, `emit`. A ledger holding a port against the typelib alone would call
32
+ * them divergences, so they are the fourth table. `set` is here because it IS installed
33
+ * (the multi-property setter, `widget.set({ label })`), and is the one name in this list
34
+ * that collides with a different contract on NativeScript's `Observable`.
35
+ */
36
+ export declare const GJS_OBJECT_METHODS: readonly string[];
37
+ /**
38
+ * Widget GType -> the installed library that has no such type.
39
+ *
40
+ * The declared remainder, and the only reason one exists: the vocabulary can describe a
41
+ * library NEWER than the one this file was generated on, so a widget can be real and
42
+ * have no chain here yet. Every widget of the runtime table is in `ANCESTRY` or in this
43
+ * table — one in neither is a silent drop, and the gate fails on it. Regenerating on a
44
+ * newer host empties it.
45
+ */
46
+ export declare const METHODS_UNAVAILABLE: Readonly<Record<string, string>>;
@@ -28,12 +28,12 @@
28
28
  * keys (TS2411). The camelCase spelling of every property IS checked, which is why
29
29
  * both spellings are generated and camelCase is the one to prefer.
30
30
  */
31
- import type { JsxAttributes, WithOnce, WithPortableMenu } from './attrs.js';
31
+ import type { JsxAttributes, WithOnce, WithPortableValues } from './attrs.js';
32
32
  import type { HostNode } from './types.js';
33
33
  import type { WidgetClassByTag, WidgetPropsByTag } from './generated/props.js';
34
34
  /** Every GTK/Adwaita tag, with its properties, its handlers and its `ref`. */
35
35
  export type GtkIntrinsicElements = {
36
- [K in keyof WidgetPropsByTag]: WithOnce<WithPortableMenu<WidgetPropsByTag[K]>> & JsxAttributes<WidgetClassByTag[K]>;
36
+ [K in keyof WidgetPropsByTag]: WithOnce<WithPortableValues<WidgetPropsByTag[K]>> & JsxAttributes<WidgetClassByTag[K]>;
37
37
  };
38
38
  export declare namespace JSX {
39
39
  /**
@@ -0,0 +1,38 @@
1
+ import Gtk from 'gi://Gtk?version=4.0';
2
+ import type { AdwListModel, AdwListModelInput } from '@gjsify/adwaita-core';
3
+ /**
4
+ * A portable list model as a live `Gtk.StringList`.
5
+ *
6
+ * Accepts the AUTHORED form as well as the normalised one: `normalizeComboOptions` is
7
+ * total and idempotent, so a JSX attribute needs no conversion step of its own, and a
8
+ * renderer handing its own normalised model back in takes the same door.
9
+ */
10
+ export declare function buildStringList(input: AdwListModelInput): Gtk.StringList;
11
+ /**
12
+ * Whether a value is a portable list model rather than a `Gio.ListModel`.
13
+ *
14
+ * An ARRAY, and nothing else — the same test `isPortableMenu` makes. A `Gio.ListModel`
15
+ * is a GObject and never an array, so the imperative path (a real `Gtk.StringList`, a
16
+ * `Gio.ListStore`) is never mistaken for the portable one.
17
+ */
18
+ export declare const isPortableListModel: (value: unknown) => value is AdwListModelInput;
19
+ /** The strings a `Gtk.StringList` holds, in order — read off GTK, never off an input. */
20
+ export declare function stringsOf(model: Gtk.StringList): string[];
21
+ /**
22
+ * Splice a freshly built list's difference into the list `widget[accessor]` holds, if
23
+ * both are this module's — see the header for the measurement that makes this a rule.
24
+ *
25
+ * Answers whether the write is DONE: `true` means the held list now reads as `fresh`
26
+ * (an equal list is left untouched, so nothing is emitted); `false` means one of the two
27
+ * is not the seam's, and the caller writes the property as it would any other.
28
+ */
29
+ export declare function reconcileStringList(widget: object, accessor: string, fresh: unknown): boolean;
30
+ /**
31
+ * A `Gtk.StringList` back as a portable model — the inverse of {@link buildStringList}
32
+ * for the half that crosses.
33
+ *
34
+ * It exists to make the claim above measurable: `list-model.spec.ts` drives every
35
+ * `LIST_NORMALIZE_VECTORS` row through the builder and back through this, so a label
36
+ * that stopped arriving fails a test naming it instead of vanishing from a popup.
37
+ */
38
+ export declare function fromStringList(model: Gtk.StringList): AdwListModel;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -1,3 +1,4 @@
1
+ import GObject from 'gi://GObject?version=2.0';
1
2
  import Gtk from 'gi://Gtk?version=4.0';
2
3
  import type { ChildPolicy, HostElement, NodePlacement, WidgetDescriptor } from './types.js';
3
4
  /** The object the PARENT addresses: a wrapper row when the policy demands one. */
@@ -86,6 +87,10 @@ export declare function setterSlots(policy: ChildPolicy): string[];
86
87
  * occupant is the widget they handed over.
87
88
  */
88
89
  export declare function slotOccupant(widget: Gtk.Widget, setter: string): Gtk.Widget | null | undefined;
90
+ /** A placement that does NOT put the node into its parent's child list. */
91
+ export type OutsideParent = Exclude<NodePlacement, {
92
+ kind: 'parented';
93
+ }>;
89
94
  /**
90
95
  * The declared placement of a node. The ONE place absence is turned into a value.
91
96
  *
@@ -94,7 +99,15 @@ export declare function slotOccupant(widget: Gtk.Widget, setter: string): Gtk.Wi
94
99
  * falsiness test that a third kind would quietly join.
95
100
  */
96
101
  export declare const placementOf: (descriptor: WidgetDescriptor) => NodePlacement;
97
- /** The portal arm, or null. The narrow question four call sites ask. */
102
+ /**
103
+ * The placement, when it is NOT `parented` — the narrow question every caller asks.
104
+ *
105
+ * Returning the arm rather than a boolean is what keeps the two non-parented kinds
106
+ * ONE question: a caller switches over what it gets and its `never` arm fails to
107
+ * compile the day a fourth kind arrives.
108
+ */
109
+ export declare function outsideParentOf(descriptor: WidgetDescriptor): OutsideParent | null;
110
+ /** The portal arm specifically, or null. */
98
111
  export declare function portalOf(descriptor: WidgetDescriptor): Extract<NodePlacement, {
99
112
  kind: 'portal';
100
113
  }> | null;
@@ -102,6 +115,18 @@ export declare function portalOf(descriptor: WidgetDescriptor): Extract<NodePlac
102
115
  export declare function unhandledPlacement(placement: never): never;
103
116
  /** Is this node placed against its parent rather than into it? */
104
117
  export declare const isPortal: (el: HostElement) => boolean;
118
+ /**
119
+ * Does this node take NO position in its parent's child list?
120
+ *
121
+ * The question four sibling walks ask, and it is the placement AXIS rather than
122
+ * the portal arm: a toplevel occupies a parent's child list exactly as little as a
123
+ * portal does. Asking `isPortal` there was correct while `portal` was the only
124
+ * non-parented kind and became a silent hole the moment it was not — counting a
125
+ * toplevel as a sibling shifts every later child by one and hands
126
+ * `insert_child_after` a widget that is not in the container (a critical at exit 0),
127
+ * and rotating one calls the parent's adder on a node that must never enter it.
128
+ */
129
+ export declare const isUnparented: (el: HostElement) => boolean;
105
130
  /**
106
131
  * Show a portal node against its parent — or subscribe and wait, if it is too early.
107
132
  *
@@ -150,6 +175,157 @@ export declare function presentPortal(parent: HostElement, child: HostElement, p
150
175
  export declare function retractPortal(child: HostElement, portal: Extract<NodePlacement, {
151
176
  kind: 'portal';
152
177
  }>): void;
178
+ /**
179
+ * Show a toplevel node — and it needs nothing from its parent, which is the point.
180
+ *
181
+ * NO ANCHOR, NO WAIT, NO SUBSCRIPTION. A portal has two positions in the tree and
182
+ * defers until the parent supplies the second one; a toplevel HAS no second
183
+ * position, so the whole `notify::root` machinery next door has nothing to watch
184
+ * for. Measured: `gtk_window_present` takes 0 arguments where
185
+ * `adw_dialog_present` takes 1, and that arity is exactly the difference.
186
+ *
187
+ * Returns whether GTK has taken the node — always true once there is a widget,
188
+ * because a root is taken by nobody: measured, a presented window answers
189
+ * `get_parent() === null` and `get_root() === itself`. That is not the portal's
190
+ * "claimed but not yet taken" state, it is the finished one.
191
+ *
192
+ * AN AUTHORED `visible: false` IS HONOURED rather than overwritten. `present()`
193
+ * sets the window visible (measured), so presenting unconditionally would make
194
+ * `<gtk-window visible={false}>` a property this host silently reverses — the
195
+ * exact shape it exists to refuse. The node is still `attached`: GTK holds it as
196
+ * its own root whether or not it is on screen, and a later `setProp(el,
197
+ * 'visible', true)` shows it through the ordinary property path.
198
+ */
199
+ export declare function presentToplevel(child: HostElement, placement: Extract<NodePlacement, {
200
+ kind: 'toplevel';
201
+ }>): boolean;
202
+ /**
203
+ * Take a toplevel back down — the FORCED call, and it is TERMINAL.
204
+ *
205
+ * `destroy` and not `close`, measured on GTK 4.22.4: `gtk_window_close()` emits
206
+ * `close-request`, and an application handler returning TRUE leaves the window
207
+ * mapped and visible. That veto is how an application asks the USER to confirm,
208
+ * and an unmount is not a user request — the same reasoning that makes the portal
209
+ * arm name `force_close`.
210
+ *
211
+ * Unconditional for the same reason too: measured, `destroy()` on a window that
212
+ * was never presented is silent, so no "is it up?" probe is needed. What differs
213
+ * from the portal is that there IS no way back — measured, `present()` after a
214
+ * destroy (or after a `close()`, whose default handler destroys) answers
215
+ * `Gtk-WARNING **: A window is shown after it has been destroyed`.
216
+ *
217
+ * SO THIS IS `destroy`'s CALL AND NOT `remove`'s, which is the whole reason
218
+ * `detachToplevel` exists next door. `remove` documents itself as reversible.
219
+ */
220
+ export declare function closeToplevel(child: HostElement, placement: Extract<NodePlacement, {
221
+ kind: 'toplevel';
222
+ }>): void;
223
+ /**
224
+ * Take a toplevel OFF SCREEN, reversibly — `remove`'s call.
225
+ *
226
+ * `remove` is documented as a detach that a later `insert` undoes ("Frameworks
227
+ * move nodes; `remove` must not destroy one"), and Solid takes it literally: its
228
+ * `removeNode` calls `remove(node)` for a move and reaches `destroy` only through
229
+ * the root disposer. Running the declared, TERMINAL close there made a move
230
+ * `destroy()` the window and then present the corpse —
231
+ * `Gtk-WARNING **: A window is shown after it has been destroyed`, at exit 0,
232
+ * visible only because `installDiagnosticsGate()` was watching.
233
+ *
234
+ * A PROPERTY WRITE AND NOT A DECLARED METHOD, and that is the honest shape rather
235
+ * than a shortcut: a window's presence on screen IS its `visible` property — which
236
+ * is why `presentToplevel` already reads it — so every toplevel detaches the same
237
+ * way and a per-row name would be the same string once per declared row. The portal
238
+ * arm needs no counterpart at all, because its declared close is ALREADY reversible.
239
+ *
240
+ * MEASURED on GTK 4.22.4, one window, in order: `set_visible(false)` leaves it
241
+ * `visible` false with one `unmap`, emits NO `close-request`, and keeps it in
242
+ * `Gtk.Window.list_toplevels()` — so it is a detach and not a teardown; `present()`
243
+ * afterwards maps it again with no diagnostic at all; a second `set_visible(false)`
244
+ * is a no-op; and `destroy()` on the hidden window adds no `unmap` and DOES drop it
245
+ * from the toplevel list. `set_visible` rather than the deprecated `hide()`, which
246
+ * is the same call one rename older.
247
+ *
248
+ * Unbracketed, unlike `writeVisible`'s host writes: this is not bookkeeping around
249
+ * a libadwaita defect that the consumer's model never mentions — the window really
250
+ * did leave the screen, and a bound `notify::visible` is entitled to hear it.
251
+ */
252
+ export declare function detachToplevel(child: HostElement): void;
253
+ /**
254
+ * Place a node that does NOT go into its parent's child list, and say whether GTK took it.
255
+ *
256
+ * The ONE dispatch over the non-parented arms. Every caller in `host.ts` reaches
257
+ * the axis through this and its two twins below, so a fourth placement kind is
258
+ * three `never` arms away from compiling rather than a search through the host.
259
+ */
260
+ export declare function placeOutsideParent(parent: HostElement, child: HostElement, placement: OutsideParent): boolean;
261
+ /**
262
+ * The REVERSIBLE take-down — what `remove` means, per arm.
263
+ *
264
+ * THE TWO ARMS DIFFER HERE AND NOWHERE ELSE, which is why one function could not
265
+ * serve both: measured, `force_close()` followed by `present(parent)` re-hosts a
266
+ * dialog against the SAME parent with no diagnostic, while `destroy()` followed by
267
+ * `present()` is `Gtk-WARNING **: A window is shown after it has been destroyed`.
268
+ * The portal arm therefore never showed this defect and the toplevel arm shipped
269
+ * with it: a single `retractOutsideParent` treated a reversible verb and a terminal
270
+ * one as the same thing.
271
+ */
272
+ export declare function detachOutsideParent(child: HostElement, placement: OutsideParent): void;
273
+ /**
274
+ * The TERMINAL take-down — what `destroy` means, and what a DISCARD means.
275
+ *
276
+ * Its one caller is `releaseWidget` in `host.ts`, which is every place the host
277
+ * drops `el.widget`: a toplevel is held by GTK's own list rather than by a parent
278
+ * (measured, `list_toplevels()` holds a window from CONSTRUCTION and loses it only
279
+ * on `destroy`), so a discard that merely detached would leak one window each time
280
+ * — per construct-only write, and per half-built element a failed replay rolls back.
281
+ */
282
+ export declare function closeOutsideParent(child: HostElement, placement: OutsideParent): void;
283
+ /**
284
+ * The placement the installed libraries give this class, or null for an ordinary child.
285
+ *
286
+ * STRUCTURAL, never a name. ADR 0027 rule 1 forbids widget knowledge in the host,
287
+ * and a list of gtypes here would be exactly that — so the class is asked two
288
+ * questions it answers itself. Both were measured over the WHOLE shipped table on
289
+ * GTK 4.22.4 / libadwaita 1.9.3 rather than over a sample, which is what makes the
290
+ * second one a partition and not an observation:
291
+ *
292
+ * - `Gtk.Root` is GTK's OWN word for "this widget is a toplevel", and every class
293
+ * in the table implementing it — `GtkWindow` through `GtkPrintUnixDialog` — is
294
+ * one no parent may legally take.
295
+ * - A `present()` that TAKES AN ARGUMENT is a node presented AGAINST something.
296
+ * In the table that set is EXACTLY the `Adw.Dialog` descendants and nothing
297
+ * else — the ones whose `root` vfunc calls `g_error()`.
298
+ * `Gtk.Popover.present()` is the discriminator that makes the ARITY part of the
299
+ * question rather than the name: it exists, it takes 0 arguments, and a popover
300
+ * is parented with `set_parent()` like any other child.
301
+ *
302
+ * The order matters and is not alphabetical: every `Gtk.Root` in the table that has
303
+ * a `present` at all has a 0-argument one, and `GtkDragIcon` has none — so the root
304
+ * test has to come first and cannot be replaced by an arity test.
305
+ *
306
+ * @param gtype the class's GType — `type_is_a` walks interfaces as well as parents
307
+ * @param present the class's own `present`, or the value found on an instance
308
+ */
309
+ export declare function classPlacementKind(gtype: GObject.GType, present: unknown): OutsideParent['kind'] | null;
310
+ /** `classPlacementKind` for a live widget, which is what the insert path holds. */
311
+ export declare function nodePlacementKind(node: Gtk.Widget): OutsideParent['kind'] | null;
312
+ /**
313
+ * Refuse a child the installed libraries will not adopt, BEFORE the adder runs.
314
+ *
315
+ * This is the catchable half of the abort class (ADR 0054). `descriptorProblems()`
316
+ * says the same thing about the whole TABLE up front, which is what keeps the
317
+ * shipped rows honest — but `registerWidget` takes descriptors from applications
318
+ * and nothing checks those, and for one of the two families the consequence is not
319
+ * a wrong window: `adw_dialog_root()` is `g_error()`, so the process is gone before
320
+ * any handler runs. A refusal is only possible while there is still a process.
321
+ *
322
+ * ONLY WHERE THE DESCRIPTOR IS SILENT, and that is the escape hatch rather than an
323
+ * oversight. `placement` present — including an explicit `{ kind: 'parented' }` —
324
+ * means the author has answered this question, and the host does not overrule an
325
+ * answer with a heuristic. A consumer widget that trips the `present(parent)` half
326
+ * of the oracle while really being a child says so in one line.
327
+ */
328
+ export declare function refuseUnparentable(parent: HostElement, child: HostElement): void;
153
329
  export interface Placement {
154
330
  parent: HostElement;
155
331
  child: HostElement;
@@ -33,7 +33,7 @@
33
33
  */
34
34
  import type { Key, ReactElement, ReactNode, Ref } from 'react';
35
35
  import type { WidgetClassByTag, WidgetPropsByTag } from './generated/props.js';
36
- import type { RawSignalAttributes, SlotAttribute, WithOnce, WithPortableMenu } from './attrs.js';
36
+ import type { RawSignalAttributes, SlotAttribute, WithOnce, WithPortableValues } from './attrs.js';
37
37
  export { Fragment } from 'react/jsx-runtime';
38
38
  /**
39
39
  * React's own factories, RE-TYPED over this package's element list.
@@ -74,7 +74,7 @@ export interface ReactWidgetAttributes<T> extends SlotAttribute, RawSignalAttrib
74
74
  }
75
75
  /** Every GTK/Adwaita tag, with its properties, its handlers, its `ref` and its `key`. */
76
76
  export type GtkReactIntrinsicElements = {
77
- [K in keyof WidgetPropsByTag]: WithOnce<WithPortableMenu<WidgetPropsByTag[K]>> & ReactWidgetAttributes<WidgetClassByTag[K]>;
77
+ [K in keyof WidgetPropsByTag]: WithOnce<WithPortableValues<WidgetPropsByTag[K]>> & ReactWidgetAttributes<WidgetClassByTag[K]>;
78
78
  };
79
79
  export declare namespace JSX {
80
80
  /**
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ /** The refusal code `fn` raises, or what it did instead — so a wrong refusal reads as one. */
2
+ export declare function codeOf(fn: () => unknown): string;