@gjsify/gtk-host 0.47.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 (53) hide show
  1. package/README.md +158 -2
  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 -2
  5. package/lib/esm/conformance/tree.js +2 -0
  6. package/lib/esm/conformance/window-chrome.js +1 -0
  7. package/lib/esm/descriptors/adw.js +1 -1
  8. package/lib/esm/descriptors/gtk.js +1 -1
  9. package/lib/esm/descriptors/index.js +1 -1
  10. package/lib/esm/errors.js +1 -1
  11. package/lib/esm/font-families.js +1 -0
  12. package/lib/esm/fonts.js +1 -1
  13. package/lib/esm/host.js +1 -1
  14. package/lib/esm/index.js +1 -1
  15. package/lib/esm/list-model.js +1 -0
  16. package/lib/esm/menu.js +1 -0
  17. package/lib/esm/policies.js +1 -1
  18. package/lib/esm/probe.js +1 -1
  19. package/lib/esm/props.js +1 -1
  20. package/lib/esm/style/font-family.js +3 -0
  21. package/lib/esm/style/index.js +1 -1
  22. package/lib/esm/style/paint.js +1 -1
  23. package/lib/types/adjustment.d.ts +28 -0
  24. package/lib/types/adjustment.spec.d.ts +2 -0
  25. package/lib/types/attrs.d.ts +79 -0
  26. package/lib/types/conformance/index.d.ts +28 -29
  27. package/lib/types/conformance/tree.d.ts +30 -0
  28. package/lib/types/conformance/vectors.d.mts +6 -0
  29. package/lib/types/conformance/window-chrome.d.ts +29 -0
  30. package/lib/types/descriptors/gtk.d.ts +32 -1
  31. package/lib/types/errors.d.ts +43 -0
  32. package/lib/types/font-families.d.ts +40 -0
  33. package/lib/types/font-families.spec.d.ts +2 -0
  34. package/lib/types/fonts.d.ts +45 -1
  35. package/lib/types/generated/enum-values.d.mts +38 -0
  36. package/lib/types/generated/methods.d.mts +46 -0
  37. package/lib/types/index.d.ts +1 -1
  38. package/lib/types/jsx-runtime.d.ts +2 -2
  39. package/lib/types/list-model.d.ts +38 -0
  40. package/lib/types/list-model.spec.d.ts +2 -0
  41. package/lib/types/menu.d.ts +43 -0
  42. package/lib/types/menu.spec.d.ts +2 -0
  43. package/lib/types/placement.spec.d.ts +2 -0
  44. package/lib/types/policies.d.ts +241 -1
  45. package/lib/types/react-jsx-runtime.d.ts +2 -2
  46. package/lib/types/shared-trees.spec.d.ts +2 -0
  47. package/lib/types/style/font-family.d.ts +64 -0
  48. package/lib/types/style/index.d.ts +3 -1
  49. package/lib/types/style/paint.d.ts +37 -0
  50. package/lib/types/testing/refusal.d.mts +2 -0
  51. package/lib/types/types.d.ts +177 -1
  52. package/lib/types/vue-components.d.ts +2 -2
  53. package/package.json +8 -5
@@ -0,0 +1,28 @@
1
+ import Gtk from 'gi://Gtk?version=4.0';
2
+ import type { AdwAdjustment, AdwAdjustmentInput } from '@gjsify/adwaita-core';
3
+ /**
4
+ * A portable adjustment as a live `Gtk.Adjustment`.
5
+ *
6
+ * `value` is written LAST, and the core has clamped it before it gets here, so neither
7
+ * half of the two-clamp hazard applies: GTK's own `set_value` clamps against whatever
8
+ * range is installed at the moment the property is written, and the order
9
+ * `g_object_new` writes two properties in is not a contract. A value that is already
10
+ * inside the range survives either order.
11
+ */
12
+ export declare function buildAdjustment(input: AdwAdjustmentInput): Gtk.Adjustment;
13
+ /**
14
+ * Whether a value is a portable adjustment rather than a `Gtk.Adjustment`.
15
+ *
16
+ * A plain OBJECT: not null, not an array, not a GObject. A bare number is NOT one — the
17
+ * decision is ADR 0047 § 1's, and `coerce` refuses it by name rather than reading it as
18
+ * the value, because `value` is a property of its own on every widget that takes an
19
+ * adjustment and two spellings of one write is what the whole convergence removes.
20
+ */
21
+ export declare const isPortableAdjustment: (value: unknown) => value is AdwAdjustmentInput;
22
+ /**
23
+ * A `Gtk.Adjustment` back as the portable value — the inverse of {@link buildAdjustment}.
24
+ *
25
+ * Six numbers read off the real object, so `adjustment.spec.ts` can compare what GTK
26
+ * holds against what the core said it would, row for row.
27
+ */
28
+ export declare function fromAdjustment(adjustment: Gtk.Adjustment): AdwAdjustment;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -1,4 +1,7 @@
1
+ import type Gio from '@girs/gio-2.0';
1
2
  import type GObject from '@girs/gobject-2.0';
