@gjsify/gtk-host 0.43.0 → 0.45.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 (63) hide show
  1. package/README.md +86 -13
  2. package/lib/esm/adapters/react.js +1 -1
  3. package/lib/esm/adapters/solid.js +1 -1
  4. package/lib/esm/conformance/diagnostics.js +2 -2
  5. package/lib/esm/conformance/index.js +2 -2
  6. package/lib/esm/descriptors/adw.js +1 -1
  7. package/lib/esm/descriptors/gtk.js +1 -1
  8. package/lib/esm/errors.js +1 -1
  9. package/lib/esm/generated/widgets.js +1 -1
  10. package/lib/esm/host.js +1 -1
  11. package/lib/esm/index.js +1 -1
  12. package/lib/esm/list/controller.js +1 -0
  13. package/lib/esm/list/index.js +1 -0
  14. package/lib/esm/list/scroll.js +1 -0
  15. package/lib/esm/policies.js +1 -1
  16. package/lib/esm/probe.js +1 -1
  17. package/lib/esm/signals.js +1 -1
  18. package/lib/esm/style/errors.js +1 -0
  19. package/lib/esm/style/gtk-css.js +1 -0
  20. package/lib/esm/style/gtk-props.js +1 -0
  21. package/lib/esm/style/index.js +1 -0
  22. package/lib/esm/style/layout.js +1 -0
  23. package/lib/esm/style/paint.js +1 -0
  24. package/lib/esm/style/resolve.js +1 -0
  25. package/lib/esm/style/sheet.js +3 -0
  26. package/lib/esm/style/tokens.js +1 -0
  27. package/lib/types/adapters/react.d.ts +59 -10
  28. package/lib/types/adapters/solid.d.ts +35 -0
  29. package/lib/types/conformance/diagnostics.d.ts +13 -3
  30. package/lib/types/conformance/index.d.ts +1 -1
  31. package/lib/types/descriptors/index.d.ts +2 -2
  32. package/lib/types/errors.d.ts +10 -0
  33. package/lib/types/generated/props.d.ts +80 -1
  34. package/lib/types/generator/emit-types.d.mts +1 -1
  35. package/lib/types/generator/gir.d.mts +36 -2
  36. package/lib/types/host.d.ts +2 -2
  37. package/lib/types/index.d.ts +1 -1
  38. package/lib/types/list/controller.d.ts +112 -0
  39. package/lib/types/list/index.d.ts +2 -0
  40. package/lib/types/list/list.spec.d.ts +2 -0
  41. package/lib/types/list/scroll.d.ts +26 -0
  42. package/lib/types/policies.d.ts +11 -0
  43. package/lib/types/probe.d.ts +80 -2
  44. package/lib/types/probe.spec.d.ts +2 -0
  45. package/lib/types/props.d.ts +7 -4
  46. package/lib/types/signals.d.ts +3 -1
  47. package/lib/types/style/errors.d.ts +6 -0
  48. package/lib/types/style/gtk-css.d.ts +24 -0
  49. package/lib/types/style/gtk-css.spec.d.ts +2 -0
  50. package/lib/types/style/gtk-props.d.ts +27 -0
  51. package/lib/types/style/gtk-props.spec.d.ts +2 -0
  52. package/lib/types/style/index.d.ts +13 -0
  53. package/lib/types/style/layout.d.ts +163 -0
  54. package/lib/types/style/layout.spec.d.ts +2 -0
  55. package/lib/types/style/paint.d.ts +53 -0
  56. package/lib/types/style/paint.spec.d.ts +2 -0
  57. package/lib/types/style/resolve.d.ts +58 -0
  58. package/lib/types/style/sheet.d.ts +40 -0
  59. package/lib/types/style/sheet.spec.d.ts +2 -0
  60. package/lib/types/style/tokens.d.ts +58 -0
  61. package/lib/types/testing/gate.d.mts +23 -0
  62. package/lib/types/types.d.ts +21 -4
  63. package/package.json +26 -12
@@ -4,8 +4,6 @@ import { adopt, widgetOf } from '../host.js';
4
4
  import type { HostElement, HostNode, HostText } from '../types.js';
5
5
  /** What React hands `createInstance`: the vnode props, `children` included. */
6
6
  export type ReactProps = Record<string, unknown>;
7
- /** One authored property that changed: name, next value, previous value. */
8
- type PropChange = readonly [key: string, next: unknown, prev: unknown];
9
7
  /**
10
8
  * The HostConfig, exported because it IS the contract.
11
9
  *
@@ -21,6 +19,8 @@ export declare const gtkHostConfig: {
21
19
  supportsPersistence: boolean;
22
20
  supportsHydration: boolean;
23
21
  isPrimaryRenderer: boolean;
22
+ supportsResources: boolean;
23
+ supportsSingletons: boolean;
24
24
  noTimeout: -1;
25
25
  scheduleTimeout: typeof setTimeout;
26
26
  cancelTimeout: typeof clearTimeout;
@@ -42,8 +42,8 @@ export declare const gtkHostConfig: {
42
42
  * flag only when `shouldSetTextContent` was true for the PREVIOUS props.
43
43
  */
44
44
  shouldSetTextContent: () => boolean;
