@gtkx/react 0.1.49 → 0.1.51

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.
@@ -19,18 +19,18 @@ export class GridChildNode extends Node {
19
19
  isVirtual() {
20
20
  return true;
21
21
  }
22
- column;
23
- row;
24
- columnSpan;
25
- rowSpan;
22
+ column = 0;
23
+ row = 0;
24
+ columnSpan = 1;
25
+ rowSpan = 1;
26
26
  childWidget = null;
27
27
  parentContainer = null;
28
- constructor(type, props) {
29
- super(type, props);
28
+ initialize(props) {
30
29
  this.column = getNumberProp(props, "column", 0);
31
30
  this.row = getNumberProp(props, "row", 0);
32
31
  this.columnSpan = getNumberProp(props, "columnSpan", 1);
33
32
  this.rowSpan = getNumberProp(props, "rowSpan", 1);
33
+ super.initialize(props);
34
34
  }
35
35
  appendChild(child) {
36
36
  const widget = child.getWidget();
@@ -1,17 +1,25 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
+ import type Reconciler from "react-reconciler";
2
3
  import { type ItemContainer } from "../container-interfaces.js";
3
4
  import type { Props } from "../factory.js";
4
5
  import { Node } from "../node.js";
5
- export declare class ListViewNode extends Node<Gtk.ListView | Gtk.GridView> implements ItemContainer<unknown> {
6
+ import type { RenderItemFn } from "../types.js";
7
+ interface ListItemInfo {
8
+ box: Gtk.Box;
9
+ fiberRoot: Reconciler.FiberRoot;
10
+ }
11
+ interface ListViewState {
12
+ stringList: Gtk.StringList;
13
+ selectionModel: Gtk.SingleSelection;
14
+ factory: Gtk.SignalListItemFactory;
15
+ renderItem: RenderItemFn<unknown>;
16
+ listItemCache: Map<number, ListItemInfo>;
17
+ items: unknown[];
18
+ committedLength: number;
19
+ }
20
+ export declare class ListViewNode extends Node<Gtk.ListView | Gtk.GridView, ListViewState> implements ItemContainer<unknown> {
6
21
  static matches(type: string): boolean;
7
- private stringList;
8
- private selectionModel;
9
- private factory;
10
- private items;
11
- private renderItem;
12
- private listItemCache;
13
- private committedLength;
14
- constructor(type: string, props: Props);
22
+ initialize(props: Props): void;
15
23
  private syncStringList;
16
24
  addItem(item: unknown): void;
17
25
  insertItemBefore(item: unknown, beforeItem: unknown): void;
@@ -23,9 +31,10 @@ export declare class ListItemNode extends Node {
23
31
  static matches(type: string): boolean;
24
32
  protected isVirtual(): boolean;
25
33
  private item;
26
- constructor(type: string, props: Props);
34
+ initialize(props: Props): void;
27
35
  getItem(): unknown;
28
36
  attachToParent(parent: Node): void;
29
37
  attachToParentBefore(parent: Node, before: Node): void;
30
38
  detachFromParent(parent: Node): void;
31
39
  }
40
+ export {};
@@ -9,84 +9,89 @@ export class ListViewNode extends Node {
9
9
  static matches(type) {
10
10
  return type === "ListView.Root" || type === "GridView.Root";
11
11
  }
12
- stringList;
13
- selectionModel;
14
- factory;
15
- items = [];
16
- renderItem;
17
- listItemCache = new Map();
18
- committedLength = 0;
19
- constructor(type, props) {
20
- super(type, props);
21
- this.stringList = new Gtk.StringList([]);
22
- this.selectionModel = new Gtk.SingleSelection(this.stringList);
23
- this.factory = new Gtk.SignalListItemFactory();
24
- this.renderItem = props.renderItem;
25
- this.factory.connect("setup", (_self, listItemObj) => {
12
+ initialize(props) {
13
+ // Initialize state before super.initialize() since updateProps accesses this.state
14
+ this.state = {
15
+ stringList: null,
16
+ selectionModel: null,
17
+ factory: null,
18
+ renderItem: props.renderItem,
19
+ listItemCache: new Map(),
20
+ items: [],
21
+ committedLength: 0,
22
+ };
23
+ super.initialize(props);
24
+ const stringList = new Gtk.StringList([]);
25
+ const selectionModel = new Gtk.SingleSelection(stringList);
26
+ const factory = new Gtk.SignalListItemFactory();
27
+ this.state.stringList = stringList;
28
+ this.state.selectionModel = selectionModel;
29
+ this.state.factory = factory;
30
+ factory.connect("setup", (_self, listItemObj) => {
26
31
  const listItem = getObject(listItemObj.ptr, Gtk.ListItem);
27
32
  const id = getObjectId(listItemObj.ptr);
28
33
  const box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
29
34
  listItem.setChild(box);
30
35
  const fiberRoot = createFiberRoot(box);
31
- this.listItemCache.set(id, { box, fiberRoot });
32
- const element = this.renderItem(null);
36
+ this.state.listItemCache.set(id, { box, fiberRoot });
37
+ const element = this.state.renderItem(null);
33
38
  reconciler.getInstance().updateContainer(element, fiberRoot, null, () => { });
34
39
  });
35
- this.factory.connect("bind", (_self, listItemObj) => {
40
+ factory.connect("bind", (_self, listItemObj) => {
36
41
  const listItem = getObject(listItemObj.ptr, Gtk.ListItem);
37
42
  const id = getObjectId(listItemObj.ptr);
38
- const info = this.listItemCache.get(id);
43
+ const info = this.state.listItemCache.get(id);
39
44
  if (!info)
40
45
  return;
41
46
  const position = listItem.getPosition();
42
- const item = this.items[position];
43
- const element = this.renderItem(item);
47
+ const item = this.state.items[position];
48
+ const element = this.state.renderItem(item);
44
49
  reconciler.getInstance().updateContainer(element, info.fiberRoot, null, () => { });
45
50
  });
46
- this.factory.connect("unbind", (_self, listItemObj) => {
51
+ factory.connect("unbind", (_self, listItemObj) => {
47
52
  const id = getObjectId(listItemObj.ptr);
48
- const info = this.listItemCache.get(id);
53
+ const info = this.state.listItemCache.get(id);
49
54
  if (!info)
50
55
  return;
51
56
  reconciler.getInstance().updateContainer(null, info.fiberRoot, null, () => { });
52
57
  });
53
- this.factory.connect("teardown", (_self, listItemObj) => {
58
+ factory.connect("teardown", (_self, listItemObj) => {
54
59
  const id = getObjectId(listItemObj.ptr);
55
- const info = this.listItemCache.get(id);
60
+ const info = this.state.listItemCache.get(id);
56
61
  if (info) {
57
62
  reconciler.getInstance().updateContainer(null, info.fiberRoot, null, () => { });
58
- this.listItemCache.delete(id);
63
+ this.state.listItemCache.delete(id);
59
64
  }
60
65
  });
61
- this.widget.setModel(this.selectionModel);
62
- this.widget.setFactory(this.factory);
66
+ this.widget.setModel(selectionModel);
67
+ this.widget.setFactory(factory);
63
68
  }
64
69
  syncStringList = () => {
65
- const newLength = this.items.length;
66
- if (newLength === this.committedLength)
70
+ const newLength = this.state.items.length;
71
+ if (newLength === this.state.committedLength)
67
72
  return;
68
73
  const placeholders = Array.from({ length: newLength }, () => "");
69
- this.stringList.splice(0, this.committedLength, placeholders);
70
- this.committedLength = newLength;
74
+ this.state.stringList.splice(0, this.state.committedLength, placeholders);
75
+ this.state.committedLength = newLength;
71
76
  };
72
77
  addItem(item) {
73
- this.items.push(item);
78
+ this.state.items.push(item);
74
79
  scheduleFlush(this.syncStringList);
75
80
  }
76
81
  insertItemBefore(item, beforeItem) {
77
- const beforeIndex = this.items.indexOf(beforeItem);
82
+ const beforeIndex = this.state.items.indexOf(beforeItem);
78
83
  if (beforeIndex === -1) {
79
- this.items.push(item);
84
+ this.state.items.push(item);
80
85
  }
81
86
  else {
82
- this.items.splice(beforeIndex, 0, item);
87
+ this.state.items.splice(beforeIndex, 0, item);
83
88
  }
84
89
  scheduleFlush(this.syncStringList);
85
90
  }
86
91
  removeItem(item) {
87
- const index = this.items.indexOf(item);
92
+ const index = this.state.items.indexOf(item);
88
93
  if (index !== -1) {
89
- this.items.splice(index, 1);
94
+ this.state.items.splice(index, 1);
90
95
  scheduleFlush(this.syncStringList);
91
96
  }
92
97
  }
@@ -97,7 +102,7 @@ export class ListViewNode extends Node {
97
102
  }
98
103
  updateProps(oldProps, newProps) {
99
104
  if (oldProps.renderItem !== newProps.renderItem) {
100
- this.renderItem = newProps.renderItem;
105
+ this.state.renderItem = newProps.renderItem;
101
106
  }
102
107
  super.updateProps(oldProps, newProps);
103
108
  }
@@ -110,9 +115,9 @@ export class ListItemNode extends Node {
110
115
  return true;
111
116
  }
112
117
  item;
113
- constructor(type, props) {
114
- super(type, props);
118
+ initialize(props) {
115
119
  this.item = props.item;
120
+ super.initialize(props);
116
121
  }
117
122
  getItem() {
118
123
  return this.item;
@@ -0,0 +1,84 @@
1
+ import * as Gio from "@gtkx/ffi/gio";
2
+ import * as Gtk from "@gtkx/ffi/gtk";
3
+ import type { Props } from "../factory.js";
4
+ import { Node } from "../node.js";
5
+ interface MenuEntry {
6
+ type: "item" | "section" | "submenu";
7
+ label?: string;
8
+ action?: string;
9
+ menu?: Gio.Menu;
10
+ }
11
+ interface MenuContainer {
12
+ getMenu(): Gio.Menu;
13
+ addMenuEntry(entry: MenuEntry): void;
14
+ removeMenuEntry(entry: MenuEntry): void;
15
+ }
16
+ declare abstract class MenuContainerNode<T extends Gtk.Widget | undefined> extends Node<T> implements MenuContainer {
17
+ protected menu: Gio.Menu;
18
+ protected entries: MenuEntry[];
19
+ private rebuildScheduled;
20
+ getMenu(): Gio.Menu;
21
+ addMenuEntry(entry: MenuEntry): void;
22
+ removeMenuEntry(entry: MenuEntry): void;
23
+ private scheduleRebuild;
24
+ protected rebuildMenu(): void;
25
+ protected onMenuRebuilt(): void;
26
+ }
27
+ export declare class PopoverMenuRootNode extends MenuContainerNode<Gtk.PopoverMenu> {
28
+ static matches(type: string): boolean;
29
+ initialize(props: Props): void;
30
+ protected onMenuRebuilt(): void;
31
+ }
32
+ export declare class PopoverMenuBarNode extends MenuContainerNode<Gtk.PopoverMenuBar> {
33
+ static matches(type: string): boolean;
34
+ initialize(props: Props): void;
35
+ protected onMenuRebuilt(): void;
36
+ }
37
+ export declare class ApplicationMenuNode extends MenuContainerNode<never> {
38
+ static matches(type: string): boolean;
39
+ protected isVirtual(): boolean;
40
+ detachFromParent(_parent: Node): void;
41
+ attachToParent(parent: Node): void;
42
+ mount(): void;
43
+ protected onMenuRebuilt(): void;
44
+ }
45
+ export declare class MenuItemNode extends Node<never> {
46
+ static matches(type: string): boolean;
47
+ protected isVirtual(): boolean;
48
+ private entry;
49
+ private action;
50
+ private actionName;
51
+ private signalHandlerId;
52
+ private onActivateCallback;
53
+ private currentAccels;
54
+ private isAttached;
55
+ initialize(props: Props): void;
56
+ attachToParent(parent: Node): void;
57
+ detachFromParent(parent: Node): void;
58
+ protected consumedProps(): Set<string>;
59
+ updateProps(oldProps: Props, newProps: Props): void;
60
+ private setupAction;
61
+ private cleanupAction;
62
+ private updateAccels;
63
+ }
64
+ export declare class MenuSectionNode extends MenuContainerNode<never> {
65
+ static matches(type: string): boolean;
66
+ protected isVirtual(): boolean;
67
+ private entry;
68
+ initialize(props: Props): void;
69
+ attachToParent(parent: Node): void;
70
+ detachFromParent(parent: Node): void;
71
+ protected consumedProps(): Set<string>;
72
+ updateProps(oldProps: Props, newProps: Props): void;
73
+ }
74
+ export declare class MenuSubmenuNode extends MenuContainerNode<never> {
75
+ static matches(type: string): boolean;
76
+ protected isVirtual(): boolean;
77
+ private entry;
78
+ initialize(props: Props): void;
79
+ attachToParent(parent: Node): void;
80
+ detachFromParent(parent: Node): void;
81
+ protected consumedProps(): Set<string>;
82
+ updateProps(oldProps: Props, newProps: Props): void;
83
+ }
84
+ export {};
@@ -0,0 +1,279 @@
1
+ import { getCurrentApp } from "@gtkx/ffi";
2
+ import * as Gio from "@gtkx/ffi/gio";
3
+ import * as GObject from "@gtkx/ffi/gobject";
4
+ import * as Gtk from "@gtkx/ffi/gtk";
5
+ import { Node } from "../node.js";
6
+ import { RootNode } from "./root.js";
7
+ let actionCounter = 0;
8
+ const generateActionName = () => `gtkx_menu_action_${actionCounter++}`;
9
+ const isMenuContainer = (node) => "getMenu" in node && "addMenuEntry" in node && "removeMenuEntry" in node;
10
+ class MenuContainerNode extends Node {
11
+ menu = new Gio.Menu();
12
+ entries = [];
13
+ rebuildScheduled = false;
14
+ getMenu() {
15
+ return this.menu;
16
+ }
17
+ addMenuEntry(entry) {
18
+ this.entries.push(entry);
19
+ this.scheduleRebuild();
20
+ }
21
+ removeMenuEntry(entry) {
22
+ const index = this.entries.indexOf(entry);
23
+ if (index !== -1) {
24
+ this.entries.splice(index, 1);
25
+ this.scheduleRebuild();
26
+ }
27
+ }
28
+ scheduleRebuild() {
29
+ if (this.rebuildScheduled)
30
+ return;
31
+ this.rebuildScheduled = true;
32
+ queueMicrotask(() => {
33
+ this.rebuildScheduled = false;
34
+ this.rebuildMenu();
35
+ });
36
+ }
37
+ rebuildMenu() {
38
+ this.menu.removeAll();
39
+ for (const entry of this.entries) {
40
+ if (entry.type === "item") {
41
+ this.menu.append(entry.label ?? null, entry.action ?? null);
42
+ }
43
+ else if (entry.type === "section" && entry.menu) {
44
+ this.menu.appendSection(entry.menu, entry.label ?? null);
45
+ }
46
+ else if (entry.type === "submenu" && entry.menu) {
47
+ this.menu.appendSubmenu(entry.menu, entry.label ?? null);
48
+ }
49
+ }
50
+ this.onMenuRebuilt();
51
+ }
52
+ onMenuRebuilt() { }
53
+ }
54
+ export class PopoverMenuRootNode extends MenuContainerNode {
55
+ static matches(type) {
56
+ return type === "PopoverMenu.Root";
57
+ }
58
+ initialize(props) {
59
+ this.widget = new Gtk.PopoverMenu(this.menu);
60
+ super.initialize(props);
61
+ }
62
+ onMenuRebuilt() {
63
+ this.widget.setMenuModel(this.menu);
64
+ }
65
+ }
66
+ export class PopoverMenuBarNode extends MenuContainerNode {
67
+ static matches(type) {
68
+ return type === "PopoverMenuBar";
69
+ }
70
+ initialize(props) {
71
+ this.widget = new Gtk.PopoverMenuBar(this.menu);
72
+ super.initialize(props);
73
+ }
74
+ onMenuRebuilt() {
75
+ this.widget.setMenuModel(this.menu);
76
+ }
77
+ }
78
+ export class ApplicationMenuNode extends MenuContainerNode {
79
+ static matches(type) {
80
+ return type === "ApplicationMenu";
81
+ }
82
+ isVirtual() {
83
+ return true;
84
+ }
85
+ detachFromParent(_parent) {
86
+ getCurrentApp().setMenubar(null);
87
+ }
88
+ attachToParent(parent) {
89
+ if (!(parent instanceof RootNode)) {
90
+ throw new Error("ApplicationMenu must be a direct child of a fragment at the root level");
91
+ }
92
+ }
93
+ mount() {
94
+ getCurrentApp().setMenubar(this.menu);
95
+ }
96
+ onMenuRebuilt() {
97
+ getCurrentApp().setMenubar(this.menu);
98
+ }
99
+ }
100
+ export class MenuItemNode extends Node {
101
+ static matches(type) {
102
+ return type === "Menu.Item";
103
+ }
104
+ isVirtual() {
105
+ return true;
106
+ }
107
+ entry = { type: "item" };
108
+ action = null;
109
+ actionName = null;
110
+ signalHandlerId = null;
111
+ onActivateCallback;
112
+ currentAccels;
113
+ isAttached = false;
114
+ initialize(props) {
115
+ this.onActivateCallback = props.onActivate;
116
+ this.currentAccels = props.accels;
117
+ this.entry.label = props.label;
118
+ super.initialize(props);
119
+ }
120
+ attachToParent(parent) {
121
+ if (!isMenuContainer(parent))
122
+ return;
123
+ this.isAttached = true;
124
+ this.setupAction();
125
+ parent.addMenuEntry(this.entry);
126
+ }
127
+ detachFromParent(parent) {
128
+ if (!isMenuContainer(parent))
129
+ return;
130
+ parent.removeMenuEntry(this.entry);
131
+ this.cleanupAction();
132
+ this.isAttached = false;
133
+ }
134
+ consumedProps() {
135
+ const consumed = super.consumedProps();
136
+ consumed.add("label");
137
+ consumed.add("onActivate");
138
+ consumed.add("accels");
139
+ return consumed;
140
+ }
141
+ updateProps(oldProps, newProps) {
142
+ // If entry doesn't exist yet, fields aren't initialized
143
+ // This happens when base class constructor calls updateProps
144
+ // before derived class field initializers run - skip in that case
145
+ if (!this.entry) {
146
+ super.updateProps(oldProps, newProps);
147
+ return;
148
+ }
149
+ const labelChanged = oldProps.label !== newProps.label;
150
+ const hadCallback = oldProps.onActivate !== undefined;
151
+ const hasCallback = newProps.onActivate !== undefined;
152
+ const accelsChanged = oldProps.accels !== newProps.accels;
153
+ // Always update the callback reference - the signal handler uses this
154
+ this.onActivateCallback = newProps.onActivate;
155
+ this.currentAccels = newProps.accels;
156
+ if (labelChanged) {
157
+ this.entry.label = newProps.label;
158
+ }
159
+ // Only cleanup/setup action if the presence of a callback changed
160
+ // (not when the callback reference changes - we store the ref and call it)
161
+ if (this.isAttached && hadCallback !== hasCallback) {
162
+ this.cleanupAction();
163
+ this.setupAction();
164
+ }
165
+ if (accelsChanged && this.actionName) {
166
+ this.updateAccels(this.currentAccels);
167
+ }
168
+ super.updateProps(oldProps, newProps);
169
+ }
170
+ setupAction() {
171
+ if (!this.onActivateCallback)
172
+ return;
173
+ this.actionName = generateActionName();
174
+ this.action = new Gio.SimpleAction(this.actionName);
175
+ this.signalHandlerId = this.action.connect("activate", () => {
176
+ // Call the current callback (may have been updated via updateProps)
177
+ this.onActivateCallback?.();
178
+ });
179
+ const app = getCurrentApp();
180
+ app.addAction(this.action);
181
+ this.entry.action = `app.${this.actionName}`;
182
+ if (this.currentAccels) {
183
+ this.updateAccels(this.currentAccels);
184
+ }
185
+ }
186
+ cleanupAction() {
187
+ if (this.actionName) {
188
+ const app = getCurrentApp();
189
+ app.removeAction(this.actionName);
190
+ if (this.currentAccels) {
191
+ app.setAccelsForAction(`app.${this.actionName}`, []);
192
+ }
193
+ }
194
+ if (this.action && this.signalHandlerId !== null) {
195
+ GObject.signalHandlerDisconnect(this.action, this.signalHandlerId);
196
+ }
197
+ this.action = null;
198
+ this.actionName = null;
199
+ this.signalHandlerId = null;
200
+ this.entry.action = undefined;
201
+ }
202
+ updateAccels(accels) {
203
+ if (!this.actionName)
204
+ return;
205
+ const app = getCurrentApp();
206
+ const accelArray = accels ? (Array.isArray(accels) ? accels : [accels]) : [];
207
+ app.setAccelsForAction(`app.${this.actionName}`, accelArray);
208
+ }
209
+ }
210
+ export class MenuSectionNode extends MenuContainerNode {
211
+ static matches(type) {
212
+ return type === "Menu.Section";
213
+ }
214
+ isVirtual() {
215
+ return true;
216
+ }
217
+ entry = { type: "section" };
218
+ initialize(props) {
219
+ this.entry.menu = this.menu;
220
+ this.entry.label = props.label;
221
+ super.initialize(props);
222
+ }
223
+ attachToParent(parent) {
224
+ if (!isMenuContainer(parent))
225
+ return;
226
+ parent.addMenuEntry(this.entry);
227
+ }
228
+ detachFromParent(parent) {
229
+ if (!isMenuContainer(parent))
230
+ return;
231
+ parent.removeMenuEntry(this.entry);
232
+ }
233
+ consumedProps() {
234
+ const consumed = super.consumedProps();
235
+ consumed.add("label");
236
+ return consumed;
237
+ }
238
+ updateProps(oldProps, newProps) {
239
+ if (oldProps.label !== newProps.label && this.entry) {
240
+ this.entry.label = newProps.label;
241
+ }
242
+ super.updateProps(oldProps, newProps);
243
+ }
244
+ }
245
+ export class MenuSubmenuNode extends MenuContainerNode {
246
+ static matches(type) {
247
+ return type === "Menu.Submenu";
248
+ }
249
+ isVirtual() {
250
+ return true;
251
+ }
252
+ entry = { type: "submenu" };
253
+ initialize(props) {
254
+ this.entry.menu = this.menu;
255
+ this.entry.label = props.label;
256
+ super.initialize(props);
257
+ }
258
+ attachToParent(parent) {
259
+ if (!isMenuContainer(parent))
260
+ return;
261
+ parent.addMenuEntry(this.entry);
262
+ }
263
+ detachFromParent(parent) {
264
+ if (!isMenuContainer(parent))
265
+ return;
266
+ parent.removeMenuEntry(this.entry);
267
+ }
268
+ consumedProps() {
269
+ const consumed = super.consumedProps();
270
+ consumed.add("label");
271
+ return consumed;
272
+ }
273
+ updateProps(oldProps, newProps) {
274
+ if (oldProps.label !== newProps.label && this.entry) {
275
+ this.entry.label = newProps.label;
276
+ }
277
+ super.updateProps(oldProps, newProps);
278
+ }
279
+ }
@@ -18,7 +18,7 @@ export declare class NotebookPageNode extends Node {
18
18
  private label;
19
19
  private childWidget;
20
20
  private parentContainer;
21
- constructor(type: string, props: Props);
21
+ initialize(props: Props): void;
22
22
  getLabel(): string;
23
23
  setChildWidget(widget: Gtk.Widget): void;
24
24
  getChildWidget(): Gtk.Widget | null;
@@ -56,12 +56,12 @@ export class NotebookPageNode extends Node {
56
56
  isVirtual() {
57
57
  return true;
58
58
  }
59
- label;
59
+ label = "";
60
60
  childWidget = null;
61
61
  parentContainer = null;
62
- constructor(type, props) {
63
- super(type, props);
62
+ initialize(props) {
64
63
  this.label = getStringProp(props, "label", "");
64
+ super.initialize(props);
65
65
  }
66
66
  getLabel() {
67
67
  return this.label;
@@ -8,6 +8,6 @@ export class RootNode extends Node {
8
8
  return true;
9
9
  }
10
10
  constructor() {
11
- super("", {});
11
+ super("");
12
12
  }
13
13
  }
@@ -1,4 +1,3 @@
1
- import type { Props } from "../factory.js";
2
1
  import { Node } from "../node.js";
3
2
  export declare class SlotNode extends Node<never> {
4
3
  static matches(type: string): boolean;
@@ -6,7 +5,7 @@ export declare class SlotNode extends Node<never> {
6
5
  private child;
7
6
  private slotName;
8
7
  private parentNode;
9
- constructor(type: string, props: Props);
8
+ constructor(type: string);
10
9
  private updateParentSlot;
11
10
  appendChild(child: Node): void;
12
11
  removeChild(_child: Node): void;
@@ -15,8 +15,8 @@ export class SlotNode extends Node {
15
15
  child = null;
16
16
  slotName;
17
17
  parentNode = null;
18
- constructor(type, props) {
19
- super(type, props);
18
+ constructor(type) {
19
+ super(type);
20
20
  const dotIndex = type.indexOf(".");
21
21
  if (dotIndex === -1) {
22
22
  throw new Error(`Invalid slot type: ${type}`);
@@ -0,0 +1,35 @@
1
+ import type * as Gtk from "@gtkx/ffi/gtk";
2
+ import { type ChildContainer, type StackPageContainer, type StackPageProps } from "../container-interfaces.js";
3
+ import type { Props } from "../factory.js";
4
+ import { Node } from "../node.js";
5
+ export declare class StackNode extends Node<Gtk.Stack> implements StackPageContainer, ChildContainer {
6
+ static matches(type: string): boolean;
7
+ private pendingVisibleChildName;
8
+ addStackPage(child: Gtk.Widget, props: StackPageProps): void;
9
+ private applyPendingVisibleChild;
10
+ insertStackPageBefore(child: Gtk.Widget, props: StackPageProps, _beforeChild: Gtk.Widget): void;
11
+ removeStackPage(child: Gtk.Widget): void;
12
+ updateStackPageProps(child: Gtk.Widget, props: StackPageProps): void;
13
+ private applyStackPageProps;
14
+ attachChild(child: Gtk.Widget): void;
15
+ insertChildBefore(child: Gtk.Widget, _before: Gtk.Widget): void;
16
+ detachChild(child: Gtk.Widget): void;
17
+ protected consumedProps(): Set<string>;
18
+ updateProps(oldProps: Props, newProps: Props): void;
19
+ }
20
+ export declare class StackPageNode extends Node {
21
+ static matches(type: string): boolean;
22
+ protected isVirtual(): boolean;
23
+ private pageProps;
24
+ private childWidget;
25
+ private parentContainer;
26
+ initialize(props: Props): void;
27
+ private extractPageProps;
28
+ getChildWidget(): Gtk.Widget | null;
29
+ appendChild(child: Node): void;
30
+ attachToParent(parent: Node): void;
31
+ attachToParentBefore(parent: Node, before: Node): void;
32
+ detachFromParent(parent: Node): void;
33
+ protected consumedProps(): Set<string>;
34
+ updateProps(oldProps: Props, newProps: Props): void;
35
+ }