@gjsify/adwaita-core 0.64.13 → 0.64.15-next.287

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.
@@ -1,46 +1,338 @@
1
- import type { AdwMenuEntryInput, AdwMenuItemInput } from './menu.js';
1
+ import { Variant } from './glib-variant.js';
2
+ import { GIR_TYPE, GObjectObject } from './gobject.js';
3
+ import type { GType } from './gobject.js';
4
+ import type { AdwMenuInput, AdwMenuTree } from './menu.js';
5
+ /** `G_MENU_ATTRIBUTE_ACTION`. */
6
+ export declare const MENU_ATTRIBUTE_ACTION = "action";
7
+ /** `G_MENU_ATTRIBUTE_ACTION_NAMESPACE` — carried, and never interpreted by the port. */
8
+ export declare const MENU_ATTRIBUTE_ACTION_NAMESPACE = "action-namespace";
9
+ /** `G_MENU_ATTRIBUTE_ICON`. The NAME is shared with GIO even where the type diverges. */
10
+ export declare const MENU_ATTRIBUTE_ICON = "icon";
11
+ /** `G_MENU_ATTRIBUTE_LABEL`. */
12
+ export declare const MENU_ATTRIBUTE_LABEL = "label";
13
+ /** `G_MENU_ATTRIBUTE_TARGET` — the one attribute whose variant type varies by target. */
14
+ export declare const MENU_ATTRIBUTE_TARGET = "target";
15
+ /** `G_MENU_LINK_SECTION`. */
16
+ export declare const MENU_LINK_SECTION = "section";
17
+ /** `G_MENU_LINK_SUBMENU`. */
18
+ export declare const MENU_LINK_SUBMENU = "submenu";
2
19
  /**
3
- * One menu item, built the way `g_menu_item_new` builds one.
20
+ * `G_MENU_EXPORTER_MAX_SECTION_SIZE`.
4
21
  *
5
- * IT IS ITSELF A PORTABLE ENTRY — `implements AdwMenuItemInput` — so `append_item` pushes
6
- * the instance and `normalizeMenuModel` reads its fields like any authored object. A
7
- * separate internal shape would need a conversion the model does not ask for.
22
+ * Nothing in the port enforces it and nothing should — it is a D-Bus exporter limit. It is
23
+ * exported so a caller reading it is handed the real number rather than `undefined`, which
24
+ * is the failure mode of a port that exports only the constants it happens to use itself.
25
+ */
26
+ export declare const MENU_EXPORTER_MAX_SECTION_SIZE = 1000;
27
+ /**
28
+ * One menu item, as `g_menu_item_new` builds one.
8
29
  *
9
- * Both halves are nullable, as they are in C: `g_menu_item_new(NULL, NULL)` is legal and
10
- * produces an item carrying neither, which {@link normalizeMenuModel} drops rather than
11
- * drawing an empty, unactionable row.
30
+ * IT IS A SNAPSHOT, and that is the measured fact a reader coming from the old `Array`
31
+ * version gets wrong: appending an item COPIES what it carries, so a later `set_label` on
32
+ * the same object does not reach the menu (`MENU_MODEL_DIVERGENCE_VECTORS`,
33
+ * `item-is-a-snapshot`). It is a builder for one position, not a view onto it.
34
+ *
35
+ * Both halves of the constructor are nullable, as they are in C: `g_menu_item_new(NULL,
36
+ * NULL)` is legal and produces an item carrying neither attribute.
12
37
  */