45
- getRootHostContext: () => null;
46
- getChildHostContext: (parentHostContext: null) => null;
45
+ getRootHostContext: () => object;
46
+ getChildHostContext: (parentHostContext: object) => object;
47
47
  /**
48
48
  * What a `ref` receives — the author's widget, never the host's wrapper.
49
49
  *
@@ -55,8 +55,10 @@ export declare const gtkHostConfig: {
55
55
  prepareForCommit: () => null;
56
56
  resetAfterCommit: () => void;
57
57
  preparePortalMount: () => void;
58
+ getCurrentUpdatePriority: () => number;
59
+ setCurrentUpdatePriority: (priority: number) => void;
58
60
  /**
59
- * The priority every update outside React's own event system gets.
61
+ * The priority an update gets when React is not already inside a lane.
60
62
  *
61
63
  * React DOM derives this from the DOM event being handled (a click is
62
64
  * discrete, a scroll continuous). A GTK signal handler is not a DOM event and
@@ -67,7 +69,11 @@ export declare const gtkHostConfig: {
67
69
  * iteration. `flushSync` is the escape hatch, and the spec pumps the main
68
70
  * context to prove the scheduled path works at all under GJS.
69
71
  */
70
- getCurrentEventPriority: () => number;
72
+ resolveUpdatePriority: () => number;
73
+ shouldAttemptEagerTransition: () => boolean;
74
+ trackSchedulerEvent: () => void;
75
+ resolveEventType: () => null;
76
+ resolveEventTimeStamp: () => number;
71
77
  appendChild: (parent: HostElement, child: HostNode) => void;
72
78
  appendChildToContainer: (container: HostElement, child: HostNode) => void;
73
79
  insertBefore: (parent: HostElement, child: HostNode, before: HostNode) => void;
