@gjsify/adwaita-core 0.30.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,349 @@
1
+ import { stripMnemonic } from './glib.js';
2
+ /**
3
+ * A caseless-compare normaliser, i.e. what `g_utf8_casefold` does for the C.
4
+ *
5
+ * Injected rather than hard-wired — the same seam style as `ToastScheduler` and
6
+ * the avatar's measurement callback — because full Unicode case folding is a
7
+ * DATA TABLE, not a language builtin, and a size-sensitive renderer may
8
+ * legitimately want to trade the table away. Making it a parameter keeps that a
9
+ * documented choice instead of an accident.
10
+ */
11
+ export type CaseFolder = (text: string) => string;
12
+ /**
13
+ * `g_utf8_casefold` (adw-preferences-dialog.c:101, :133) — Unicode FULL case
14
+ * folding, i.e. `toLowerCase()` plus the mappings where a case fold and a
15
+ * lowercase mapping disagree.
16
+ *
17
+ * This is the one place in the family where the obvious implementation ships
18
+ * wrong behaviour in languages people actually use, invisibly to an ASCII test
19
+ * suite. The three canaries, all verified against a real full-folding
20
+ * implementation:
21
+ *
22
+ * | input | `toLowerCase()` | case fold |
23
+ * |----------|-----------------|------------|
24
+ * | `Straße` | `straße` | `strasse` |
25
+ * | `ΟΔΟΣ` | `οδος` | `οδοσ` |
26
+ * | `file` | `file` | `file` |
27
+ *
28
+ * `normalize('NFKC').toLowerCase()` is NOT a substitute: it repairs the
29
+ * ligature, still misses `ß` and final sigma, and OVER-normalises `DŽ` (U+01C4)
30
+ * to the two-character `dž` where a case fold gives the single character `dž`.
31
+ */
32
+ export declare const defaultCaseFolder: CaseFolder;
33
+ /**
34
+ * `g_markup_escape_text` — the escape `create_search_row_subtitle` puts a page
35
+ * title through before it becomes a markup subtitle
36
+ * (adw-preferences-dialog.c:201-207).
37
+ *
38
+ * GLib emits NUMERIC references for the quote characters (`'`, `"`),
39
+ * not `'`/`"`; a port that "tidies" those up produces a different
40
+ * string for the same input. Control characters become `&#xN;` — GLib's own C1
41
+ * branch is unreachable for valid UTF-8 (it compares a signed `char` against
42
+ * `0x7f`-`0x9f`), so only the ASCII controls are escaped here.
43
+ */
44
+ export declare function escapeMarkup(text: string): string;
45
+ /**
46
+ * `pango_parse_markup (text, -1, 0, NULL, &parsed, NULL, &error)` reduced to the
47
+ * part `make_comparable` uses: the plain text, with tags dropped and entities
48
+ * resolved.
49
+ *
50
+ * Returns `null` — NEVER throws — when the markup does not parse, so callers
51
+ * reproduce the C fallback exactly: `g_critical` and keep the UNPARSED string
52
+ * (adw-preferences-dialog.c:110-113). A row whose title contains a bare `&` must
53
+ * stay in the search index under its literal text, not vanish from it.
54
+ *
55
+ * Pango wraps the input in an implicit `<markup>` element, so several top-level
56
+ * tags are legal. Unknown tag names are a parse error, which is why this keeps
57
+ * pango's tag list rather than stripping anything that looks like a tag: `<3`
58
+ * and `<div>` are TEXT to libadwaita, and a search for them must find them.
59
+ *
60
+ * Deviations, both in the fail-closed direction (unparsed → caller keeps the raw
61
+ * string, never a wrongly-stripped one): pango additionally validates `<span>`'s
62
+ * attribute NAMES, and this does not; GMarkup's DOCTYPE/PI/CDATA handling is
63
+ * modelled as plain passthrough, which is what pango's parser does with it
64
+ * (its `passthrough` handler is NULL, so the content is discarded).
65
+ */
66
+ export declare function stripMarkup(text: string): string | null;
67
+ /** Per-row flags `make_comparable` reads off the row it is comparing. */
68
+ export interface MakeComparableOptions {
69
+ /** `AdwPreferencesRow:use-markup`. Defaults to `true`, as the property does. */
70
+ useMarkup?: boolean;
71
+ /** `AdwPreferencesRow:use-underline`. Defaults to `false`, as the property does. */
72
+ useUnderline?: boolean;
73
+ /**
74
+ * `make_comparable`'s third argument. The TITLE path passes `true`, the
75
+ * SUBTITLE path passes `false` (adw-preferences-dialog.c:133, :141) — so a
76
+ * subtitle keeps its underscores even on a row that uses mnemonics.
77
+ */
78
+ allowUnderline?: boolean;
79
+ }
80
+ /**
81
+ * `make_comparable` (adw-preferences-dialog.c:96-123): the form of a string the
82
+ * search compares against, i.e. case-folded, markup-stripped and (for titles on
83
+ * mnemonic rows) mnemonic-stripped.
84
+ *
85
+ * THE ORDER IS THE POINT AND IT IS NOT THE OBVIOUS ONE: fold FIRST, parse the
86
+ * FOLDED string second. Parsing first would work too — but folding first is what
87
+ * the C does, and the two differ for any markup whose tag name is case-sensitive
88
+ * to the parser. Folding a lowercase-only tag set leaves it parseable, which is
89
+ * why `<b>Dark</b> Style` still reduces to `dark style` rather than keeping its
90
+ * tags.
91
+ */
92
+ export declare function makeComparable(source: string | null | undefined, options?: MakeComparableOptions, fold?: CaseFolder): string;
93
+ /** What {@link derivePreferencesGroupHeader} is asked about. */
94
+ export interface PreferencesGroupHeaderInput {
95
+ /**
96
+ * `AdwPreferencesGroup:title`. `null`/`undefined` is the empty string —
97
+ * `adw_preferences_group_set_title` normalises NULL to `""`
98
+ * (adw-preferences-group.c:508).
99
+ */
100
+ title?: string | null;
101
+ /**
102
+ * `AdwPreferencesGroup:description`. Normalised here as well, although
103
+ * `adw_preferences_group_set_description` passes NULL straight through
104
+ * (:555) where its own `set_title` and `adw_preferences_page_set_title`
105
+ * (adw-preferences-page.c:538) both normalise — an inconsistency in the C
106
+ * with no behavioural consequence, since the visibility test treats NULL and
107
+ * `""` alike.
108
+ */
109
+ description?: string | null;
110
+ /** Whether an `AdwPreferencesGroup:header-suffix` widget is set. */
111
+ hasHeaderSuffix?: boolean;
112
+ /**
113
+ * How many children the listbox holds. This is the RAW child count —
114
+ * `update_listbox_visibility` reads `gtk_widget_observe_children (listbox)`
115
+ * (adw-preferences-group.c:111-123), NOT the title-filtered model that
116
+ * `get_rows` builds, so a row with an empty title still keeps the card
117
+ * painted.
118
+ */
119
+ rowCount?: number;
120
+ /**
121
+ * Whether the title/description labels interpret Pango markup. `true` by
122
+ * default because both labels are `use-markup=True` in
123
+ * adw-preferences-group.ui — a renderer that shows the strings verbatim
124
+ * passes `false`.
125
+ */
126
+ useMarkup?: boolean;
127
+ }
128
+ /** The five derived visual states of a preferences group. */
129
+ export interface PreferencesGroupHeaderState {
130
+ /** `update_title_visibility` (adw-preferences-group.c:91-99). */
131
+ titleVisible: boolean;
132
+ /** `update_description_visibility` (:101-109). */
133
+ descriptionVisible: boolean;
134
+ /** `update_header_visibility` (:142-156) — the header box takes no space otherwise. */
135
+ headerVisible: boolean;
136
+ /**
137
+ * `is_single_line` (:125-140), carried as the `single-line` style class.
138
+ * Load-bearing: the stylesheet gives a single-line header `min-height: 34px`
139
+ * and a multi-line one `margin-bottom: 6px`
140
+ * (stylesheet/widgets/_preferences.scss:6-13).
141
+ */
142
+ singleLine: boolean;
143
+ /** `update_listbox_visibility` (:111-123) — the `.boxed-list` card is hidden at zero rows. */
144
+ listboxVisible: boolean;
145
+ }
146
+ /**
147
+ * The five header/listbox states of an `Adw.PreferencesGroup`, derived once for
148
+ * every renderer.
149
+ *
150
+ * A pure derivation rather than a state machine, which is the honest shape: C
151
+ * recomputes all of this from scratch in `update_*_visibility` on every change,
152
+ * holding no state of its own beyond the widgets it is reading.
153
+ *
154
+ * Only the EXACT empty string hides a label — `g_strcmp0 (text, "")`, so a title
155
+ * of a single space is a visible title and must not be trimmed. That is the same
156
+ * rule {@link stringIsNotEmpty} carries for the label bindings, so it is applied
157
+ * from there rather than respelled here; what stays local is only which STRING it
158
+ * is applied to, since this widget judges the markup-stripped display text.
159
+ */
160
+ export declare function derivePreferencesGroupHeader(input: PreferencesGroupHeaderInput): PreferencesGroupHeaderState;
161
+ /**
162
+ * One indexable row, as the search reasons about it.
163
+ *
164
+ * `isActionRow` is load-bearing and is NOT "has a subtitle": only
165
+ * `ADW_IS_ACTION_ROW` rows have their subtitle searched
166
+ * (adw-preferences-dialog.c:140-146), and `AdwEntryRow` derives from
167
+ * `AdwPreferencesRow`, not from `AdwActionRow` (adw-entry-row.c:90) — so the
168
+ * text typed into an entry row is deliberately not searchable. Same for
169
+ * `AdwExpanderRow` and `AdwButtonRow`.
170
+ */
171
+ export interface PreferencesSearchRow<T = unknown> {
172
+ /** `AdwPreferencesRow:title`. A row with an empty title is not indexed at all. */
173
+ title: string;
174
+ /** `AdwActionRow:subtitle`, consulted only when `isActionRow`. */
175
+ subtitle?: string | null;
176
+ /** `AdwPreferencesRow:use-markup`, default `true`. */
177
+ useMarkup?: boolean;
178
+ /** `AdwPreferencesRow:use-underline`, default `false`. */
179
+ useUnderline?: boolean;
180
+ /** `gtk_widget_get_visible`, default `true`. A hidden row leaves the corpus. */
181
+ visible?: boolean;
182
+ /** Whether the row derives from `AdwActionRow`, default `false`. */
183
+ isActionRow?: boolean;
184
+ /** The renderer's own row object, carried through to the result untouched. */
185
+ ref?: T;
186
+ }
187
+ /** One group of rows, as the search reasons about it. */
188
+ export interface PreferencesSearchGroup<T = unknown> {
189
+ /** `AdwPreferencesGroup:title`; an empty one drops out of the result subtitle. */
190
+ title?: string | null;
191
+ /** `is_visible_group` (adw-preferences-page.c:76-82), default `true`. */
192
+ visible?: boolean;
193
+ /** The group's preferences rows, in listbox order. */
194
+ rows: readonly PreferencesSearchRow<T>[];
195
+ /** The renderer's own group object. */
196
+ ref?: T;
197
+ }
198
+ /**
199
+ * One page, as the search reasons about it.
200
+ *
201
+ * `visible` is the same flag `ViewStackState.setPageVisible` maintains —
202
+ * the dialog's pages ARE an `AdwViewStack` (adw-preferences-dialog.c:707-711),
203
+ * so a renderer holds the page ORDER and SELECTION there and describes the
204
+ * same pages here for indexing.
205
+ */
206
+ export interface PreferencesSearchPage<T = unknown> {
207
+ /** `AdwPreferencesPage:name`, the view stack child name. */
208
+ name?: string | null;
209
+ /** `AdwPreferencesPage:title`; shown in a result subtitle when several pages are visible. */
210
+ title?: string;
211
+ /** `AdwPreferencesPage:icon-name`. Not read by the search; carried for the switcher. */
212
+ iconName?: string | null;
213
+ /** `AdwPreferencesPage:use-underline`, default `false`. */
214
+ useUnderline?: boolean;
215
+ /** `AdwViewStackPage:visible`, default `true`. An invisible page contributes nothing. */
216
+ visible?: boolean;
217
+ /** `AdwPreferencesPage:description`. Not searched — only rows are. */
218
+ description?: string;
219
+ /** The page's groups, in order. */
220
+ groups: readonly PreferencesSearchGroup<T>[];
221
+ /** The renderer's own page object. */
222
+ ref?: T;
223
+ }
224
+ /** One row of the corpus, with the ancestors a result subtitle needs. */
225
+ export interface PreferencesSearchEntry<T = unknown> {
226
+ page: PreferencesSearchPage<T>;
227
+ group: PreferencesSearchGroup<T>;
228
+ row: PreferencesSearchRow<T>;
229
+ }
230
+ /**
231
+ * `get_n_pages` (adw-preferences-dialog.c:150-166) — how many pages are visible,
232
+ * which is what decides whether a result subtitle names its page.
233
+ */
234
+ export declare function countVisiblePages<T>(pages: readonly PreferencesSearchPage<T>[]): number;
235
+ /**
236
+ * The search corpus: every row the dialog will ever match against.
237
+ *
238
+ * This is the filter → map → flatten chain of `adw_preferences_dialog_init`
239
+ * (:632-641) composed with `adw_preferences_page_get_rows` (:821-841) and
240
+ * `adw_preferences_group_get_rows` (:726-741), i.e. THREE filters written in
241
+ * three different C files:
242
+ *
243
+ * 1. visible PAGES only — a `GtkBoolFilter` over `AdwViewStackPage:visible`;
244
+ * 2. visible GROUPS only — `is_visible_group`;
245
+ * 3. rows that are preferences rows AND visible AND have a NON-EMPTY title —
246
+ * `row_has_title`.
247
+ *
248
+ * Filter 3 is the one a port drops, and dropping it is invisible: nothing
249
+ * errors, the search just silently indexes rows a user cannot recognise (an
250
+ * untitled separator row) or, with the visibility half missing, rows that are
251
+ * not on screen. The `ADW_IS_PREFERENCES_ROW` half of it is expressed
252
+ * statically here — a `PreferencesSearchRow[]` cannot hold a plain list-box row.
253
+ */
254
+ export declare function collectSearchRows<T>(pages: readonly PreferencesSearchPage<T>[]): PreferencesSearchEntry<T>[];
255
+ /**
256
+ * `filter_search_results` (adw-preferences-dialog.c:125-153): whether a row
257
+ * matches the current search terms.
258
+ *
259
+ * Three properties a port tends to get wrong, all of them user-visible:
260
+ *
261
+ * - it is a SUBSTRING test (`strstr`), not a prefix and not word-boundary —
262
+ * `ARK` matches `Dark Style`;
263
+ * - the EMPTY query matches everything (`strstr (title, "")` returns `title`),
264
+ * which is why the dialog shows "results" and not "no results" before the
265
+ * user has typed anything;
266
+ * - the query is only case-FOLDED. It is not markup-parsed and not
267
+ * mnemonic-stripped, so typing `_` searches for a literal underscore.
268
+ */
269
+ export declare function rowMatchesQuery<T>(row: PreferencesSearchRow<T>, query: string, fold?: CaseFolder): boolean;
270
+ /**
271
+ * The translated fallback for a page with no title
272
+ * (adw-preferences-dialog.c:218). Exported so a renderer with a translation
273
+ * catalogue can pass its own through `untitledPageLabel`.
274
+ */
275
+ export declare const UNTITLED_PAGE_LABEL = "Untitled page";
276
+ /** What {@link createSearchRowSubtitle} needs about a matched row's ancestors. */
277
+ export interface SearchRowSubtitleInput {
278
+ /** The group's title. `''` counts as absent. */
279
+ groupTitle?: string | null;
280
+ /**
281
+ * The page's title. `undefined` means there is no page ancestor at all —
282
+ * unreachable through the public API, since a row always sits in a page.
283
+ */
284
+ pageTitle?: string | null;
285
+ /** `AdwPreferencesPage:use-underline` — decides whether the page title is mnemonic-stripped. */
286
+ pageUseUnderline?: boolean;
287
+ /** The matched ROW's `use-markup` — decides whether the page title is markup-escaped. Default `true`. */
288
+ rowUseMarkup?: boolean;
289
+ /** `get_n_pages` — the page is only named when more than one page is visible. */
290
+ nVisiblePages: number;
291
+ /** Override for {@link UNTITLED_PAGE_LABEL}. */
292
+ untitledPageLabel?: string;
293
+ }
294
+ /**
295
+ * `create_search_row_subtitle` (adw-preferences-dialog.c:168-234) — the second
296
+ * line of a search result, e.g. `General → Appearance`.
297
+ *
298
+ * The rules, in the order the C applies them, none of them symmetric:
299
+ *
300
+ * - an empty GROUP title becomes "absent", and the whole `page → group` join
301
+ * is then skipped — the result falls through to the bare page title;
302
+ * - the PAGE title is mnemonic-stripped when the PAGE uses underline, then
303
+ * markup-escaped when the ROW uses markup (a page-level property and a
304
+ * row-level property deciding two steps on the same string), and only then
305
+ * tested for emptiness;
306
+ * - the join happens only when more than one page is VISIBLE; with a single
307
+ * page the subtitle is the group title alone;
308
+ * - the group title is NOT escaped, so the two halves of `page → group` are
309
+ * escaped differently on purpose.
310
+ *
311
+ * `null` means "no subtitle at all", which is what a renderer should render as
312
+ * an absent line rather than as an empty one.
313
+ */
314
+ export declare function createSearchRowSubtitle(input: SearchRowSubtitleInput): string | null;
315
+ /** One row of the search results list. */
316
+ export interface PreferencesSearchResult<T = unknown> {
317
+ /** Copied verbatim from the matched row (`new_search_row_for_preference`, :245-256). */
318
+ title: string;
319
+ /** {@link createSearchRowSubtitle}; `null` when there is nothing to show. */
320
+ subtitle: string | null;
321
+ /** The matched row's `use-markup`, copied onto the result row. */
322
+ useMarkup: boolean;
323
+ /** The matched row's `use-underline`, copied onto the result row. */
324
+ useUnderline: boolean;
325
+ /** The page the row lives on — what `search_result_activated_cb` switches to. */
326
+ page: PreferencesSearchPage<T>;
327
+ /** The group the row lives in. */
328
+ group: PreferencesSearchGroup<T>;
329
+ /** The matched row — what `search_result_activated_cb` focuses. */
330
+ row: PreferencesSearchRow<T>;
331
+ }
332
+ /** Knobs for {@link searchPreferences}. */
333
+ export interface SearchPreferencesOptions {
334
+ /** Case folder to compare with. Defaults to {@link defaultCaseFolder}. */
335
+ fold?: CaseFolder;
336
+ /** Translated replacement for {@link UNTITLED_PAGE_LABEL}. */
337
+ untitledPageLabel?: string;
338
+ }
339
+ /**
340
+ * The whole search half in one call: corpus → filter → result rows, in corpus
341
+ * order (which is page order, then group order, then row order — the same order
342
+ * `GtkFlattenListModel` produces).
343
+ *
344
+ * Each result carries the source `page`/`group`/`row` so a renderer can
345
+ * implement `search_result_activated_cb` (adw-preferences-dialog.c:267-290) —
346
+ * switch the visible page, focus the row — without re-deriving anything.
347
+ */
348
+ export declare function searchPreferences<T>(pages: readonly PreferencesSearchPage<T>[], query: string, options?: SearchPreferencesOptions): PreferencesSearchResult<T>[];
349
+ export { stripMnemonic };
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -30,6 +30,31 @@ export interface AdwComboOption {
30
30
  /** Underlying value returned by {@link ComboState.selectedValue}. */
31
31
  value: string;
32
32
  }
