@gjsify/adwaita-react-native 0.53.0 → 0.55.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 (2) hide show
  1. package/lib/types/props.d.ts +145 -215
  2. package/package.json +5 -5
@@ -3,13 +3,11 @@ import type { ReactNode, Ref } from 'react';
3
3
  /**
4
4
  * What a widget that HOLDS a child accepts.
5
5
  *
6
- * Not every widget does. `Adw.WindowTitle` is two labels and no child slot; `Adw.Avatar`,
6
+ * Not every widget does: `Adw.WindowTitle` is two labels and no child slot; `Adw.Avatar`,
7
7
  * `Adw.Banner`, `Adw.Spinner` and `Adw.ButtonContent` are leaves; `Adw.ButtonRow` has no
8
- * child API in libadwaita at all, and `Adw.SwitchRow` and `Adw.EntryRow` fill their one
9
- * slot themselves. Their prop types deliberately do NOT extend this, so a child written
10
- * into one is a TYPE error rather than a node `@gjsify/gtk-host` refuses at runtime on one
11
- * half while React Native renders it on the other. A `children` a widget would have to
12
- * drop is a hole in the surface, not a convenience.
8
+ * child API in libadwaita at all. Their prop types deliberately do NOT extend this, so a
9
+ * child written into one is a TYPE error rather than a node one half renders and the other
10
+ * refuses.
13
11
  */
