@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.
- package/README.md +86 -13
- package/lib/esm/adapters/react.js +1 -1
- package/lib/esm/adapters/solid.js +1 -1
- package/lib/esm/conformance/diagnostics.js +2 -2
- package/lib/esm/conformance/index.js +2 -2
- package/lib/esm/descriptors/adw.js +1 -1
- package/lib/esm/descriptors/gtk.js +1 -1
- package/lib/esm/errors.js +1 -1
- package/lib/esm/generated/widgets.js +1 -1
- package/lib/esm/host.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/list/controller.js +1 -0
- package/lib/esm/list/index.js +1 -0
- package/lib/esm/list/scroll.js +1 -0
- package/lib/esm/policies.js +1 -1
- package/lib/esm/probe.js +1 -1
- package/lib/esm/signals.js +1 -1
- package/lib/esm/style/errors.js +1 -0
- package/lib/esm/style/gtk-css.js +1 -0
- package/lib/esm/style/gtk-props.js +1 -0
- package/lib/esm/style/index.js +1 -0
- package/lib/esm/style/layout.js +1 -0
- package/lib/esm/style/paint.js +1 -0
- package/lib/esm/style/resolve.js +1 -0
- package/lib/esm/style/sheet.js +3 -0
- package/lib/esm/style/tokens.js +1 -0
- package/lib/types/adapters/react.d.ts +59 -10
- package/lib/types/adapters/solid.d.ts +35 -0
- package/lib/types/conformance/diagnostics.d.ts +13 -3
- package/lib/types/conformance/index.d.ts +1 -1
- package/lib/types/descriptors/index.d.ts +2 -2
- package/lib/types/errors.d.ts +10 -0
- package/lib/types/generated/props.d.ts +80 -1
- package/lib/types/generator/emit-types.d.mts +1 -1
- package/lib/types/generator/gir.d.mts +36 -2
- package/lib/types/host.d.ts +2 -2
- package/lib/types/index.d.ts +1 -1
- package/lib/types/list/controller.d.ts +112 -0
- package/lib/types/list/index.d.ts +2 -0
- package/lib/types/list/list.spec.d.ts +2 -0
- package/lib/types/list/scroll.d.ts +26 -0
- package/lib/types/policies.d.ts +11 -0
- package/lib/types/probe.d.ts +80 -2
- package/lib/types/probe.spec.d.ts +2 -0
- package/lib/types/props.d.ts +7 -4
- package/lib/types/signals.d.ts +3 -1
- package/lib/types/style/errors.d.ts +6 -0
- package/lib/types/style/gtk-css.d.ts +24 -0
- package/lib/types/style/gtk-css.spec.d.ts +2 -0
- package/lib/types/style/gtk-props.d.ts +27 -0
- package/lib/types/style/gtk-props.spec.d.ts +2 -0
- package/lib/types/style/index.d.ts +13 -0
- package/lib/types/style/layout.d.ts +163 -0
- package/lib/types/style/layout.spec.d.ts +2 -0
- package/lib/types/style/paint.d.ts +53 -0
- package/lib/types/style/paint.spec.d.ts +2 -0
- package/lib/types/style/resolve.d.ts +58 -0
- package/lib/types/style/sheet.d.ts +40 -0
- package/lib/types/style/sheet.spec.d.ts +2 -0
- package/lib/types/style/tokens.d.ts +58 -0
- package/lib/types/testing/gate.d.mts +23 -0
- package/lib/types/types.d.ts +21 -4
- 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: () =>
|
|
46
|
-
getChildHostContext: (parentHostContext:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
94
|
-
|
|
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
|
-
|
|
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 `
|
|
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
|
|
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
|
|
24
|
-
*
|
|
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
|
*
|
package/lib/types/errors.d.ts
CHANGED
|
@@ -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
|
|
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,
|
|
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:
|
|
60
|
-
*
|
|
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[];
|
package/lib/types/host.d.ts
CHANGED
|
@@ -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:
|
|
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:
|
|
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;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -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,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;
|