3
+ import type Gtk from '@girs/gtk-4.0';
4
+ import type { AdwAdjustmentInput, AdwListModelInput, AdwMenuInput } from '@gjsify/adwaita-core';
2
5
  import type { HostNode } from './types.js';
3
6
  /**
4
7
  * A `notify::` handler.
@@ -99,4 +102,80 @@ export interface JsxAttributes<T> extends SlotAttribute, RawSignalAttributes {
99
102
  */
100
103
  export interface VueAttributes extends SlotAttribute, RawSignalAttributes {
101
104
  }
105
+ /**
106
+ * The properties whose GObject type is a `GMenuModel`, in both spellings.
107
+ *
108
+ * A NAME LIST, not a type test, and the reason is measured rather than stylistic: the
109
+ * obvious `Gio.MenuModel extends NonNullable<T[K]> ? …` also matches every property
110
+ * typed as a wider GObject — `Gio.MenuModel extends GObject.Object` is TRUE — so the
111
+ * widening would leak onto properties that take an entirely different object. The three
112
+ * names below are the whole set on the shipped table (`menu-model` on the two menu
113
+ * buttons, the popover menu and the menu bar; `extra-menu` on the text widgets;
114
+ * `secondary-menu` on `AdwToolbarView`'s header bar), and `type-tests/` holds the
115
+ * widening against real markup in both dialects.
116
+ */
117
+ type MenuModelProp = 'menuModel' | 'menu-model' | 'extraMenu' | 'extra-menu' | 'secondaryMenu' | 'secondary-menu';
118
+ /**
119
+ * A props interface with every `GMenuModel` property widened to accept the PORTABLE
120
+ * menu model as well (ADR 0042).
121
+ *
122
+ * `Gio.MenuModel` is a GObject with no literal spelling, so before this a declarative
123
+ * dialect could not express a menu at all — the website gallery refused a Solid, Vue and
124
+ * React snippet for `Adw.SplitButton`, `Gtk.MenuButton` and `Gtk.PopoverMenu` for
125
+ * exactly that reason. The runtime half is `coerce`'s `GMenuModel` branch, which turns
126
+ * an authored array into a real `Gio.Menu` at the ParamSpec seam; this is the type that
127
+ * lets the array be written.
128
+ *
129
+ * A widget with NO such property is returned unchanged: `Omit` over a key it has not got
130
+ * is a no-op, and `MenuModelProp & keyof T` is then empty, so nothing is added either.
131
+ */
132
+ export type WithPortableMenu<T> = Omit<T, MenuModelProp> & {
133
+ [K in MenuModelProp & keyof T]?: T[K] | AdwMenuInput;
134
+ };
135
+ /** `A` and `B` are the SAME type — assignable both ways, tuple-wrapped so a union does not distribute. */
136
+ type Same<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
137
+ /**
138
+ * The property name a list model travels under, and it is deliberately NOT enough on
139
+ * its own: `model` is also `Gtk.ListView`'s `Gtk.SelectionModel`, `Gtk.TreeView`'s
140
+ * `Gtk.TreeModel` and `Gtk.ColumnView`'s selection. The name picks the candidates; the
141
+ * declared TYPE decides, exactly as the runtime branch keys on the ParamSpec.
142
+ */
143
+ type ListModelProp = 'model';
144
+ /**
145
+ * A props interface with every `Gio.ListModel`-typed `model` widened to accept the
146
+ * PORTABLE list model as well (ADR 0046 § Amendment).
147
+ *
148
+ * Widened only where the declared type IS `Gio.ListModel` — both directions, so a
149
+ * `Gtk.SelectionModel` (which extends it) stays as generated. `type-tests/` holds
150
+ * `<gtk-list-view model={[…]}>` as a compile error, and `coerce` refuses the same
151
+ * write by name at runtime (`list-model-mismatch`): one keying, two layers.
152
+ */
153
+ export type WithPortableList<T> = Omit<T, ListModelProp> & {
154
+ [K in ListModelProp & keyof T]?: Same<NonNullable<T[K]>, Gio.ListModel> extends true ? T[K] | AdwListModelInput : T[K];
155
+ };
156
+ /**
157
+ * The spellings an adjustment property has on the shipped table — `adjustment` on the
158
+ * widgets that hold one, `hadjustment`/`vadjustment` on `GtkScrollable` and
159
+ * `GtkScrolledWindow`. The name picks the candidates; the declared TYPE decides.
160
+ */
161
+ type AdjustmentProp = 'adjustment' | 'hadjustment' | 'vadjustment';
162
+ /**
163
+ * A props interface with every `Gtk.Adjustment`-typed property widened to accept the
164
+ * PORTABLE adjustment as well (ADR 0047 § Amendment).
165
+ *
166
+ * `AdwAdjustmentInput` is any SUBSET of the six numbers, so `{}` is legal (the shared
167
+ * defaults) and a bare number is not — ADR 0047 § 1's decision, held at compile time
168
+ * here and by name at runtime (`bad-adjustment`).
169
+ */
170
+ export type WithPortableAdjustment<T> = Omit<T, AdjustmentProp> & {
171
+ [K in AdjustmentProp & keyof T]?: Same<NonNullable<T[K]>, Gtk.Adjustment> extends true ? T[K] | AdwAdjustmentInput : T[K];
172
+ };
173
+ /**
174
+ * All three portable values on one props interface — what every dialect surface applies.
175
+ *
176
+ * One name so the three surfaces cannot each apply a different subset of the
177
+ * widenings: the menu was on all three, and the list and the adjustment join it here
178
+ * rather than in three files.
179
+ */
180
+ export type WithPortableValues<T> = WithPortableMenu<WithPortableList<WithPortableAdjustment<T>>>;
102
181
  export {};
