@gjsify/adwaita-core 0.31.0 → 0.32.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 (112) hide show
  1. package/lib/esm/about-dialog.js +3 -0
  2. package/lib/esm/action-row.js +1 -0
  3. package/lib/esm/avatar.js +1 -0
  4. package/lib/esm/banner.js +1 -0
  5. package/lib/esm/button-content.js +1 -0
  6. package/lib/esm/carousel.js +1 -0
  7. package/lib/esm/checks.js +1 -0
  8. package/lib/esm/chrome.js +1 -0
  9. package/lib/esm/conformance/about-dialog.js +6 -0
  10. package/lib/esm/conformance/action-row.js +1 -0
  11. package/lib/esm/conformance/avatar.js +1 -0
  12. package/lib/esm/conformance/banner.js +1 -0
  13. package/lib/esm/conformance/button-content.js +1 -0
  14. package/lib/esm/conformance/carousel.js +1 -0
  15. package/lib/esm/conformance/checks.js +1 -0
  16. package/lib/esm/conformance/chrome.js +1 -0
  17. package/lib/esm/conformance/data-grid.js +1 -0
  18. package/lib/esm/conformance/dialog.js +1 -0
  19. package/lib/esm/conformance/entry-row.js +1 -0
  20. package/lib/esm/conformance/index.js +1 -0
  21. package/lib/esm/conformance/navigation-view.js +1 -0
  22. package/lib/esm/conformance/popover.js +1 -0
  23. package/lib/esm/conformance/preferences.js +1 -0
  24. package/lib/esm/conformance/rows.js +1 -0
  25. package/lib/esm/conformance/sidebar.js +1 -0
  26. package/lib/esm/conformance/split-button.js +1 -0
  27. package/lib/esm/conformance/split-view.js +1 -0
  28. package/lib/esm/conformance/tab-view.js +1 -0
  29. package/lib/esm/conformance/view-stack.js +1 -0
  30. package/lib/esm/conformance/view-switcher.js +1 -0
  31. package/lib/esm/conformance/wrap-box.js +1 -0
  32. package/lib/esm/data-grid.js +1 -0
  33. package/lib/esm/dialog.js +1 -1
  34. package/lib/esm/entry-row.js +1 -0
  35. package/lib/esm/glib.js +1 -0
  36. package/lib/esm/index.js +1 -1
  37. package/lib/esm/navigation-view.js +1 -0
  38. package/lib/esm/popover.js +1 -0
  39. package/lib/esm/preferences.js +1 -0
  40. package/lib/esm/rows.js +1 -1
  41. package/lib/esm/sidebar.js +1 -0
  42. package/lib/esm/split-button.js +1 -0
  43. package/lib/esm/split-view.js +1 -0
  44. package/lib/esm/tab-view.js +1 -0
  45. package/lib/esm/view-stack.js +1 -0
  46. package/lib/esm/view-switcher.js +1 -0
  47. package/lib/types/about-dialog.d.ts +391 -0
  48. package/lib/types/about-dialog.spec.d.ts +2 -0
  49. package/lib/types/action-row.d.ts +270 -0
  50. package/lib/types/action-row.spec.d.ts +2 -0
  51. package/lib/types/avatar.d.ts +112 -0
  52. package/lib/types/avatar.spec.d.ts +2 -0
  53. package/lib/types/banner.d.ts +104 -0
  54. package/lib/types/banner.spec.d.ts +2 -0
  55. package/lib/types/button-content.d.ts +141 -0
  56. package/lib/types/button-content.spec.d.ts +2 -0
  57. package/lib/types/carousel.d.ts +535 -0
  58. package/lib/types/carousel.spec.d.ts +2 -0
  59. package/lib/types/checks.d.ts +63 -0
  60. package/lib/types/checks.spec.d.ts +2 -0
  61. package/lib/types/chrome.d.ts +355 -0
  62. package/lib/types/chrome.spec.d.ts +2 -0
  63. package/lib/types/conformance/about-dialog.d.ts +300 -0
  64. package/lib/types/conformance/action-row.d.ts +186 -0
  65. package/lib/types/conformance/avatar.d.ts +61 -0
  66. package/lib/types/conformance/banner.d.ts +91 -0
  67. package/lib/types/conformance/button-content.d.ts +110 -0
  68. package/lib/types/conformance/carousel.d.ts +284 -0
  69. package/lib/types/conformance/checks.d.ts +29 -0
  70. package/lib/types/conformance/chrome.d.ts +195 -0
  71. package/lib/types/conformance/data-grid.d.ts +134 -0
  72. package/lib/types/conformance/dialog.d.ts +97 -0
  73. package/lib/types/conformance/entry-row.d.ts +185 -0
  74. package/lib/types/conformance/index.d.ts +44 -0
  75. package/lib/types/conformance/navigation-view.d.ts +235 -0
  76. package/lib/types/conformance/popover.d.ts +56 -0
  77. package/lib/types/conformance/preferences.d.ts +170 -0
  78. package/lib/types/conformance/rows.d.ts +51 -0
  79. package/lib/types/conformance/sidebar.d.ts +182 -0
  80. package/lib/types/conformance/split-button.d.ts +189 -0
  81. package/lib/types/conformance/split-view.d.ts +290 -0
  82. package/lib/types/conformance/tab-view.d.ts +441 -0
  83. package/lib/types/conformance/view-stack.d.ts +121 -0
  84. package/lib/types/conformance/view-switcher.d.ts +443 -0
  85. package/lib/types/conformance/wrap-box.d.ts +134 -0
  86. package/lib/types/data-grid.d.ts +140 -0
  87. package/lib/types/data-grid.spec.d.ts +2 -0
  88. package/lib/types/dialog.d.ts +144 -0
  89. package/lib/types/entry-row.d.ts +308 -0
  90. package/lib/types/entry-row.spec.d.ts +2 -0
  91. package/lib/types/glib.d.ts +49 -0
  92. package/lib/types/index.d.ts +43 -4
  93. package/lib/types/navigation-view.d.ts +343 -0
  94. package/lib/types/navigation-view.spec.d.ts +2 -0
  95. package/lib/types/popover.d.ts +155 -0
  96. package/lib/types/popover.spec.d.ts +2 -0
  97. package/lib/types/preferences.d.ts +349 -0
  98. package/lib/types/preferences.spec.d.ts +2 -0
  99. package/lib/types/rows.d.ts +49 -2
  100. package/lib/types/sidebar.d.ts +308 -0
  101. package/lib/types/sidebar.spec.d.ts +2 -0
  102. package/lib/types/split-button.d.ts +316 -0
  103. package/lib/types/split-button.spec.d.ts +2 -0
  104. package/lib/types/split-view.d.ts +714 -0
  105. package/lib/types/split-view.spec.d.ts +2 -0
  106. package/lib/types/tab-view.d.ts +616 -0
  107. package/lib/types/tab-view.spec.d.ts +2 -0
  108. package/lib/types/view-stack.d.ts +266 -0
  109. package/lib/types/view-stack.spec.d.ts +2 -0
  110. package/lib/types/view-switcher.d.ts +521 -0
  111. package/lib/types/view-switcher.spec.d.ts +2 -0
  112. package/package.json +8 -4
