@gjsify/adwaita-nativescript 0.31.0 → 0.33.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 (147) hide show
  1. package/lib/esm/index.js +1 -1
  2. package/lib/esm/widgets/adw-action-row.js +1 -1
  3. package/lib/esm/widgets/adw-avatar.js +1 -1
  4. package/lib/esm/widgets/adw-banner.js +1 -1
  5. package/lib/esm/widgets/adw-bottom-sheet.js +1 -1
  6. package/lib/esm/widgets/adw-button-content.js +1 -1
  7. package/lib/esm/widgets/adw-button-row.js +1 -1
  8. package/lib/esm/widgets/adw-carousel.js +1 -1
  9. package/lib/esm/widgets/adw-clamp.js +1 -1
  10. package/lib/esm/widgets/adw-combo-row.js +1 -1
  11. package/lib/esm/widgets/adw-data-grid.js +1 -0
  12. package/lib/esm/widgets/adw-drop-down.js +1 -0
  13. package/lib/esm/widgets/adw-entry-row.js +1 -1
  14. package/lib/esm/widgets/adw-entry.js +1 -0
  15. package/lib/esm/widgets/adw-expander-row.js +1 -1
  16. package/lib/esm/widgets/adw-header-bar.js +1 -1
  17. package/lib/esm/widgets/adw-inline-view-switcher.js +1 -1
  18. package/lib/esm/widgets/adw-navigation-split-view.js +1 -1
  19. package/lib/esm/widgets/adw-navigation-view.js +1 -1
  20. package/lib/esm/widgets/adw-overlay-split-view.js +1 -1
  21. package/lib/esm/widgets/adw-password-entry-row.js +1 -1
  22. package/lib/esm/widgets/adw-preferences-dialog.js +1 -1
  23. package/lib/esm/widgets/adw-preferences-group.js +1 -1
  24. package/lib/esm/widgets/adw-preferences-page.js +1 -1
  25. package/lib/esm/widgets/adw-sidebar.js +1 -1
  26. package/lib/esm/widgets/adw-spin-row.js +1 -1
  27. package/lib/esm/widgets/adw-spinner.js +1 -1
  28. package/lib/esm/widgets/adw-split-button.js +1 -1
  29. package/lib/esm/widgets/adw-status-page.js +1 -1
  30. package/lib/esm/widgets/adw-switch-row.js +1 -1
  31. package/lib/esm/widgets/adw-tab-view.js +1 -1
  32. package/lib/esm/widgets/adw-toolbar-view.js +1 -1
  33. package/lib/esm/widgets/adw-view-stack.js +1 -1
  34. package/lib/esm/widgets/adw-view-switcher-bar.js +1 -1
  35. package/lib/esm/widgets/adw-window-title.js +1 -1
  36. package/lib/esm/widgets/adw-wrap-box.js +1 -1
  37. package/lib/esm/widgets/avatar-color.js +1 -0
  38. package/lib/esm/widgets/bottom-sheet-state.js +1 -0
  39. package/lib/esm/widgets/button-content.js +1 -0
  40. package/lib/esm/widgets/carousel-state.js +1 -0
  41. package/lib/esm/widgets/chrome.js +1 -0
  42. package/lib/esm/widgets/data-grid-model.js +1 -0
  43. package/lib/esm/widgets/entry-row-view.js +1 -0
  44. package/lib/esm/widgets/icon-path.js +2 -2
  45. package/lib/esm/widgets/icons.ios.js +1 -0
  46. package/lib/esm/widgets/index.js +1 -1
  47. package/lib/esm/widgets/navigation-stack.js +1 -0
  48. package/lib/esm/widgets/preferences-group-state.js +1 -0
  49. package/lib/esm/widgets/preferences-search.js +1 -0
  50. package/lib/esm/widgets/row-state.js +1 -0
  51. package/lib/esm/widgets/sidebar-model.js +1 -0
  52. package/lib/esm/widgets/split-button.js +1 -0
  53. package/lib/esm/widgets/split-view-base.js +1 -1
  54. package/lib/esm/widgets/split-view-state.js +1 -0
  55. package/lib/esm/widgets/split-view-width.js +1 -0
  56. package/lib/esm/widgets/status-page-content.js +1 -0
  57. package/lib/esm/widgets/svg-path.js +2 -0
  58. package/lib/esm/widgets/tab-view-state.js +1 -0
  59. package/lib/esm/widgets/view-stack-state.js +1 -0
  60. package/lib/esm/widgets/view-switcher-base.js +1 -1
  61. package/lib/esm/widgets/view-switcher-model.js +1 -0
  62. package/lib/esm/widgets/wrap-box-layout.js +1 -0
  63. package/lib/types/banner.spec.d.ts +2 -0
  64. package/lib/types/bottom-sheet.spec.d.ts +2 -0
  65. package/lib/types/button-content.spec.d.ts +2 -0
  66. package/lib/types/carousel.spec.d.ts +1 -0
  67. package/lib/types/chrome.spec.d.ts +2 -0
  68. package/lib/types/data-grid.spec.d.ts +2 -0
  69. package/lib/types/drop-down.spec.d.ts +2 -0
  70. package/lib/types/entry-rows.spec.d.ts +2 -0
  71. package/lib/types/entry.spec.d.ts +2 -0
  72. package/lib/types/index.d.ts +2 -2
  73. package/lib/types/navigation-view.spec.d.ts +2 -0
  74. package/lib/types/preferences.spec.d.ts +2 -0
  75. package/lib/types/row-state.spec.d.ts +2 -0
  76. package/lib/types/sidebar.spec.d.ts +1 -0
  77. package/lib/types/split-button.spec.d.ts +1 -0
  78. package/lib/types/split-view-state.spec.d.ts +2 -0
  79. package/lib/types/split-view-width.spec.d.ts +2 -0
  80. package/lib/types/status-page.spec.d.ts +2 -0
  81. package/lib/types/svg-path.spec.d.ts +2 -0
  82. package/lib/types/tab-view.spec.d.ts +2 -0
  83. package/lib/types/view-stack.spec.d.ts +2 -0
  84. package/lib/types/view-switcher.spec.d.ts +1 -0
  85. package/lib/types/widgets/adw-action-row.d.ts +63 -7
  86. package/lib/types/widgets/adw-avatar.d.ts +2 -7
  87. package/lib/types/widgets/adw-banner.d.ts +26 -7
  88. package/lib/types/widgets/adw-bottom-sheet.d.ts +29 -11
  89. package/lib/types/widgets/adw-button-content.d.ts +41 -6
  90. package/lib/types/widgets/adw-button-row.d.ts +31 -9
  91. package/lib/types/widgets/adw-carousel.d.ts +70 -15
  92. package/lib/types/widgets/adw-clamp.d.ts +21 -4
  93. package/lib/types/widgets/adw-combo-row.d.ts +9 -0
  94. package/lib/types/widgets/adw-data-grid.d.ts +73 -0
  95. package/lib/types/widgets/adw-drop-down.d.ts +45 -0
  96. package/lib/types/widgets/adw-entry-row.d.ts +98 -2
  97. package/lib/types/widgets/adw-entry.d.ts +43 -0
  98. package/lib/types/widgets/adw-expander-row.d.ts +3 -0
  99. package/lib/types/widgets/adw-header-bar.d.ts +11 -2
  100. package/lib/types/widgets/adw-inline-view-switcher.d.ts +26 -0
  101. package/lib/types/widgets/adw-navigation-split-view.d.ts +23 -1
  102. package/lib/types/widgets/adw-navigation-view.d.ts +71 -16
  103. package/lib/types/widgets/adw-overlay-split-view.d.ts +29 -2
  104. package/lib/types/widgets/adw-password-entry-row.d.ts +33 -3
  105. package/lib/types/widgets/adw-preferences-dialog.d.ts +18 -0
  106. package/lib/types/widgets/adw-preferences-group.d.ts +56 -8
  107. package/lib/types/widgets/adw-preferences-page.d.ts +32 -1
  108. package/lib/types/widgets/adw-sidebar.d.ts +49 -7
  109. package/lib/types/widgets/adw-spinner.d.ts +22 -6
  110. package/lib/types/widgets/adw-split-button.d.ts +48 -13
  111. package/lib/types/widgets/adw-status-page.d.ts +5 -10
  112. package/lib/types/widgets/adw-switch-row.d.ts +21 -1
  113. package/lib/types/widgets/adw-tab-view.d.ts +129 -15
  114. package/lib/types/widgets/adw-toolbar-view.d.ts +39 -0
  115. package/lib/types/widgets/adw-view-stack.d.ts +30 -27
  116. package/lib/types/widgets/adw-view-switcher-bar.d.ts +22 -10
  117. package/lib/types/widgets/adw-window-title.d.ts +12 -8
  118. package/lib/types/widgets/adw-wrap-box.d.ts +93 -7
  119. package/lib/types/widgets/avatar-color.d.ts +14 -0
  120. package/lib/types/widgets/bottom-sheet-state.d.ts +73 -0
  121. package/lib/types/widgets/button-content.d.ts +43 -0
  122. package/lib/types/widgets/carousel-state.d.ts +85 -0
  123. package/lib/types/widgets/chrome.d.ts +161 -0
  124. package/lib/types/widgets/data-grid-model.d.ts +104 -0
  125. package/lib/types/widgets/entry-row-view.d.ts +88 -0
  126. package/lib/types/widgets/icon-path.d.ts +20 -0
  127. package/lib/types/widgets/icons.ios.d.ts +13 -0
  128. package/lib/types/widgets/index.d.ts +20 -5
  129. package/lib/types/widgets/navigation-stack.d.ts +153 -0
  130. package/lib/types/widgets/preferences-group-state.d.ts +52 -0
  131. package/lib/types/widgets/preferences-search.d.ts +68 -0
  132. package/lib/types/widgets/row-state.d.ts +71 -0
  133. package/lib/types/widgets/sidebar-model.d.ts +18 -0
  134. package/lib/types/widgets/split-button.d.ts +55 -0
  135. package/lib/types/widgets/split-view-base.d.ts +72 -12
  136. package/lib/types/widgets/split-view-state.d.ts +228 -0
  137. package/lib/types/widgets/split-view-width.d.ts +76 -0
  138. package/lib/types/widgets/status-page-content.d.ts +23 -0
  139. package/lib/types/widgets/svg-path.d.ts +28 -0
  140. package/lib/types/widgets/tab-view-state.d.ts +74 -0
  141. package/lib/types/widgets/view-stack-state.d.ts +35 -0
  142. package/lib/types/widgets/view-switcher-base.d.ts +75 -33
  143. package/lib/types/widgets/view-switcher-model.d.ts +114 -0
  144. package/lib/types/widgets/wrap-box-layout.d.ts +97 -0
  145. package/lib/types/wrap-box.spec.d.ts +2 -0
  146. package/package.json +7 -7
  147. package/src/theme/adwaita.css +413 -8