13
- export declare class GioMenuItem implements AdwMenuItemInput {
14
- /** The user-visible string; ABSENT rather than `undefined` when the item has none. */
15
- label?: string;
16
- /** The DETAILED action name — `app.save-as`, `app.view::list` (ADR 0042 § divergence 2). */
17
- action?: string;
38
+ export declare class GioMenuItem extends GObjectObject {
39
+ static [GIR_TYPE]: string;
18
40
  constructor(label?: string | null, detailedAction?: string | null);
41
+ /** `g_menu_item_new_section` — an item whose whole content is the `section` link. */
42
+ static new_section(label: string | null, section: GioMenuModel): GioMenuItem;
43
+ /** `g_menu_item_new_submenu`. */
44
+ static new_submenu(label: string | null, submenu: GioMenuModel): GioMenuItem;
45
+ /**
46
+ * `g_menu_item_new_from_model` — a COPY of what the model holds at `itemIndex`.
47
+ *
48
+ * The copy is the point: this is how an item is edited at all, since a position is not
49
+ * addressable and {@link GioMenu.remove} plus an insert is the only way back in.
50
+ */
51
+ static new_from_model(model: GioMenuModel, itemIndex: number): GioMenuItem;
19
52
  /** `g_menu_item_set_label`. `null` REMOVES the attribute, which is what C does. */
20
53
  set_label(label: string | null): void;
21
- /** `g_menu_item_set_detailed_action`, and `null` is `g_menu_item_set_action_and_target(…, NULL)`. */
54
+ /**
55
+ * `g_menu_item_set_detailed_action` — the action NAME and its target, parsed apart.
56
+ *
57
+ * The parse is why the model carries one string: `app.view::list` becomes `action` plus
58
+ * a `target` of the target's own type, and {@link printDetailedName} puts it back
59
+ * together. A malformed name is REFUSED here rather than stored — see
60
+ * {@link parseDetailedName} for why that is the twin's own decision and not GIO's.
61
+ */
22
62
  set_detailed_action(detailedAction: string | null): void;
63
+ /** `g_menu_item_set_action_and_target_value`; a `null` action removes the target too. */
64
+ set_action_and_target_value(action: string | null, target: Variant | null): void;
65
+ /**
66
+ * `g_menu_item_set_attribute_value`. `null` is a DELETE, never a stored empty value.
67
+ *
68
+ * A bare JS string is refused in GJS's own words (measured): the convenience of passing
69
+ * text belongs to `g_menu_item_set_attribute`, which is varargs and therefore not part
70
+ * of the surface a port owes.
71
+ */
72
+ set_attribute_value(name: string, value: Variant | null): void;
73
+ /** `g_menu_item_get_attribute_value` — see {@link GioMenuModel.get_item_attribute_value}. */
74
+ get_attribute_value(name: string, expectedType?: string | null): Variant | null;
75
+ /** `g_menu_item_set_link`. `null` removes it; any link name is legal, as in C. */
76
+ set_link(name: string, model: GioMenuModel | null): void;
77
+ /** `g_menu_item_get_link` — the INSTANCE, not a copy. */
78
+ get_link(name: string): GioMenuModel | null;
79
+ /** `g_menu_item_set_section`. */
80
+ set_section(section: GioMenuModel | null): void;
81
+ /** `g_menu_item_set_submenu`. */
82
+ set_submenu(submenu: GioMenuModel | null): void;
83
+ }
84
+ /**
85
+ * `Gio.MenuAttributeIter` — the attributes of one item, in insertion order.
86
+ *
87
+ * `next()` BEFORE the first read, as in C: an iterator starts before the beginning, so a
88
+ * loop is `while (iter.next())` and `get_name()` is only valid inside it. Only the
89
+ * attributes actually SET are yielded (measured: a section item carrying a heading yields
90
+ * `label` alone, not both link names with one empty).
91
+ */
92
+ export declare class GioMenuAttributeIter extends GObjectObject {
93
+ static [GIR_TYPE]: string;
94
+ constructor(entries?: ReadonlyArray<readonly [string, Variant]>);
95
+ /** `g_menu_attribute_iter_next`. */
96
+ next(): boolean;
97
+ /** `g_menu_attribute_iter_get_name` — `null` outside a successful `next()`. */
98
+ get_name(): string | null;
99
+ /** `g_menu_attribute_iter_get_value`. */
100
+ get_value(): Variant | null;
101
+ /** `g_menu_attribute_iter_get_next` — the three out-arguments GJS returns as a tuple. */
102
+ get_next(): [boolean, string | null, Variant | null];
103
+ }
104
+ /** `Gio.MenuLinkIter` — the same walk over an item's links, and the value is a MODEL. */
105
+ export declare class GioMenuLinkIter extends GObjectObject {
106
+ static [GIR_TYPE]: string;
107
+ constructor(entries?: ReadonlyArray<readonly [string, GioMenuModel]>);
108
+ /** `g_menu_link_iter_next`. */
109
+ next(): boolean;
110
+ /** `g_menu_link_iter_get_name`. */
111
+ get_name(): string | null;
112
+ /** `g_menu_link_iter_get_value` — the linked model itself. */
113
+ get_value(): GioMenuModel | null;
114
+ /** `g_menu_link_iter_get_next`. */
115
+ get_next(): [boolean, string | null, GioMenuModel | null];
116
+ }
117
+ /**
118
+ * `Gio.MenuModel` — what a `menu-model` property takes, and it cannot be constructed.
119
+ *
120
+ * `new Gio.MenuModel()` throws `Cannot instantiate abstract type GMenuModel` (measured), so
121
+ * this constructor refuses too: a base a caller can instantiate is a type GTK does not have,
122
+ * and a widget door accepting one would accept a model with no items and no way to get any.
123
+ *
124
+ * THE READS DELEGATE TO VFUNCS, as they do in C — `g_menu_model_get_n_items` calls
125
+ * `GMenuModelClass->get_n_items`. {@link GioMenu} is the only subclass the port ships, but a
126
+ * CALLER's subclass is the reason the indirection is here: a model backed by something else
127
+ * overrides `vfunc_get_n_items` and the public reads, `menuTree` and every renderer follow it.
128
+ *
129
+ * `items-changed` is declared HERE and inherited, which is where it is in GTK —
130
+ * `GObject.signal_lookup('items-changed', Gio.MenuModel.$gtype)` is non-zero (measured), and
131
+ * `findSignal` walks the static chain, so a `GioMenu` instance resolves it from this class.
132
+ */
133
+ export declare abstract class GioMenuModel extends GObjectObject {
134
+ static [GIR_TYPE]: string;
135
+ /**
136
+ * `Gio.MenuModel.$gtype` — installed by the `registerBaseClass` below, declared here so a
137
+ * caller can NAME the type. It is the `valueType` a widget declaring a `menu-model` property
138
+ * passes (`ForeignObjectProperty`), which is why this one needs a type where the other
139
+ * registered base classes do not: `Gtk.FileFilter.$gtype` is declared for the same reason,
140
+ * a `Gio.ListStore`'s `item_type`.
141
+ */
142
+ static readonly $gtype: GType;
143
+ constructor();
144
+ /** `g_menu_model_is_mutable`. */
145
+ is_mutable(): boolean;
146
+ /** `g_menu_model_get_n_items`. */
147
+ get_n_items(): number;
148
+ /**
149
+ * `g_menu_model_get_item_attribute_value`.
150
+ *
151
+ * `expectedType` is a type STRING and not a `GLib.VariantType`, which the variant subset
152
+ * does not have (`MENU_MODEL_DIVERGENCE_VECTORS`, `variant-type-is-a-string`). A
153
+ * mismatch answers `null` rather than converting or throwing, as GIO does.
154
+ */
155
+ get_item_attribute_value(itemIndex: number, attribute: string, expectedType?: string | null): Variant | null;
156
+ /** `g_menu_model_get_item_link` — the linked model INSTANCE, or `null`. */
157
+ get_item_link(itemIndex: number, link: string): GioMenuModel | null;
158
+ /** `g_menu_model_iterate_item_attributes`. */
159
+ iterate_item_attributes(itemIndex: number): GioMenuAttributeIter;
160
+ /** `g_menu_model_iterate_item_links`. */
161
+ iterate_item_links(itemIndex: number): GioMenuLinkIter;
162
+ /**
163
+ * `g_menu_model_items_changed` — PUBLIC, and it changes nothing.
164
+ *
165
+ * Measured: `model.items_changed(3, 2, 1)` emits that triple and leaves the count alone,
166
+ * because it is how a SUBCLASS reports a splice it made in its own storage. A lying triple
167
+ * is not policed, here or in GIO.
168
+ */
169
+ items_changed(position: number, removed: number, added: number): void;
170
+ /** `GMenuModelClass->is_mutable`; a model is immutable unless it says otherwise. */
171
+ vfunc_is_mutable(): boolean;
172
+ abstract vfunc_get_n_items(): number;
173
+ abstract vfunc_get_item_attribute_value(itemIndex: number, attribute: string, expectedType: string | null): Variant | null;
174
+ abstract vfunc_get_item_link(itemIndex: number, link: string): GioMenuModel | null;
175
+ abstract vfunc_iterate_item_attributes(itemIndex: number): GioMenuAttributeIter;
176
+ abstract vfunc_iterate_item_links(itemIndex: number): GioMenuLinkIter;
23
177
  }
24
178
  /**
25
- * A menu under construction — `Gio.Menu`'s four append entry points over the portable model.
179
+ * `Gio.Menu` — a mutable `Gio.MenuModel`, and what every menu in the port is.
180
+ *
181
+ * ONE `items-changed` PER MUTATOR, with the triple each one emits held by
182
+ * `MENU_MUTATOR_EMISSION_VECTORS`. The row that separates this from `Gtk.StringList`:
183
+ * `remove_all()` on an EMPTY menu STILL emits `(0, 0, 0)` (measured), so the no-op skip ADR
184
+ * 0122 § 3 is right about for a list store is wrong here, and neither {@link remove_all} nor
185
+ * {@link insertEntry} has one.
26
186
  *
27
- * `new GioMenu()` is empty, as `g_menu_new()` is. Every `append*` puts one entry on the end,
28
- * and the instance IS the value a `menuModel` property takes.
187
+ * An item is COPIED IN. `append_item(item)` takes what the item carries at that moment and a
188
+ * later `set_label` on the same object reaches nothing — see {@link GioMenuItem}.
29
189
  */
30
- export declare class GioMenu extends Array<AdwMenuEntryInput> {
31
- /** `g_menu_append` — the convenience C implements as `menu_item_new` + `append_item`. */
190
+ export declare class GioMenu extends GioMenuModel {
191
+ static [GIR_TYPE]: string;
192
+ constructor();
193
+ /** `g_menu_new`. */
194
+ static new(): GioMenu;
195
+ /** `g_menu_insert` — a plain item at `position`. */
196
+ insert(position: number, label: string | null, detailedAction?: string | null): void;
197
+ /** `g_menu_append`. */
32
198
  append(label: string | null, detailedAction?: string | null): void;
199
+ /** `g_menu_prepend`. */
200
+ prepend(label: string | null, detailedAction?: string | null): void;
201
+ /** `g_menu_insert_item` — the item's attributes and links, copied. */
202
+ insert_item(position: number, item: GioMenuItem): void;
33
203
  /** `g_menu_append_item`. */
34
204
  append_item(item: GioMenuItem): void;
205
+ /** `g_menu_prepend_item`. */
206
+ prepend_item(item: GioMenuItem): void;
207
+ /** `g_menu_insert_section` — ONE item of this menu, however many the section holds. */
208
+ insert_section(position: number, label: string | null, section: GioMenuModel): void;
209
+ /** `g_menu_append_section`. */
210
+ append_section(label: string | null, section: GioMenuModel): void;
211
+ /** `g_menu_prepend_section`. */
212
+ prepend_section(label: string | null, section: GioMenuModel): void;
213
+ /** `g_menu_insert_submenu`. */
214
+ insert_submenu(position: number, label: string | null, submenu: GioMenuModel): void;
215
+ /** `g_menu_append_submenu`. */
216
+ append_submenu(label: string | null, submenu: GioMenuModel): void;
217
+ /** `g_menu_prepend_submenu`. */
218
+ prepend_submenu(label: string | null, submenu: GioMenuModel): void;
219
+ /** `g_menu_remove` — one item, reported where it was. */
220
+ remove(position: number): void;
221
+ /**
222
+ * `g_menu_remove_all`.
223
+ *
224
+ * It emits on an EMPTY menu too — `(0, 0, 0)`, measured. A renderer may therefore drop
225
+ * every row it holds on this one emission without reading the count first.
226
+ */
227
+ remove_all(): void;
228
+ /**
229
+ * `g_menu_freeze` — a FLAG, not a lock.
230
+ *
231
+ * Measured both ways: `is_mutable()` flips to false and the mutators keep working, so a
232
+ * twin that refused a post-freeze append would break a caller GIO lets through
233
+ * (`MENU_MODEL_DIVERGENCE_VECTORS`, `freeze-does-not-lock`).
234
+ */
235
+ freeze(): void;
236
+ vfunc_is_mutable(): boolean;
237
+ vfunc_get_n_items(): number;
238
+ vfunc_get_item_attribute_value(itemIndex: number, attribute: string, expectedType: string | null): Variant | null;
239
+ vfunc_get_item_link(itemIndex: number, link: string): GioMenuModel | null;
240
+ vfunc_iterate_item_attributes(itemIndex: number): GioMenuAttributeIter;
241
+ vfunc_iterate_item_links(itemIndex: number): GioMenuLinkIter;
242
+ /** The one insert, so the emission rule is written once. Out of range clamps, as C does. */
243
+ private insertEntry;
244
+ }
245
+ /**
246
+ * An authored or normalised menu TREE as a live {@link GioMenu} — the one-way street.
247
+ *
248
+ * It takes the AUTHORED form as well as the normalised one because `normalizeMenuModel` is
249
+ * idempotent, so a JSX attribute needs no conversion step of its own. This is the only way
250
+ * an array becomes a model now that `menuModel` refuses one: ADR 0128 § 4 closed the door
251
+ * and this is the door's replacement, named so a caller can find it.
252
+ */
253
+ export declare function buildMenu(input: AdwMenuInput | AdwMenuTree): GioMenu;
254
+ /**
255
+ * A `Gio.MenuModel` as a portable TREE — the inverse of {@link buildMenu}.
256
+ *
257
+ * THIS IS THE ONE BRIDGE every renderer crosses, and it crosses it ONCE PER RENDER. The
258
+ * tree walkers (`menuNodeAt`, `flattenMenu`, `menuRefusals`, `assertMenuRenderable`) all take
259
+ * an `AdwMenuTree` rather than a model, because a walker reading through the model would make
260
+ * every path lookup a chain of `get_item_link` calls and every renderer's loop a different
261
+ * number of them. One snapshot, then plain data.
262
+ *
263
+ * IT IS A DEEP SNAPSHOT, which is the measured behaviour and not a convenience: an item read
264
+ * out of a `Gio.Menu` is a copy (`MENU_MODEL_DIVERGENCE_VECTORS`, `item-is-a-snapshot`), so a
265
+ * tree that aliased the model would promise a sharing GIO does not do. A mutation arrives
266
+ * through `items-changed` and the renderer takes a new snapshot — see {@link watchMenuModel}.
267
+ *
268
+ * It reads what GTK reads plus `id`, so an application's own extra attributes do not survive
269
+ * the trip. Stated rather than implied: this is the inverse of the builder above, not a
270
+ * general `GMenuModel` serialiser. Both edges a hand-built menu can reach are GTK's own: an
271
+ * item carrying BOTH links reads as a SECTION (`gtkmenutracker.c:317-352` decides the same
272
+ * way), and a non-string `label` reads as `''` (so does `g_menu_item_get_attribute(…, "&s")`).
273
+ */
274
+ export declare function menuTree(model: GioMenuModel): AdwMenuTree;
275
+ /**
276
+ * Connect `handler` to `model` and to every model it LINKS TO, recursively.
277
+ *
278
+ * THIS IS WHY IT EXISTS: a section's own `items-changed` does NOT bubble to the menu holding
279
+ * it (measured — `MENU_LINK_VECTORS`, `link-emission-does-not-bubble`), while the link read
280
+ * reflects the change at once. A renderer connected to the root alone therefore shows a stale
281
+ * section for ever. The defect was unreachable while a menu was an array, because every
282
+ * mutation went through a re-parse of the whole tree; it arrives WITH the real model, so the
283
+ * watcher arrives with it.
284
+ *
285
+ * The returned function disconnects every handler it made. It is RE-RUN on each emission by
286
+ * its caller — a renderer calls `watchMenuModel` again after it re-snapshots — because a
287
+ * mutation can add a link that was not there to connect to.
288
+ */
289
+ export declare function watchMenuModel(model: GioMenuModel, handler: () => void): () => void;
290
+ /**
291
+ * The menu a SURFACE owns, so an authored `menuModel` attribute keeps its identity.
292
+ *
293
+ * ONE instance per element, re-parsed INTO rather than replaced: a `menu-model` write notifies
294
+ * and rebuilds the popover, while an edit to the same `menu='[…]'` attribute is a content
295
+ * change the popover already open should follow. Mirrors `GjsifyOptionList` (ADR 0122 § 5),
296
+ * and it is the same reason — the authored door is the one place the port, not GIO, decides.
297
+ */
298
+ export declare class GjsifyMenu extends GioMenu {
35
299
  /**
36
- * `g_menu_append_section` — the `section` LINK, whose items are drawn inline with a
37
- * separator rather than behind a further click.
300
+ * Replace the contents with `next` IN PLACE, keeping this menu's identity.
38
301
  *
39
- * The label is optional in C and stays optional here: a section with none is a plain
40
- * group, and writing `label: null` onto the entry would be an attribute the model
41
- * then has to ignore.
302
+ * EQUAL CONTENT EMITS NOTHING, so re-rendering an unchanged attribute does not reopen a
303
+ * popover; anything else is ONE `items-changed(0, old, new)`. Not the minimal splice
304
+ * `GjsifyOptionList` computes: a menu is a TREE, so "the one splice that turns one into
305
+ * the other" is not a position and a length, and a renderer re-snapshots the whole tree
306
+ * on any emission anyway ({@link menuTree}).
42
307
  */
43
- append_section(label: string | null, section: readonly AdwMenuEntryInput[]): void;
44
- /** `g_menu_append_submenu` — the `submenu` LINK: a nested menu the user opens. */
45
- append_submenu(label: string | null, submenu: readonly AdwMenuEntryInput[]): void;
308
+ reconcile(next: AdwMenuInput | AdwMenuTree | null | undefined): void;
46
309
  }
310
+ /**
311
+ * What a write to a `menu-model` property reads as — the ONE door, for all four surfaces.
312
+ *
313
+ * ADR 0128 § 4 makes `menu-model` an object property over `Gio.MenuModel` and § 7 leaves the
314
+ * JSON markup attribute open, so every `menuModel` setter in this repository has the same
315
+ * four-way answer to give. It is written here once because it was about to be written fifteen
316
+ * times, and it mirrors `readModelWrite` (`option-list.ts`) deliberately — the two doors
317
+ * answer the same question about two different models, and a reader who knows one knows this.
318
+ *
319
+ * - `null` / `undefined` is the "no menu" write, which clears the popover;
320
+ * - a STRING is the markup attribute, parsed and reconciled into `authored` — the surface's
321
+ * OWN menu, whose identity survives the edit;
322
+ * - a real model is handed through by IDENTITY, so `widget.menuModel === model` holds as it
323
+ * is measured to in libadwaita;
324
+ * - anything else, an ARRAY above all, is a `TypeError`.
325
+ *
326
+ * THE DUCK TEST, and not `instanceof` alone, because a REAL `Gio.Menu` reached through node-gi
327
+ * (ADR 0104) is no registered class of this subset — and handing one to `Gtk.MenuButton`
328
+ * is the whole point of having the property.
329
+ *
330
+ * THE TYPE REFUSAL IS THE PORT'S OWN, which is the one place this door is wider than
331
+ * `checkPropertyValue`. A `TYPE_OBJECT` spec catches a non-object and an unregistered object,
332
+ * and that is all it can catch: `G_TYPE_OBJECT` accepts ANY GObject, so a registered
333
+ * `Gtk.StringList` passes the value check and still cannot be a menu. GJS raises
334
+ * `Object is of type … - cannot convert to GMenuModel` at the GValue conversion that follows
335
+ * (measured with a `Gtk.Label`); the subset has no such conversion, so the message is raised
336
+ * here, with the GType found by walking the constructor chain.
337
+ */
338
+ export declare function readMenuModelWrite(value: unknown, authored: GjsifyMenu): GioMenuModel | null;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -97,14 +97,14 @@ export { ADW_SWIPE_BORDER, DEFAULT_MAX_SIDEBAR_WIDTH, DEFAULT_MIN_SIDEBAR_WIDTH,
97
97
  export type { AdwPackType, AdwTextDirection, NavigationActionInput, NavigationActionResult, NavigationPageRef, NavigationSplitViewChange, NavigationSplitViewHandlers, NavigationSplitViewLayout, NavigationSplitViewListener, NavigationSplitViewOptions, NavigationSplitViewProperty, NavigationStackPlan, OverlaySplitViewChange, OverlaySplitViewLayout, OverlaySplitViewListener, OverlaySplitViewOptions, OverlaySplitViewProperty, SidebarBounds, SidebarWidthInput, SidebarWidthSpec, SplitViewAnimation, SplitViewAnimationRequest, SplitViewAnimator, SplitViewMeasureInput, SplitViewPane, SplitViewPaneRect, SwipeReleasePlan, } from './split-view.js';
98
98
  export { DEFAULT_DROPDOWN_TOOLTIP, SPLIT_BUTTON_DISABLED_OPACITY, SplitButtonState, isSplitButtonDirection, menuButtonArrowIcon, menuButtonPopupDirection, resolveDropdownTooltip, splitButtonArrowIcon, splitButtonPopupDirection, splitButtonRootState, splitButtonStyleClasses, } from './split-button.js';
99
99
  export type { AdwArrowIcon, SplitButtonChange, SplitButtonContentMode, SplitButtonDirection, SplitButtonHalfState, SplitButtonListener, SplitButtonProperty, SplitButtonStyleClass, } from './split-button.js';
100
- export { GioMenu, GioMenuItem } from './gio-menu.js';
100
+ export { GioMenu, GioMenuAttributeIter, GioMenuItem, GioMenuLinkIter, GioMenuModel, GjsifyMenu, MENU_ATTRIBUTE_ACTION, MENU_ATTRIBUTE_ACTION_NAMESPACE, MENU_ATTRIBUTE_ICON, MENU_ATTRIBUTE_LABEL, MENU_ATTRIBUTE_TARGET, MENU_EXPORTER_MAX_SECTION_SIZE, MENU_LINK_SECTION, MENU_LINK_SUBMENU, buildMenu, menuTree, readMenuModelWrite, watchMenuModel, } from './gio-menu.js';
101
101
  export { activateMenuItem, menuActionsFor } from './menu-actions.js';
102
102
  export { assertPopupMenuPlan, planPopupMenu } from './popup-menu-plan.js';
103
103
  export type { PopupMenuEntryPlan, PopupMenuGroupPlan, PopupMenuItemPlan, PopupMenuLevelPlan, PopupMenuPlan, PopupMenuRefusal, PopupMenuSubmenuPlan, } from './popup-menu-plan.js';
104
104
  export { menuAssignments } from './menu-tree.js';
105
105
  export type { MenuTreeNode } from './menu-tree.js';
106
106
  export { ADW_MENU_SURFACE_NATIVESCRIPT, ADW_MENU_SURFACE_WEB, assertMenuRenderable, flattenMenu, menuItemAt, menuLabelText, menuNodeAt, menuRefusals, normalizeMenuModel, parseDetailedAction, parseMenuModel, resolveMenuItemState, } from './menu.js';
107
- export type { AdwDetailedAction, AdwMenuAction, AdwMenuActions, AdwMenuDisplayHint, AdwMenuEntryInput, AdwMenuFlatRow, AdwMenuHiddenWhen, AdwMenuInput, AdwMenuItem, AdwMenuItemInput, AdwMenuItemRole, AdwMenuItemState, AdwMenuModel, AdwMenuNode, AdwMenuPath, AdwMenuRefusal, AdwMenuSection, AdwMenuSectionInput, AdwMenuSubmenu, AdwMenuSubmenuInput, AdwMenuSurface, AdwMenuTextDirection, } from './menu.js';
107
+ export type { AdwDetailedAction, AdwMenuAction, AdwMenuActions, AdwMenuDisplayHint, AdwMenuEntryInput, AdwMenuFlatRow, AdwMenuHiddenWhen, AdwMenuInput, AdwMenuItem, AdwMenuItemInput, AdwMenuItemRole, AdwMenuItemState, AdwMenuModel, AdwMenuNode, AdwMenuPath, AdwMenuRefusal, AdwMenuSection, AdwMenuSectionInput, AdwMenuSubmenu, AdwMenuSubmenuInput, AdwMenuSurface, AdwMenuTextDirection, AdwMenuTree, } from './menu.js';
108
108
  export { DEFAULT_INDICATOR_DESCRIPTION_STRINGS, INLINE_VIEW_SWITCHER_DISPLAY_MODES, VIEW_SWITCHER_BADGE_LIMIT, VIEW_SWITCHER_DRAG_SWITCH_DELAY, VIEW_SWITCHER_FALLBACK_ICON, VIEW_SWITCHER_NO_SELECTION, VIEW_SWITCHER_POLICIES, ViewSwitcherBarState, ViewSwitcherDragSwitch, ViewSwitcherState, buildInlineToggles, buildViewSwitcherButtons, createViewSwitcherPage, inlineToggleTooltip, isInlineViewSwitcherDisplayMode, isViewSwitcherButtonVisible, isViewSwitcherPolicy, pageIndexForToggle, shouldRevealViewSwitcherBar, stripMnemonic, toggleIndexForPage, viewSwitcherBadgeLabel, viewSwitcherButtonOrientation, viewSwitcherIconName, viewSwitcherIndicatorDescription, viewSwitcherLabel, viewSwitcherPageFromStackPage, viewSwitcherPagesFromStack, viewSwitcherSidebarSections, } from './view-switcher.js';
109
109
  export type { AdwInlineViewSwitcherDisplayMode, AdwViewSwitcherPage, AdwViewSwitcherPageInit, AdwViewSwitcherPolicy, IndicatorDescriptionStrings, InlineToggleModel, ViewSwitcherBarChange, ViewSwitcherBarListener, ViewSwitcherButtonModel, ViewSwitcherDragSwitchOptions, ViewSwitcherScheduler, ViewSwitcherSidebarSection, ViewSwitcherStateChange, ViewSwitcherStateListener, ViewSwitcherStateOptions, ViewSwitcherTimerHandle, } from './view-switcher.js';
110
110
  export { DEFAULT_TAB_AUTOHIDE, TabViewState, isDescendantOfPage, successorAfterClose, tabCloseVisible, tabIconState, tabSearchMatches, tabTooltip, tabTooltipIsMarkup, tabViewItemsChanged, tabsRevealed, } from './tab-view.js';
@@ -1,13 +1,13 @@
1
- import type { AdwMenuActions, AdwMenuModel, AdwMenuItem } from './menu.js';
1
+ import type { AdwMenuActions, AdwMenuItem, AdwMenuTree } from './menu.js';
2
2
  type Parent = (node: object) => object | null | undefined;
3
3
  /**
4
- * The actions the model's items name, as `widget` resolves them. An action the walk does not find,
4
+ * The actions the tree's items name, as `widget` resolves them. An action the walk does not find,
5
5
  * because no group has its prefix or the group lacks it, is left out, which is "missing" and makes
6
6
  * the item insensitive. That is GTK's answer, measured on GJS (`menu-actions.gjs.spec.ts`), and it
7
7
  * overrules ADR 0097 § 3's "no group dims nothing": an application that dispatches an action
8
8
  * itself declares it, or passes `actions` to say what it knows.
9
9
  */
10
- export declare function menuActionsFor(model: AdwMenuModel, widget: object, parent: Parent): AdwMenuActions;
10
+ export declare function menuActionsFor(tree: AdwMenuTree, widget: object, parent: Parent): AdwMenuActions;
11
11
  /**
12
12
  * Fire the action an item names, the way `GtkMenuTrackerItem` does on activation. A target is
13
13
  * passed as its text: `GLib.Variant` is outside the subset until stage 3.
@@ -1,4 +1,4 @@
1
- import type { AdwMenuModel } from './menu.js';
1
+ import type { AdwMenuTree } from './menu.js';
2
2
  /** The slice of a tree node this reads. */
3
3
  export interface MenuTreeNode {
4
4
  readonly tag: string;
@@ -6,7 +6,7 @@ export interface MenuTreeNode {
6
6
  readonly menuModels?: Readonly<Record<string, readonly unknown[]>>;
7
7
  }
8
8
  /**
9
- * The menus a node assigns, as `[property, model]`: the root menu `menu-model: id` names, and each
10
- * model written at a property. An id with no root menu is refused by name.
9
+ * The menus a node assigns, as `[property, tree]`: the root menu `menu-model: id` names, and each
10
+ * tree written at a property. An id with no root menu is refused by name.
11
11
  */
12
- export declare function menuAssignments(node: MenuTreeNode, menus: Readonly<Record<string, readonly unknown[]>> | undefined): Array<[string, AdwMenuModel]>;
12
+ export declare function menuAssignments(node: MenuTreeNode, menus: Readonly<Record<string, readonly unknown[]>> | undefined): Array<[string, AdwMenuTree]>;
@@ -1,3 +1,4 @@
1
+ import type { GioMenuModel } from './gio-menu.js';
1
2
  /**
2
3
  * The values `hidden-when` is documented to take.
3
4
  *
@@ -91,12 +92,28 @@ export interface AdwMenuSubmenu {
91
92
  /** Any node of a normalised model. */
92
93
  export type AdwMenuNode = AdwMenuItem | AdwMenuSection | AdwMenuSubmenu;
93
94
  /**
94
- * A normalised menu: the value a renderer walks and the GTK host converts.
95
+ * A normalised menu TREE: the value a renderer walks and the GTK host converts.
95
96
  *
96
97
  * `readonly` throughout, because every renderer holds one across a render and a shared
97
98
  * mutable tree is how two widgets showing the same menu would diverge.
99
+ *
100
+ * IT IS NOT {@link AdwMenuModel} ANY MORE, and that split is ADR 0128. A menu MODEL is a
101
+ * `Gio.MenuModel` — the object a `menu-model` property takes, which emits `items-changed`
102
+ * and which the two widgets declare `value_type=GMenuModel` for. A menu TREE is the plain
103
+ * data the model is built from and snapshotted back into: `normalizeMenuModel` produces
104
+ * one, `buildMenu` turns one into a model, `menuTree` takes one out of a model, and every
105
+ * walker below takes one. The old name meant both, which is exactly what made
106
+ * `menuModel: [...]` and `menuModel: menu` look like the same write.
107
+ */
108
+ export type AdwMenuTree = readonly AdwMenuNode[];
109
+ /**
110
+ * A menu model — `Gio.MenuModel`, re-exported under the name the port's surfaces use.
111
+ *
112
+ * The alias and not a direct import, because `menuModel` is the PROPERTY on fifteen
113
+ * widgets and `AdwMenuModel` is the name their signatures have always read; what changed
114
+ * is what the name means. See {@link AdwMenuTree} for the half that is still plain data.
98
115
  */
99
- export type AdwMenuModel = readonly AdwMenuNode[];
116
+ export type AdwMenuModel = GioMenuModel;
100
117
  /** An item as authored — `kind` is implied by the absence of a link. */
101
118
  export interface AdwMenuItemInput {
102
119
  label?: unknown;
@@ -151,7 +168,7 @@ export type AdwMenuInput = readonly AdwMenuEntryInput[];
151
168
  * submenu with a label, never an item that happens to carry a list, because that is how
152
169
  * `g_menu_item_get_link` reads the same object.
153
170
  */
154
- export declare function normalizeMenuModel(input: AdwMenuInput | null | undefined): AdwMenuModel;
171
+ export declare function normalizeMenuModel(input: AdwMenuInput | null | undefined): AdwMenuTree;
155
172
  /**
156
173
  * A `menu` ATTRIBUTE — a JSON array — as a model.
157
174
  *
@@ -159,7 +176,7 @@ export declare function normalizeMenuModel(input: AdwMenuInput | null | undefine
159
176
  * markup can produce that a JS value cannot: `JSON.parse` genuinely throws on a typo,
160
177
  * and the widget must degrade to "no menu" rather than fail to upgrade.
161
178
  */
162
- export declare function parseMenuModel(json: string | null | undefined): AdwMenuModel;
179
+ export declare function parseMenuModel(json: string | null | undefined): AdwMenuTree;
163
180
  /**
164
181
  * Where a node sits: the index chain from the model's root.
165
182
  *
@@ -171,9 +188,9 @@ export declare function parseMenuModel(json: string | null | undefined): AdwMenu
171
188
  */
172
189
  export type AdwMenuPath = readonly number[];
173
190
  /** The node at a path, or `null` when the path names none. */
174
- export declare function menuNodeAt(model: AdwMenuModel, path: AdwMenuPath): AdwMenuNode | null;
191
+ export declare function menuNodeAt(tree: AdwMenuTree, path: AdwMenuPath): AdwMenuNode | null;
175
192
  /** The item at a path — `null` for a path that names a section, a submenu or nothing. */
176
- export declare function menuItemAt(model: AdwMenuModel, path: AdwMenuPath): AdwMenuItem | null;
193
+ export declare function menuItemAt(tree: AdwMenuTree, path: AdwMenuPath): AdwMenuItem | null;
177
194
  /** One row of a {@link flattenMenu} walk. */
178
195
  export interface AdwMenuFlatRow {
179
196
  /** The node this row draws. Sections never appear — they become {@link separated}. */
@@ -204,7 +221,7 @@ export interface AdwMenuFlatRow {
204
221
  * `separated` marks the FIRST row after a boundary and is never set on the first row of
205
222
  * all, because a separator above nothing is a line at the top of the menu.
206
223
  */
207
- export declare function flattenMenu(model: AdwMenuModel, path?: AdwMenuPath): readonly AdwMenuFlatRow[];
224
+ export declare function flattenMenu(tree: AdwMenuTree, path?: AdwMenuPath): readonly AdwMenuFlatRow[];
208
225
  /** What a `GActionGroup` publishes about one action, in portable form. */
209
226
  export interface AdwMenuAction {
210
227
  /** `g_action_group_get_action_enabled`. Absent counts as enabled. */
@@ -366,9 +383,9 @@ export interface AdwMenuRefusal {
366
383
  * would be useless: NativeScript renders no icon and no accelerator on any menu, so a
367
384
  * refusal per decoration would fire on every well-formed menu and be switched off.
368
385
  */
369
- export declare function menuRefusals(model: AdwMenuModel, surface: AdwMenuSurface, path?: AdwMenuPath): AdwMenuRefusal[];
386
+ export declare function menuRefusals(tree: AdwMenuTree, surface: AdwMenuSurface, path?: AdwMenuPath): AdwMenuRefusal[];
370
387
  /**
371
- * Throw if the surface cannot render the model.
388
+ * Throw if the surface cannot render the menu TREE.
372
389
  *
373
390
  * Called by a renderer when a menu is SET, so the throw names the assignment rather than
374
391
  * arriving as a missing row three interactions later. The message carries every refusal,
@@ -376,4 +393,4 @@ export declare function menuRefusals(model: AdwMenuModel, surface: AdwMenuSurfac
376
393
  * and reporting them one run at a time is how a port becomes a series of identical bug
377
394
  * reports.
378
395
  */
379
- export declare function assertMenuRenderable(model: AdwMenuModel, surface: AdwMenuSurface): void;
396
+ export declare function assertMenuRenderable(tree: AdwMenuTree, surface: AdwMenuSurface): void;
@@ -1,4 +1,4 @@
1
- import type { AdwMenuActions, AdwMenuModel, AdwMenuPath } from './menu.js';
1
+ import type { AdwMenuActions, AdwMenuPath, AdwMenuTree } from './menu.js';
2
2
  /** An item of the plan; `path` maps a tap back to the model. */
3
3
  export interface PopupMenuItemPlan {
4
4
  readonly kind: 'item';
@@ -41,7 +41,7 @@ export interface PopupMenuPlan {
41
41
  readonly level: PopupMenuLevelPlan;
42
42
  readonly refusals: readonly PopupMenuRefusal[];
43
43
  }
44
- /** Lower `model` for `PopupMenu`. `actions` is what {@link resolveMenuItemState} reads. */
45
- export declare function planPopupMenu(model: AdwMenuModel, actions?: AdwMenuActions): PopupMenuPlan;
44
+ /** Lower `tree` for `PopupMenu`. `actions` is what {@link resolveMenuItemState} reads. */
45
+ export declare function planPopupMenu(tree: AdwMenuTree, actions?: AdwMenuActions): PopupMenuPlan;
46
46
  /** Throw naming every refusal, as `assertMenuRenderable` does for the sheet. */
47
47
  export declare function assertPopupMenuPlan(plan: PopupMenuPlan): void;
@@ -1,4 +1,4 @@
1
- import type { AdwMenuInput, AdwMenuItem, AdwMenuModel, AdwMenuPath } from './menu.js';
1
+ import type { AdwMenuItem, AdwMenuModel, AdwMenuPath } from './menu.js';
2
2
  /**
3
3
  * The four mutually exclusive content slots of the action half. `'empty'` is the
4
4
  * initial state — `label`, `icon-name` and `child` are all `NULL`.
@@ -190,28 +190,23 @@ export declare class SplitButtonState {
190
190
  * PROPERTY lives here; the `_S` → underlined-S derivation belongs to `GtkLabel`.
191
191
  */
192
192
  setUseUnderline(value: boolean): boolean;
193
- /** The menu model, or `null` when none is set. Always normalised (ADR 0042). */
193
+ /** The menu model, or `null` when none is set. */
194
194
  get menuModel(): AdwMenuModel | null;
195
195
  /**
196
196
  * Set the menu model, dissociating any popover and replacing it with the model-derived
197
197
  * one.
198
198
  *
199
- * NORMALISES AT THE DOOR, so every surface stores the same shape whatever it was
200
- * handed — a JSON attribute, a bare `string[]`, a JSX array of descriptors. It is
201
- * {@link normalizeMenuModel}'s idempotence that makes `setMenuModel(state.menuModel)`
202
- * a no-op rather than a quiet flattening.
203
- *
204
- * DELIBERATE NORMALISATION: an EMPTY list is stored as "no menu model". C can hold a
205
- * non-`NULL` but empty `GMenu`, which leaves the dropdown live and pops up an empty
206
- * popover; collapsing the two is what makes "no menu ⇒ insensitive dropdown" hold
207
- * from a renderer's point of view. A model that is non-empty but draws nothing — one
208
- * empty section — is NOT collapsed: it has a node, so it is a menu, which is the
209
- * answer GTK gives for the same `GMenu`.
199
+ * `null` is the ONLY spelling of "no menu" (ADR 0128). MEASURED: an empty but
200
+ * non-`NULL` `Gio.Menu` written at `Adw.SplitButton.menu-model` still builds a
201
+ * `GtkPopoverMenu`, so the dropdown is live and pops up an empty popover. While the
202
+ * port's menu was an array this class had to collapse `[]` onto "no menu" — an array
203
+ * cannot be both empty and present — and that collapse was a divergence. A real model
204
+ * can be empty, so the collapse is gone.
210
205
  *
211
206
  * Notifies both properties per {@link DROPDOWN_NOTIFY_ORDER}; the guard is on the
212
207
  * menu model ALONE, so clearing it on a popover-only button emits nothing.
213
208
  */
214
- setMenuModel(input: AdwMenuInput | null | undefined): boolean;
209
+ setMenuModel(next: AdwMenuModel | null): boolean;
215
210
  /** The popover: the one the app set, or the model-derived stand-in, or `null`. */
216
211
  get popover(): object | null;
217
212
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/adwaita-core",
3
- "version": "0.64.13",
3
+ "version": "0.64.15-next.287",
4
4
  "description": "Headless Adwaita widget behavior (breakpoint condition grammar + apply/unapply state machine, color-scheme observable, avatar derivation) shared by the web and NativeScript Adwaita renderers — pure TS, no platform imports",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -67,9 +67,9 @@
67
67
  "headless"
68
68
  ],
69
69
  "devDependencies": {
70
- "@gjsify/cli": "^0.64.13",
70
+ "@gjsify/cli": "0.64.15-next.287",
71
71
  "@gjsify/node-gi": "file:../../../packages/node-gi/node-gi",
72
- "@gjsify/unit": "^0.64.13",
72
+ "@gjsify/unit": "0.64.15-next.287",
73
73
  "@types/node": "^25.9.2",
74
74
  "typescript": "^6.0.3"
75
75
  },
@@ -92,5 +92,6 @@
92
92
  "bugs": {
93
93
  "url": "https://github.com/gjsify/gjsify/issues"
94
94
  },
95
- "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/web/adwaita-core#readme"
95
+ "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/web/adwaita-core#readme",
96
+ "gitHead": "5742b282a8a2bc8633dd8384ef436768447f6a83"
96
97
  }