@@ -0,0 +1,714 @@
1
+ /** `AdwLengthUnit` — the unit min/max sidebar widths are written in. */
2
+ export type AdwLengthUnit = 'px' | 'pt' | 'sp';
3
+ /** `GtkPackType` — which side of the view a pane is packed on. */
4
+ export type AdwPackType = 'start' | 'end';
5
+ /** `GtkTextDirection` — the reading direction `start`/`end` are resolved against. */
6
+ export type AdwTextDirection = 'ltr' | 'rtl';
7
+ /** The dpi `adw_length_unit_to_px` falls back to when `gtk-xft-dpi` is unset. */
8
+ export declare const DEFAULT_DPI = 96;
9
+ /** `min-sidebar-width` default, in {@link DEFAULT_SIDEBAR_WIDTH_UNIT}. */
10
+ export declare const DEFAULT_MIN_SIDEBAR_WIDTH = 180;
11
+ /** `max-sidebar-width` default, in {@link DEFAULT_SIDEBAR_WIDTH_UNIT}. */
12
+ export declare const DEFAULT_MAX_SIDEBAR_WIDTH = 280;
13
+ /** `sidebar-width-fraction` default — a quarter of the total width. */
14
+ export declare const DEFAULT_SIDEBAR_WIDTH_FRACTION = 0.25;
15
+ /** `sidebar-width-unit` default. Both widgets default to scale-independent pixels. */
16
+ export declare const DEFAULT_SIDEBAR_WIDTH_UNIT: AdwLengthUnit;
17
+ /** The minimum grabbable edge width for the reveal gesture — `ADW_SWIPE_BORDER`. */
18
+ export declare const ADW_SWIPE_BORDER = 32;
19
+ /**
20
+ * `adw_length_unit_to_px` (adw-length-unit.c:57-82) — convert `value` to pixels.
21
+ *
22
+ * `pt` and `sp` both scale with the text-scale factor, which GTK reads from
23
+ * `gtk-xft-dpi`; a renderer that has no such setting passes the default 96, where
24
+ * `sp` is a pixel passthrough and `pt` is the familiar 4/3 ratio.
25
+ */
26
+ export declare function adwLengthToPx(unit: AdwLengthUnit, value: number, dpi?: number): number;
27
+ /**
28
+ * GLib's `CLAMP` (gmacros.h) — `x > high ? high : x < low ? low : x`.
29
+ *
30
+ * HIGH is tested FIRST, which only matters when the bounds are inverted
31
+ * (`low > high`) — there GLib returns `low` for anything below it, where
32
+ * `Math.min(high, Math.max(low, x))` returns `high`. Not a curiosity:
33
+ * `allocate_uncollapsed` (adw-navigation-split-view.c:297-304) inverts the bounds
34
+ * whenever the content pane's own minimum leaves less room than
35
+ * `min-sidebar-width`, and libadwaita then keeps the sidebar at its minimum and
36
+ * lets the content overflow.
37
+ */
38
+ /**
39
+ * Whether the sidebar is laid out at `x = 0`, i.e. `sidebar_position ==
40
+ * get_start_or_end (self)` (adw-navigation-split-view.c:220-227,
41
+ * adw-overlay-split-view.c:227-234).
42
+ *
43
+ * `start`/`end` are LOGICAL: under RTL `get_start_or_end` returns `GTK_PACK_END`,
44
+ * so a `start` sidebar is drawn on the RIGHT. This one predicate drives pane
45
+ * placement, the overlay's slide direction and the swipe area — neither renderer
46
+ * mirrored any of them before.
47
+ */
48
+ export declare function isSidebarAtVisualStart(position: AdwPackType, direction?: AdwTextDirection): boolean;
49
+ /** The four sizing properties `Adw.NavigationSplitView` and `Adw.OverlaySplitView` share. */
50
+ export interface SidebarWidthSpec {
51
+ /** `min-sidebar-width`, in {@link sidebarWidthUnit}. Default 180. */
52
+ minSidebarWidth?: number;
53
+ /** `max-sidebar-width`, in {@link sidebarWidthUnit}. Default 280. */
54
+ maxSidebarWidth?: number;
55
+ /** `sidebar-width-fraction` of the total width. Default 0.25. */
56
+ sidebarWidthFraction?: number;
57
+ /** `sidebar-width-unit`. Default `'sp'`. */
58
+ sidebarWidthUnit?: AdwLengthUnit;
59
+ /** The `gtk-xft-dpi` a renderer reports, for `pt`/`sp`. Default 96. */
60
+ dpi?: number;
61
+ }
62
+ /** The resolved pixel bounds a sidebar width is clamped into. */
63
+ export interface SidebarBounds {
64
+ /** Lower bound: the larger of the sidebar child's own minimum and `min-sidebar-width`. */
65
+ min: number;
66
+ /** Upper bound: never below {@link min} — `max-sidebar-width` is raised to it. */
67
+ max: number;
68
+ }
69
+ /**
70
+ * `sidebar_min` / `sidebar_max` in pixels, i.e. the two `MAX (…, length_to_px (…))`
71
+ * lines both widgets open their sizing with.
72
+ *
73
+ * `ceil: true` reproduces the ALLOCATE paths, which wrap the conversion in `ceil()`
74
+ * (adw-navigation-split-view.c:292-300, adw-overlay-split-view.c:452-460);
75
+ * `ceil: false` (the default) reproduces the MEASURE paths, which assign the raw
76
+ * double to an `int` and therefore truncate (adw-navigation-split-view.c:251-256,
77
+ * adw-overlay-split-view.c:545-550). At dpi ≠ 96 the two disagree by a pixel, and
78
+ * that is upstream behaviour, not rounding noise.
79
+ *
80
+ * `max` is raised to `min` BEFORE any other cap, so a `max-sidebar-width` below
81
+ * `min-sidebar-width` is silently widened rather than inverting the range here.
82
+ */
83
+ export declare function resolveSidebarBounds(spec: SidebarWidthSpec, sidebarChildMin?: number, options?: {
84
+ ceil?: boolean;
85
+ }): SidebarBounds;
86
+ /**
87
+ * The sidebar's NATURAL width, estimated from the content's natural width and the
88
+ * fraction — `ceil (content_nat * f / (1 - f))`, clamped into `bounds`
89
+ * (adw-navigation-split-view.c:260-262, adw-overlay-split-view.c:554-556).
90
+ *
91
+ * The sidebar's OWN natural width is deliberately ignored: a sidebar asks for the
92
+ * share of the window the fraction promises it, not for however wide its widest row
93
+ * happens to be.
94
+ *
95
+ * DELIBERATE DEVIATION: the pspec permits `fraction == 1` (range `[0, 1]`), where C
96
+ * divides by zero and the `ceil()`→`int` conversion is undefined. The limit is +∞,
97
+ * which the clamp pins to `max`, so that is returned directly rather than
98
+ * reproducing undefined behaviour.
99
+ */
100
+ export declare function resolveNaturalSidebarWidth(contentNatural: number, bounds: SidebarBounds, fraction: number): number;
101
+ /** Input to {@link resolveNavigationSidebarWidth} / {@link resolveOverlaySidebarWidth}. */
102
+ export interface SidebarWidthInput extends SidebarWidthSpec {
103
+ /** The width the split view itself was allocated. */
104
+ totalWidth: number;
105
+ /** The content pane's own minimum width. Default 0. */
106
+ contentMin?: number;
107
+ /** The sidebar child's own minimum width. Default 0. */
108
+ sidebarChildMin?: number;
109
+ }
110
+ /**
111
+ * `Adw.NavigationSplitView`'s allocated sidebar width
112
+ * (adw-navigation-split-view.c:292-304).
113
+ *
114
+ * The content pane's minimum is protected by capping the MAX BOUND
115
+ * (`sidebar_max = MIN (sidebar_max, width - content_min)`) and only then clamping.
116
+ * When that cap falls below `min`, the bounds invert and {@link glibClamp} keeps the
117
+ * sidebar at its minimum — see the 300px vector, where this returns 180 and
118
+ * {@link resolveOverlaySidebarWidth} returns 100 for the same input.
119
+ */
120
+ export declare function resolveNavigationSidebarWidth(input: SidebarWidthInput): number;
121
+ /**
122
+ * `Adw.OverlaySplitView`'s allocated sidebar width — `get_sidebar_width`
123
+ * (adw-overlay-split-view.c:441-466) plus `allocate_uncollapsed`'s cap
124
+ * (adw-overlay-split-view.c:585).
125
+ *
126
+ * Two differences from the navigation widget, both load-bearing:
127
+ * - COLLAPSED the fraction is IGNORED and the VIEW width is clamped instead, so
128
+ * an overlay sidebar keeps its natural size on a phone rather than shrinking to
129
+ * a quarter of it (and may legitimately end up WIDER than the view);
130
+ * - uncollapsed the content-minimum cap lands on the RESULT, not on the bound.
131
+ */
132
+ export declare function resolveOverlaySidebarWidth(input: SidebarWidthInput & {
133
+ collapsed?: boolean;
134
+ }): number;
135
+ /** Input to {@link measureSplitViewHorizontal}. */
136
+ export interface SplitViewMeasureInput {
137
+ /** Bounds from {@link resolveSidebarBounds} — MEASURE flavour (`ceil: false`). */
138
+ bounds: SidebarBounds;
139
+ /** The sidebar's natural width from {@link resolveNaturalSidebarWidth}. */
140
+ sidebarNatural: number;
141
+ /** The content pane's own minimum width. */
142
+ contentMin: number;
143
+ /** The content pane's own natural width. */
144
+ contentNatural: number;
145
+ /** The overlay's reveal progress. Default 1, which reduces to the navigation rule. */
146
+ showProgress?: number;
147
+ }
148
+ /**
149
+ * The horizontal size request of an uncollapsed split view —
150
+ * `measure_uncollapsed` (adw-overlay-split-view.c:558-563; the navigation variant
151
+ * at adw-navigation-split-view.c:264-267 is the same rule with progress pinned to 1).
152
+ *
153
+ * This is the container MINIMUM neither renderer had, and its absence is why their
154
+ * content pane can be squeezed to nothing: the sidebar is `flex-shrink: 0` (web) or
155
+ * sits in an `auto` column (NativeScript), so it always wins and the content
156
+ * collapses. Feeding this number into the host's own minimum makes the split view
157
+ * refuse to be narrower than sidebar + content instead.
158
+ */
159
+ export declare function measureSplitViewHorizontal(input: SplitViewMeasureInput): {
160
+ minimum: number;
161
+ natural: number;
162
+ };
163
+ /** One pane's horizontal placement, in pixels from the view's left edge. */
164
+ export interface SplitViewPaneRect {
165
+ /** Offset from the view's LEFT edge — negative while a sidebar is slid out. */
166
+ x: number;
167
+ /** Allocated width. */
168
+ width: number;
169
+ }
170
+ /** The two pane rects of an uncollapsed `Adw.NavigationSplitView`. */
171
+ export interface NavigationSplitViewLayout {
172
+ /** The sidebar pane. */
173
+ sidebar: SplitViewPaneRect;
174
+ /** The content pane. */
175
+ content: SplitViewPaneRect;
176
+ }
177
+ /**
178
+ * `allocate_uncollapsed` (adw-navigation-split-view.c:306-316) — the two pane rects,
179
+ * including the RTL mirror that neither renderer had.
180
+ */
181
+ export declare function layoutNavigationSplitView(input: {
182
+ totalWidth: number;
183
+ sidebarWidth: number;
184
+ sidebarPosition?: AdwPackType;
185
+ direction?: AdwTextDirection;
186
+ }): NavigationSplitViewLayout;
187
+ /** The full paint state of an `Adw.OverlaySplitView` allocation. */
188
+ export interface OverlaySplitViewLayout {
189
+ /** The sidebar pane. May be wider than `sidebarWidth` while overshooting. */
190
+ sidebar: SplitViewPaneRect;
191
+ /** The content pane. Fills the whole view when collapsed. */
192
+ content: SplitViewPaneRect;
193
+ /** Whether the click-outside shield takes input — `collapsed && progress > 0`. */
194
+ shieldVisible: boolean;
195
+ /** Whether the sidebar is painted at all — `progress > 0` (snapshot gate). */
196
+ sidebarPainted: boolean;
197
+ /** Shadow-helper progress: **1 = no shadow**, 0 = fully shadowed. */
198
+ shadowProgress: number;
199
+ /** Which edge the shadow is cast from (`GTK_PAN_DIRECTION_LEFT`/`RIGHT`). */
200
+ shadowSide: 'left' | 'right';
201
+ }
202
+ /**
203
+ * `allocate_uncollapsed` (adw-overlay-split-view.c:572-610) and
204
+ * `allocate_collapsed` (:653-703), plus the shield (`update_shield`, :249-256) and
205
+ * the paint gate (`adw_overlay_split_view_snapshot`, :757).
206
+ *
207
+ * The overshoot swap is the subtle part: the swipe tracker enables UPPER overshoot
208
+ * (:1121), so `showProgress` can exceed 1. When the offset then runs past the
209
+ * measured width, libadwaita WIDENS the pane to the offset and pins the offset to
210
+ * the measured width — the sidebar stretches instead of detaching from its edge.
211
+ *
212
+ * `shadowProgress` is inverted relative to the reveal: `adw_shadow_helper` hides
213
+ * the shadow at 1 and paints it fully at 0 (adw-shadow-helper.c:234-249). It is only
214
+ * ALLOCATED in the collapsed layout, and `set_collapsed(FALSE)` re-allocates it at 1
215
+ * (adw-overlay-split-view.c:1466-1477) — which is exactly what the formula returns
216
+ * for an uncollapsed view, so a renderer can apply it unconditionally.
217
+ */
218
+ export declare function layoutOverlaySplitView(input: {
219
+ totalWidth: number;
220
+ sidebarWidth: number;
221
+ showProgress: number;
222
+ collapsed: boolean;
223
+ sidebarPosition?: AdwPackType;
224
+ direction?: AdwTextDirection;
225
+ }): OverlaySplitViewLayout;
226
+ /**
227
+ * `tags_equal` (adw-navigation-split-view.c:413-429) — whether the sidebar and
228
+ * content pages collide on their `Adw.NavigationPage:tag`.
229
+ *
230
+ * Two rules a `a === b` port loses: an ABSENT tag never collides (so two untagged
231
+ * pages are fine), but two EMPTY-STRING tags DO. The comparison is `strcmp`, i.e.
232
+ * byte-exact — no case folding and no Unicode normalisation, so a precomposed and a
233
+ * decomposed `Ü` are different tags.
234
+ *
235
+ * A missing PAGE is passed as `null`, which lands on the same "no tag" answer the C
236
+ * gives for a missing page.
237
+ */
238
+ export declare function tagsConflict(sidebarTag: string | null | undefined, contentTag: string | null | undefined): boolean;
239
+ /** Which of the two panes a stack entry or transition refers to. */
240
+ export type SplitViewPane = 'sidebar' | 'content';
241
+ /** What `update_navigation_stack` does to the underlying `Adw.NavigationView`. */
242
+ export interface NavigationStackPlan {
243
+ /** The pages in the navigation view, root first. The LAST one is visible. */
244
+ stack: SplitViewPane[];
245
+ /** `replace` for a structural rebuild; `push`/`pop` for an animated page change. */
246
+ transition: 'replace' | 'push' | 'pop';
247
+ /** The page being pushed or popped, or `null` for a `replace`. */
248
+ page: SplitViewPane | null;
249
+ }
250
+ /**
251
+ * `update_navigation_stack` (adw-navigation-split-view.c:342-405) — the whole
252
+ * ordering table.
253
+ *
254
+ * Two rules both renderers were missing. A LONE child stays visible no matter what
255
+ * `show-content` says (`self->content && (self->show_content || !self->sidebar)`
256
+ * and its mirror, :389-401) — without it a collapsed split view with only a sidebar
257
+ * renders blank. And with `sidebar-position: end` the CONTENT is the root page, so
258
+ * `show-content: false` means the sidebar is PUSHED ON TOP of the content rather
259
+ * than replacing it.
260
+ *
261
+ * `changingPage` selects the animated branch (:351-387), which requires BOTH
262
+ * children. Its final stack is always identical to the static branch's — it differs
263
+ * only in reaching that stack by a push or a pop, which is the direction a renderer
264
+ * needs for its transition.
265
+ */
266
+ export declare function resolveNavigationStack(input: {
267
+ hasSidebar: boolean;
268
+ hasContent: boolean;
269
+ sidebarPosition: AdwPackType;
270
+ showContent: boolean;
271
+ changingPage?: boolean;
272
+ }): NavigationStackPlan;
273
+ /** What the `navigation.push` / `navigation.pop` actions resolve to. */
274
+ export type NavigationActionResult =
275
+ /** Flip `show-content` — the tag named a pane of THIS split view. */
276
+ {
277
+ kind: 'set-show-content';
278
+ showContent: boolean;
279
+ }
280
+ /** `g_critical`: the tag is already in the stack, so pushing it is a bug. */
281
+ | {
282
+ kind: 'already-in-stack';
283
+ tag: string;
284
+ }
285
+ /** `g_critical`: no pane carries this tag and no ancestor handled it either. */
286
+ | {
287
+ kind: 'not-found';
288
+ tag: string;
289
+ }
290
+ /** Hand the action to the parent widget — an ancestor may own the tag. */
291
+ | {
292
+ kind: 'delegate';
293
+ };
294
+ /** A `navigation.push` / `navigation.pop` activation, as data. */
295
+ export type NavigationActionInput = {
296
+ action: 'push';
297
+ /** The tag the action names. */
298
+ tag: string;
299
+ /** The sidebar page's tag, or `null` when it has none / there is no sidebar. */
300
+ sidebarTag?: string | null;
301
+ /** The content page's tag, or `null` when it has none / there is no content. */
302
+ contentTag?: string | null;
303
+ showContent: boolean;
304
+ collapsed: boolean;
305
+ } | {
306
+ action: 'pop';
307
+ hasSidebar: boolean;
308
+ hasContent: boolean;
309
+ showContent: boolean;
310
+ };
311
+ /**
312
+ * `navigation_push_cb` (adw-navigation-split-view.c:644-685) and
313
+ * `navigation_pop_cb` (:687-702) — the action routing both renderers lack entirely.
314
+ *
315
+ * Three details the shape hides. The CONTENT tag is tested first, so a split view
316
+ * whose panes share a tag pushes the content. The "already in the navigation stack"
317
+ * critical fires for a content-tag push only when `show_content && collapsed` —
318
+ * uncollapsed both panes are on screen, so re-pushing is a harmless no-op set. And
319
+ * an unmatched tag DELEGATES to the parent before it may become a critical, which
320
+ * is how nested split views forward a push outwards.
321
+ *
322
+ * Whether a page is absent or merely untagged makes no difference here: the action
323
+ * always carries a real string, and `g_strcmp0` never matches it against `NULL`.
324
+ */
325
+ export declare function resolveNavigationAction(input: NavigationActionInput): NavigationActionResult;
326
+ /** `g_critical` texts, verbatim from the C so a renderer's diagnostics match GTK's. */
327
+ export declare const NAVIGATION_SPLIT_VIEW_CRITICALS: {
328
+ /** `navigation_push_cb` :657 / :672. */
329
+ readonly alreadyInStack: (tag: string) => string;
330
+ /** `navigation_push_cb` :683. The C also prints the widget pointer, which has no meaning here. */
331
+ readonly notFound: (tag: string) => string;
332
+ /** `adw_navigation_split_view_set_sidebar` :1103. */
333
+ readonly sidebarCollision: (tag: string) => string;
334
+ /** `adw_navigation_split_view_set_content` :1196. */
335
+ readonly contentCollision: (tag: string) => string;
336
+ /** `check_tags_cb` :440. */
337
+ readonly sidebarTagCollision: (tag: string) => string;
338
+ /** `check_tags_cb` :450. */
339
+ readonly contentTagCollision: (tag: string) => string;
340
+ };
341
+ /** A page mounted into a split-view pane. Only its tag is behaviour-relevant. */
342
+ export interface NavigationPageRef {
343
+ /** `Adw.NavigationPage:tag`, or `null`/absent when untagged. */
344
+ tag?: string | null;
345
+ }
346
+ /** Which property a {@link NavigationSplitViewState} change reports. */
347
+ export type NavigationSplitViewProperty = 'sidebar' | 'content' | 'sidebar-position' | 'collapsed' | 'show-content';
348
+ /** Payload of a {@link NavigationSplitViewState} change. */
349
+ export interface NavigationSplitViewChange {
350
+ /** The GObject property that changed — the `notify::<property>` to re-emit. */
351
+ property: NavigationSplitViewProperty;
352
+ /** True for a user-driven `show-content` change (a row tap, a back button). */
353
+ interactive: boolean;
354
+ /** What the renderer should do now: the settled stack plus push/pop direction. */
355
+ plan: NavigationStackPlan;
356
+ }
357
+ /** Subscriber for {@link NavigationSplitViewState} changes. */
358
+ export type NavigationSplitViewListener = (change: NavigationSplitViewChange) => void;
359
+ /** Diagnostics seam — a renderer routes these to `console.error` / `g_critical`. */
360
+ export interface NavigationSplitViewHandlers {
361
+ /** Called with a fully-formatted {@link NAVIGATION_SPLIT_VIEW_CRITICALS} message. */
362
+ onCritical?: (message: string) => void;
363
+ /** Offer an unmatched `navigation.push`/`pop` to the parent. Return whether it was handled. */
364
+ onDelegate?: (action: 'push' | 'pop', tag?: string) => boolean;
365
+ }
366
+ /** Construction options for {@link NavigationSplitViewState}. */
367
+ export interface NavigationSplitViewOptions extends NavigationSplitViewHandlers {
368
+ sidebarPosition?: AdwPackType;
369
+ collapsed?: boolean;
370
+ showContent?: boolean;
371
+ }
372
+ /**
373
+ * `Adw.NavigationSplitView`'s state machine: which pane is visible, the duplicate-tag
374
+ * guard and the `navigation.*` action routing.
375
+ *
376
+ * The tag guard has TWO different failure modes and both matter. Mounting a page
377
+ * whose tag already belongs to the other pane REFUSES THE ASSIGNMENT
378
+ * (adw-navigation-split-view.c:1102-1108 / :1195-1201) — the pane keeps whatever it
379
+ * had. RETAGGING a mounted page instead keeps the page and CLEARS the offending tag
380
+ * (`check_tags_cb`, :431-460), because by then the page is already installed.
381
+ *
382
+ * Tags are held HERE, not written back into the {@link NavigationPageRef} you hand
383
+ * in: {@link setTag} resets a colliding tag, and silently mutating a caller's object
384
+ * to do it would be a surprise. Read {@link sidebarTag} / {@link contentTag} back.
385
+ */
386
+ export declare class NavigationSplitViewState {
387
+ private _sidebar;
388
+ private _content;
389
+ private _sidebarTag;
390
+ private _contentTag;
391
+ private _sidebarPosition;
392
+ private _collapsed;
393
+ private _showContent;
394
+ private readonly _handlers;
395
+ private readonly _listeners;
396
+ constructor(options?: NavigationSplitViewOptions);
397
+ /** Subscribe to state changes. Returns an unsubscribe function. */
398
+ subscribe(listener: NavigationSplitViewListener): () => void;
399
+ private _emit;
400
+ private _critical;
401
+ private _plan;
402
+ /** Whether the panes are stacked (one at a time) rather than side by side. */
403
+ get collapsed(): boolean;
404
+ /** Whether the CONTENT pane is the visible one while collapsed. */
405
+ get showContent(): boolean;
406
+ /** Which side the sidebar is packed on. */
407
+ get sidebarPosition(): AdwPackType;
408
+ /** The mounted sidebar page, or `null`. Its tag of record is {@link sidebarTag}. */
409
+ get sidebar(): NavigationPageRef | null;
410
+ /** The mounted content page, or `null`. Its tag of record is {@link contentTag}. */
411
+ get content(): NavigationPageRef | null;
412
+ /** The sidebar page's tag, or `null` when untagged / unmounted. */
413
+ get sidebarTag(): string | null;
414
+ /** The content page's tag, or `null` when untagged / unmounted. */
415
+ get contentTag(): string | null;
416
+ /** The settled navigation stack — what SHOULD be mounted right now. */
417
+ get stack(): NavigationStackPlan;
418
+ /** The pane on top of the stack, or `null` when neither child is mounted. */
419
+ get visiblePane(): SplitViewPane | null;
420
+ /**
421
+ * Mount (or unmount) the sidebar page. REFUSES a page whose tag the content pane
422
+ * already carries, logging the critical and leaving the sidebar untouched.
423
+ * Returns whether the sidebar changed.
424
+ */
425
+ setSidebar(page: NavigationPageRef | null): boolean;
426
+ /**
427
+ * Mount (or unmount) the content page. REFUSES a page whose tag the sidebar
428
+ * already carries. Returns whether the content changed.
429
+ */
430
+ setContent(page: NavigationPageRef | null): boolean;
431
+ /**
432
+ * Retag a MOUNTED pane. On a collision the page stays but its tag is cleared —
433
+ * `check_tags_cb`'s failure mode, which differs from {@link setSidebar}'s refusal.
434
+ * Returns whether the tag stuck.
435
+ */
436
+ setTag(pane: SplitViewPane, tag: string | null): boolean;
437
+ /** Set which side the sidebar is packed on. Returns whether it changed. */
438
+ setSidebarPosition(position: AdwPackType): boolean;
439
+ /** Collapse or expand the view. Returns whether it changed. */
440
+ setCollapsed(value: boolean): boolean;
441
+ /**
442
+ * Show the content pane (`true`) or the sidebar (`false`).
443
+ *
444
+ * The emitted plan carries a `push`/`pop` transition only when the change is
445
+ * actually animatable — collapsed WITH both children, the condition under which
446
+ * `set_show_content` drives the navigation view instead of just setting the flag
447
+ * (adw-navigation-split-view.c:1403-1428). Returns whether it changed.
448
+ */
449
+ setShowContent(value: boolean, interactive?: boolean): boolean;
450
+ /** Activate `navigation.push` with `tag`, applying the result. */
451
+ push(tag: string): NavigationActionResult;
452
+ /** Activate `navigation.pop`, applying the result. */
453
+ pop(): NavigationActionResult;
454
+ private _runAction;
455
+ }
456
+ /** A running reveal animation, cancellable when a new one supersedes it. */
457
+ export interface SplitViewAnimation {
458
+ /** Stop the animation. Must be safe to call after it already finished. */
459
+ cancel(): void;
460
+ }
461
+ /** What {@link SplitViewAnimator.animate} is asked to run. */
462
+ export interface SplitViewAnimationRequest {
463
+ /** Progress to start from. */
464
+ from: number;
465
+ /** Progress to settle on — 1 shown, 0 hidden. */
466
+ to: number;
467
+ /** Initial velocity, in progress units per second (0 for a plain toggle). */
468
+ velocity: number;
469
+ /** Whether to clamp the spring's overshoot — `to < 0.5` (adw-overlay-split-view.c:288-289). */
470
+ clamp: boolean;
471
+ /** Feed every intermediate progress back to the state. */
472
+ onValue: (progress: number) => void;
473
+ /** Signal that the animation settled. */
474
+ onDone: () => void;
475
+ }
476
+ /**
477
+ * The injected timing seam for the reveal, mirroring `ToastScheduler`. libadwaita
478
+ * uses a spring with params `(1, 0.5, 500)` (adw-overlay-split-view.c:1163-1165);
479
+ * a renderer supplies whatever its platform has — a CSS transition, NativeScript's
480
+ * `View.animate()`, or a deterministic fake in tests.
481
+ */
482
+ export interface SplitViewAnimator {
483
+ animate(request: SplitViewAnimationRequest): SplitViewAnimation;
484
+ }
485
+ /**
486
+ * The default animator: jump straight to `to`. Keeps `OverlaySplitViewState`
487
+ * timer-free and deterministic, so a renderer that has no animation (or has not
488
+ * wired one yet) still gets correct end states.
489
+ */
490
+ export declare const INSTANT_SPLIT_VIEW_ANIMATOR: SplitViewAnimator;
491
+ /** Which property an {@link OverlaySplitViewState} change reports. */
492
+ export type OverlaySplitViewProperty = 'show-sidebar' | 'collapsed' | 'pin-sidebar' | 'sidebar-position' | 'show-progress';
493
+ /** Payload of an {@link OverlaySplitViewState} change. */
494
+ export interface OverlaySplitViewChange {
495
+ /** The GObject property that changed — the `notify::<property>` to re-emit. */
496
+ property: OverlaySplitViewProperty;
497
+ /** Whether the sidebar is meant to be shown. */
498
+ showSidebar: boolean;
499
+ /** Whether the sidebar overlays the content instead of sitting beside it. */
500
+ collapsed: boolean;
501
+ /** The reveal progress, 0…1 (and briefly above 1 while overshooting). */
502
+ showProgress: number;
503
+ /** Whether the click-outside shield takes input. */
504
+ shieldVisible: boolean;
505
+ /**
506
+ * True when the change came from the USER (Escape, a shield click, a released
507
+ * swipe). Extra provenance only: libadwaita notifies for both paths, so do NOT
508
+ * gate the `notify::show-sidebar` re-emit on it.
509
+ */
510
+ interactive: boolean;
511
+ }
512
+ /** Subscriber for {@link OverlaySplitViewState} changes. */
513
+ export type OverlaySplitViewListener = (change: OverlaySplitViewChange) => void;
514
+ /** What releasing a swipe at a snap point means — see {@link resolveSwipeRelease}. */
515
+ export type SwipeReleasePlan =
516
+ /** Settle the progress only; `show-sidebar` already agrees, so nothing notifies. */
517
+ {
518
+ kind: 'animate';
519
+ to: number;
520
+ }
521
+ /** A real `show-sidebar` change, which notifies. */
522
+ | {
523
+ kind: 'set-show-sidebar';
524
+ showSidebar: boolean;
525
+ };
526
+ /** Construction options for {@link OverlaySplitViewState}. */
527
+ export interface OverlaySplitViewOptions {
528
+ collapsed?: boolean;
529
+ showSidebar?: boolean;
530
+ pinSidebar?: boolean;
531
+ sidebarPosition?: AdwPackType;
532
+ enableShowGesture?: boolean;
533
+ enableHideGesture?: boolean;
534
+ /** Reveal timing. Defaults to {@link INSTANT_SPLIT_VIEW_ANIMATOR}. */
535
+ animator?: SplitViewAnimator;
536
+ }
537
+ /**
538
+ * `Adw.OverlaySplitView`'s state machine.
539
+ *
540
+ * The rule worth having lifted is the collapse coupling: unless `pin-sidebar` is
541
+ * set, collapsing HIDES the sidebar and uncollapsing SHOWS it, without animating
542
+ * (`if (!self->pin_sidebar) set_show_sidebar (self, !self->collapsed, FALSE, 0);`,
543
+ * adw-overlay-split-view.c:1454-1455). Neither renderer had it, so BOTH storybooks
544
+ * re-derived it by hand next to their own breakpoint code — the clearest possible
545
+ * evidence that it belongs in the widget.
546
+ *
547
+ * `show-sidebar` defaults to TRUE and `show-progress` to 1 (:1107-1109); the web
548
+ * element's presence-attribute reading had it inverted, so an
549
+ * `<adw-overlay-split-view>` with no attributes started with the sidebar hidden.
550
+ */
551
+ export declare class OverlaySplitViewState {
552
+ private _showSidebar;
553
+ private _collapsed;
554
+ private _pinSidebar;
555
+ private _sidebarPosition;
556
+ private _enableShowGesture;
557
+ private _enableHideGesture;
558
+ private _showProgress;
559
+ private _swipeActive;
560
+ private _animation;
561
+ private readonly _animator;
562
+ private readonly _listeners;
563
+ constructor(options?: OverlaySplitViewOptions);
564
+ /** Subscribe to state changes. Returns an unsubscribe function. */
565
+ subscribe(listener: OverlaySplitViewListener): () => void;
566
+ private _emit;
567
+ /** Whether the sidebar is meant to be shown. */
568
+ get showSidebar(): boolean;
569
+ /** Whether the sidebar overlays the content instead of sitting beside it. */
570
+ get collapsed(): boolean;
571
+ /** Whether collapsing/uncollapsing leaves the sidebar's visibility alone. */
572
+ get pinSidebar(): boolean;
573
+ /** Which side the sidebar is packed on. */
574
+ get sidebarPosition(): AdwPackType;
575
+ /** Whether an edge swipe may OPEN the sidebar. */
576
+ get enableShowGesture(): boolean;
577
+ /** Whether a swipe may CLOSE the sidebar. */
578
+ get enableHideGesture(): boolean;
579
+ /** The reveal progress: 0 hidden, 1 shown, briefly above 1 while overshooting. */
580
+ get showProgress(): number;
581
+ /** Whether the click-outside shield takes input — `update_shield` (:249-256). */
582
+ get shieldVisible(): boolean;
583
+ /** Whether the sidebar is painted at all — the snapshot gate (:757). */
584
+ get sidebarPainted(): boolean;
585
+ /** `gtk_widget_set_can_focus (sidebar_bin, …)` (:330). */
586
+ get sidebarFocusable(): boolean;
587
+ /** `gtk_widget_set_can_focus (content_bin, …)` (:331). */
588
+ get contentFocusable(): boolean;
589
+ /**
590
+ * Show or hide the sidebar — `set_show_sidebar` (:294-360). No-op (and no
591
+ * notification) when the value is unchanged; the public GTK setter animates, so
592
+ * `animate` defaults to true. Returns whether it changed.
593
+ */
594
+ setShowSidebar(value: boolean, options?: {
595
+ animate?: boolean;
596
+ velocity?: number;
597
+ interactive?: boolean;
598
+ }): boolean;
599
+ /**
600
+ * Collapse or expand — `adw_overlay_split_view_set_collapsed` (:1439-1481).
601
+ *
602
+ * Unless the sidebar is pinned this also flips `show-sidebar` to match, WITHOUT
603
+ * animating, and emits that change first: GTK freezes notifications across the
604
+ * whole setter, so `notify::show-sidebar` is queued before `notify::collapsed`
605
+ * and thawed in that order. Returns whether `collapsed` changed.
606
+ */
607
+ setCollapsed(value: boolean): boolean;
608
+ /** Pin the sidebar so collapsing no longer hides it. Returns whether it changed. */
609
+ setPinSidebar(value: boolean): boolean;
610
+ /** Set which side the sidebar is packed on. Returns whether it changed. */
611
+ setSidebarPosition(position: AdwPackType): boolean;
612
+ /** Enable/disable the edge-swipe-to-open gesture. Returns whether it changed. */
613
+ setEnableShowGesture(value: boolean): boolean;
614
+ /** Enable/disable the swipe-to-close gesture. Returns whether it changed. */
615
+ setEnableHideGesture(value: boolean): boolean;
616
+ /**
617
+ * Drive the reveal progress directly — `set_show_progress` (:258-270), the sink
618
+ * an in-flight animation and a live swipe both write to. Does not touch
619
+ * `show-sidebar`.
620
+ */
621
+ setShowProgress(progress: number): void;
622
+ /**
623
+ * Handle Escape — `escape_shortcut_cb` (:705-716). Only a COLLAPSED view with a
624
+ * visible sidebar consumes the key; otherwise it propagates so an enclosing
625
+ * dialog still closes. Returns whether the key was consumed.
626
+ */
627
+ escape(): boolean;
628
+ /**
629
+ * Handle a click on the shield — `released_cb` (:431-439), which hides the
630
+ * sidebar unconditionally. Returns whether anything changed.
631
+ */
632
+ dismissShield(): boolean;
633
+ /** Whether a swipe currently owns the progress. */
634
+ get swipeActive(): boolean;
635
+ /** `begin_swipe_cb` (:389-401) — pause the animation and take over the progress. */
636
+ beginSwipe(): void;
637
+ /**
638
+ * `end_swipe_cb` (:414-429) — settle on `to`. When `to` agrees with the current
639
+ * `show-sidebar` this only animates (no property change, no notification);
640
+ * otherwise it is a real `show-sidebar` change. Returns what was done.
641
+ */
642
+ endSwipe(to: number, velocity?: number): SwipeReleasePlan;
643
+ /** The snap points a swipe may settle on right now. */
644
+ get snapPoints(): number[];
645
+ private _cancelAnimation;
646
+ private _startAnimation;
647
+ }
648
+ /**
649
+ * `adw_overlay_split_view_get_snap_points` (:1214-1243) — where a swipe may settle.
650
+ *
651
+ * A gesture already in flight (`swipeActive`) unlocks both ends regardless of the
652
+ * `enable-*-gesture` properties, so a swipe that started legally can always be
653
+ * completed or cancelled.
654
+ */
655
+ export declare function resolveSwipeSnapPoints(input: {
656
+ showProgress: number;
657
+ enableShowGesture: boolean;
658
+ enableHideGesture: boolean;
659
+ swipeActive: boolean;
660
+ }): number[];
661
+ /**
662
+ * `prepare_cb` (:362-387) — whether a starting swipe is picked up at all.
663
+ *
664
+ * A MID-FLIGHT swipe (neither fully open nor fully closed) is always resumable,
665
+ * which is why the gesture-enable flags are only consulted at the two ends.
666
+ */
667
+ export declare function resolveSwipeStart(input: {
668
+ showProgress: number;
669
+ collapsed: boolean;
670
+ direction: 'forward' | 'back';
671
+ enableShowGesture: boolean;
672
+ enableHideGesture: boolean;
673
+ }): boolean;
674
+ /**
675
+ * `end_swipe_cb` (:414-429) — what releasing a swipe at `to` means.
676
+ *
677
+ * Landing back where `show-sidebar` already is only SETTLES the animation; landing
678
+ * on the other side is a real property change that must notify.
679
+ */
680
+ export declare function resolveSwipeRelease(input: {
681
+ to: number;
682
+ showSidebar: boolean;
683
+ }): SwipeReleasePlan;
684
+ /**
685
+ * `adw_overlay_split_view_get_cancel_progress` (:1253-1258) — where a cancelled
686
+ * swipe snaps back to.
687
+ *
688
+ * C's `round()` is half-away-from-zero; JS `Math.round` is half-UP, so it disagrees
689
+ * for every negative half (`Math.round(-0.5)` is `-0`, C's is `-1`). Progress goes
690
+ * negative on a lower overshoot, so the difference is reachable.
691
+ */
692
+ export declare function swipeCancelProgress(showProgress: number): number;
693
+ /**
694
+ * `adw_overlay_split_view_get_swipe_area` (:1261-1290) — the rectangle that starts
695
+ * a reveal swipe.
696
+ *
697
+ * With the sidebar closed the grabbable strip never shrinks below
698
+ * {@link ADW_SWIPE_BORDER}; once it is open the whole revealed width is grabbable,
699
+ * so the same gesture closes it again.
700
+ */
701
+ export declare function resolveSwipeArea(input: {
702
+ isDrag: boolean;
703
+ sidebarWidth: number;
704
+ showProgress: number;
705
+ totalWidth: number;
706
+ totalHeight: number;
707
+ sidebarPosition?: AdwPackType;
708
+ direction?: AdwTextDirection;
709
+ }): {
710
+ x: number;
711
+ y: number;
712
+ width: number;
713
+ height: number;
714
+ };