@@ -0,0 +1,228 @@
1
+ import type { AdwPackType, AdwTextDirection, NavigationActionResult, NavigationStackPlan, OverlaySplitViewOptions, SplitViewPane } from '@gjsify/adwaita-core';
2
+ export type { AdwPackType, NavigationStackPlan, SplitViewPane };
3
+ /** Payload of the `notify::show-sidebar` a state change asks the widget to emit. */
4
+ export interface NsShowSidebarNotification {
5
+ /** Whether the sidebar is meant to be shown. */
6
+ showSidebar: boolean;
7
+ /** Whether the view is in its collapsed (narrow) mode. */
8
+ collapsed: boolean;
9
+ }
10
+ /**
11
+ * The NativeScript side of a split view: what a state change makes it do.
12
+ *
13
+ * Only the changes with real ordering or animation semantics come through here.
14
+ * Structural mutations (mounting a pane, moving the sidebar to the other side)
15
+ * stay the widget's own business, because they also have to re-declare the grid
16
+ * columns — a callback would only be able to run after that anyway.
17
+ */
18
+ export interface NsSplitViewHost {
19
+ /** Re-run the structural layout for the SETTLED state. Instant. */
20
+ applyLayout(): void;
21
+ /** Run the animated sidebar reveal / master⇄detail swap — a user-driven toggle. */
22
+ transitionSidebar(): void;
23
+ /** Re-emit `notify::show-sidebar`. */
24
+ notifyShowSidebar(event: NsShowSidebarNotification): void;
25
+ }
26
+ /** The `collapsed` + `show-sidebar` surface `AdwSplitViewBase` delegates to. */
27
+ export interface NsSplitViewState {
28
+ /** Whether the panes are stacked (one at a time) rather than side by side. */
29
+ readonly collapsed: boolean;
30
+ /** Whether the sidebar is meant to be shown. */
31
+ readonly showSidebar: boolean;
32
+ /** Which side the sidebar is packed on. */
33
+ readonly sidebarPosition: AdwPackType;
34
+ /** Attach the widget. Called exactly once, from the base constructor. */
35
+ bind(host: NsSplitViewHost): void;
36
+ /** Collapse or expand. Returns whether it changed. */
37
+ setCollapsed(value: boolean): boolean;
38
+ /** Show or hide the sidebar. Returns whether it changed. */
39
+ setShowSidebar(value: boolean): boolean;
40
+ /** Move the sidebar to the other side. Returns whether it changed. */
41
+ setSidebarPosition(position: AdwPackType): boolean;
42
+ /** Record that a pane was mounted or unmounted. Returns whether it changed. */
43
+ setPaneMounted(pane: SplitViewPane, mounted: boolean): boolean;
44
+ }
45
+ /**
46
+ * Which of the two grid columns each pane takes.
47
+ *
48
+ * `AdwSplitViewBase._syncColumns` makes the SIDEBAR's column the fixed (`'auto'`)
49
+ * one and the content's the expanding (`'star'`) one, ordered by
50
+ * `sidebar-position`. So a pane placed in the wrong column is not merely
51
+ * mirrored — it also swaps its sizing mode, which is what made an
52
+ * `end`-positioned navigation split view fully inverted: it wrote the sidebar
53
+ * into column 0 and the content into column 1 unconditionally, while the base had
54
+ * already made column 0 the star column. libadwaita allocates an `end` sidebar at
55
+ * `width - sidebar_width` (adw-navigation-split-view.c:306-316).
56
+ */
57
+ export declare function splitViewColumns(sidebarPosition: AdwPackType, direction?: AdwTextDirection): {
58
+ sidebar: number;
59
+ content: number;
60
+ };
61
+ /**
62
+ * `Adw.OverlaySplitView` bound to a NativeScript widget.
63
+ *
64
+ * Holds an `OverlaySplitViewState` and turns its notifications into the two
65
+ * things NativeScript can do: re-lay the panes out, or animate the reveal. The
66
+ * widget keeps ZERO split-view state.
67
+ *
68
+ * The reveal itself is NOT driven from here. NativeScript animates with a native
69
+ * `View.animate()` on `translateX`/`opacity`, not by sampling a progress value,
70
+ * so the core's `SplitViewAnimator` seam stays on its instant default and
71
+ * `show-progress` settles at 0 or 1 — which is also what a renderer without a
72
+ * spring gets from `adw_animation_skip`.
73
+ */
74
+ export declare class NsOverlaySplitViewState implements NsSplitViewState {
75
+ private readonly _state;
76
+ private _host;
77
+ /**
78
+ * True while {@link setCollapsed} runs. The `show-sidebar` flip it couples is
79
+ * STRUCTURAL, not a user toggle: `set_collapsed` passes `animate = FALSE`
80
+ * (adw-overlay-split-view.c:1457-1458) and the `collapsed` notification right
81
+ * behind it re-lays the whole view out anyway.
82
+ */
83
+ private _coupling;
84
+ constructor(options?: OverlaySplitViewOptions);
85
+ bind(host: NsSplitViewHost): void;
86
+ /** Whether the sidebar overlays the content instead of sitting beside it. */
87
+ get collapsed(): boolean;
88
+ /** Whether the sidebar is meant to be shown. */
89
+ get showSidebar(): boolean;
90
+ /** Whether collapsing/uncollapsing leaves the sidebar's visibility alone. */
91
+ get pinSidebar(): boolean;
92
+ /** Which side the sidebar is packed on. */
93
+ get sidebarPosition(): AdwPackType;
94
+ /** The reveal progress: 0 hidden, 1 shown. */
95
+ get showProgress(): number;
96
+ /** Whether the tap-to-dismiss scrim takes input — `update_shield` (:249-256). */
97
+ get shieldVisible(): boolean;
98
+ /**
99
+ * Whether the SIDEBAR pane may take focus — `gtk_widget_set_can_focus
100
+ * (sidebar_bin, !collapsed || show_sidebar)` (:330, :1460).
101
+ *
102
+ * NativeScript's equivalent is `isUserInteractionEnabled` (the precedent is
103
+ * the decorative bottom-sheet handle, adw-bottom-sheet.c:1198). Without it the
104
+ * pane hidden behind the overlay keeps answering taps and stays in the
105
+ * screen-reader order.
106
+ */
107
+ get sidebarFocusable(): boolean;
108
+ /** Whether the CONTENT pane may take focus — the mirror of {@link sidebarFocusable} (:331, :1461). */
109
+ get contentFocusable(): boolean;
110
+ /**
111
+ * Collapse or expand. Unless the sidebar is pinned this also flips
112
+ * `show-sidebar` to match, notifying it FIRST — GTK freezes notifications
113
+ * across the whole setter and thaws them in queue order
114
+ * (adw-overlay-split-view.c:1449-1483).
115
+ */
116
+ setCollapsed(value: boolean): boolean;
117
+ /** Show or hide the sidebar — the animated, user-driven path. */
118
+ setShowSidebar(value: boolean): boolean;
119
+ /** Pin the sidebar so collapsing no longer hides it (`pin-sidebar`, :990-992). */
120
+ setPinSidebar(value: boolean): boolean;
121
+ /** Move the sidebar to the other side. The widget re-declares its columns. */
122
+ setSidebarPosition(position: AdwPackType): boolean;
123
+ /**
124
+ * No-op: `Adw.OverlaySplitView` has no navigation stack, so which children
125
+ * exist changes none of its state. Present so the two adapters share one seam.
126
+ */
127
+ setPaneMounted(_pane: SplitViewPane, _mounted: boolean): boolean;
128
+ /** Tap on the scrim — `released_cb` (:431-439) hides the sidebar unconditionally. */
129
+ dismissShield(): boolean;
130
+ private _apply;
131
+ }
132
+ /**
133
+ * `Adw.NavigationSplitView` bound to a NativeScript widget.
134
+ *
135
+ * NativeScript spells the visible pane as `showSidebar`, GTK as `show-content`;
136
+ * they are each other's negation and the core owns the meaning. What the core
137
+ * adds is the whole ordering table: which pane is on top for a given
138
+ * `sidebar-position` × `show-content` × which children exist, and whether
139
+ * reaching it is a push or a pop.
140
+ *
141
+ * Tags and the `navigation.push`/`navigation.pop` actions ARE wired, through an
142
+ * explicit {@link setTag} rather than by handing the core a `View`: a `View` is
143
+ * not a `NavigationPageRef`, and reading a `tag` property off one would silently
144
+ * adopt whatever NativeScript happens to put there. The panes stay tracked by
145
+ * presence with a marker object, and the tag of record lives in the core — which
146
+ * is where it lives in the browser port too, because `setTag` CLEARS a colliding
147
+ * tag and mutating a caller's view to do that would be a surprise.
148
+ */
149
+ export declare class NsNavigationSplitViewState implements NsSplitViewState {
150
+ private readonly _state;
151
+ /** Presence markers — one per pane, so mounting one never looks like the other. */
152
+ private readonly _markers;
153
+ private _host;
154
+ private _plan;
155
+ constructor(options?: {
156
+ sidebarPosition?: AdwPackType;
157
+ collapsed?: boolean;
158
+ showContent?: boolean;
159
+ /** Where a `g_critical` goes on this port. */
160
+ onCritical?: (message: string) => void;
161
+ /** Offer an unmatched `navigation.*` to the parent — how nesting forwards a push. */
162
+ onDelegate?: (action: 'push' | 'pop', tag?: string) => boolean;
163
+ });
164
+ bind(host: NsSplitViewHost): void;
165
+ /**
166
+ * Retag a mounted pane — `check_tags_cb` (adw-navigation-split-view.c:431-460).
167
+ *
168
+ * On a collision the pane KEEPS its page and loses the tag, which is a
169
+ * different failure from mounting a colliding page (that one is refused
170
+ * outright). Returns whether the tag stuck.
171
+ */
172
+ setTag(pane: SplitViewPane, tag: string | null): boolean;
173
+ /** The sidebar page's tag of record, or `null`. */
174
+ get sidebarTag(): string | null;
175
+ /** The content page's tag of record, or `null`. */
176
+ get contentTag(): string | null;
177
+ /** `navigation.push` with `tag` — `navigation_push_cb` (:644-685). */
178
+ push(tag: string): NavigationActionResult;
179
+ /** `navigation.pop` — `navigation_pop_cb` (:687-702). */
180
+ pop(): NavigationActionResult;
181
+ /**
182
+ * `Adw.NavigationSplitView:show-content` under ITS OWN NAME.
183
+ *
184
+ * This port spells the visible pane `showSidebar`, which is the negation —
185
+ * and that costs every consumer a `!(…)`, including the storybook, which
186
+ * carries one purely to bind a shared story arg. Both spellings are here now
187
+ * and neither is derived from a second copy of the flag.
188
+ */
189
+ get showContent(): boolean;
190
+ set showContent(value: boolean);
191
+ /** Whether the panes are stacked (one at a time) rather than side by side. */
192
+ get collapsed(): boolean;
193
+ /** Whether the SIDEBAR is the visible pane — GTK's `show-content`, negated. */
194
+ get showSidebar(): boolean;
195
+ /** Which side the sidebar is packed on. */
196
+ get sidebarPosition(): AdwPackType;
197
+ /** The settled navigation stack, root first. */
198
+ get stack(): readonly SplitViewPane[];
199
+ /**
200
+ * The pane on top of the stack — what a COLLAPSED view shows.
201
+ *
202
+ * Keyed on the stack, not on `showSidebar`: a LONE child stays visible
203
+ * whatever `show-content` says (adw-navigation-split-view.c:389-401), and
204
+ * keying on the flag alone is what rendered a sidebar-only split view blank.
205
+ */
206
+ get visiblePane(): SplitViewPane | null;
207
+ /** Whether `pane` is the one a collapsed view shows. */
208
+ isVisible(pane: SplitViewPane): boolean;
209
+ /**
210
+ * How the last `show-content` change reached its stack: `push`, `pop`, or
211
+ * `replace` for a structural rebuild that NativeScript paints instantly.
212
+ *
213
+ * This is the animation DIRECTION, and it is not `showSidebar`: with
214
+ * `sidebar-position: end` the content is the ROOT page, so showing it is a POP
215
+ * and hiding it a PUSH — the reverse of `start` (:1414-1428). Taking the
216
+ * direction from the flag ran an `end`-positioned swap backwards.
217
+ */
218
+ get transition(): NavigationStackPlan['transition'];
219
+ /** Collapse or expand. `Adw.NavigationSplitView` has no `show-content` coupling (:1341-1353). */
220
+ setCollapsed(value: boolean): boolean;
221
+ /** Show the sidebar (`true`) or the content (`false`) while collapsed. */
222
+ setShowSidebar(value: boolean): boolean;
223
+ /** Move the sidebar to the other side. The widget re-declares its columns. */
224
+ setSidebarPosition(position: AdwPackType): boolean;
225
+ /** Record that a pane was mounted or unmounted — it changes the stack. */
226
+ setPaneMounted(pane: SplitViewPane, mounted: boolean): boolean;
227
+ private _apply;
228
+ }
@@ -0,0 +1,76 @@
1
+ import { DEFAULT_MAX_SIDEBAR_WIDTH, DEFAULT_MIN_SIDEBAR_WIDTH, DEFAULT_SIDEBAR_WIDTH_FRACTION } from '@gjsify/adwaita-core';
2
+ export { DEFAULT_MAX_SIDEBAR_WIDTH, DEFAULT_MIN_SIDEBAR_WIDTH, DEFAULT_SIDEBAR_WIDTH_FRACTION };
3
+ /** The three width properties, as a split view holds them. */
4
+ export interface SidebarWidthProps {
5
+ /** Lower bound in DIPs. Defaults to libadwaita's 180. */
6
+ minSidebarWidth: number;
7
+ /** Upper bound in DIPs. Defaults to libadwaita's 280. */
8
+ maxSidebarWidth: number;
9
+ /** Share of the container the sidebar asks for. Defaults to 0.25. */
10
+ sidebarWidthFraction: number;
11
+ }
12
+ /** The property defaults a fresh split view starts with. */
13
+ export declare function defaultSidebarWidthProps(): SidebarWidthProps;
14
+ /** Which split view is asking — the two answer the same input differently. */
15
+ export type SplitViewWidthRule = 'navigation' | 'overlay';
16
+ /** What the renderer knows about the layout the width is being derived for. */
17
+ export interface SplitViewWidthContext {
18
+ /** The content pane's own minimum width. */
19
+ contentMin?: number;
20
+ /** The sidebar child's own minimum width. */
21
+ sidebarChildMin?: number;
22
+ /**
23
+ * Whether the view is collapsed. Overlay only, and not a detail: COLLAPSED
24
+ * `get_sidebar_width` IGNORES the fraction and clamps the VIEW width instead
25
+ * (adw-overlay-split-view.c:462-463), so on a 360 DIP phone GTK draws 280
26
+ * where a fraction would give 180.
27
+ */
28
+ collapsed?: boolean;
29
+ }
30
+ /**
31
+ * The sidebar width for a container of `totalWidth` DIPs.
32
+ *
33
+ * The two widgets genuinely differ, and not only in a corner: OVERLAY takes a
34
+ * final `min(width, totalWidth - contentMin)`, so it never claims more than the
35
+ * view has left; NAVIGATION folds that same limit into the clamp's UPPER bound,
36
+ * where the LOWER bound can still win — so it may exceed the view. A 100 DIP
37
+ * container with no content minimum at all already splits them: navigation
38
+ * answers 180 (its minimum), overlay answers 100 (all there is).
39
+ *
40
+ * `collapsed` only reaches the overlay rule, because only the overlay has a
41
+ * collapsed sidebar to size — a collapsed NAVIGATION pane fills the view and
42
+ * takes no derived width at all ({@link appliesDerivedSidebarWidth}).
43
+ *
44
+ * `totalWidth <= 0` means the view has not been laid out yet — NativeScript
45
+ * reports a zero size before the first pass — so the MINIMUM is returned rather
46
+ * than a fraction of nothing. That is the smallest thing libadwaita would ever
47
+ * draw, so the first layout can only widen it, never jump down.
48
+ */
49
+ export declare function sidebarWidthFor(totalWidth: number, props: SidebarWidthProps, rule?: SplitViewWidthRule, context?: SplitViewWidthContext): number;
50
+ /**
51
+ * Whether the sidebar pane takes a DERIVED width at all, or sizes itself.
52
+ *
53
+ * Only one case says no, and it is the one that cost a frame-late regression:
54
+ * a COLLAPSED navigation split view has no sidebar column. Its visible page
55
+ * fills the whole view (`gtk_bin_layout_new`,
56
+ * adw-navigation-split-view.c:538), which NativeScript expresses as
57
+ * `width = 'auto'` spanning both columns — so writing a number over it, as the
58
+ * post-layout re-measure did, snapped the full-screen pane back to 180-280 DIP
59
+ * one frame after the collapse.
60
+ *
61
+ * The overlay is deliberately NOT exempt. Its collapsed sidebar really is a
62
+ * clamped-width overlay drawn above the content
63
+ * (adw-overlay-split-view.c:462-463), so it still wants a number — a shared
64
+ * "collapsed means auto" rule would have been wrong for half the callers.
65
+ */
66
+ export declare function appliesDerivedSidebarWidth(collapsed: boolean, rule: SplitViewWidthRule): boolean;
67
+ /**
68
+ * Normalise one width property, keeping a nonsense value from reaching layout.
69
+ *
70
+ * A non-finite or negative input falls back to the default rather than to zero:
71
+ * a zero-width sidebar is indistinguishable from a missing one on screen, which
72
+ * turns a typo into a widget that looks broken instead of one that looks wrong.
73
+ */
74
+ export declare function normalizeWidthProp(value: number, fallback: number): number;
75
+ /** Clamp the fraction into the `[0, 1]` range its GTK property is declared with. */
76
+ export declare function normalizeWidthFraction(value: number): number;
@@ -0,0 +1,23 @@
1
+ /** NativeScript's `visible` / not-in-layout pair, the counterpart of GTK `visible`. */
2
+ export type StatusPageVisibility = 'visible' | 'collapse';
3
+ /**
4
+ * `string_is_not_empty` (adw-status-page.c:91-96), bound to the `visible` of BOTH
5
+ * the title and the description labels (adw-status-page.ui:41-46, :57-62).
6
+ *
7
+ * It is `string && string[0]` — one byte, no trim. A title of `" "` is a
8
+ * VISIBLE title in libadwaita, which is why this takes the raw text and never
9
+ * trims it: trimming would hide a widget GTK draws.
10
+ */
11
+ export declare function statusPageLabelVisibility(text: string | null | undefined): StatusPageVisibility;
12
+ /**
13
+ * `has_image` (adw-status-page.c:83-89), bound to the image's `visible`
14
+ * (adw-status-page.ui:23-28).
15
+ *
16
+ * C is `paintable || (icon_name && icon_name[0])` — two sources, either of which
17
+ * shows the image. This port has no `paintable` counterpart (the icon is an SVG
18
+ * string handed to `AdwIcon`), so only the second half applies; it is kept as its
19
+ * own predicate rather than folded into
20
+ * {@link statusPageLabelVisibility} because upstream really are two different
21
+ * closures, and the missing half is a real gap rather than a simplification.
22
+ */
23
+ export declare function statusPageIconVisibility(icon: string | null | undefined): StatusPageVisibility;
@@ -0,0 +1,28 @@
1
+ /** One absolute drawing command. Every SVG command reduces to these four. */
2
+ export type SvgPathCommand = {
3
+ type: 'M';
4
+ x: number;
5
+ y: number;
6
+ } | {
7
+ type: 'L';
8
+ x: number;
9
+ y: number;
10
+ } | {
11
+ type: 'C';
12
+ x1: number;
13
+ y1: number;
14
+ x2: number;
15
+ y2: number;
16
+ x: number;
17
+ y: number;
18
+ } | {
19
+ type: 'Z';
20
+ };
21
+ /**
22
+ * Parse SVG path data into absolute `M`/`L`/`C`/`Z` commands.
23
+ *
24
+ * Unparsable input yields the commands read so far rather than throwing: a
25
+ * single malformed icon must not take down the view that renders it, which is
26
+ * the same call the Android backend makes when `PathParser` rejects a subpath.
27
+ */
28
+ export declare function parseSvgPath(d: string): SvgPathCommand[];
@@ -0,0 +1,74 @@
1
+ import type { View } from '@nativescript/core';
2
+ import { TabViewState } from '@gjsify/adwaita-core';
3
+ import type { AdwTabPageState, TabViewHandlers, TabViewSelectionChange } from '@gjsify/adwaita-core';
4
+ /** One page of an `AdwTabView`, as a renderer reads it. */
5
+ export type AdwTabPage = AdwTabPageState<View>;
6
+ /** The two `View.visibility` values a stacked page or a tab affordance ever takes. */
7
+ export type NsVisibility = 'visible' | 'collapse';
8
+ /** The model an `AdwTabView` delegates to, typed on the NS `View`. */
9
+ export declare function createTabViewState(handlers?: TabViewHandlers<View>): TabViewState<View>;
10
+ /**
11
+ * The `visibility` each page's content view must carry for the current
12
+ * selection, in page order. Exactly one entry is `'visible'` — none when nothing
13
+ * is selected, which is a real state here: closing the last tab EMPTIES the view
14
+ * (adw-tab-view.c:1912-1913), where the old port refused the close outright.
15
+ */
16
+ export declare function tabPageVisibilities(state: TabViewState<View>): NsVisibility[];
17
+ /** Push {@link tabPageVisibilities} onto the real content views. */
18
+ export declare function applyTabViewVisibility(state: TabViewState<View>): void;
19
+ /**
20
+ * The `visibility` each tab's close button must carry, in page order.
21
+ *
22
+ * `tabCloseVisible` is `(hovering && fullyVisible) || selected || dragging`, and
23
+ * never on a pinned tab (adw-tab.c:124, :645-650). Touch has no hover and this
24
+ * port has no tab drag-and-drop, so `hovering` and `dragging` are constantly
25
+ * false and the predicate REDUCES to "selected, and not pinned" — which is the
26
+ * old port's rule plus the pinned gate it was missing. Calling the shared
27
+ * predicate rather than writing `active` keeps that a derivation instead of a
28
+ * coincidence, and gives the pinned gate for free.
29
+ */
30
+ export declare function tabCloseVisibilities(state: TabViewState<View>): NsVisibility[];
31
+ /**
32
+ * The `visibility` of the whole tab bar — `tabsRevealed` (adw-tab-bar.c:142-164)
33
+ * projected onto NS. The old port had no autohide at all; the bar was added in
34
+ * the constructor and never hidden.
35
+ */
36
+ export declare function tabBarVisibility(state: TabViewState<View>, autohide: boolean): NsVisibility;
37
+ /**
38
+ * The text a tab's label shows.
39
+ *
40
+ * A pinned tab is a single-glyph chip in libadwaita — `adw_tab_constructed`
41
+ * hides its title outright (adw-tab.c:645-650) — so it renders no label at all
42
+ * here either. Everything else shows its title, which is already `''` rather
43
+ * than `undefined` for a page that declared none: the old port assigned
44
+ * `page.title` straight to `Label.text` with no coercion, so an `AdwViewPage`
45
+ * literal without a title rendered the string "undefined".
46
+ */
47
+ export declare function tabLabelText(page: AdwTabPage): string;
48
+ /**
49
+ * The tooltip text for a tab — `tabTooltip`, i.e. the page's own tooltip when it
50
+ * has one and its title otherwise (adw-tab.c:137-146).
51
+ *
52
+ * NS has no tooltip primitive, so this is exposed for a consumer (and for the
53
+ * accessibility label) rather than rendered. It is deliberately the TEXT form:
54
+ * a page-supplied tooltip is Pango markup in C, and NS has no markup sink to
55
+ * push it through.
56
+ */
57
+ export declare function tabTooltipText(page: AdwTabPage): string;
58
+ /** The data half of the `notify::selected-page` event (minus NS's `eventName`/`object`). */
59
+ export interface TabViewNotifyPayload {
60
+ /** Id of the newly-selected page, `null` when the view is empty. */
61
+ selectedId: string | null;
62
+ /** Its index, `-1` when the view is empty. */
63
+ selectedIndex: number;
64
+ /** The previously-selected id, `null` when there was none. */
65
+ previousId: string | null;
66
+ /** `false` for a model-driven pick (auto-select, close successor), `true` otherwise. */
67
+ interactive: boolean;
68
+ }
69
+ /**
70
+ * Project a core change onto the event payload. Kept as a function rather than
71
+ * spreading the change directly so that if the core payload ever grows a live
72
+ * model object, it does not silently leak into an event a consumer holds on to.
73
+ */
74
+ export declare function tabViewNotifyPayload(change: TabViewSelectionChange): TabViewNotifyPayload;
@@ -0,0 +1,35 @@
1
+ import type { View } from '@nativescript/core';
2
+ import { ViewStackState } from '@gjsify/adwaita-core';
3
+ import type { AdwViewStackPageInfo, ViewStackStateChange } from '@gjsify/adwaita-core';
4
+ /** One page registered with an `AdwViewStack`, as a bound switcher reads it. */
5
+ export type AdwViewStackPage = AdwViewStackPageInfo<View>;
6
+ /** The two `View.visibility` values a stacked page ever takes. */
7
+ export type NsPageVisibility = 'visible' | 'collapse';
8
+ /** The selection machine an `AdwViewStack` delegates to, typed on the NS `View`. */
9
+ export declare function createViewStackState(): ViewStackState<View>;
10
+ /**
11
+ * The `visibility` each page's content view must carry for the current
12
+ * selection, in page order. Exactly one entry is `'visible'` — none when nothing
13
+ * is selected, which is a real state here (an empty stack, every page hidden, or
14
+ * the visible page removed).
15
+ */
16
+ export declare function pageVisibilities(state: ViewStackState<View>): NsPageVisibility[];
17
+ /** Push {@link pageVisibilities} onto the real content views. */
18
+ export declare function applyViewStackVisibility(state: ViewStackState<View>): void;
19
+ /** The data half of the `notify::visible-child` event (minus NS's `eventName`/`object`). */
20
+ export interface ViewStackNotifyPayload {
21
+ /** The newly-visible page's index, `-1` when nothing is selected. */
22
+ index: number;
23
+ /** The newly-visible page's name, `''` when nothing is selected. */
24
+ name: string;
25
+ /** The newly-visible page's title, `''` when nothing is selected. */
26
+ title: string;
27
+ /** `false` for an auto-pick (add / hide / show), `true` for an explicit select. */
28
+ interactive: boolean;
29
+ }
30
+ /**
31
+ * Project a core change onto the event payload. Kept as a function rather than
32
+ * spreading the change directly so the `page` descriptor — a live model object —
33
+ * never leaks into an event a consumer might hold on to.
34
+ */
35
+ export declare function viewStackNotifyPayload(change: ViewStackStateChange<View>): ViewStackNotifyPayload;
@@ -1,21 +1,15 @@
1
- import { GridLayout, StackLayout, View, type EventData } from '@nativescript/core';
1
+ import { GridLayout, type EventData } from '@nativescript/core';
2
+ import type { AdwInlineViewSwitcherDisplayMode, AdwViewSwitcherPolicy, ViewSwitcherState } from '@gjsify/adwaita-core';
3
+ import { type AdwViewPage, type ViewSwitcherKind, type ViewSwitcherNotifyPayload } from './view-switcher-model.js';
4
+ export type { AdwViewPage };
2
5
  /** Event name emitted when the selected view changes. Mirrors GObject `notify::selected`. */