33
+ /**
34
+ * What an author may write for one option before {@link normalizeComboOptions}
35
+ * has seen it: a bare string (value === label, the `Gtk.StringList` case), or a
36
+ * partial descriptor where either half may stand in for the other.
37
+ */
38
+ export type AdwComboOptionInput = string | {
39
+ value?: unknown;
40
+ label?: unknown;
41
+ };
42
+ /**
43
+ * Raw authored options → the stable `{ value, label }` descriptors every combo
44
+ * surface works with.
45
+ *
46
+ * A bare string is both value and label (`Gtk.StringList`'s model, which is what
47
+ * `Adw.ComboRow` is fed in the common case). In a descriptor either half stands
48
+ * in for the missing other, so `{ label: 'Apple' }` is addressable by the value
49
+ * `'Apple'` rather than by `undefined`.
50
+ *
51
+ * ONE home, because there were two: `<adw-combo-row>` mapped `string[]` inline
52
+ * from its JSON attribute while `<adw-drop-down>` carried a private
53
+ * `normalizeOptions` that also handled descriptors — so the same widget family
54
+ * accepted two different option vocabularies depending on which element you
55
+ * reached for.
56
+ */
57
+ export declare function normalizeComboOptions(raw: ReadonlyArray<AdwComboOptionInput> | null | undefined): AdwComboOption[];
33
58
  /** Payload of a {@link ComboState} change. */
