@gtkx/react 0.6.1 → 0.8.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 (84) hide show
  1. package/dist/batch.d.ts +4 -1
  2. package/dist/batch.js +19 -10
  3. package/dist/codegen/jsx-generator.d.ts +4 -4
  4. package/dist/codegen/jsx-generator.js +24 -27
  5. package/dist/container-interfaces.d.ts +19 -6
  6. package/dist/container-interfaces.js +26 -6
  7. package/dist/errors.d.ts +8 -0
  8. package/dist/errors.js +38 -0
  9. package/dist/factory.js +9 -3
  10. package/dist/generated/jsx.d.ts +38 -26
  11. package/dist/generated/jsx.js +12 -2
  12. package/dist/index.js +3 -1
  13. package/dist/node.d.ts +5 -0
  14. package/dist/node.js +62 -6
  15. package/dist/nodes/action-bar.d.ts +2 -6
  16. package/dist/nodes/action-bar.js +3 -12
  17. package/dist/nodes/column-view.d.ts +19 -44
  18. package/dist/nodes/column-view.js +70 -243
  19. package/dist/nodes/combo-row.d.ts +5 -0
  20. package/dist/nodes/combo-row.js +6 -0
  21. package/dist/nodes/drop-down.d.ts +9 -0
  22. package/dist/nodes/drop-down.js +12 -0
  23. package/dist/nodes/flow-box.d.ts +4 -3
  24. package/dist/nodes/flow-box.js +26 -10
  25. package/dist/nodes/grid.d.ts +15 -15
  26. package/dist/nodes/grid.js +21 -64
  27. package/dist/nodes/header-bar.d.ts +34 -11
  28. package/dist/nodes/header-bar.js +55 -24
  29. package/dist/nodes/indexed-child-container.d.ts +16 -0
  30. package/dist/nodes/indexed-child-container.js +22 -0
  31. package/dist/nodes/list-box.d.ts +4 -3
  32. package/dist/nodes/list-box.js +33 -6
  33. package/dist/nodes/list-item-factory.d.ts +19 -0
  34. package/dist/nodes/list-item-factory.js +58 -0
  35. package/dist/nodes/list-view.d.ts +24 -0
  36. package/dist/nodes/list-view.js +46 -0
  37. package/dist/nodes/menu.d.ts +25 -19
  38. package/dist/nodes/menu.js +30 -59
  39. package/dist/nodes/notebook.d.ts +13 -14
  40. package/dist/nodes/notebook.js +18 -56
  41. package/dist/nodes/paged-stack.d.ts +39 -0
  42. package/dist/nodes/paged-stack.js +54 -0
  43. package/dist/nodes/selectable-list.d.ts +41 -0
  44. package/dist/nodes/selectable-list.js +228 -0
  45. package/dist/nodes/stack-page-props.d.ts +11 -0
  46. package/dist/nodes/stack-page-props.js +23 -0
  47. package/dist/nodes/stack.d.ts +14 -28
  48. package/dist/nodes/stack.js +30 -142
  49. package/dist/nodes/string-list-container.d.ts +41 -0
  50. package/dist/nodes/string-list-container.js +90 -0
  51. package/dist/nodes/string-list-item.d.ts +15 -0
  52. package/dist/nodes/string-list-item.js +48 -0
  53. package/dist/nodes/string-list-store.d.ts +13 -0
  54. package/dist/nodes/string-list-store.js +44 -0
  55. package/dist/nodes/text-view.d.ts +1 -1
  56. package/dist/nodes/text-view.js +1 -5
  57. package/dist/nodes/toggle-button.d.ts +1 -1
  58. package/dist/nodes/toggle-button.js +1 -3
  59. package/dist/nodes/view-stack.d.ts +9 -0
  60. package/dist/nodes/view-stack.js +28 -0
  61. package/dist/nodes/virtual-item.d.ts +20 -0
  62. package/dist/nodes/virtual-item.js +57 -0
  63. package/dist/nodes/virtual-slot.d.ts +25 -0
  64. package/dist/nodes/virtual-slot.js +71 -0
  65. package/dist/nodes/widget.d.ts +0 -3
  66. package/dist/nodes/widget.js +0 -28
  67. package/dist/nodes/window.d.ts +1 -1
  68. package/dist/nodes/window.js +9 -15
  69. package/dist/predicates.d.ts +8 -0
  70. package/dist/predicates.js +8 -0
  71. package/dist/props.d.ts +7 -5
  72. package/dist/props.js +11 -9
  73. package/dist/reconciler/host-config.d.ts +19 -0
  74. package/dist/reconciler/host-config.js +89 -0
  75. package/dist/reconciler.d.ts +2 -26
  76. package/dist/reconciler.js +15 -106
  77. package/dist/render.d.ts +3 -4
  78. package/dist/render.js +6 -4
  79. package/dist/types.d.ts +22 -19
  80. package/package.json +6 -5
  81. package/dist/nodes/dropdown.d.ts +0 -39
  82. package/dist/nodes/dropdown.js +0 -103
  83. package/dist/nodes/list.d.ts +0 -43
  84. package/dist/nodes/list.js +0 -153