3
6
  export declare const NOTIFY_SELECTED = "notify::selected";
4
- /** Payload of the `notify::selected` event. */
5
- export interface NotifyViewSelectedEventData extends EventData {
6
- /** The newly-selected view index. */
7
- selected: number;
8
- /** The newly-selected view's title. */
9
- title: string;
10
- }
11
- /** One page registered with a {@link AdwViewSwitcherBase}. */
12
- export interface AdwViewPage {
13
- /** The switcher button label. */
14
- title: string;
15
- /** The page content view, shown when this page is selected. */
16
- content: View;
17
- /** Optional Adwaita symbolic SVG shown left of the label in the switcher button. */
18
- icon?: string;
7
+ /**
8
+ * Payload of the `notify::selected` event. `selected` is `-1` and `name`/`title`
9
+ * are `''` when nothing is selected — the state an empty switcher and a
10
+ * fully-hidden one both land in.
11
+ */
12
+ export interface NotifyViewSelectedEventData extends EventData, ViewSwitcherNotifyPayload {
19
13
  }
20
14
  /**
21
15
  * Shared base: a switcher bar (row 0) + a content area (row 1), one page visible.
@@ -23,40 +17,88 @@ export interface AdwViewPage {
23
17
  */
24
18
  export declare abstract class AdwViewSwitcherBase extends GridLayout {
25
19
  /** The horizontal switcher bar holding the buttons. */
26
- protected readonly _bar: StackLayout;
20
+ protected readonly _bar: GridLayout;
21
+ /** `Adw.ViewSwitcher:policy`, default NARROW (adw-view-switcher.c:447-451). */
22
+ private _policy;
27
23
  /** The content area where the selected page is shown. */
28
24
  protected readonly _contentArea: GridLayout;
25
+ /** The registered pages, in bar order. */
29
26
  protected readonly _pages: AdwViewPage[];
30
- /** The tappable button containers (one per page), in bar order. */
31
- protected readonly _buttons: StackLayout[];
32
- protected _selected: number;
27
+ /** The headless selection + page model every derivation reads. */
28
+ protected readonly _state: ViewSwitcherState;
29
+ private _nodes;
33
30
  /** CSS class applied to the switcher bar — subclass-specific. */
34
31
  protected abstract get barClass(): string;
35
32
  /** CSS class applied to each switcher button — subclass-specific. */
36
33
  protected abstract get buttonClass(): string;
34
+ /**
35
+ * `AdwViewSwitcher:policy`, which decides the button orientation
36
+ * (adw-view-switcher.c:534-537).
37
+ *
38
+ * It used to be a HARD-CODED `'wide'` with a note saying there was no policy
39
+ * property on NS — so a consumer could not follow a breakpoint, and the
40
+ * default was the opposite of C's, which is `ADW_VIEW_SWITCHER_POLICY_NARROW`
41
+ * (adw-view-switcher.c:447-451). It is a real property now, defaulting to
42
+ * `narrow`; a subclass may still pin it.
43
+ */
44
+ protected get policy(): AdwViewSwitcherPolicy;
45
+ /**
46
+ * `Adw.ViewSwitcher:policy` — settable, defaulting to NARROW as in C
47
+ * (adw-view-switcher.c:447-451).
48
+ *
49
+ * A hard-coded `'wide'` meant an NS consumer could not follow a breakpoint
50
+ * at all, and the value it was pinned to was not even the default.
51
+ */
52
+ get switcherPolicy(): AdwViewSwitcherPolicy;
53
+ set switcherPolicy(value: AdwViewSwitcherPolicy);
54
+ /**
55
+ * What the buttons show. `'both'` for the classic switcher, whose buttons
56
+ * "always have an icon and a label" (adw-view-switcher.c class docs);
57
+ * `AdwInlineViewSwitcher` overrides it with the real
58
+ * `AdwInlineViewSwitcherDisplayMode`.
59
+ */
60
+ protected get buttonDisplayMode(): AdwInlineViewSwitcherDisplayMode;
37
61
  constructor(rootClass: string);
38
62
  /** Initialise the bar class after the subclass fields are ready. */
39
63
  protected _initClasses(): void;
40
- /** Register the view pages. Rebuilds the switcher bar + content stack. */
41
- setViews(pages: AdwViewPage[]): void;
42
- /** Show only the selected page; mark its button active. */
43
- protected _applySelection(): void;
44
64
  /**
45
- * Hook: append extra chrome to a freshly-built button (after icon + label).
46
- * Default no-op. Subclasses (e.g. {@link AdwTabView}) override to add a close
47
- * button. The button is the tappable `StackLayout` container.
65
+ * Register the view pages. Rebuilds the switcher bar + content stack.
66
+ *
67
+ * The SELECTED PAGE survives the rebuild whenever a page of the same name
68
+ * does — libadwaita's selection is a page pointer, not an index
69
+ * (adw-view-stack.c:660-672) — and falls back to the first VISIBLE page
70
+ * otherwise (:1149-1151).
48
71
  */
49
- protected _buildButtonExtras(_button: StackLayout, _page: AdwViewPage, _index: number): void;
72
+ setViews(pages: AdwViewPage[]): void;
73
+ /** Build one button's NS nodes. Painted by {@link _applySelection}. */
74
+ private _buildButton;
50
75
  /**
51
- * Hook: react to a button's active/inactive state on every selection change.
52
- * Default no-op. Subclasses override to e.g. show the close button only on the
53
- * active tab.
76
+ * Which visibility rule this switcher follows — see
77
+ * {@link switcherButtonVisible}, which holds the rule itself so a spec can
78
+ * reach it.
54
79
  */
55
- protected _applyButtonState(_button: StackLayout, _index: number, _active: boolean): void;
80
+ protected get switcherKind(): ViewSwitcherKind;
81
+ /** Paint the derived models: show only the selected page, mark its button active. */
82
+ protected _applySelection(): void;
56
83
  /** The registered view pages. */
57
84
  get views(): AdwViewPage[];
58
85
  set views(pages: AdwViewPage[]);
59
- /** The selected view index. Swaps the visible page + emits `notify::selected`. */
86
+ /**
87
+ * The selected view index, `-1` when nothing is selected. Swaps the visible
88
+ * page + emits `notify::selected`.
89
+ *
90
+ * Out-of-range, negative, fractional and hidden-page indices are all silent
91
+ * NO-OPS — refused, never clamped, exactly as
92
+ * `adw_view_stack_pages_select_item` refuses (adw-view-stack.c:682-684).
93
+ */
60
94
  get selected(): number;
61
95
  set selected(value: number);
96
+ /** Name of the selected page, `''` when nothing is selected. */
97
+ get selectedName(): string;
98
+ /**
99
+ * Show or hide a page by name. Returns whether the SELECTION moved: hiding
100
+ * the selected page falls back to the first still-visible one
101
+ * (`update_child_visible`, adw-view-stack.c:1061-1082).
102
+ */
103
+ setPageVisible(name: string, visible: boolean): boolean;
62
104
  }