@@ -90,8 +96,17 @@ export declare const gtkHostConfig: {
90
96
  * for the life of the process.
91
97
  */
92
98
  clearContainer: (container: HostElement) => void;
93
- prepareUpdate: (_instance: HostElement, _type: string, oldProps: ReactProps, newProps: ReactProps) => PropChange[] | null;
94
- commitUpdate: (instance: HostElement, updatePayload: PropChange[]) => void;
99
+ /**
100
+ * Diff AND apply — one phase, because React 19 deleted the other one.
101
+ *
102
+ * The argument list is the change with teeth: React 18 passed
103
+ * `(instance, updatePayload, type, prevProps, nextProps, handle)` and 19 passes
104
+ * `(instance, type, prevProps, nextProps, handle)`. The payload slot was
105
+ * removed from the FRONT, so an adapter that kept the old signature would read
106
+ * the type string as its payload and iterate a string — which is why this is
107
+ * spelled out rather than left to positional luck.
108
+ */
109
+ commitUpdate: (instance: HostElement, _type: string, prevProps: ReactProps, nextProps: ReactProps) => void;
95
110
  commitTextUpdate: (textInstance: HostText, _oldText: string, newText: string) => void;
96
111
  commitMount: () => void;
97
112
  resetTextContent: (instance: HostElement) => void;
@@ -111,17 +126,30 @@ export declare const gtkHostConfig: {
111
126
  getInstanceFromScope: () => null;
112
127
  prepareScopeUpdate: () => void;
113
128
  beforeActiveInstanceBlur: () => void;
114
- afterActiveInstanceBlur: () => void;
129
+ maySuspendCommit: () => boolean;
130
+ maySuspendCommitOnUpdate: () => boolean;
131
+ maySuspendCommitInSyncRender: () => boolean;
132
+ preloadInstance: () => boolean;
133
+ startSuspendingCommit: () => void;
134
+ suspendInstance: () => void;
135
+ waitForCommitToBeReady: () => null;
136
+ requestPostPaintCallback: () => void;
137
+ NotPendingTransition: any;
138
+ HostTransitionContext: import("react").Context<any>;
139
+ resetFormInstance: () => void;
115
140
  detachDeletedInstance: () => void;
116
141
  };
117
142
  export type GtkHostConfig = typeof gtkHostConfig;
118
143
  /**
119
144
  * Run `fn` and flush every update it schedules before returning.
120
145
  *
121
- * The default lane is concurrent (see `getCurrentEventPriority`), so a `setState`
146
+ * The default lane is concurrent (see `resolveUpdatePriority`), so a `setState`
122
147
  * from a GTK signal handler lands on a later main-loop iteration. In an
123
148
  * application that is right — GTK is running a main loop. Outside one, and in a
124
149
  * test, this is how a change becomes visible without pumping.
150
+ *
151
+ * `reconciler.flushSync` was RENAMED to `flushSyncFromReconciler` in React 19.
152
+ * The rename is the harmless half; see `createRoot` for the half that is not.
125
153
  */
126
154
  export declare const flushSync: <T>(fn: () => T) => T;
127
155
  export interface ReactRoot {
@@ -144,6 +172,27 @@ export interface ReactRootOptions {
144
172
  * and asserts nothing arrived.
145
173
  */
146
174
  onRecoverableError?(error: Error): void;
175
+ /**
176
+ * An error NO error boundary caught. React 19 split this out of the single
177
+ * callback React 18 had, and it is the one that means the tree is broken.
178
+ *
179
+ * SUPPLYING THIS TURNS OFF THE RETHROW. By default `render()` throws the first
180
+ * uncaught error rather than returning normally, because a host refusal that
181
+ * only reaches a log has bought nothing. An application with its own error
182
+ * surface should not also get a throw — but it then owns reporting entirely.
183
+ */
184
+ onUncaughtError?(error: Error): void;
185
+ /**
186
+ * An error an error boundary DID catch — reported, then handled by the boundary.
187
+ *
188
+ * The default reports through `console.error`, which under GJS routes into the
189
+ * GLib log system at CRITICAL — so `installDiagnosticsGate()` COUNTS it, and a
190
+ * spec that deliberately renders a failing boundary will be told GTK reported a
191
+ * diagnostic. Such a spec should pass its own recorder here. Left as
192
+ * `console.error` because that is the right channel for an application, and a
193
+ * quieter default would be the wrong trade for the common case.
194
+ */
195
+ onCaughtError?(error: Error): void;
147
196
  }
148
197
  /**
149
198
  * A React root over a widget the application owns.
@@ -1,5 +1,6 @@
1
1
  import type Gtk from '@girs/gtk-4.0';
2
2
  import { widgetOf } from '../host.js';
3
+ import type { ListRowKey, ListRowSink } from '../list/index.js';
3
4
  import type { HostNode } from '../types.js';
4
5
  export declare const render: (code: () => HostNode, node: HostNode) => () => void, effect: <T>(fn: (prev?: T) => T, init?: T) => void, memo: <T>(fn: () => T, equal: boolean) => () => T, createComponent: <T>(Comp: (props: T) => HostNode, props: T) => HostNode, createElement: (tag: string) => HostNode, createTextNode: (value: string) => HostNode, insertNode: (parent: HostNode, node: HostNode, anchor?: HostNode) => void, insert: <T>(parent: any, accessor: T | (() => T), marker?: any | null, initial?: any) => HostNode, spread: <T>(node: any, accessor: (() => T) | T, skipChildren?: boolean) => void, setProp: <T>(node: HostNode, name: string, value: T, prev?: T) => T, mergeProps: (...sources: unknown[]) => unknown, use: <A, T>(fn: (element: HostNode, arg: A) => T, element: HostNode, arg: A) => T;
5
6
  /**
@@ -14,6 +15,40 @@ export declare const render: (code: () => HostNode, node: HostNode) => () => voi
14
15
  * disconnects the signal handlers.
15
16
  */
16
17
  export declare function mount(code: () => HostNode, container: Gtk.Widget): () => void;
18
+ /**
19
+ * What `listRows` keeps for one ROW WIDGET: a way to show a row in it, and a way to
20
+ * let go. Opaque to the controller, which stores it and hands it back.
21
+ */
22
+ export interface ListRowHandle<Row extends ListRowKey> {
23
+ show(row: Row | null, index: number): void;
24
+ dispose(): void;
25
+ }
26
+ /**
27
+ * Solid's half of a `Gtk.ListView`, for `ListController` in `@gjsify/gtk-host/list`.
28
+ *
29
+ * The controller owns the model, the factory and the key diff — none of which has a
30
+ * framework in it. This supplies the three callbacks it cannot have: what to put in a
31
+ * row widget, what to show there, and how to let go.
32
+ *
33
+ * ONE REACTIVE ROOT PER ROW WIDGET, created in `mountRow` and never again, for two
34
+ * reasons that are not the same kind of thing. The carrier is taken ONCE because taking
35
+ * it per bind is REFUSED: `adopt` snapshots what a container already held and cannot
36
+ * tell our own previous child from application chrome, and the same carrier comes back
37
+ * on the next show, so the second one reads our own row as someone else's and raises
38
+ * `occupied-slot` (measured against this seam; `host.spec.ts` pins the same refusal
39
+ * from the host's side). The row's signals live INSIDE the root rather than beside it
40
+ * for a documented reason rather than a measured one — Solid never disposes a
41
+ * computation created with no owner, which for a per-row memo would be one leak per
42
+ * row.
43
+ *
44
+ * What the row sees is an ACCESSOR, not a value, and that is the capability this seam
45
+ * buys over re-rendering: when `setRows` finds unchanged keys over changed content, the
46
+ * controller shows every live row again, this writes one signal, and Solid updates the
47
+ * properties that actually changed — the widgets stay. Only the transition between
48
+ * "holds a row" and "holds nothing" rebuilds the subtree, which is what `present`
49
+ * isolates.
50
+ */
51
+ export declare function listRows<Row extends ListRowKey>(renderRow: (row: () => Row, index: () => number) => HostNode): ListRowSink<Row, ListRowHandle<Row>>;
17
52
  /** `<For each={items}>` — keyed by item identity, so a reorder MOVES nodes. */
18
53
  export declare const For: <T>(props: {
19
54
  each: readonly T[] | undefined | null | false;
@@ -1,10 +1,20 @@
1
1
  export interface DiagnosticsGate {
2
- /** Warning-or-worse messages seen since the last `reset()`. */
2
+ /** Warning-or-worse messages ABOUT THE TREE, seen since the last `reset()`. */
3
3
  readonly seen: readonly string[];
4
+ /**
5
+ * Warning-or-worse messages about the HOST's graphics stack, kept apart.
6
+ *
7
+ * Recorded rather than dropped: `assertQuiet` names the count so a run is
8
+ * never quietly forgiven, and a caller that genuinely wants to assert on the
9
+ * environment can read them.
10
+ */
11
+ readonly environment: readonly string[];
4
12
  reset(): void;
5
- /** Throw if anything was recorded, naming every message. */
13
+ /** Throw if anything about the tree was recorded, naming every message. */
6
14
  assertQuiet(context?: string): void;
7
15
  }
16
+ /** Whether `message` describes the host's graphics stack rather than the tree. */
17
+ export declare function isEnvironmentDiagnostic(message: string): boolean;
8
18
  /**
9
19
  * Install the writer func once per process and return the gate.
10
20
  *
@@ -21,7 +31,7 @@ export interface DiagnosticsGate {
21
31
  * arrive without one. The first version answered `String(raw ?? '')`, so such a
22
32
  * record was counted and then described as nothing: a CI run failed with
23
33
  * `GTK reported 1 diagnostic(s) that would have passed at exit 0:` followed by a
24
- * BLANK LIST, over a test that had just constructed 164 widgets. A gate that can
34
+ * BLANK LIST, over a test that had just constructed the whole table. A gate that can
25
35
  * count a failure but not name it sends the reader back to guessing, which is the
26
36
  * state this whole module exists to end.
27
37
  *
@@ -1,4 +1,4 @@
1
- export { describeLogRecord, installDiagnosticsGate, type DiagnosticsGate } from './diagnostics.js';
1
+ export { describeLogRecord, installDiagnosticsGate, isEnvironmentDiagnostic, type DiagnosticsGate, } from './diagnostics.js';
2
2
  import type Gtk from '@girs/gtk-4.0';
3
3
  import type { ChildPolicy, HostElement, WidgetDescriptor } from '../types.js';
4
4
  /** Every method name a policy names, so the check does not have to know the shapes. */
@@ -20,8 +20,8 @@ export declare const CURATED_DESCRIPTORS: readonly WidgetDescriptor[];
20
20
  * that merely LISTS such a tag hands a renderer a way to kill the process, and
21
21
  * `descriptorProblems()` cannot see it because it never instantiates anything.
22
22
  *
23
- * MEASURED bare-constructing all 164 generated rows on gjs 1.88.1 / GTK 4.22.4 /
24
- * Adw 1.10, resuming past each abort: **163 construct, one does not**, and not a
23
+ * MEASURED bare-constructing every generated row on gjs 1.88.1 / GTK 4.22.4 /
24
+ * libadwaita 1.9.3, resuming past each abort: **all but one construct**, and not a
25
25
  * single row throws. So this map is one entry rather than a policy — and
26
26
  * `constructsEveryDescriptor` in `generated.spec.ts` is what keeps it one entry.
27
27
  *
@@ -43,6 +43,16 @@ export declare const err: {
43
43
  textNotAccepted: (tag: string, text: string) => GtkHostError;
44
44
  unclaimedChild: (parentTag: string, childTag: string) => GtkHostError;
45
45
  unknownSlot: (parentTag: string, slot: string, known: string[]) => GtkHostError;
46
+ /**
47
+ * An adder-backed slot with nothing that takes the child back out.
48
+ *
49
+ * `descriptorProblems()` rejects this shape up front, so a BUILT-IN descriptor can
50
+ * never reach here — but `registerWidget` takes descriptors from applications, which
51
+ * run no such check. Without this the unmount would be
52
+ * `TypeError: host[undefined] is not a function`, blaming the host for a claim the
53
+ * descriptor made.
54
+ */
55
+ slotNeedsRemove: (parentTag: string, slot: string, adder: string) => GtkHostError;
46
56
  rejectedChild: (parentTag: string, childTag: string, reason: string) => GtkHostError;
47
57
  uncuratedPlacement: (parentTag: string, childTag: string) => GtkHostError;
48
58
  siblingCycle: (parentTag: string) => GtkHostError;
@@ -1586,6 +1586,35 @@ export interface AdwToggleGroupProps extends GtkWidgetProps, GtkAccessibleProps,
1586
1586
  onNotifyCanShrink?: NotifyHandler;
1587
1587
  onNotifyHomogeneous?: NotifyHandler;
1588
1588
  }
1589
+ /** A toggle within [class@ToggleGroup]. */
1590
+ export interface AdwToggleProps extends GObjectProps {
1591
+ /** The toggle child. */
1592
+ child?: Gtk.Widget | null;
1593
+ /** The description of the toggle. */
1594
+ description?: string;
1595
+ /** Whether this toggle is enabled. */
1596
+ enabled?: boolean;
1597
+ /** The toggle icon name. */
1598
+ iconName?: string;
1599
+ 'icon-name'?: string;
1600
+ /** The toggle label. */
1601
+ label?: string;
1602
+ /** The toggle name. */
1603
+ name?: string;
1604
+ /** The tooltip of the toggle. */
1605
+ tooltip?: string;
1606
+ /** Whether an embedded underline in the label indicates a mnemonic. */
1607
+ useUnderline?: boolean;
1608
+ 'use-underline'?: boolean;
1609
+ onNotifyChild?: NotifyHandler;
1610
+ onNotifyDescription?: NotifyHandler;
1611
+ onNotifyEnabled?: NotifyHandler;
1612
+ onNotifyIconName?: NotifyHandler;
1613
+ onNotifyLabel?: NotifyHandler;
1614
+ onNotifyName?: NotifyHandler;
1615
+ onNotifyTooltip?: NotifyHandler;
1616
+ onNotifyUseUnderline?: NotifyHandler;
1617
+ }
1589
1618
  /** A widget containing a page, as well as top and/or bottom bars. */
1590
1619
  export interface AdwToolbarViewProps extends GtkWidgetProps, GtkAccessibleProps, GtkBuildableProps, GtkConstraintTargetProps {
1591
1620
  /** Appearance of the bottom bars. */
@@ -2267,6 +2296,15 @@ export interface GtkColorDialogButtonProps extends GtkWidgetProps, GtkAccessible
2267
2296
  onNotifyDialog?: NotifyHandler;
2268
2297
  onNotifyRgba?: NotifyHandler;
2269
2298
  }
2299
+ /** Represents items in a cell in [class@Gtk.ColumnView]. */
2300
+ export interface GtkColumnViewCellProps extends GtkListItemProps {
2301
+ /** Widget used for display. */
2302
+ child?: Gtk.Widget | null;
2303
+ /** If the item can be focused with the keyboard. */
2304
+ focusable?: boolean;
2305
+ onNotifyChild?: NotifyHandler;
2306
+ onNotifyFocusable?: NotifyHandler;
2307
+ }
2270
2308
  /** Presents a large dynamic list of items using multiple columns with headers. */
2271
2309
  export interface GtkColumnViewProps extends GtkWidgetProps, GtkAccessibleProps, GtkBuildableProps, GtkConstraintTargetProps, GtkScrollableProps {
2272
2310
  /** Allow rubberband selection. */
@@ -3369,6 +3407,35 @@ export interface GtkListBoxRowProps extends GtkWidgetProps, GtkAccessibleProps,
3369
3407
  onNotifyChild?: NotifyHandler;
3370
3408
  onNotifySelectable?: NotifyHandler;
3371
3409
  }
3410
+ /** Used by list widgets to represent the headers they display. */
3411
+ export interface GtkListHeaderProps extends GObjectProps {
3412
+ /** Widget used for display. */
3413
+ child?: Gtk.Widget | null;
3414
+ onNotifyChild?: NotifyHandler;
3415
+ }
3416
+ /** Used by list widgets to represent items in a [iface@Gio.ListModel]. */
3417
+ export interface GtkListItemProps extends GObjectProps {
3418
+ /** The accessible description to set on the listitem. */
3419
+ accessibleDescription?: string;
3420
+ 'accessible-description'?: string;
3421
+ /** The accessible label to set on the listitem. */
3422
+ accessibleLabel?: string;
3423
+ 'accessible-label'?: string;
3424
+ /** If the item can be activated by the user. */
3425
+ activatable?: boolean;
3426
+ /** Widget used for display. */
3427
+ child?: Gtk.Widget | null;
3428
+ /** If the item can be focused with the keyboard. */
3429
+ focusable?: boolean;
3430
+ /** If the item can be selected by the user. */
3431
+ selectable?: boolean;
3432
+ onNotifyAccessibleDescription?: NotifyHandler;
3433
+ onNotifyAccessibleLabel?: NotifyHandler;
3434
+ onNotifyActivatable?: NotifyHandler;
3435
+ onNotifyChild?: NotifyHandler;
3436
+ onNotifyFocusable?: NotifyHandler;
3437
+ onNotifySelectable?: NotifyHandler;
3438
+ }
3372
3439
  /** Presents a large dynamic list of items. */
3373
3440
  export interface GtkListViewProps extends GtkListBaseProps, GtkAccessibleProps, GtkBuildableProps, GtkConstraintTargetProps, GtkOrientableProps, GtkScrollableProps {
3374
3441
  /** Allow rubberband selection. */
@@ -5037,6 +5104,7 @@ export interface WidgetPropsByTag {
5037
5104
  'adw-tab-overview': AdwTabOverviewProps;
5038
5105
  'adw-tab-view': AdwTabViewProps;
5039
5106
  'adw-toast-overlay': AdwToastOverlayProps;
5107
+ 'adw-toggle': AdwToggleProps;
5040
5108
  'adw-toggle-group': AdwToggleGroupProps;
5041
5109
  'adw-toolbar-view': AdwToolbarViewProps;
5042
5110
  'adw-view-stack': AdwViewStackProps;
@@ -5066,6 +5134,7 @@ export interface WidgetPropsByTag {
5066
5134
  'gtk-color-chooser-widget': GtkColorChooserWidgetProps;
5067
5135
  'gtk-color-dialog-button': GtkColorDialogButtonProps;
5068
5136
  'gtk-column-view': GtkColumnViewProps;
5137
+ 'gtk-column-view-cell': GtkColumnViewCellProps;
5069
5138
  'gtk-combo-box': GtkComboBoxProps;
5070
5139
  'gtk-combo-box-text': GtkComboBoxTextProps;
5071
5140
  'gtk-dialog': GtkDialogProps;
@@ -5100,6 +5169,8 @@ export interface WidgetPropsByTag {
5100
5169
  'gtk-link-button': GtkLinkButtonProps;
5101
5170
  'gtk-list-box': GtkListBoxProps;
5102
5171
  'gtk-list-box-row': GtkListBoxRowProps;
5172
+ 'gtk-list-header': GtkListHeaderProps;
5173
+ 'gtk-list-item': GtkListItemProps;
5103
5174
  'gtk-list-view': GtkListViewProps;
5104
5175
  'gtk-lock-button': GtkLockButtonProps;
5105
5176
  'gtk-media-controls': GtkMediaControlsProps;
@@ -5204,6 +5275,7 @@ export interface WidgetPropsByGType {
5204
5275
  AdwTabOverview: AdwTabOverviewProps;
5205
5276
  AdwTabView: AdwTabViewProps;
5206
5277
  AdwToastOverlay: AdwToastOverlayProps;
5278
+ AdwToggle: AdwToggleProps;
5207
5279
  AdwToggleGroup: AdwToggleGroupProps;
5208
5280
  AdwToolbarView: AdwToolbarViewProps;
5209
5281
  AdwViewStack: AdwViewStackProps;
@@ -5233,6 +5305,7 @@ export interface WidgetPropsByGType {
5233
5305
  GtkColorChooserWidget: GtkColorChooserWidgetProps;
5234
5306
  GtkColorDialogButton: GtkColorDialogButtonProps;
5235
5307
  GtkColumnView: GtkColumnViewProps;
5308
+ GtkColumnViewCell: GtkColumnViewCellProps;
5236
5309
  GtkComboBox: GtkComboBoxProps;
5237
5310
  GtkComboBoxText: GtkComboBoxTextProps;
5238
5311
  GtkDialog: GtkDialogProps;
@@ -5267,6 +5340,8 @@ export interface WidgetPropsByGType {
5267
5340
  GtkLinkButton: GtkLinkButtonProps;
5268
5341
  GtkListBox: GtkListBoxProps;
5269
5342
  GtkListBoxRow: GtkListBoxRowProps;
5343
+ GtkListHeader: GtkListHeaderProps;
5344
+ GtkListItem: GtkListItemProps;
5270
5345
  GtkListView: GtkListViewProps;
5271
5346
  GtkLockButton: GtkLockButtonProps;
5272
5347
  GtkMediaControls: GtkMediaControlsProps;
@@ -5320,7 +5395,7 @@ export interface WidgetPropsByGType {
5320
5395
  /**
5321
5396
  * Kebab keys for the widgets Volar's camelize cannot reach from their GType name.
5322
5397
  *
5323
- * 1 of 164. Generated, not curated: any future GType with two adjacent
5398
+ * 1 of 168. Generated, not curated: any future GType with two adjacent
5324
5399
  * capitals lands here by itself instead of becoming a bug report.
5325
5400
  */
5326
5401
  export interface WidgetPropsVueAliases {
@@ -5388,6 +5463,7 @@ export interface WidgetClassByTag {
5388
5463
  'adw-tab-overview': Adw.TabOverview;
5389
5464
  'adw-tab-view': Adw.TabView;
5390
5465
  'adw-toast-overlay': Adw.ToastOverlay;
5466
+ 'adw-toggle': Adw.Toggle;
5391
5467
  'adw-toggle-group': Adw.ToggleGroup;
5392
5468
  'adw-toolbar-view': Adw.ToolbarView;
5393
5469
  'adw-view-stack': Adw.ViewStack;
@@ -5417,6 +5493,7 @@ export interface WidgetClassByTag {
5417
5493
  'gtk-color-chooser-widget': Gtk.ColorChooserWidget;
5418
5494
  'gtk-color-dialog-button': Gtk.ColorDialogButton;
5419
5495
  'gtk-column-view': Gtk.ColumnView;
5496
+ 'gtk-column-view-cell': Gtk.ColumnViewCell;
5420
5497
  'gtk-combo-box': Gtk.ComboBox;
5421
5498
  'gtk-combo-box-text': Gtk.ComboBoxText;
5422
5499
  'gtk-dialog': Gtk.Dialog;
@@ -5451,6 +5528,8 @@ export interface WidgetClassByTag {
5451
5528
  'gtk-link-button': Gtk.LinkButton;
5452
5529
  'gtk-list-box': Gtk.ListBox;
5453
5530
  'gtk-list-box-row': Gtk.ListBoxRow;
5531
+ 'gtk-list-header': Gtk.ListHeader;
5532
+ 'gtk-list-item': Gtk.ListItem;
5454
5533
  'gtk-list-view': Gtk.ListView;
5455
5534
  'gtk-lock-button': Gtk.LockButton;
5456
5535
  'gtk-media-controls': Gtk.MediaControls;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Emit the TYPE surfaces: one interface per GIR declaration, two tag maps.
2
+ * Emit the TYPE surfaces: one interface per GIR declaration, four tag maps.
3
3
  *
4
4
  * WHAT THE DIALECTS FORCED, all of it measured rather than assumed (ADR 0028 § 7,
5
5
  * and the numbers live there):
@@ -56,8 +56,16 @@ export interface GirProperty {
56
56
  * GIR writes `baseline_fill`; the nick GObject registered is `baseline-fill`. This
57
57
  * is the FALLBACK for a `<member>` with no `glib:nick` — the attribute itself is
58
58
  * the answer wherever it exists, because the substitution is right for Gtk and Adw
59
- * by luck and not by construction: across every GIR in this workspace 40,940
60
- * members carry the attribute and 97 disagree with it.
59
+ * by luck and not by construction: some nicks keep an underscore it would have
60
+ * replaced, and nothing but the attribute knows which one survived.
61
+ *
62
+ * The count that used to sit here is now `ts-for-gir/scripts/check-nick-derivation.mjs`,
63
+ * which owns the corpus this measures over. It also settles what looked like a
64
+ * contradiction: this file said 97 and ts-for-gir said 889 over the SAME 705 GIRs,
65
+ * and both were right — the derivations differ. 889 counts a fallback that also
66
+ * lowercases, which adds the 792 members whose GIR name carries uppercase and whose
67
+ * nick preserves it. This one does not lowercase, so 97 is its number. Quote a
68
+ * derived-nick count without naming its derivation and you get that pair back.
61
69
  */
62
70
  export declare const nickOf: (member: string) => string;
63
71
  export interface GirParam {
@@ -154,3 +162,29 @@ export declare function declarations(cls: GirClass, index: Map<string, GirClass>
154
162
  * where an off-by-one is invisible.
155
163
  */
156
164
  export declare function concreteWidgets(namespaces: readonly GirNamespace[], root?: string): GirClass[];
165
+ /**
166
+ * The placement carriers: concrete classes that are NOT widgets and yet hold one.
167
+ *
168
+ * GTK4's list widgets do not take children. A `Gtk.ListView` installs no `append`,
169
+ * `add`, `insert`, `prepend`, `remove` or `set_child` at all — measured against its
170
+ * prototype — because what it takes is a factory, and the factory hands back a
171
+ * carrier whose `child` is where a row's subtree goes. Those carriers are plain
172
+ * `GObject.Object` descendants: `GObject.type_is_a(Gtk.ListItem, Gtk.Widget)` is
173
+ * FALSE, measured on gjs 1.88.1 / GTK 4.22.4.
174
+ *
175
+ * So "every concrete descendant of GtkWidget" is one class short of the set a
176
+ * renderer must be able to name, and this is the other half. It is a RULE and not a
177
+ * list on purpose: a hand-written list is the kind of curated data ADR 0028 § 2
178
+ * reserves for what the GIR cannot express, and the GIR expresses this perfectly
179
+ * well — a carrier is a concrete non-widget that declares both halves of a
180
+ * one-child slot.
181
+ *
182
+ * Measured across Gtk-4.0 + Adw-1, the rule selects exactly four:
183
+ * `GtkListItem`, `GtkListHeader`, `GtkColumnViewCell` and `AdwToggle`. The fourth is
184
+ * the argument for the rule — it was not on the hand-written list that preceded it,
185
+ * has the identical shape, and would have been an arbitrary gap.
186
+ *
187
+ * What this does NOT do is give them a policy. A generated row is always
188
+ * `uncurated`; which method adopts the child stays curated, exactly as for widgets.
189
+ */
190
+ export declare function placementCarriers(namespaces: readonly GirNamespace[]): GirClass[];
@@ -107,7 +107,7 @@ export declare function destroy(node: HostNode): void;
107
107
  * `GObject.registerClass` subclass inherits its ancestor's policy. Guessing a
108
108
  * method name here would be the generic `add` that GTK4 deliberately removed.
109
109
  */
110
- export declare function mountRoot(el: HostElement, container: Gtk.Widget): void;
110
+ export declare function mountRoot(el: HostElement, container: GObject.Object): void;
111
111
  /**
112
112
  * The materialised widget of a host node — for a `ref`, or for a test.
113
113
  *
@@ -149,7 +149,7 @@ export declare const createDetachedContainer: () => HostElement;
149
149
  * through `nearestRegistered`, so an application's own `GObject.registerClass`
150
150
  * subclass inherits its ancestor's placement rules instead of failing.
151
151
  */
152
- export declare function adopt(container: Gtk.Widget): HostElement;
152
+ export declare function adopt(container: GObject.Object): HostElement;
153
153
  export declare const parentNode: (node: HostNode) => HostElement | null;
154
154
  export declare const firstChild: (el: HostElement) => HostNode | null;
155
155
  export declare const nextSibling: (node: HostNode) => HostNode | null;
@@ -5,7 +5,7 @@ export { addressOf, reorderMode } from './policies.js';
5
5
  export { toSignalName, isEventProp } from './signals.js';
6
6
  export { constructOnlyNames, isConstructOnly, isWritable, lookupEnumNick, paramSpecs, toPropertyName, } from './props.js';
7
7
  export { assertInjective, tagOf } from './tags.js';
8
- export { probeEnabled, runHostProbe, runHostProbeApp, type HostProbe, type HostProbeApp, type ProbeCheck, } from './probe.js';
8
+ export { blankReason, checkRendered, probeEnabled, runHostProbe, runHostProbeApp, shotEvidence, type CaptureWidget, type HostProbe, type HostProbeApp, type ProbeCheck, type ShotEvidence, } from './probe.js';
9
9
  export type { ElementChild, ElementChildren, JsxAttributes, RawSignalAttributes, SlotAttribute, VueAttributes, WithOnce, } from './attrs.js';
10
10
  export { clearRegistry, hasWidget, lookupWidget, nearestRegistered, registerWidget, registerWidgets, registeredTags, } from './registry.js';
11
11
  export { ADW_DESCRIPTORS, BUILTIN_DESCRIPTORS, CURATED_DESCRIPTORS, GENERATED_PROVENANCE, GENERATED_WIDGETS, GTK_DESCRIPTORS, mergeGenerated, registerBuiltinWidgets, tableProvenance, } from './descriptors/index.js';
@@ -0,0 +1,112 @@
1
+ import Gtk from 'gi://Gtk?version=4.0';
2
+ /**
3
+ * A row's identity, and the only thing this layer reads off a row.
4
+ *
5
+ * `key` decides whether the model has to be rebuilt at all. Everything else a dialect
6
+ * wants to carry — a render function, a component, a plain record — rides along in the
7
+ * type parameter and is handed straight back to `showRow`.
8
+ */
9
+ export interface ListRowKey {
10
+ readonly key: string;
11
+ }
12
+ /**
13
+ * The dialect's half of a list — three callbacks, one per factory phase that needs one.
14
+ *
15
+ * `Handle` is whatever the dialect needs to keep per ROW WIDGET: a React root, a Solid
16
+ * disposer plus a setter, a Vue app instance. The controller stores it, hands it back,
17
+ * and never looks inside it.
18
+ */
19
+ export interface ListRowSink<Row extends ListRowKey, Handle> {
20
+ /**
21
+ * GTK made a row widget's carrier; put something in it and keep what you need.
22
+ *
23
+ * Called from `setup`, ONCE per row widget, and that is not a convenience: `adopt`'s
24
+ * `foreign` snapshot cannot tell the host's own previous child from application
25
+ * chrome, so taking the carrier a SECOND time reads our own row as someone else's
26
+ * and refuses with `occupied-slot`. `host.spec.ts` pins that refusal.
27
+ *
28
+ * TWO routes reach it, and the nearer one is not the obvious one. GTK reusing a
29
+ * carrier across `bind`/`unbind` is the route people expect, and it needs scrolling
30
+ * or recycling to happen at all. The route that fires FIRST is `setRows` over
31
+ * unchanged keys: it shows every live row again through the same handle, with no
32
+ * GTK involvement, so a dialect that adopts per show meets the refusal on its first
33
+ * content change — measured, and it is what `list.spec.ts`'s in-place vector
34
+ * exercises. Adopt here, keep the element in the handle.
35
+ */
36
+ mountRow(item: Gtk.ListItem): Handle;
37
+ /**
38
+ * Show `row` in the widget behind `handle`, or empty it when `row` is `null`.
39
+ *
40
+ * Called from `bind`, from `unbind` with `null`, and again for every live row when
41
+ * `setRows` sees unchanged keys over changed content — which GTK does not re-bind
42
+ * for us (the splice measurement in the header says why).
43
+ */
44
+ showRow(handle: Handle, row: Row | null, index: number): void;
45
+ /** GTK is done with this row widget, or the controller is. Let go of everything. */
46
+ disposeRow(handle: Handle): void;
47
+ }
48
+ /**
49
+ * WHERE A SINK'S OWN THROW GOES, because there are TWO paths and they differ.
50
+ *
51
+ * `setRows` over unchanged keys calls `showRow` DIRECTLY — no GTK in between — so a
52
+ * throw there propagates out of `setRows` to whoever called it, and a dialect can catch
53
+ * it. Every other call (`setup`, `bind`, `unbind`, `teardown`) runs inside a GObject
54
+ * signal callback, where GJS does not let an exception cross the C frame: it is swallowed
55
+ * and logged as `Gjs-CRITICAL … JS ERROR`, the emission continues, and the controller
56
+ * carries on with a row that never rendered. A diagnostics gate sees that; nothing else
57
+ * does.
58
+ *
59
+ * The asymmetry is not fixable from here — it is GJS's signal boundary — so it is
60
+ * DECLARED instead, and it decides where a sink should put its own error handling. It
61
+ * bites unevenly: React Native's sink only fills a Map on this path and cannot really
62
+ * throw, while Solid's `show()` runs the row's reactive updates synchronously inside
63
+ * `batch()`, so an error in application code lands here.
64
+ *
65
+ * Note what is NOT the answer: `@gjsify/react-native`'s `onRowError` is React's own root
66
+ * error channel, not this seam's. A sink that needs one owns it, because only the
67
+ * dialect knows what a row's error means — a controller-level hook would have to decide
68
+ * whether to keep binding, and neither answer is right for every renderer.
69
+ */
70
+ /**
71
+ * A `Gtk.ListView`'s model, factory and per-row handles.
72
+ *
73
+ * Constructed by a dialect with its `ListRowSink`, attached to a view someone else
74
+ * created, disposed from that someone's own cleanup. Nothing here is reactive:
75
+ * `setRows` is called with the current rows and works out whether GTK has to hear
76
+ * about it.
77
+ */
78
+ export declare class ListController<Row extends ListRowKey, Handle> {
79
+ #private;
80
+ constructor(sink: ListRowSink<Row, Handle>);
81
+ /**
82
+ * Give the view its model and factory.
83
+ *
84
+ * `Gtk.NoSelection` and not the store directly: `Gtk.ListView:model` is a
85
+ * `Gtk.SelectionModel`, and a plain `Gio.ListModel` is not one. `NoSelection` is the
86
+ * wrapper that says "no selection", and it is what this controller installs because
87
+ * a `Gtk.SingleSelection` would give rows a selected state nothing here would ever
88
+ * clear. Selection is a dialect-level feature nobody has asked for yet; adding it
89
+ * means widening `attach`, not reaching around it.
90
+ */
91
+ attach(view: Gtk.ListView): void;
92
+ /**
93
+ * The rows GTK should be showing.
94
+ *
95
+ * The model is only touched when the KEYS changed. When they did not, every row's
96
+ * subtree is shown again instead — a row whose key is the same but whose data
97
+ * changed has to repaint, and the splice measurement says GTK will not re-bind it
98
+ * for us. That is strictly cheaper than a splice, which tears down every row.
99
+ */
100
+ setRows(rows: readonly Row[]): void;
101
+ /** How many rows GTK is currently holding a widget for. A spec seam and a leak detector. */
102
+ get liveRows(): number;
103
+ /**
104
+ * Release every row, disconnect every handler, and let go of the view.
105
+ *
106
+ * Called from the owner's cleanup, which runs while JS callbacks still work —
107
+ * unlike GTK's own `teardown`, which fires during GC sweeping when the view is
108
+ * collected and is BLOCKED there (measured, see the header). Idempotent, because an
109
+ * owner's cleanup and an explicit dispose both reach it.
110
+ */
111
+ dispose(): void;
112
+ }
@@ -0,0 +1,2 @@
1
+ export { ListController, type ListRowKey, type ListRowSink } from './controller.js';
2
+ export { onScrollNearEnd } from './scroll.js';
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,26 @@
1
+ import type Gtk from '@girs/gtk-4.0';
2
+ /**
3
+ * Call `listener` when the scroller gets within `threshold` page-lengths of the end.
4
+ *
5
+ * `Gtk.Adjustment`, because that is where GTK keeps a scroll position: the scrolled
6
+ * window has no scroll signal of its own, and `notify::value` on the adjustment behind
7
+ * `hadjustment`/`vadjustment` is the only place the position is observable. MEASURED: a
8
+ * `Gtk.ScrolledWindow` hands out its adjustments with no window anywhere, and
9
+ * `set_value` on one raised `notify::value` — so this is drivable, and asserted, in a
10
+ * spec that presents nothing.
11
+ *
12
+ * `upper` and `page-size` are subscribed too, and not for completeness: `upper` grows
13
+ * when rows are added, which is the event that ARMS the next call — a list that grew has
14
+ * a new end.
15
+ *
16
+ * A list with nothing to scroll (`upper <= page-size`) never fires. That is the state
17
+ * every list is in before it has been allocated, and firing there would call the
18
+ * listener on mount for every list in the application.
19
+ *
20
+ * ONCE PER ARRIVAL, and this is the one policy here that came from a framework: it is
21
+ * React Native's `onEndReached` semantics. It is the core's behaviour anyway because
22
+ * every "load more" caller wants it — firing on every frame while the user rests at the
23
+ * bottom would issue a page request per frame. A dialect that wants the raw stream has
24
+ * the adjustment and can subscribe to it directly; this function is the debounced edge.
25
+ */
26
+ export declare function onScrollNearEnd(scroller: Gtk.ScrolledWindow, axis: 'horizontal' | 'vertical', threshold: number, listener: (distanceFromEnd: number) => void): () => void;