14
12
  export interface AdwWidgetProps {
15
13
  children?: ReactNode;
@@ -31,18 +29,15 @@ export interface AdwClampProps extends AdwWidgetProps {
31
29
  /**
32
30
  * `Adw.HeaderBar` — the start / centre / end bar at the top of a window.
33
31
  *
34
- * THE THREE SLOTS ARE PROPS, NOT CHILDREN, and the names are the GTK host's own slot
35
- * names (`start`, `end`, `title` — `packages/framework/gtk-host/src/descriptors/adw.ts`),
36
- * which are `adw_header_bar_pack_start` / `_pack_end` / `:title-widget`. A bare child
37
- * would have to pick one of them, and `Adw.HeaderBar`'s buildable default picking `start`
38
- * is a GTK detail no React caller should have to know.
39
- *
40
- * PACK ORDER DOES NOT ARISE HERE, and that is the one place this surface is SIMPLER than
41
- * the imperative API rather than different from it. `adw_header_bar_pack_end` PREPENDS
42
- * (adw-header-bar.c:1106), so `packEnd(menu); packEnd(search)` draws `search | menu`;
43
- * `HeaderBarState` in `@gjsify/adwaita-core` stores the end slot in DRAW order for
44
- * exactly that reason. A prop is already draw order — `end={<><Search /><Menu /></>}` is
45
- * what it looks like — so there is no order to reverse and no rule to get backwards.
32
+ * THE THREE SLOTS ARE PROPS, NOT CHILDREN, and the names are the GTK host's own slot names
33
+ * (`start`, `end`, `title`), which are `adw_header_bar_pack_start` / `_pack_end` /
34
+ * `:title-widget`. A bare child would have to pick one of them, and the buildable default
35
+ * picking `start` is a GTK detail no React caller should have to know.
36
+ *
37
+ * PACK ORDER DOES NOT ARISE HERE, and that is the one place this surface is SIMPLER than the
38
+ * imperative API rather than different from it. `adw_header_bar_pack_end` PREPENDS, so
39
+ * `packEnd(menu); packEnd(search)` draws `search | menu`; a prop is already draw order —
40
+ * `end={<><Search /><Menu /></>}` is what it looks like — so there is no order to reverse.
46
41
  */
47
42
  export interface AdwHeaderBarProps {
48
43
  /**
@@ -57,9 +52,8 @@ export interface AdwHeaderBarProps {
57
52
  *
58
53
  * A DIVERGENCE FROM LIBADWAITA, and the same one both other renderers carry:
59
54
  * `Adw.HeaderBar` has NO `title` property at all. Its derived centre is a plain
60
- * `gtk_label_new (NULL)` (`construct_title_label`, adw-header-bar.c:512) over a title
61
- * RESOLVED from the navigation page, then the dialog, then the window, then the
62
- * application name (`update_title`, :475) — and an app that wants a subtitle sets an
55
+ * `gtk_label_new (NULL)` over a title RESOLVED from the navigation page, then the dialog,
56
+ * then the window, then the application name — and an app that wants a subtitle sets an
63
57
  * `AdwWindowTitle` as its title widget. A declarative surface wants the attribute, so
64
58
  * authoring one installs an {@link AdwWindowTitleProps} centre; it is recorded as
65
59
  * `HeaderBarRenderState.derivedSubtitle` in `@gjsify/adwaita-core`.
@@ -78,10 +72,8 @@ export interface AdwStatusPageProps extends AdwWidgetProps {
78
72
  * `icon-name` — the symbolic icon above the title.
79
73
  *
80
74
  * CARRIED ON BOTH HALVES AND DRAWN ONLY ON GTK. An icon NAME needs an icon theme to
81
- * resolve it, and React Native has none — the same wall `@gjsify/adwaita-nativescript`
82
- * hit, which took an SVG string instead. The README names it; `status-page.native.spec.tsx`
83
- * pins that the tree has no icon node, so the day one appears is a decision and not a
84
- * drift.
75
+ * resolve it, and React Native has none. The README names it; `status-page.native.spec.tsx`
76
+ * pins that the tree has no icon node.
85
77
  */
86
78
  iconName?: string;
87
79
  /** `title` — the bold line. An empty title takes no space (`string_is_not_empty`). */
@@ -160,19 +152,18 @@ export interface AdwWrapBoxProps extends AdwWidgetProps {
160
152
  * `Adw.Avatar` — a round avatar showing initials derived from a name, or a
161
153
  * fallback icon.
162
154
  *
163
- * `size` IS REQUIRED, and that is the one place this file departs from "libadwaita's
164
- * defaults are the defaults". `AdwAvatar:size`'s GParamSpec default is the `-1`
165
- * sentinel meaning "take the size from the stylesheet", and a renderer with no
166
- * stylesheet cannot honour a stylesheet value. Measured against libadwaita 1.9.3, that
167
- * path is degenerate on GTK too: a default-constructed avatar measures 20 wide and 18
168
- * tall — not even square — and raises one `Pango-CRITICAL` from `update_font_size`,
169
- * because the font cap for a negative size is negative. Reproducing that is not a goal
170
- * and inventing a number behind the caller's back is how the two halves come to
155
+ * `size` IS REQUIRED, and that is the one place this file departs from "libadwaita's defaults
156
+ * are the defaults". `AdwAvatar:size`'s GParamSpec default is the `-1` sentinel meaning "take
157
+ * the size from the stylesheet", and a renderer with no stylesheet cannot honour a stylesheet
158
+ * value. Measured on libadwaita 1.9.3, that path is degenerate on GTK too: a
159
+ * default-constructed avatar measures 20 wide and 18 tall — not even square — and raises one
160
+ * `Pango-CRITICAL` from `update_font_size`, because the font cap for a negative size is
161
+ * negative. Inventing a number behind the caller's back is how the two halves come to
171
162
  * disagree, so the caller says.
172
163
  *
173
- * `custom-image` IS ABSENT. It is a `GdkPaintable` on GTK and an image source on React
174
- * Native — two types with no shared spelling, and this file may import neither. The
175
- * consequence is that `avatarMode` here only ever answers `'initials'` or `'icon'`.
164
+ * `custom-image` IS ABSENT: a `GdkPaintable` on GTK and an image source on React Native are
165
+ * two types with no shared spelling, and this file may import neither. `avatarMode` here
166
+ * therefore only ever answers `'initials'` or `'icon'`.
176
167
  */
177
168
  export interface AdwAvatarProps {
178
169
  /** `size` — the diameter. Required; see above. */
@@ -189,14 +180,12 @@ export interface AdwAvatarProps {
189
180
  * action button.
190
181
  *
191
182
  * ON `useMarkup`'s DEFAULT, which is measured and not the one written down.
192
- * `AdwBanner:use-markup`'s GParamSpec declares TRUE (adw-banner.c:422-425) and
193
- * `@gjsify/adwaita-core`'s `ADW_BANNER_DEFAULTS` records that — but a freshly
194
- * constructed `Adw.Banner` READS BACK FALSE, measured on libadwaita 1.9.3.
195
- * `adw_banner_get_use_markup` delegates to `gtk_label_get_use_markup (self->title)`,
196
- * `adw-banner.ui` never sets `use-markup` on that label, and a pspec default is only
197
- * applied to properties construction actually writes. So the declared default is never
198
- * reached. Both halves here answer FALSE for an omitted value, because that is what the
199
- * widget on the other side of the surface answers.
183
+ * `AdwBanner:use-markup`'s GParamSpec declares TRUE — the pspec default, which construction
184
+ * never writes, because `adw_banner_get_use_markup` delegates to
185
+ * `gtk_label_get_use_markup (self->title)` and `adw-banner.ui` does not set it there. So the
186
+ * declared default is never reached, and a freshly constructed `Adw.Banner` READS BACK FALSE
187
+ * (libadwaita 1.9.3). Both halves here answer FALSE for an omitted value, because that is
188
+ * what the widget on the other side of the surface answers.
200
189
  */
201
190
  export interface AdwBannerProps {
202
191
  /** `title` — the message. Pango markup when {@link useMarkup}. */
@@ -215,17 +204,16 @@ export interface AdwBannerProps {
215
204
  /**
216
205
  * `Adw.Spinner` — a busy indicator.
217
206
  *
218
- * THE PROPERTIES ARE `GtkWidget`'s, BECAUSE `Adw.Spinner` HAS NONE OF ITS OWN. Its
219
- * whole `GParamSpec` set is inherited: `adw_spinner_measure` reports `MIN_SIZE` as both
220
- * the minimum AND the natural size, so the widget never grows on its own and the only
221
- * way to make one bigger is to ask for a size. Measured on libadwaita 1.9.3: a fresh
222
- * spinner measures `[16, 16]` and one with `width-request` 200 measures `[200, 200]`.
223
- * A `size` prop would therefore be a renderer-ism of exactly the kind `maximumSize`
224
- * exists to avoid — the two other Adwaita renderers each invented one.
225
- *
226
- * The BOX and the RING are different numbers, and only the box is a property: the ring
227
- * is `spinnerGeometry`'s, capped at 64 and centred on the box, so a 200-point request
228
- * occupies 200 points of layout around a 64-point ring.
207
+ * THE PROPERTIES ARE `GtkWidget`'s, BECAUSE `Adw.Spinner` HAS NONE OF ITS OWN.
208
+ * `adw_spinner_measure` reports `MIN_SIZE` as both the minimum AND the natural size, so the
209
+ * widget never grows on its own and the only way to make one bigger is to ask for a size.
210
+ * Measured on libadwaita 1.9.3: a fresh spinner measures `[16, 16]` and one with
211
+ * `width-request` 200 measures `[200, 200]`. A `size` prop would be a renderer-ism of exactly
212
+ * the kind `maximumSize` exists to avoid — the two other Adwaita renderers each invented one.
213
+ *
214
+ * The BOX and the RING are different numbers, and only the box is a property: the ring is
215
+ * `spinnerGeometry`'s, capped at 64 and centred on the box, so a 200-point request occupies
216
+ * 200 points of layout around a 64-point ring.
229
217
  */
230
218
  export interface AdwSpinnerProps {
231
219
  /** `width-request` — the box width. Unset (or `-1`) is libadwaita's natural 16. */
@@ -247,16 +235,13 @@ export interface AdwButtonContentProps {
247
235
  /**
248
236
  * What a caller does to an {@link AdwToastOverlayProps} through its `ref`.
249
237
  *
250
- * A TOAST IS PUSHED, NEVER DECLARED, and that is libadwaita's shape rather than a
251
- * React convenience: `adw_toast_overlay_add_toast` is a call, the overlay owns the
252
- * queue, and nothing about "which toast is on screen" is a property a caller writes.
253
- * Modelling it as a `toasts={[…]}` array would put the ordering in the caller's hands
254
- * on one half and in libadwaita's on the other.
238
+ * A TOAST IS PUSHED, NEVER DECLARED, and that is libadwaita's shape rather than a React
239
+ * convenience: the overlay owns the queue, and nothing about "which toast is on screen" is a
240
+ * property a caller writes. Modelling it as a `toasts={[…]}` array would put the ordering in
241
+ * the caller's hands on one half and in libadwaita's on the other.
255
242
  *
256
- * `dismissAll` and not `dismiss`: `adw_toast_overlay_dismiss_all` is the only dismissal
257
- * the OVERLAY has. Dismissing just the current toast is `adw_toast_dismiss`, a method on
258
- * the toast, so an overlay-level `dismiss()` would be a name libadwaita does not have —
259
- * and `AdwToastQueue.clear()` is the same operation on the other half.
243
+ * `dismissAll` and not `dismiss`, because `adw_toast_dismiss` is a method on the TOAST — an
244
+ * overlay-level `dismiss()` would be a name libadwaita does not have.
260
245
  */
261
246
  export interface AdwToastOverlayHandle {
262
247
  /** `add_toast` — show it now if the slot is free, otherwise queue it FIFO. */
@@ -403,19 +388,15 @@ export interface AdwExpanderRowProps extends AdwRowProps, AdwWidgetProps {
403
388
  /**
404
389
  * `Adw.PreferencesPage` — a scrolling page of {@link AdwPreferencesGroupProps}.
405
390
  *
406
- * FOUR OF THE FIVE PROPERTIES ARE IDENTITY, NOT PAINT, and that is libadwaita's design
407
- * rather than a thin port: `adw_preferences_dialog_add` binds `title`, `name`, `icon-name`
408
- * and `use-underline` onto the view-stack page it wraps the page in, and
409
- * `create_search_row_subtitle` reads the title back when a second page is visible. The page
410
- * itself draws none of them — a view switcher and the search results do. Both sibling
411
- * renderers carry them for the same reason and paint them just as little.
391
+ * FOUR OF THE FIVE PROPERTIES ARE IDENTITY, NOT PAINT: `adw_preferences_dialog_add` binds
392
+ * `title`, `name`, `icon-name` and `use-underline` onto the view-stack page it wraps the page
393
+ * in. The page itself draws none of them — a view switcher and the search results do.
412
394
  *
413
- * `description` IS the exception: it is drawn at the top of the page, above the first
414
- * group, and both halves draw it.
395
+ * `description` IS the exception: it is drawn at the top of the page, above the first group,
396
+ * and both halves draw it.
415
397
  *
416
- * `banner` IS ABSENT. `AdwPreferencesPage:banner` takes an `Adw.Banner` INSTANCE — a
417
- * GObject, not a description of one — and this file may import neither `gi://Adw` nor a
418
- * React Native module. Same wall, and the same answer, as `AdwAvatarProps`' `custom-image`.
398
+ * `banner` IS ABSENT: it takes an `Adw.Banner` INSTANCE — a GObject, not a description of one —
399
+ * and this file may import neither `gi://Adw` nor a React Native module.
419
400
  */
420
401
  export interface AdwPreferencesPageProps extends AdwWidgetProps {
421
402
  /** `title` — shown by a view switcher and by search results, never by the page. */
@@ -430,8 +411,7 @@ export interface AdwPreferencesPageProps extends AdwWidgetProps {
430
411
  * ON THE RAW STRING, unlike {@link AdwPreferencesGroupProps}' two labels.
431
412
  * `adw_preferences_page_set_description` tests `description && *description` while
432
413
  * `update_title_visibility` reads the label's DISPLAYED text, so a pure-markup page
433
- * description is visible on GTK where a pure-markup group title is not. Both halves
434
- * therefore agree here, and the group's divergence must not be copied onto this one.
414
+ * description is visible on GTK where a pure-markup group title is not.
435
415
  */
436
416
  description?: string;
437
417
  /** `description-centered` — whether {@link description} is centred. Default false. */
@@ -442,23 +422,19 @@ export interface AdwPreferencesPageProps extends AdwWidgetProps {
442
422
  /**
443
423
  * `Adw.PreferencesGroup` — a titled card of rows.
444
424
  *
445
- * THE FIVE VISIBILITY ANSWERS COME FROM `derivePreferencesGroupHeader`, on the React Native
446
- * half, and from libadwaita on the GTK one. They are not `title !== ''`: `header-visible` is
447
- * a three-way OR, `single-line` is load-bearing for the stylesheet's `min-height: 34px`, and
448
- * `listbox-visible` reads the RAW child count — `update_listbox_visibility` counts
449
- * `gtk_widget_observe_children`, not the title-filtered model `get_rows` builds, so a row
450
- * with an empty title still keeps the card painted.
451
- *
452
- * `header-suffix` IS ABSENT, and it is a placement question rather than a naming one.
453
- * `AdwPreferencesGroup:header-suffix` holds a WIDGET, so a React surface has to spell it as
454
- * a slot — and the group's curated descriptor in `@gjsify/gtk-host` is `ordered`
455
- * (`add`/`remove`, `remove-all` to reorder), which has no slots at all. Adding one means
456
- * changing a placement policy other conformance vectors already assert, with its own
457
- * measurement; it is not something a widget lands on the way past. The README names it.
458
- *
459
- * `separate-rows` IS ABSENT for the opposite reason: it is pure card styling, and this
460
- * package's React Native half draws no theme (see `row-shell.native.tsx`), so the GTK half
461
- * would honour it and the phone half could only ignore it.
425
+ * THE VISIBILITY ANSWERS COME FROM `derivePreferencesGroupHeader` on the React Native half and
426
+ * from libadwaita on the GTK one. They are not `title !== ''`: `header-visible` is a three-way
427
+ * OR, and `listbox-visible` reads the RAW child count — `update_listbox_visibility` counts
428
+ * `gtk_widget_observe_children`, not the title-filtered model `get_rows` builds, so a row with
429
+ * an empty title still keeps the card painted.
430
+ *
431
+ * `header-suffix` IS ABSENT, and it is a placement question rather than a naming one. It holds a
432
+ * WIDGET, so a React surface has to spell it as a slot — and the group's curated descriptor in
433
+ * `@gjsify/gtk-host` is `ordered`, which has no slots at all. The README names it.
434
+ *
435
+ * `separate-rows` IS ABSENT for the opposite reason: it is pure card styling, and this package's
436
+ * React Native half draws no theme, so the GTK half would honour it and the phone half could
437
+ * only ignore it.
462
438
  */
463
439
  export interface AdwPreferencesGroupProps extends AdwWidgetProps {
464
440
  /** `title` — the card's heading. Hidden when empty, not merely blank. */
@@ -473,33 +449,24 @@ export interface AdwPreferencesGroupProps extends AdwWidgetProps {
473
449
  * their derived visibility, which is not `title !== ''`.
474
450
  *
475
451
  * `model` IS THE LIBADWAITA NAME AND NOT THE LIBADWAITA TYPE, which is the one liberty this
476
- * surface takes and the reason it can exist at all. `AdwComboRow:model` is a
477
- * `Gio.ListModel`; a props file that may import neither `gi://Gio` nor `react-native` cannot
478
- * name that type, and the gallery still refuses the widget — no longer for the value but for
479
- * the seam (`adwaita-gallery-trees.mjs`: "its model is a Gio.ListModel, and nothing turns
480
- * the portable list form into one at the ParamSpec seam"). What both halves CAN share is
481
- * `@gjsify/adwaita-core`'s `AdwListModelInput` — the portable list model (ADR 0046), the
482
- * item vocabulary `<adw-combo-row>` and `@gjsify/adwaita-nativescript` already accept —
483
- * so the property keeps libadwaita's name
484
- * and takes the shared description of a model. The GTK half turns it into the real
485
- * `Gtk.StringList` it has to be; the React Native half feeds it to `ComboState`.
452
+ * surface takes. `AdwComboRow:model` is a `Gio.ListModel`, and a props file that may import
453
+ * neither `gi://Gio` nor `react-native` cannot name that type. What both halves CAN share is
454
+ * `@gjsify/adwaita-core`'s `AdwListModelInput` — the portable list model (ADR 0046) — so the
455
+ * property keeps libadwaita's name and takes the shared description of a model. The GTK half
456
+ * turns it into the real `Gtk.StringList` it has to be.
486
457
  *
487
458
  * `onNotifySelected` REPORTS A USER PICK ON BOTH HALVES AND A PROGRAMMATIC ONE ON ONE, which
488
- * is a NAMED DIVERGENCE and not the agreement this paragraph used to claim. `ComboState` tags
489
- * its changes `interactive` and the React Native half deliberately does not gate on it, so a
490
- * `selected` the consumer authored comes back there. The GTK half cannot: gtk-host suppresses
491
- * a `notify::` raised inside its OWN property write (`inHostWrite()` in its `signals.ts`), and
492
- * writing the `selected` prop IS that write. MEASURED on libadwaita 1.9.3 — a re-render from
493
- * `selected={0}` to `selected={2}` moves the widget and calls NOTHING, while `row.selected = 1`
494
- * from outside React calls it. Benign for the ordinary controlled pattern, where the consumer
495
- * made the change and already knows; not benign as a claim, because "fires on every change"
496
- * sends a reader looking for a callback that never arrives. Same rule, same reason and the
497
- * same README entry as `onNotifyVisibleChild`. A consumer that wants user picks only compares
498
- * against the value it authored.
459
+ * is a NAMED DIVERGENCE. `ComboState` tags its changes `interactive` and the React Native half
460
+ * deliberately does not gate on it, so a `selected` the consumer authored comes back there.
461
+ * The GTK half cannot: gtk-host suppresses a `notify::` raised inside its OWN property write,
462
+ * and writing the `selected` prop IS that write. MEASURED on libadwaita 1.9.3 — a re-render
463
+ * from `selected={0}` to `selected={2}` moves the widget and calls NOTHING, while
464
+ * `row.selected = 1` from outside React calls it. A consumer that wants user picks only
465
+ * compares against the value it authored.
499
466
  *
500
467
  * `expression`, `factory`, `list-factory`, `header-factory`, `enable-search` and
501
- * `search-match-mode` are all absent, and all for the `model` reason one step further: each
502
- * is a `Gtk.*` instance. Neither sibling renderer has them either.
468
+ * `search-match-mode` are absent, each being a `Gtk.*` instance. Neither sibling renderer has
469
+ * them either.
503
470
  */
504
471
  export interface AdwComboRowProps extends AdwRowProps {
505
472
  /** `model` — the selectable items. See above on the type. */
@@ -511,11 +478,11 @@ export interface AdwComboRowProps extends AdwRowProps {
511
478
  *
512
479
  * REPLACES, not "appears twice": `adw-combo-row.ui` binds the inline value view's `visible`
513
480
  * to this property with `sync-create|invert-boolean`, so the value is drawn in the subtitle
514
- * OR in the trailing slot and never in both. Both halves are held to that.
481
+ * OR in the trailing slot and never in both.
515
482
  *
516
- * WHEN the subtitle picks the value up is a NAMED DIVERGENCE, in the README: this surface
517
- * publishes it at once, libadwaita on the next selection change. Measured — the setter calls
518
- * `selection_changed`, and the subtitle is written by `selection_item_changed`.
483
+ * WHEN the subtitle picks the value up is a NAMED DIVERGENCE: this surface publishes it at
484
+ * once, libadwaita on the next selection change — the setter calls `selection_changed`, and
485
+ * the subtitle is written by `selection_item_changed`.
519
486
  */
520
487
  useSubtitle?: boolean;
521
488
  /** `notify::selected` — the selected position moved. */
@@ -531,20 +498,13 @@ export interface AdwComboRowProps extends AdwRowProps {
531
498
  * of it, `@gjsify/adwaita-core`'s {@link AdwAdjustmentInput} (ADR 0047), which is the value
532
499
  * all four surfaces take under this one key.
533
500
  *
534
- * IT USED TO BE THREE SCALARS HERE, hoisted onto the ROW: `lower`, `upper` and
535
- * `stepIncrement` — the adjustment's own GObject property names, on an object that has
536
- * none of them. The right vocabulary in the wrong place, and a fourth shape beside the two
537
- * sibling renderers' `min`/`max`/`step`. All three converged on the one key the row has.
538
- *
539
501
  * `digits` IS A ROW PROPERTY AND NOT AN ADJUSTMENT ONE — `AdwSpinRow:digits`, the number of
540
502
  * decimal places DISPLAYED. It is carried because it is the only one of the row's own
541
- * properties both halves can honour: the core has no `digits`, so the React Native half
542
- * formats with it directly and the GTK half hands it to the real widget.
503
+ * properties both halves can honour: the core has no `digits`, so the React Native half formats
504
+ * with it directly and the GTK half hands it to the real widget.
543
505
  *
544
- * `climb-rate`, `snap-to-ticks`, `numeric`, `update-policy` and `wrap` are absent: each
545
- * needs an editable text entry or a key-repeat timer that the React Native half does not
546
- * have, so carrying them would mean a property GTK honours and the phone ignores. Neither
547
- * sibling renderer has them either.
506
+ * `climb-rate`, `snap-to-ticks`, `numeric`, `update-policy` and `wrap` are absent: each needs
507
+ * an editable text entry or a key-repeat timer the React Native half does not have.
548
508
  */
549
509
  export interface AdwSpinRowProps extends AdwRowProps {
550
510
  /** `value` — the current number, clamped into the {@link adjustment}'s range. Default 0. */
@@ -553,10 +513,8 @@ export interface AdwSpinRowProps extends AdwRowProps {
553
513
  * `adjustment` — the range this row steps through, as `@gjsify/adwaita-core`'s portable
554
514
  * {@link AdwAdjustmentInput} (ADR 0047).
555
515
  *
556
- * It used to be three flat props here (`lower`, `upper`, `stepIncrement`), which were
557
- * `Gtk.Adjustment`'s own field names hoisted onto the ROW — the right vocabulary in the
558
- * wrong place, since `Adw.SpinRow` has no such properties. Unwritten fields take
559
- * `ADW_ADJUSTMENT_DEFAULTS`, so `adjustment={{ upper: 20 }}` is 0…20 step 1.
516
+ * Unwritten fields take `ADW_ADJUSTMENT_DEFAULTS`, so `adjustment={{ upper: 20 }}` is 0…20
517
+ * step 1.
560
518
  */
561
519
  adjustment?: AdwAdjustmentInput;
562
520
  /** `digits` — decimal places DISPLAYED. Default 0. */
@@ -574,25 +532,17 @@ export interface AdwSpinRowProps extends AdwRowProps {
574
532
  * `Adw.PasswordEntryRow` — an entry row whose contents are masked, with a peek button.
575
533
  *
576
534
  * IT DECLARES NO PROPERTIES OF ITS OWN, and that is measured rather than assumed:
577
- * `AdwPasswordEntryRowProps` in `@gjsify/gtk-host`'s generated table is an EMPTY interface
578
- * over `AdwEntryRowProps`. Everything the subclass adds is behaviour — the mask, the peek
579
- * toggle installed through `add_suffix`, and the caps-lock indicator driven through the
580
- * private `adw_entry_row_set_show_indicator` hook. So this surface is `Adw.EntryRow`'s, and
581
- * `@gjsify/adwaita-core`'s `PasswordEntryRowState` composes an `EntryRowState` for the same
582
- * reason the C subclasses rather than copies.
583
- *
584
- * WHICH IS WHY IT EXTENDS RATHER THAN RESTATES {@link AdwEntryRowProps}. The two carried the
585
- * same eight members written out twice, and a second copy of a prop surface is the shape that
586
- * drifts silently: a member added to the entry row would simply not reach this one, and
587
- * `parity.spec.ts` compares each widget against its OWN base, so nothing would notice.
535
+ * `AdwPasswordEntryRowProps` in `@gjsify/gtk-host`'s generated table is an EMPTY interface over
536
+ * `AdwEntryRowProps`. Everything the subclass adds is behaviour — the mask, the peek toggle, and
537
+ * the caps-lock indicator.
588
538
  *
589
- * `revealed` IS THEREFORE NOT A PROP, although both sibling renderers publish one. It is not
590
- * a libadwaita property, the peek state is private to the widget, and a prop would be the
591
- * one place this file invents a name. The button owns it on both halves.
539
+ * WHICH IS WHY IT EXTENDS RATHER THAN RESTATES {@link AdwEntryRowProps}. A second copy of a prop
540
+ * surface drifts silently: a member added to the entry row would simply not reach this one, and
541
+ * `parity.spec.ts` compares each widget against its OWN base, so nothing would notice.
592
542
  *
593
- * `activates-default`, `enable-emoji-completion`, `input-hints`, `input-purpose` and
594
- * `attributes` are absent — the last two by type, the first by there being no default widget
595
- * on a phone. Neither sibling renderer has them.
543
+ * `revealed` IS THEREFORE NOT A PROP, although both sibling renderers publish one. It is not a
544
+ * libadwaita property, the peek state is private to the widget, and a prop would be the one
545
+ * place this file invents a name.
596
546
  */
597
547
  export interface AdwPasswordEntryRowProps extends AdwEntryRowProps {
598
548
  }
@@ -601,11 +551,9 @@ export interface AdwPasswordEntryRowProps extends AdwEntryRowProps {
601
551
  *
602
552
  * IT IS A WIDGET IN ITS OWN RIGHT ON GTK AND THAT IS WHY IT IS ONE HERE.
603
553
  * `adw_navigation_view_add` takes an `AdwNavigationPage`, not a `GtkWidget`, and so do
604
- * `adw_navigation_split_view_set_sidebar` / `_set_content` — a `Gtk.Box` handed to any
605
- * of them is a rejected child. `@gjsify/adwaita-web` exposes it as its own element
606
- * (`<adw-navigation-page>`) for the same reason; `@gjsify/adwaita-nativescript` does
607
- * not, because a NativeScript `View` cannot carry the tag and it keeps the tag of
608
- * record in the core instead.
554
+ * `adw_navigation_split_view_set_sidebar` / `_set_content` — a `Gtk.Box` handed to any of
555
+ * them is a rejected child. `@gjsify/adwaita-web` exposes it as its own element for the
556
+ * same reason.
609
557
  */
610
558
  export interface AdwNavigationPageProps extends AdwWidgetProps {
611
559
  /**
@@ -613,10 +561,9 @@ export interface AdwNavigationPageProps extends AdwWidgetProps {
613
561
  *
614
562
  * OPTIONAL IN THE TYPE AND EXPECTED IN PRACTICE, measured on libadwaita 1.9.3: a page
615
563
  * with no title prints `AdwNavigationPage 0x… is missing a title. To hide a header bar
616
- * title, consider using AdwHeaderBar:show-title instead.` — a real GTK diagnostic that
617
- * the React Native half has no counterpart for, and one the GTK suite's
618
- * `installDiagnosticsGate` fails on. It is not `g_return_if_fail`, so the widget still
619
- * works; it is the difference between an omitted title and a deliberate one.
564
+ * title, consider using AdwHeaderBar:show-title instead.` — a real GTK diagnostic the
565
+ * React Native half has no counterpart for, and one the GTK suite's `installDiagnosticsGate`
566
+ * fails on. It is not `g_return_if_fail`, so the widget still works.
620
567
  */
621
568
  title?: string;
622
569
  /**
@@ -645,11 +592,9 @@ export interface AdwNavigationPageProps extends AdwWidgetProps {
645
592
  * `custom-image` hits on {@link AdwAvatarProps}. The tag overloads are strings on both
646
593
  * halves, and a tag is what makes a page addressable at all, so those are the surface.
647
594
  *
648
- * `visiblePageTag`, `canGoBack` and `backButtonTooltip` are METHODS rather than
649
- * properties because they are reads of live widget state: `Adw.NavigationView` answers
650
- * them from its own stack, the React Native half from `NavigationViewState`, and a
651
- * value snapshotted into an object at `useImperativeHandle` time would be stale by the
652
- * first push.
595
+ * `visiblePageTag`, `canGoBack` and `backButtonTooltip` are METHODS rather than properties
596
+ * because they are reads of LIVE widget state: a value snapshotted into an object at
597
+ * `useImperativeHandle` time would be stale by the first push.
653
598
  */
654
599
  export interface AdwNavigationViewHandle {
655
600
  /**
@@ -690,11 +635,10 @@ export interface AdwNavigationViewProps extends AdwWidgetProps {
690
635
  /**
691
636
  * `animate-transitions` — whether a push or a pop slides. Default true.
692
637
  *
693
- * CARRIED ON BOTH HALVES AND ANIMATED ONLY ON GTK, which is the same shape
694
- * `@gjsify/adwaita-nativescript` records ("kept for API parity"): this package has
695
- * no animation layer, so the swap is instant on React Native either way. The value
696
- * still reaches `NavigationViewState`, whose `finishTransition()` seam is what a
697
- * renderer with no animation settles immediately.
638
+ * CARRIED ON BOTH HALVES AND ANIMATED ONLY ON GTK: this package has no animation
639
+ * layer, so the swap is instant on React Native either way. The value still reaches
640
+ * `NavigationViewState`, whose `finishTransition()` seam is what a renderer with no
641
+ * animation settles immediately.
698
642
  */
699
643
  animateTransitions?: boolean;
700
644
  /**
@@ -710,12 +654,11 @@ export interface AdwNavigationViewProps extends AdwWidgetProps {
710
654
  /**
711
655
  * The four sizing properties both split views share, under libadwaita's own names.
712
656
  *
713
- * They come as a QUARTET and not a single width because that is what the widgets are:
714
- * a FRACTION of the view, clamped between a minimum and a maximum, with the two bounds
715
- * written in a scale-aware unit. `@gjsify/adwaita-core` resolves them —
716
- * `resolveSidebarBounds` then `resolveNavigationSidebarWidth` /
717
- * `resolveOverlaySidebarWidth`, which answer the SAME input differently and both
718
- * halves of this package run.
657
+ * They come as a QUARTET and not a single width because that is what the widgets are: a
658
+ * FRACTION of the view, clamped between a minimum and a maximum, with the two bounds written
659
+ * in a scale-aware unit. `@gjsify/adwaita-core` resolves them — `resolveSidebarBounds` then
660
+ * `resolveNavigationSidebarWidth` / `resolveOverlaySidebarWidth`, which answer the SAME
661
+ * input differently and both halves of this package run.
719
662
  */
720
663
  export interface AdwSidebarWidthProps {
721
664
  /** `min-sidebar-width`, in {@link sidebarWidthUnit}. Default 180. */
@@ -736,13 +679,10 @@ export interface AdwSidebarWidthProps {
736
679
  * by a `slot` prop on the CHILD, which a `ReactNode` handed in as a prop has nothing
737
680
  * to carry.
738
681
  *
739
- * BOTH PANES ARE WRAPPED IN AN `Adw.NavigationPage` ON GTK, and that is not a
740
- * convenience: `adw_navigation_split_view_set_sidebar` takes an `AdwNavigationPage`,
741
- * so an unwrapped `Gtk.Box` is a rejected child. Hence the four `sidebar*` /
742
- * `content*` page properties below — the tag pair is what
743
- * `@gjsify/adwaita-nativescript` calls `sidebarTag`/`contentTag` for exactly this
744
- * reason ("a `View` is not an `Adw.NavigationPage`"), and `@gjsify/adwaita-web` reads
745
- * the same `tag` off its slotted pane.
682
+ * BOTH PANES ARE WRAPPED IN AN `Adw.NavigationPage` ON GTK, and that is not a convenience:
683
+ * `adw_navigation_split_view_set_sidebar` takes an `AdwNavigationPage`, so an unwrapped
684
+ * `Gtk.Box` is a rejected child. Hence the four `sidebar*` / `content*` page properties
685
+ * below.
746
686
  */
747
687
  export interface AdwNavigationSplitViewProps extends AdwWidgetProps, AdwSidebarWidthProps {
748
688
  /** `sidebar` — the sidebar pane's content. */
@@ -760,10 +700,10 @@ export interface AdwNavigationSplitViewProps extends AdwWidgetProps, AdwSidebarW
760
700
  /**
761
701
  * `show-content` — which pane a COLLAPSED view shows. Default false (the sidebar).
762
702
  *
763
- * It is not the whole answer, which is the widget's entire point: a LONE child
764
- * stays visible whatever this says, and with `sidebar-position: end` the CONTENT is
765
- * the root page. That ordering table is `resolveNavigationStack` in the core, and
766
- * both halves read `visiblePane` out of it rather than this flag.
703
+ * It is not the whole answer, which is the widget's entire point: a LONE child stays visible
704
+ * whatever this says, and with `sidebar-position: end` the CONTENT is the root page. That
705
+ * ordering table is `resolveNavigationStack` in the core, and both halves read
706
+ * `visiblePane` out of it rather than this flag.
767
707
  */
768
708
  showContent?: boolean;
769
709
  /** `sidebar-position` — which side the sidebar is packed on. Default `start`. */
@@ -804,13 +744,9 @@ export interface AdwOverlaySplitViewProps extends AdwWidgetProps, AdwSidebarWidt
804
744
  /**
805
745
  * One page of an {@link AdwViewStackProps}.
806
746
  *
807
- * IT IS A PROP OBJECT AND NOT A WIDGET, because `Adw.ViewStackPage` is not one: it is
808
- * a GObject the stack hands back from `adw_view_stack_get_page (child)`, so it can be
809
- * neither a JSX child nor a `slot`. Both other renderers reach the same shape from the
810
- * other direction — `@gjsify/adwaita-web` consumes its `<adw-view-stack-page>`
811
- * children into descriptors at connect, `@gjsify/adwaita-nativescript` takes
812
- * `add(content, name, title, icon)` — and `@gjsify/adwaita-core`'s
813
- * `AdwViewStackPageSpec` is the record both already build.
747
+ * IT IS A PROP OBJECT AND NOT A WIDGET, because `Adw.ViewStackPage` is not one: it is a
748
+ * GObject the stack hands back from `adw_view_stack_get_page (child)`, so it can be neither
749
+ * a JSX child nor a `slot`.
814
750
  */
815
751
  export interface AdwViewStackPageProps {
816
752
  /** `name` — the page's identity, and what `visible-child-name` selects. */
@@ -835,9 +771,8 @@ export interface AdwViewStackPageProps {
835
771
  *
836
772
  * `visibleChildName` is AUTHORED, not owned: an absent one leaves the stack on its own
837
773
  * auto-pick (`adw_view_stack_add` selects the first VISIBLE page and notifies), and an
838
- * unknown name is REFUSED rather than clamped — `adw_view_stack_set_visible_child_name`
839
- * warns and leaves the selection alone. Both rules are `ViewStackState`'s, which is
840
- * what `@gjsify/adwaita-web` and `@gjsify/adwaita-nativescript` run too.
774
+ * unknown name is REFUSED rather than clamped — `adw_view_stack_set_visible_child_name` warns
775
+ * and leaves the selection alone. Both rules are `ViewStackState`'s.
841
776
  */
842
777
  export interface AdwViewStackProps {
843
778
  /** The pages, in `add` order. */
@@ -847,28 +782,23 @@ export interface AdwViewStackProps {
847
782
  /**
848
783
  * `notify::visible-child` — the name the stack settled on.
849
784
  *
850
- * WHAT REACHES IT IS NOT THE SAME SET ON THE TWO HALVES, measured. A press on the
851
- * switcher reaches both. A change the CALLER made through {@link visibleChildName}
852
- * reaches the React Native half only, because gtk-host drops the notify raised
853
- * inside its own property write — the rule {@link AdwExpanderRowProps.onNotifyExpanded}
854
- * records. And the mount AUTO-PICK reaches neither: libadwaita notifies it from
855
- * inside `adw_view_stack_add_titled`, before React has committed the `ref` the name
856
- * would be read off, and the core's own auto-pick lands before the subscription
857
- * exists. The README carries the table.
785
+ * WHAT REACHES IT IS NOT THE SAME SET ON THE TWO HALVES, measured. A press on the switcher
786
+ * reaches both. A change the CALLER made through {@link visibleChildName} reaches the React
787
+ * Native half only, because gtk-host drops the notify raised inside its own property
788
+ * write. And the mount AUTO-PICK reaches neither: libadwaita notifies it from inside
789
+ * `adw_view_stack_add_titled`, before React has committed the `ref` the name would be read
790
+ * off. The README carries the table.
858
791
  */
859
792
  onNotifyVisibleChild?: (name: string) => void;
860
793
  }
861
794
  /**
862
795
  * `Adw.ViewSwitcher` — a row of buttons over an {@link AdwViewStackProps}.
863
796
  *
864
- * IT BUNDLES THE STACK LIBADWAITA KEEPS SEPARATE, and so do both other renderers.
865
- * `Adw.ViewSwitcher:stack` is a WIDGET-valued property — the switcher points at an
866
- * `Adw.ViewStack` somewhere else in the tree — and a React prop cannot hold a widget
867
- * that does not exist yet on the half where widgets exist at all. So the switcher owns
868
- * its pages here, exactly as `<adw-view-switcher>` and NativeScript's
869
- * `AdwViewSwitcherBase` do; on GTK it still builds a real `Adw.ViewStack` and hands it
870
- * to a real `Adw.ViewSwitcher` through that property, so nothing about the widget is
871
- * simulated.
797
+ * IT BUNDLES THE STACK LIBADWAITA KEEPS SEPARATE. `Adw.ViewSwitcher:stack` is a
798
+ * WIDGET-valued property, and a React prop cannot hold a widget that does not exist yet on the
799
+ * half where widgets exist at all. So the switcher owns its pages here; on GTK it still builds
800
+ * a real `Adw.ViewStack` and hands it to a real `Adw.ViewSwitcher` through that property, so
801
+ * nothing about the widget is simulated.
872
802
  */
873
803
  export interface AdwViewSwitcherProps extends AdwViewStackProps {
874
804
  /** `policy` — `narrow` stacks icon over label, `wide` puts them side by side. Default `narrow`. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/adwaita-react-native",
3
- "version": "0.53.0",
3
+ "version": "0.55.0",
4
4
  "description": "Adwaita widgets with one API surface and two implementations — the real Adw.* widget on GTK4, React Native primitives on a phone",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -182,8 +182,8 @@
182
182
  "design-system"
183
183
  ],
184
184
  "dependencies": {
185
- "@gjsify/adwaita-core": "^0.53.0",
186
- "@gjsify/gtk-host": "^0.53.0"
185
+ "@gjsify/adwaita-core": "^0.55.0",
186
+ "@gjsify/gtk-host": "^0.55.0"
187
187
  },
188
188
  "peerDependencies": {
189
189
  "react": "^19.2.0",
@@ -198,8 +198,8 @@
198
198
  "@girs/adw-1": "5.4.0",
199
199
  "@girs/gjs": "5.4.0",
200
200
  "@girs/gtk-4.0": "5.4.0",
201
- "@gjsify/cli": "^0.53.0",
202
- "@gjsify/unit": "^0.53.0",
201
+ "@gjsify/cli": "^0.55.0",
202
+ "@gjsify/unit": "^0.55.0",
203
203
  "@types/node": "^25.9.2",
204
204
  "@types/react": "^19.2.2",
205
205
  "@types/react-test-renderer": "^19.1.0",