34
59
  export interface ComboStateChange {
35
60
  /** The (new) selected index. */
@@ -78,10 +103,32 @@ export declare class ComboState {
78
103
  get selectedLabel(): string;
79
104
  /** Programmatic value set — moves the index to the first option with this `value`. No-op for an unknown value. */
80
105
  setSelectedValue(value: string): boolean;
106
+ /**
107
+ * Whether `index` addresses an option that exists.
108
+ *
109
+ * The bounds arithmetic lives here; the POLICY for a programmatic
110
+ * out-of-range set does not, because this tree cannot settle it:
111
+ * `adw_combo_row_set_selected` forwards the position straight to
112
+ * `gtk_single_selection_set_selected` (adw-combo-row.c:788) and documents
113
+ * `GTK_INVALID_LIST_POSITION` as a legal argument, but `refs/gtk` is EMPTY
114
+ * so what GtkSingleSelection does with it is not verifiable here. So each
115
+ * renderer states its own answer against this one predicate:
116
+ * {@link setSelectedIndex} keeps the permissive model (an index past the end
117
+ * is how "nothing selected" is spelled — {@link selectedValue} then reads
118
+ * `''`), while `<adw-drop-down>` rejects the set, as its published `selected`
119
+ * docs promise. Neither re-derives `index >= 0 && index < count`.
120
+ */
121
+ hasIndex(index: number): boolean;
81
122
  /**
82
123
  * Select an option by index as a USER pick (the chooser result) — notifies
83
- * `interactive: true`. A no-op (returns false) for a negative index or the
84
- * already-selected one, matching the renderer's chooser guard.
124
+ * `interactive: true`. A no-op (returns false) for the already-selected index
125
+ * or one that addresses no option, matching the renderer's chooser guard.
126
+ *
127
+ * The upper bound is part of that guard: a pick is a pick OF something, so
128
+ * `select(99)` on a three-option model is not "select nothing", it is a
129
+ * chooser reporting an index the model does not have. Only the negative half
130
+ * used to be checked, which left the interactive path able to move the index
131
+ * somewhere {@link setSelectedIndex} would have called "no selection".
85
132
  */
86
133
  select(index: number): boolean;
87
134
  /** Number of options. */