@@ -0,0 +1,23 @@
1
+ export function applyStackPageProps(page, props) {
2
+ if (props.name !== undefined) {
3
+ page.setName(props.name);
4
+ }
5
+ if (props.title !== undefined) {
6
+ page.setTitle(props.title);
7
+ }
8
+ if (props.iconName !== undefined) {
9
+ page.setIconName(props.iconName);
10
+ }
11
+ if (props.needsAttention !== undefined) {
12
+ page.setNeedsAttention(props.needsAttention);
13
+ }
14
+ if (props.visible !== undefined) {
15
+ page.setVisible(props.visible);
16
+ }
17
+ if (props.useUnderline !== undefined) {
18
+ page.setUseUnderline(props.useUnderline);
19
+ }
20
+ if (props.badgeNumber !== undefined && page.setBadgeNumber) {
21
+ page.setBadgeNumber(props.badgeNumber);
22
+ }
23
+ }
@@ -1,36 +1,22 @@
1
1
  import type * as Gtk from "@gtkx/ffi/gtk";
2
- import { type ChildContainer, type StackPageContainer, type StackPageProps } from "../container-interfaces.js";
2
+ import { type StackPageContainer, type StackPageProps } from "../container-interfaces.js";
3
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 {
4
+ import type { Node } from "../node.js";
5
+ import { PagedStackNode } from "./paged-stack.js";
6
+ import { VirtualSlotNode } from "./virtual-slot.js";
7
+ export declare class StackNode extends PagedStackNode<Gtk.Stack> {
6
8
  static matches(type: string): boolean;
7
- private pendingVisibleChildName;
8
9
  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
- private setVisibleChildOrDefer;
19
- updateProps(oldProps: Props, newProps: Props): void;
10
+ protected addChildToWidget(child: Gtk.Widget): void;
20
11
  }
21
- export declare class StackPageNode extends Node {
12
+ export declare class StackPageNode extends VirtualSlotNode<StackPageContainer, StackPageProps> {
13
+ static consumedPropNames: string[];
22
14
  static matches(type: string): boolean;
23
- protected isVirtual(): boolean;
24
- private pageProps;
25
- private childWidget;
26
- private parentContainer;
27
- initialize(props: Props): void;
28
- private extractPageProps;
29
- getChildWidget(): Gtk.Widget | null;
30
- appendChild(child: Node): void;
31
- attachToParent(parent: Node): void;
32
- attachToParentBefore(parent: Node, before: Node): void;
33
- detachFromParent(parent: Node): void;
34
- protected consumedProps(): Set<string>;
15
+ protected isValidContainer(parent: Node): parent is Node & StackPageContainer;
16
+ protected extractSlotProps(props: Props): StackPageProps;
17
+ protected addToContainer(container: StackPageContainer, child: Gtk.Widget, props: StackPageProps): void;
18
+ protected insertBeforeInContainer(container: StackPageContainer, child: Gtk.Widget, props: StackPageProps, before: Gtk.Widget): void;
19
+ protected removeFromContainer(container: StackPageContainer, child: Gtk.Widget): void;
20
+ protected updateInContainer(container: StackPageContainer, child: Gtk.Widget, props: StackPageProps): void;
35
21
  updateProps(oldProps: Props, newProps: Props): void;
36
22
  }
@@ -1,10 +1,12 @@
1
- import { isStackPageContainer, } from "../container-interfaces.js";
2
- import { Node } from "../node.js";
3
- export class StackNode extends Node {
1
+ import { isStackPageContainer } from "../container-interfaces.js";
2
+ import { PagedStackNode } from "./paged-stack.js";
3
+ import { applyStackPageProps } from "./stack-page-props.js";
4
+ import { VirtualSlotNode } from "./virtual-slot.js";
5
+ const STACK_PAGE_PROP_KEYS = ["name", "title", "iconName", "needsAttention", "visible", "useUnderline", "badgeNumber"];
6
+ export class StackNode extends PagedStackNode {
4
7
  static matches(type) {
5
8
  return type === "Stack" || type === "Stack.Root";
6
9
  }
7
- pendingVisibleChildName = null;
8
10
  addStackPage(child, props) {
9
11
  const { name, title } = props;
10
12
  let stackPage;
@@ -17,160 +19,46 @@ export class StackNode extends Node {
17
19
  else {
18
20
  stackPage = this.widget.addChild(child);
19
21
  }
20
- this.applyStackPageProps(stackPage, props);
22
+ applyStackPageProps(stackPage, props);
21
23
  this.applyPendingVisibleChild();
22
24
  }
23
- applyPendingVisibleChild() {
24
- if (this.pendingVisibleChildName !== null) {
25
- const child = this.widget.getChildByName(this.pendingVisibleChildName);
26
- if (child) {
27
- this.widget.setVisibleChild(child);
28
- this.pendingVisibleChildName = null;
29
- }
30
- }
31
- }
32
- insertStackPageBefore(child, props, _beforeChild) {
33
- this.addStackPage(child, props);
34
- }
35
- removeStackPage(child) {
36
- this.widget.remove(child);
37
- }
38
- updateStackPageProps(child, props) {
39
- const stackPage = this.widget.getPage(child);
40
- this.applyStackPageProps(stackPage, props);
41
- }
42
- applyStackPageProps(stackPage, props) {
43
- if (props.name !== undefined) {
44
- stackPage.setName(props.name);
45
- }
46
- if (props.title !== undefined) {
47
- stackPage.setTitle(props.title);
48
- }
49
- if (props.iconName !== undefined) {
50
- stackPage.setIconName(props.iconName);
51
- }
52
- if (props.needsAttention !== undefined) {
53
- stackPage.setNeedsAttention(props.needsAttention);
54
- }
55
- if (props.visible !== undefined) {
56
- stackPage.setVisible(props.visible);
57
- }
58
- if (props.useUnderline !== undefined) {
59
- stackPage.setUseUnderline(props.useUnderline);
60
- }
61
- }
62
- attachChild(child) {
25
+ addChildToWidget(child) {
63
26
  this.widget.addChild(child);
64
27
  }
65
- insertChildBefore(child, _before) {
66
- this.widget.addChild(child);
67
- }
68
- detachChild(child) {
69
- this.widget.remove(child);
70
- }
71
- consumedProps() {
72
- const consumed = super.consumedProps();
73
- consumed.add("visibleChildName");
74
- return consumed;
75
- }
76
- setVisibleChildOrDefer(name) {
77
- const child = this.widget.getChildByName(name);
78
- if (child) {
79
- this.widget.setVisibleChild(child);
80
- this.pendingVisibleChildName = null;
81
- }
82
- else {
83
- this.pendingVisibleChildName = name;
84
- }
85
- }
86
- updateProps(oldProps, newProps) {
87
- if (newProps.visibleChildName !== undefined) {
88
- this.setVisibleChildOrDefer(newProps.visibleChildName);
89
- }
90
- super.updateProps(oldProps, newProps);
91
- }
92
28
  }
93
- export class StackPageNode extends Node {
29
+ export class StackPageNode extends VirtualSlotNode {
30
+ static consumedPropNames = STACK_PAGE_PROP_KEYS;
94
31
  static matches(type) {
95
- return type === "Stack.Page";
32
+ return type === "Stack.Page" || type === "AdwViewStack.Page";
96
33
  }
97
- isVirtual() {
98
- return true;
34
+ isValidContainer(parent) {
35
+ return isStackPageContainer(parent);
99
36
  }
100
- pageProps = {};
101
- childWidget = null;
102
- parentContainer = null;
103
- initialize(props) {
104
- this.pageProps = this.extractPageProps(props);
105
- super.initialize(props);
106
- }
107
- extractPageProps(props) {
37
+ extractSlotProps(props) {
108
38
  return {
109
- name: typeof props.name === "string" ? props.name : undefined,
110
- title: typeof props.title === "string" ? props.title : undefined,
111
- iconName: typeof props.iconName === "string" ? props.iconName : undefined,
112
- needsAttention: typeof props.needsAttention === "boolean" ? props.needsAttention : undefined,
113
- visible: typeof props.visible === "boolean" ? props.visible : undefined,
114
- useUnderline: typeof props.useUnderline === "boolean" ? props.useUnderline : undefined,
39
+ name: props.name,
40
+ title: props.title,
41
+ iconName: props.iconName,
42
+ needsAttention: props.needsAttention,
43
+ visible: props.visible,
44
+ useUnderline: props.useUnderline,
45
+ badgeNumber: props.badgeNumber,
115
46
  };
116
47
  }
117
- getChildWidget() {
118
- return this.childWidget;
119
- }
120
- appendChild(child) {
121
- const childWidget = child.getWidget();
122
- if (childWidget) {
123
- this.childWidget = childWidget;
124
- }
125
- }
126
- attachToParent(parent) {
127
- if (isStackPageContainer(parent) && this.childWidget) {
128
- this.parentContainer = parent;
129
- parent.addStackPage(this.childWidget, this.pageProps);
130
- }
48
+ addToContainer(container, child, props) {
49
+ container.addStackPage(child, props);
131
50
  }
132
- attachToParentBefore(parent, before) {
133
- if (isStackPageContainer(parent) && this.childWidget) {
134
- this.parentContainer = parent;
135
- const beforePage = before instanceof StackPageNode ? before.getChildWidget() : before.getWidget();
136
- if (beforePage) {
137
- parent.insertStackPageBefore(this.childWidget, this.pageProps, beforePage);
138
- }
139
- else {
140
- parent.addStackPage(this.childWidget, this.pageProps);
141
- }
142
- }
51
+ insertBeforeInContainer(container, child, props, before) {
52
+ container.insertStackPageBefore(child, props, before);
143
53
  }
144
- detachFromParent(parent) {
145
- if (isStackPageContainer(parent) && this.childWidget) {
146
- parent.removeStackPage(this.childWidget);
147
- this.parentContainer = null;
148
- }
54
+ removeFromContainer(container, child) {
55
+ container.removeStackPage(child);
149
56
  }
150
- consumedProps() {
151
- const consumed = super.consumedProps();
152
- consumed.add("name");
153
- consumed.add("title");
154
- consumed.add("iconName");
155
- consumed.add("needsAttention");
156
- consumed.add("visible");
157
- consumed.add("useUnderline");
158
- return consumed;
57
+ updateInContainer(container, child, props) {
58
+ container.updateStackPageProps(child, props);
159
59
  }
160
60
  updateProps(oldProps, newProps) {
161
- const newPageProps = this.extractPageProps(newProps);
162
- const propsChanged = oldProps.name !== newProps.name ||
163
- oldProps.title !== newProps.title ||
164
- oldProps.iconName !== newProps.iconName ||
165
- oldProps.needsAttention !== newProps.needsAttention ||
166
- oldProps.visible !== newProps.visible ||
167
- oldProps.useUnderline !== newProps.useUnderline;
168
- if (propsChanged) {
169
- this.pageProps = newPageProps;
170
- if (this.parentContainer && this.childWidget) {
171
- this.parentContainer.updateStackPageProps(this.childWidget, this.pageProps);
172
- }
173
- }
61
+ this.updateSlotPropsIfChanged(oldProps, newProps, STACK_PAGE_PROP_KEYS);
174
62
  super.updateProps(oldProps, newProps);
175
63
  }
176
64
  }
@@ -0,0 +1,41 @@
1
+ import * as Gio from "@gtkx/ffi/gio";
2
+ import type * as Gtk from "@gtkx/ffi/gtk";
3
+ import type { Props } from "../factory.js";
4
+ import type { Node } from "../node.js";
5
+ import { Node as NodeClass } from "../node.js";
6
+ import { StringListStore } from "./string-list-store.js";
7
+ export type StringListItem = {
8
+ id: string;
9
+ label: string;
10
+ };
11
+ type StringListContainer = {
12
+ addStringListItem(id: string, label: string): void;
13
+ insertStringListItemBefore(id: string, label: string, beforeId: string): void;
14
+ removeStringListItem(id: string): void;
15
+ updateStringListItem(oldId: string, newId: string, newLabel: string): void;
16
+ };
17
+ export declare const isStringListContainer: (node: Node) => node is Node & StringListContainer;
18
+ type StringListContainerState = {
19
+ store: StringListStore;
20
+ onSelectionChanged?: (id: string) => void;
21
+ initialSelection?: string;
22
+ hasAppliedInitialSelection: boolean;
23
+ };
24
+ type StringListWidget = Gtk.Widget & {
25
+ setModel(model: Gio.ListModel | null): void;
26
+ getSelected(): number;
27
+ setSelected(position: number): void;
28
+ };
29
+ export declare abstract class StringListContainerNode<T extends StringListWidget> extends NodeClass<T, StringListContainerState> implements StringListContainer {
30
+ static consumedPropNames: string[];
31
+ initialize(props: Props): void;
32
+ private connectSelectionHandler;
33
+ addStringListItem(id: string, label: string): void;
34
+ private scheduleInitialSelectionIfNeeded;
35
+ private applyInitialSelection;
36
+ insertStringListItemBefore(id: string, label: string, beforeId: string): void;
37
+ removeStringListItem(id: string): void;
38
+ updateStringListItem(oldId: string, newId: string, newLabel: string): void;
39
+ updateProps(oldProps: Props, newProps: Props): void;
40
+ }
41
+ export {};
@@ -0,0 +1,90 @@
1
+ import { getInterface } from "@gtkx/ffi";
2
+ import * as Gio from "@gtkx/ffi/gio";
3
+ import { Node as NodeClass } from "../node.js";
4
+ import { getCallbackChange } from "../props.js";
5
+ import { StringListStore } from "./string-list-store.js";
6
+ export const isStringListContainer = (node) => "addStringListItem" in node &&
7
+ "insertStringListItemBefore" in node &&
8
+ "removeStringListItem" in node &&
9
+ "updateStringListItem" in node;
10
+ const SELECTION_SIGNAL = "notify::selected";
11
+ export class StringListContainerNode extends NodeClass {
12
+ static consumedPropNames = ["onSelectionChanged", "selectedId"];
13
+ initialize(props) {
14
+ const store = new StringListStore();
15
+ const onSelectionChanged = props.onSelectionChanged;
16
+ const initialSelection = props.selectedId;
17
+ this.state = { store, onSelectionChanged, initialSelection, hasAppliedInitialSelection: false };
18
+ super.initialize(props);
19
+ this.widget.setModel(getInterface(store.getModel().id, Gio.ListModel));
20
+ }
21
+ connectSelectionHandler() {
22
+ const handler = () => {
23
+ const index = this.widget.getSelected();
24
+ const id = this.state.store.getIdAtIndex(index);
25
+ if (id !== undefined) {
26
+ this.state.onSelectionChanged?.(id);
27
+ }
28
+ };
29
+ this.connectSignal(this.widget, SELECTION_SIGNAL, handler);
30
+ }
31
+ addStringListItem(id, label) {
32
+ this.state.store.append(id, label);
33
+ this.scheduleInitialSelectionIfNeeded();
34
+ }
35
+ scheduleInitialSelectionIfNeeded() {
36
+ if (!this.state.hasAppliedInitialSelection) {
37
+ this.state.hasAppliedInitialSelection = true;
38
+ queueMicrotask(() => this.applyInitialSelection());
39
+ }
40
+ }
41
+ applyInitialSelection() {
42
+ if (this.state.initialSelection !== undefined) {
43
+ const index = this.state.store.getIndexForId(this.state.initialSelection);
44
+ if (index !== -1) {
45
+ this.widget.setSelected(index);
46
+ }
47
+ }
48
+ if (this.state.onSelectionChanged) {
49
+ this.connectSelectionHandler();
50
+ const currentIndex = this.widget.getSelected();
51
+ const id = this.state.store.getIdAtIndex(currentIndex);
52
+ if (id !== undefined) {
53
+ this.state.onSelectionChanged(id);
54
+ }
55
+ }
56
+ }
57
+ insertStringListItemBefore(id, label, beforeId) {
58
+ this.state.store.insertBefore(id, label, beforeId);
59
+ }
60
+ removeStringListItem(id) {
61
+ this.state.store.remove(id);
62
+ }
63
+ updateStringListItem(oldId, newId, newLabel) {
64
+ this.state.store.update(oldId, newId, newLabel);
65
+ }
66
+ updateProps(oldProps, newProps) {
67
+ const oldCallback = oldProps.onSelectionChanged;
68
+ const newCallback = newProps.onSelectionChanged;
69
+ const change = getCallbackChange(oldCallback, newCallback);
70
+ if (change.action !== "none") {
71
+ this.state.onSelectionChanged = change.callback;
72
+ if (change.action === "disconnect") {
73
+ this.disconnectSignal(SELECTION_SIGNAL);
74
+ }
75
+ else if (change.action === "connect") {
76
+ this.connectSelectionHandler();
77
+ }
78
+ }
79
+ const oldSelected = oldProps.selectedId;
80
+ const newSelected = newProps.selectedId;
81
+ if (oldSelected !== newSelected && newSelected !== undefined) {
82
+ this.state.initialSelection = newSelected;
83
+ const index = this.state.store.getIndexForId(newSelected);
84
+ if (index !== -1) {
85
+ this.widget.setSelected(index);
86
+ }
87
+ }
88
+ super.updateProps(oldProps, newProps);
89
+ }
90
+ }
@@ -0,0 +1,15 @@
1
+ import type { Props } from "../factory.js";
2
+ import { Node } from "../node.js";
3
+ import { type StringListItem } from "./string-list-container.js";
4
+ export declare abstract class StringListItemNode extends Node<never> {
5
+ static consumedPropNames: string[];
6
+ protected isVirtual(): boolean;
7
+ private id;
8
+ private label;
9
+ initialize(props: Props): void;
10
+ getStringListItem(): StringListItem;
11
+ attachToParent(parent: Node): void;
12
+ attachToParentBefore(parent: Node, before: Node): void;
13
+ detachFromParent(parent: Node): void;
14
+ updateProps(oldProps: Props, newProps: Props): void;
15
+ }
@@ -0,0 +1,48 @@
1
+ import { Node } from "../node.js";
2
+ import { isStringListContainer } from "./string-list-container.js";
3
+ export class StringListItemNode extends Node {
4
+ static consumedPropNames = ["id", "label"];
5
+ isVirtual() {
6
+ return true;
7
+ }
8
+ id = "";
9
+ label = "";
10
+ initialize(props) {
11
+ this.id = props.id;
12
+ this.label = props.label;
13
+ super.initialize(props);
14
+ }
15
+ getStringListItem() {
16
+ return { id: this.id, label: this.label };
17
+ }
18
+ attachToParent(parent) {
19
+ if (isStringListContainer(parent)) {
20
+ parent.addStringListItem(this.id, this.label);
21
+ }
22
+ }
23
+ attachToParentBefore(parent, before) {
24
+ if (isStringListContainer(parent) && before instanceof StringListItemNode) {
25
+ parent.insertStringListItemBefore(this.id, this.label, before.id);
26
+ }
27
+ else {
28
+ this.attachToParent(parent);
29
+ }
30
+ }
31
+ detachFromParent(parent) {
32
+ if (isStringListContainer(parent)) {
33
+ parent.removeStringListItem(this.id);
34
+ }
35
+ }
36
+ updateProps(oldProps, newProps) {
37
+ const oldId = oldProps.id;
38
+ const newId = newProps.id;
39
+ const oldLabel = oldProps.label;
40
+ const newLabel = newProps.label;
41
+ if ((oldId !== newId || oldLabel !== newLabel) && this.parent && isStringListContainer(this.parent)) {
42
+ this.parent.updateStringListItem(this.id, newId, newLabel);
43
+ this.id = newId;
44
+ this.label = newLabel;
45
+ }
46
+ super.updateProps(oldProps, newProps);
47
+ }
48
+ }
@@ -0,0 +1,13 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ export declare class StringListStore {
3
+ private stringList;
4
+ private ids;
5
+ constructor();
6
+ getModel(): Gtk.StringList;
7
+ append(id: string, label: string): void;
8
+ insertBefore(id: string, label: string, beforeId: string): void;
9
+ remove(id: string): void;
10
+ update(oldId: string, newId: string, newLabel: string): void;
11
+ getIdAtIndex(index: number): string | undefined;
12
+ getIndexForId(id: string): number;
13
+ }
@@ -0,0 +1,44 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ export class StringListStore {
3
+ stringList;
4
+ ids = [];
5
+ constructor() {
6
+ this.stringList = new Gtk.StringList([]);
7
+ }
8
+ getModel() {
9
+ return this.stringList;
10
+ }
11
+ append(id, label) {
12
+ this.stringList.append(label);
13
+ this.ids.push(id);
14
+ }
15
+ insertBefore(id, label, beforeId) {
16
+ const beforeIndex = this.ids.indexOf(beforeId);
17
+ if (beforeIndex === -1) {
18
+ this.append(id, label);
19
+ return;
20
+ }
21
+ this.stringList.splice(beforeIndex, 0, [label]);
22
+ this.ids.splice(beforeIndex, 0, id);
23
+ }
24
+ remove(id) {
25
+ const index = this.ids.indexOf(id);
26
+ if (index !== -1) {
27
+ this.stringList.remove(index);
28
+ this.ids.splice(index, 1);
29
+ }
30
+ }
31
+ update(oldId, newId, newLabel) {
32
+ const index = this.ids.indexOf(oldId);
33
+ if (index !== -1) {
34
+ this.stringList.splice(index, 1, [newLabel]);
35
+ this.ids[index] = newId;
36
+ }
37
+ }
38
+ getIdAtIndex(index) {
39
+ return this.ids[index];
40
+ }
41
+ getIndexForId(id) {
42
+ return this.ids.indexOf(id);
43
+ }
44
+ }
@@ -2,7 +2,7 @@ import type * as Gtk from "@gtkx/ffi/gtk";
2
2
  import type { Props } from "../factory.js";
3
3
  import { Node } from "../node.js";
4
4
  export declare class TextViewNode extends Node<Gtk.TextView> {
5
+ static consumedPropNames: string[];
5
6
  static matches(type: string): boolean;
6
- protected consumedProps(): Set<string>;
7
7
  updateProps(oldProps: Props, newProps: Props): void;
8
8
  }
@@ -1,13 +1,9 @@
1
1
  import { Node } from "../node.js";
2
2
  export class TextViewNode extends Node {
3
+ static consumedPropNames = ["buffer"];
3
4
  static matches(type) {
4
5
  return type === "TextView";
5
6
  }
6
- consumedProps() {
7
- const consumed = super.consumedProps();
8
- consumed.add("buffer");
9
- return consumed;
10
- }
11
7
  updateProps(oldProps, newProps) {
12
8
  if (oldProps.buffer !== newProps.buffer) {
13
9
  const buffer = newProps.buffer;
@@ -13,12 +13,12 @@ type ToggleButtonState = {
13
13
  * suppressing callbacks when the signal was caused by a programmatic update.
14
14
  */
15
15
  export declare class ToggleButtonNode extends Node<Gtk.ToggleButton, ToggleButtonState> {
16
+ static consumedPropNames: string[];
16
17
  static matches(type: string): boolean;
17
18
  initialize(props: Props): void;
18
19
  attachToParent(parent: Node): void;
19
20
  attachToParentBefore(parent: Node, before: Node): void;
20
21
  detachFromParent(parent: Node): void;
21
- protected consumedProps(): Set<string>;
22
22
  updateProps(_oldProps: Props, newProps: Props): void;
23
23
  protected connectSignal(widget: Gtk.Widget, eventName: string, handler: (...args: unknown[]) => unknown): void;
24
24
  }
@@ -9,6 +9,7 @@ import { Node } from "../node.js";
9
9
  * suppressing callbacks when the signal was caused by a programmatic update.
10
10
  */
11
11
  export class ToggleButtonNode extends Node {
12
+ static consumedPropNames = ["active"];
12
13
  static matches(type) {
13
14
  return type === "ToggleButton.Root";
14
15
  }
@@ -43,9 +44,6 @@ export class ToggleButtonNode extends Node {
43
44
  }
44
45
  super.detachFromParent(parent);
45
46
  }
46
- consumedProps() {
47
- return new Set(["children", "active"]);
48
- }
49
47
  updateProps(_oldProps, newProps) {
50
48
  const widget = this.getWidget();
51
49
  if (!widget) {
@@ -0,0 +1,9 @@
1
+ import type * as Adw from "@gtkx/ffi/adw";
2
+ import type * as Gtk from "@gtkx/ffi/gtk";
3
+ import type { StackPageProps } from "../container-interfaces.js";
4
+ import { PagedStackNode } from "./paged-stack.js";
5
+ export declare class ViewStackNode extends PagedStackNode<Adw.ViewStack> {
6
+ static matches(type: string): boolean;
7
+ addStackPage(child: Gtk.Widget, props: StackPageProps): void;
8
+ protected addChildToWidget(child: Gtk.Widget): void;
9
+ }
@@ -0,0 +1,28 @@
1
+ import { PagedStackNode } from "./paged-stack.js";
2
+ import { applyStackPageProps } from "./stack-page-props.js";
3
+ export class ViewStackNode extends PagedStackNode {
4
+ static matches(type) {
5
+ return type === "AdwViewStack" || type === "AdwViewStack.Root";
6
+ }
7
+ addStackPage(child, props) {
8
+ const { name, title, iconName } = props;
9
+ let page;
10
+ if (title !== undefined && iconName !== undefined) {
11
+ page = this.widget.addTitledWithIcon(child, title, iconName, name ?? null);
12
+ }
13
+ else if (title !== undefined) {
14
+ page = this.widget.addTitled(child, title, name ?? null);
15
+ }
16
+ else if (name !== undefined) {
17
+ page = this.widget.addNamed(child, name);
18
+ }
19
+ else {
20
+ page = this.widget.add(child);
21
+ }
22
+ applyStackPageProps(page, props);
23
+ this.applyPendingVisibleChild();
24
+ }
25
+ addChildToWidget(child) {
26
+ this.widget.add(child);
27
+ }
28
+ }
@@ -0,0 +1,20 @@
1
+ import type { Props } from "../factory.js";
2
+ import { Node } from "../node.js";
3
+ /**
4
+ * Base class for virtual item nodes used in list-based containers.
5
+ * Virtual nodes don't create GTK widgets directly but represent items
6
+ * in list models (ListView, GridView, ColumnView).
7
+ */
8
+ export declare abstract class VirtualItemNode extends Node<never> {
9
+ static consumedPropNames: string[];
10
+ protected isVirtual(): boolean;
11
+ private id;
12
+ private item;
13
+ initialize(props: Props): void;
14
+ getId(): string;
15
+ getItem(): unknown;
16
+ attachToParent(parent: Node): void;
17
+ attachToParentBefore(parent: Node, before: Node): void;
18
+ detachFromParent(parent: Node): void;
19
+ updateProps(oldProps: Props, newProps: Props): void;
20
+ }