@@ -1,8 +1,28 @@
1
1
  export { describeLogRecord, installDiagnosticsGate, isEnvironmentDiagnostic, type DiagnosticsGate, } from './diagnostics.js';
2
+ export { windowChromeCensus, windowChromeProblems, type WindowChromeCensus } from './window-chrome.js';
2
3
  import type Gtk from '@girs/gtk-4.0';
3
- import type { ChildPolicy, HostElement, WidgetDescriptor } from '../types.js';
4
+ import type { ChildPolicy, HostElement, NodePlacement, WidgetDescriptor } from '../types.js';
4
5
  /** Every method name a policy names, so the check does not have to know the shapes. */
5
6
  export declare function methodsOf(policy: ChildPolicy): string[];
7
+ /**
8
+ * Every method a PLACEMENT names — the second axis's answer to `methodsOf`.
9
+ *
10
+ * Separate from `methodsOf` rather than folded into it, because the two are
11
+ * checked against different things: a child policy's methods are called on the
12
+ * PARENT and a placement's on the NODE ITSELF, so a single list would make the
13
+ * message name the wrong object.
14
+ */
15
+ export declare function placementMethodsOf(placement: NodePlacement): string[];
16
+ /**
17
+ * How many arguments this placement's `present` must take, or null when it names none.
18
+ *
19
+ * THE ARITY IS THE DISCRIMINATOR between the two non-parented arms, measured on
20
+ * GTK 4.22.4 / libadwaita 1.9.3: `adw_dialog_present` takes 1 and
21
+ * `gtk_window_present` takes 0. A zero-argument `present` called with a widget
22
+ * ignores it silently and opens a window of its own; a one-argument one called
23
+ * with nothing has no host to reach. Both are exit 0, so the check is here.
24
+ */
25
+ export declare function presentArityOf(placement: NodePlacement): number | null;
6
26
  export interface DescriptorProblem {
7
27
  gtype: string;
8
28
  problem: string;
@@ -16,34 +36,13 @@ export interface DescriptorProblem {
16
36
  * the check runs up front and names the widget.
17
37
  */
18
38
  export declare function descriptorProblems(descriptors?: readonly WidgetDescriptor[]): DescriptorProblem[];
19
- /** Direct GTK children of a widget, in GTK's own order. */
20
- export declare function gtkChildren(widget: Gtk.Widget): Gtk.Widget[];
21
- /** GType names of a widget's direct children — the cheap shape assertion. */
22
- export declare const gtkChildTypes: (widget: Gtk.Widget) => string[];
23
- /** The addresses a host element's element-children occupy, in shadow order. */
24
- export declare function addressesOf(el: HostElement): Gtk.Widget[];
25
- /**
26
- * First STRICT descendant matching `pred`, breadth-first over the REAL GTK tree.
27
- *
28
- * Both showcase probes wrote this, identically. It excludes the root on purpose:
29
- * every caller is asking "what did the renderer put INSIDE this", and a root that
30
- * matches its own predicate answers a different question.
31
- *
32
- * Breadth-first is not incidental either — `findDescendant(root, w => w instanceof
33
- * Gtk.Box)` on an Adwaita window finds an INTERNAL box of the header bar before
34
- * anything the author wrote, which is why a probe that needs a specific widget
35
- * reaches it through a landmark (a button's `get_parent()`) rather than by type.
36
- * Measured: with a search-by-type version, authoring `orientation="horizontal"`
37
- * still printed PROBE: PASS with byte-identical output.
38
- */
39
- export declare function findDescendant(root: Gtk.Widget, pred: (widget: Gtk.Widget) => boolean): Gtk.Widget | null;
39
+ export { descendants, dumpTree, findDescendant, gtkChildTypes, gtkChildren } from './tree.js';
40
40
  /**
41
- * Every widget in a subtree, ROOT FIRST and depth-first — GTK's own document order.
41
+ * The addresses a host element's element-children occupy, in shadow order.
42
42
  *
43
- * Depth-first and not breadth-first, because the callers that collect (rather than
44
- * search) are asserting on ORDER: "the rows land before the counter row" is only a
45
- * claim about the tree if the walk visits it the way the tree reads.
43
+ * A NON-PARENTED child occupies none — a portal is presented against this element
44
+ * and lives under the toplevel's dialog host, a toplevel is its own root — so
45
+ * including either would make every vector that compares this against the real
46
+ * child list disagree by a node that is not there.
46
47
  */
47
- export declare function descendants(root: Gtk.Widget): Gtk.Widget[];
48
- /** Recursive GType dump — what a devtools tree walk would show. */
49
- export declare function dumpTree(widget: Gtk.Widget, depth?: number): string;
48
+ export declare function addressesOf(el: HostElement): Gtk.Widget[];
@@ -0,0 +1,30 @@
1
+ import type Gtk from '@girs/gtk-4.0';
2
+ /** Direct GTK children of a widget, in GTK's own order. */
3
+ export declare function gtkChildren(widget: Gtk.Widget): Gtk.Widget[];
4
+ /** GType names of a widget's direct children — the cheap shape assertion. */
5
+ export declare const gtkChildTypes: (widget: Gtk.Widget) => string[];
6
+ /**
7
+ * First STRICT descendant matching `pred`, breadth-first over the REAL GTK tree.
8
+ *
9
+ * Both showcase probes wrote this, identically. It excludes the root on purpose:
10
+ * every caller is asking "what did the renderer put INSIDE this", and a root that
11
+ * matches its own predicate answers a different question.
12
+ *
13
+ * Breadth-first is not incidental either — `findDescendant(root, w => w instanceof
14
+ * Gtk.Box)` on an Adwaita window finds an INTERNAL box of the header bar before
15
+ * anything the author wrote, which is why a probe that needs a specific widget
16
+ * reaches it through a landmark (a button's `get_parent()`) rather than by type.
17
+ * Measured: with a search-by-type version, authoring `orientation="horizontal"`
18
+ * still printed PROBE: PASS with byte-identical output.
19
+ */
20
+ export declare function findDescendant(root: Gtk.Widget, pred: (widget: Gtk.Widget) => boolean): Gtk.Widget | null;
21
+ /**
22
+ * Every widget in a subtree, ROOT FIRST and depth-first — GTK's own document order.
23
+ *
24
+ * Depth-first and not breadth-first, because the callers that collect (rather than
25
+ * search) are asserting on ORDER: "the rows land before the counter row" is only a
26
+ * claim about the tree if the walk visits it the way the tree reads.
27
+ */
28
+ export declare function descendants(root: Gtk.Widget): Gtk.Widget[];
29
+ /** Recursive GType dump — what a devtools tree walk would show. */
30
+ export declare function dumpTree(widget: Gtk.Widget, depth?: number): string;
@@ -30,5 +30,11 @@ export interface VectorHarness {
30
30
  * `gated` rather than a bare `describe`: `@gjsify/unit` keeps ONE
31
31
  * `beforeEach`/`afterEach` slot per module and nulls both when a describe returns,
32
32
  * so hooks registered outside the block cover exactly one sibling.
33
+ *
34
+ * CORRECTED 2026-09-04 (#1554): hooks are SCOPED now — one frame per `describe`,
35
+ * popped when it returns — so hooks registered outside the block cover every
36
+ * sibling, and two registrations in one scope both run. `gated` stays because it
37
+ * keeps one declaration of what a gated block means, not because the runner
38
+ * forgets.
33
39
  */
34
40
  export declare function runAdapterVectors(harness: VectorHarness, gate: DiagnosticsGate): Promise<void>;
@@ -0,0 +1,29 @@
1
+ import Gtk from 'gi://Gtk?version=4.0';
2
+ /** What a window's chrome actually draws, per side of the decoration layout. */
3
+ export interface WindowChromeCensus {
4
+ /** Mapped, non-empty `GtkWindowControls` packed at the start of their header bar. */
5
+ readonly start: number;
6
+ /** The same at the end. On a GNOME host with a `:close` layout this is the close button. */
7
+ readonly end: number;
8
+ /** Mapped header bars, for the report. NOT the invariant — see the header. */
9
+ readonly headerBars: number;
10
+ /** Whether the root is mapped at all, i.e. whether the three counts mean anything. */
11
+ readonly mapped: boolean;
12
+ }
13
+ /**
14
+ * Count what the window's chrome draws.
15
+ *
16
+ * `get_empty()` is asked as well as `get_mapped()` because a `GtkWindowControls` is
17
+ * mapped on both sides of every header bar and draws buttons only on the side the
18
+ * decoration layout puts them: measured, a GNOME `:close` layout leaves six of the
19
+ * eight controls in a three-bar window empty and invisible.
20
+ */
21
+ export declare function windowChromeCensus(root: Gtk.Widget): WindowChromeCensus;
22
+ /**
23
+ * Every way this window's chrome is wrong, in sentences.
24
+ *
25
+ * An empty array is the only clean answer, and it is not reachable by accident: an
26
+ * unmapped root and a window whose chrome draws nothing at all are both named, so
27
+ * "no duplicates" cannot be produced by a tree that draws no chrome to duplicate.
28
+ */
29
+ export declare function windowChromeProblems(root: Gtk.Widget): string[];
@@ -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[];
@@ -19,6 +19,22 @@ export declare const err: {
19
19
  missingConstructProp: (tag: string, prop: string) => GtkHostError;
20
20
  unknownProp: (tag: string, prop: string) => GtkHostError;
21
21
  readOnlyProp: (tag: string, prop: string) => GtkHostError;
22
+ noAccessor: (tag: string, prop: string, accessor: string) => GtkHostError;
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;
22
38
  badEnum: (tag: string, prop: string, nick: string, gtypeName: string) => GtkHostError;
23
39
  unknownSignal: (tag: string, prop: string, signal: string) => GtkHostError;
24
40
  signalTaken: (tag: string, prop: string, other: string, signal: string) => GtkHostError;
@@ -58,6 +74,33 @@ export declare const err: {
58
74
  siblingCycle: (parentTag: string) => GtkHostError;
59
75
  notAWidget: (tag: string) => GtkHostError;
60
76
  occupiedSlot: (parentTag: string, childTag: string, setter: string) => GtkHostError;
77
+ /**
78
+ * A placement naming a method the installed class does not have.
79
+ *
80
+ * `descriptorProblems()` rejects this shape up front, so a BUILT-IN descriptor
81
+ * can never reach here — an application-registered one is checked by nobody,
82
+ * and the alternative is `TypeError: widget[placement.present] is not a
83
+ * function` thrown from inside an insert, naming neither the tag nor the axis.
84
+ */
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;
61
104
  notAnElement: (kind: string) => GtkHostError;
62
105
  destroyedNode: (tag: string) => GtkHostError;
63
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>>;
@@ -1,7 +1,7 @@
1
1
  export * from './types.js';
2
2
  export { GtkHostError } from './errors.js';
3
3
  export { adopt, createAnchor, createDetachedContainer, createElement, createText, destroyChildren, destroy, disconnectHandlers, firstChild, insert, isHostElement, isText, materialize, mountRoot, nextSibling, parentNode, prevSibling, remove, setElementText, setEventHandler, setProp, setSlot, setText, widgetOf, } from './host.js';
4
- export { addressOf, reorderMode } from './policies.js';
4
+ export { addressOf, isPortal, placementOf, portalOf, reorderMode } from './policies.js';
5
5
  export { toSignalName, isEventProp } from './signals.js';
6
6
  export { constructOnlyNames, isConstructOnly, isWritable, lookupEnumNick, paramSpecs, toPropertyName, } from './props.js';
7
7
  export { assertInjective, tagOf } from './tags.js';
@@ -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 } 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<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;