@gtkx/react 0.1.47 → 0.1.49

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 (43) hide show
  1. package/README.md +8 -0
  2. package/dist/codegen/jsx-generator.js +9 -19
  3. package/dist/container-interfaces.d.ts +51 -0
  4. package/dist/container-interfaces.js +5 -0
  5. package/dist/factory.d.ts +1 -1
  6. package/dist/factory.js +17 -3
  7. package/dist/generated/jsx.d.ts +9 -11
  8. package/dist/node.d.ts +4 -4
  9. package/dist/node.js +7 -6
  10. package/dist/nodes/about-dialog.d.ts +9 -0
  11. package/dist/nodes/about-dialog.js +14 -0
  12. package/dist/nodes/action-bar.d.ts +9 -0
  13. package/dist/nodes/action-bar.js +15 -0
  14. package/dist/nodes/column-view.d.ts +32 -7
  15. package/dist/nodes/column-view.js +217 -34
  16. package/dist/nodes/dropdown.d.ts +7 -17
  17. package/dist/nodes/dropdown.js +17 -10
  18. package/dist/nodes/flow-box.d.ts +9 -0
  19. package/dist/nodes/flow-box.js +25 -0
  20. package/dist/nodes/grid.d.ts +6 -3
  21. package/dist/nodes/grid.js +28 -26
  22. package/dist/nodes/list-box.d.ts +9 -0
  23. package/dist/nodes/list-box.js +21 -0
  24. package/dist/nodes/list.d.ts +4 -3
  25. package/dist/nodes/list.js +8 -7
  26. package/dist/nodes/notebook.d.ts +7 -3
  27. package/dist/nodes/notebook.js +31 -14
  28. package/dist/nodes/overlay.d.ts +2 -1
  29. package/dist/nodes/root.d.ts +2 -3
  30. package/dist/nodes/root.js +3 -3
  31. package/dist/nodes/slot.d.ts +1 -2
  32. package/dist/nodes/slot.js +2 -2
  33. package/dist/nodes/text-view.d.ts +2 -7
  34. package/dist/nodes/text-view.js +10 -49
  35. package/dist/nodes/widget.d.ts +6 -5
  36. package/dist/nodes/widget.js +9 -149
  37. package/dist/nodes/window.d.ts +11 -0
  38. package/dist/nodes/window.js +37 -0
  39. package/dist/props.d.ts +5 -0
  40. package/dist/props.js +10 -0
  41. package/dist/reconciler.js +4 -5
  42. package/dist/types.d.ts +22 -2
  43. package/package.json +3 -3
@@ -1,7 +1,8 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { type ItemContainer } from "../container-interfaces.js";
2
3
  import type { Props } from "../factory.js";
3
4
  import { Node } from "../node.js";
4
- export declare class ListViewNode extends Node<Gtk.ListView | Gtk.GridView> {
5
+ export declare class ListViewNode extends Node<Gtk.ListView | Gtk.GridView> implements ItemContainer<unknown> {
5
6
  static matches(type: string): boolean;
6
7
  private stringList;
7
8
  private selectionModel;
@@ -10,7 +11,7 @@ export declare class ListViewNode extends Node<Gtk.ListView | Gtk.GridView> {
10
11
  private renderItem;
11
12
  private listItemCache;
12
13
  private committedLength;
13
- constructor(type: string, props: Props, app: Gtk.Application);
14
+ constructor(type: string, props: Props);
14
15
  private syncStringList;
15
16
  addItem(item: unknown): void;
16
17
  insertItemBefore(item: unknown, beforeItem: unknown): void;
@@ -22,7 +23,7 @@ export declare class ListItemNode extends Node {
22
23
  static matches(type: string): boolean;
23
24
  protected isVirtual(): boolean;
24
25
  private item;
25
- constructor(type: string, props: Props, app: Gtk.Application);
26
+ constructor(type: string, props: Props);
26
27
  getItem(): unknown;
27
28
  attachToParent(parent: Node): void;
28
29
  attachToParentBefore(parent: Node, before: Node): void;
@@ -1,6 +1,7 @@
1
1
  import { getObject, getObjectId } from "@gtkx/ffi";
2
2
  import * as Gtk from "@gtkx/ffi/gtk";
3
3
  import { scheduleFlush } from "../batch.js";
4
+ import { isItemContainer } from "../container-interfaces.js";
4
5
  import { createFiberRoot } from "../fiber-root.js";
5
6
  import { Node } from "../node.js";
6
7
  import { reconciler } from "../reconciler.js";
@@ -15,8 +16,8 @@ export class ListViewNode extends Node {
15
16
  renderItem;
16
17
  listItemCache = new Map();
17
18
  committedLength = 0;
18
- constructor(type, props, app) {
19
- super(type, props, app);
19
+ constructor(type, props) {
20
+ super(type, props);
20
21
  this.stringList = new Gtk.StringList([]);
21
22
  this.selectionModel = new Gtk.SingleSelection(this.stringList);
22
23
  this.factory = new Gtk.SignalListItemFactory();
@@ -109,20 +110,20 @@ export class ListItemNode extends Node {
109
110
  return true;
110
111
  }
111
112
  item;
112
- constructor(type, props, app) {
113
- super(type, props, app);
113
+ constructor(type, props) {
114
+ super(type, props);
114
115
  this.item = props.item;
115
116
  }
116
117
  getItem() {
117
118
  return this.item;
118
119
  }
119
120
  attachToParent(parent) {
120
- if (parent instanceof ListViewNode) {
121
+ if (isItemContainer(parent)) {
121
122
  parent.addItem(this.item);
122
123
  }
123
124
  }
124
125
  attachToParentBefore(parent, before) {
125
- if (parent instanceof ListViewNode && before instanceof ListItemNode) {
126
+ if (isItemContainer(parent) && before instanceof ListItemNode) {
126
127
  parent.insertItemBefore(this.item, before.getItem());
127
128
  }
128
129
  else {
@@ -130,7 +131,7 @@ export class ListItemNode extends Node {
130
131
  }
131
132
  }
132
133
  detachFromParent(parent) {
133
- if (parent instanceof ListViewNode) {
134
+ if (isItemContainer(parent)) {
134
135
  parent.removeItem(this.item);
135
136
  }
136
137
  }
@@ -1,20 +1,24 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { type ChildContainer, type PageContainer } from "../container-interfaces.js";
2
3
  import type { Props } from "../factory.js";
3
4
  import { Node } from "../node.js";
4
- export declare class NotebookNode extends Node<Gtk.Notebook> {
5
+ export declare class NotebookNode extends Node<Gtk.Notebook> implements PageContainer, ChildContainer {
5
6
  static matches(type: string): boolean;
6
7
  addPage(child: Gtk.Widget, label: string): void;
7
8
  insertPageBefore(child: Gtk.Widget, label: string, beforeChild: Gtk.Widget): void;
8
9
  removePage(child: Gtk.Widget): void;
9
10
  updatePageLabel(child: Gtk.Widget, label: string): void;
11
+ attachChild(child: Gtk.Widget): void;
12
+ insertChildBefore(child: Gtk.Widget, before: Gtk.Widget): void;
13
+ detachChild(child: Gtk.Widget): void;
10
14
  }
11
15
  export declare class NotebookPageNode extends Node {
12
16
  static matches(type: string): boolean;
13
17
  protected isVirtual(): boolean;
14
18
  private label;
15
19
  private childWidget;
16
- private parentNotebook;
17
- constructor(type: string, props: Props, app: Gtk.Application);
20
+ private parentContainer;
21
+ constructor(type: string, props: Props);
18
22
  getLabel(): string;
19
23
  setChildWidget(widget: Gtk.Widget): void;
20
24
  getChildWidget(): Gtk.Widget | null;
@@ -1,8 +1,10 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { isPageContainer } from "../container-interfaces.js";
2
3
  import { Node } from "../node.js";
4
+ import { getStringProp } from "../props.js";
3
5
  export class NotebookNode extends Node {
4
6
  static matches(type) {
5
- return type === "Notebook.Root";
7
+ return type === "Notebook" || type === "Notebook.Root";
6
8
  }
7
9
  addPage(child, label) {
8
10
  const tabLabel = new Gtk.Label();
@@ -31,6 +33,21 @@ export class NotebookNode extends Node {
31
33
  tabLabel.setLabel(label);
32
34
  this.widget.setTabLabel(child, tabLabel);
33
35
  }
36
+ attachChild(child) {
37
+ this.widget.appendPage(child, null);
38
+ }
39
+ insertChildBefore(child, before) {
40
+ const beforePageNum = this.widget.pageNum(before);
41
+ if (beforePageNum >= 0) {
42
+ this.widget.insertPage(child, beforePageNum, null);
43
+ }
44
+ else {
45
+ this.widget.appendPage(child, null);
46
+ }
47
+ }
48
+ detachChild(child) {
49
+ this.removePage(child);
50
+ }
34
51
  }
35
52
  export class NotebookPageNode extends Node {
36
53
  static matches(type) {
@@ -41,10 +58,10 @@ export class NotebookPageNode extends Node {
41
58
  }
42
59
  label;
43
60
  childWidget = null;
44
- parentNotebook = null;
45
- constructor(type, props, app) {
46
- super(type, props, app);
47
- this.label = props.label ?? "";
61
+ parentContainer = null;
62
+ constructor(type, props) {
63
+ super(type, props);
64
+ this.label = getStringProp(props, "label", "");
48
65
  }
49
66
  getLabel() {
50
67
  return this.label;
@@ -62,14 +79,14 @@ export class NotebookPageNode extends Node {
62
79
  }
63
80
  }
64
81
  attachToParent(parent) {
65
- if (parent instanceof NotebookNode && this.childWidget) {
66
- this.parentNotebook = parent;
82
+ if (isPageContainer(parent) && this.childWidget) {
83
+ this.parentContainer = parent;
67
84
  parent.addPage(this.childWidget, this.label);
68
85
  }
69
86
  }
70
87
  attachToParentBefore(parent, before) {
71
- if (parent instanceof NotebookNode && this.childWidget) {
72
- this.parentNotebook = parent;
88
+ if (isPageContainer(parent) && this.childWidget) {
89
+ this.parentContainer = parent;
73
90
  const beforePage = before instanceof NotebookPageNode ? before.getChildWidget() : before.getWidget();
74
91
  if (beforePage) {
75
92
  parent.insertPageBefore(this.childWidget, this.label, beforePage);
@@ -80,9 +97,9 @@ export class NotebookPageNode extends Node {
80
97
  }
81
98
  }
82
99
  detachFromParent(parent) {
83
- if (parent instanceof NotebookNode && this.childWidget) {
100
+ if (isPageContainer(parent) && this.childWidget) {
84
101
  parent.removePage(this.childWidget);
85
- this.parentNotebook = null;
102
+ this.parentContainer = null;
86
103
  }
87
104
  }
88
105
  consumedProps() {
@@ -92,9 +109,9 @@ export class NotebookPageNode extends Node {
92
109
  }
93
110
  updateProps(oldProps, newProps) {
94
111
  if (oldProps.label !== newProps.label) {
95
- this.label = newProps.label ?? "";
96
- if (this.parentNotebook && this.childWidget) {
97
- this.parentNotebook.updatePageLabel(this.childWidget, this.label);
112
+ this.label = getStringProp(newProps, "label", "");
113
+ if (this.parentContainer && this.childWidget) {
114
+ this.parentContainer.updatePageLabel(this.childWidget, this.label);
98
115
  }
99
116
  }
100
117
  super.updateProps(oldProps, newProps);
@@ -1,6 +1,7 @@
1
1
  import type * as Gtk from "@gtkx/ffi/gtk";
2
+ import type { ChildContainer } from "../container-interfaces.js";
2
3
  import { Node } from "../node.js";
3
- export declare class OverlayNode extends Node<Gtk.Overlay> {
4
+ export declare class OverlayNode extends Node<Gtk.Overlay> implements ChildContainer {
4
5
  static matches(type: string): boolean;
5
6
  private mainChild;
6
7
  private overlayChildren;
@@ -1,9 +1,8 @@
1
1
  import type * as Gtk from "@gtkx/ffi/gtk";
2
- import type { Props } from "../factory.js";
3
2
  import { Node } from "../node.js";
4
3
  export declare const ROOT_NODE_CONTAINER: unique symbol;
5
4
  export declare class RootNode extends Node<never> {
6
- static matches(_type: string, _props: Props, existingWidget?: Gtk.Widget | typeof ROOT_NODE_CONTAINER): boolean;
5
+ static matches(_type: string, existingWidget?: Gtk.Widget | typeof ROOT_NODE_CONTAINER): boolean;
7
6
  protected isVirtual(): boolean;
8
- constructor(app: Gtk.Application);
7
+ constructor();
9
8
  }
@@ -1,13 +1,13 @@
1
1
  import { Node } from "../node.js";
2
2
  export const ROOT_NODE_CONTAINER = Symbol.for("ROOT_NODE_CONTAINER");
3
3
  export class RootNode extends Node {
4
- static matches(_type, _props, existingWidget) {
4
+ static matches(_type, existingWidget) {
5
5
  return existingWidget === ROOT_NODE_CONTAINER;
6
6
  }
7
7
  isVirtual() {
8
8
  return true;
9
9
  }
10
- constructor(app) {
11
- super("", {}, app);
10
+ constructor() {
11
+ super("", {});
12
12
  }
13
13
  }
@@ -1,4 +1,3 @@
1
- import type * as Gtk from "@gtkx/ffi/gtk";
2
1
  import type { Props } from "../factory.js";
3
2
  import { Node } from "../node.js";
4
3
  export declare class SlotNode extends Node<never> {
@@ -7,7 +6,7 @@ export declare class SlotNode extends Node<never> {
7
6
  private child;
8
7
  private slotName;
9
8
  private parentNode;
10
- constructor(type: string, props: Props, app: Gtk.Application);
9
+ constructor(type: string, props: Props);
11
10
  private updateParentSlot;
12
11
  appendChild(child: Node): void;
13
12
  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, app) {
19
- super(type, props, app);
18
+ constructor(type, props) {
19
+ super(type, props);
20
20
  const dotIndex = type.indexOf(".");
21
21
  if (dotIndex === -1) {
22
22
  throw new Error(`Invalid slot type: ${type}`);
@@ -1,14 +1,9 @@
1
- import * as Gtk from "@gtkx/ffi/gtk";
1
+ 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
5
  static matches(type: string): boolean;
6
- private buffer;
7
- private onChanged?;
8
- private bufferChangedHandlerId?;
9
- constructor(type: string, props: Props, app: Gtk.Application);
10
- private connectBufferSignal;
11
- private disconnectBufferSignal;
6
+ constructor(type: string, props: Props);
12
7
  protected consumedProps(): Set<string>;
13
8
  updateProps(oldProps: Props, newProps: Props): void;
14
9
  }
@@ -1,64 +1,25 @@
1
- import { createRef } from "@gtkx/ffi";
2
- import * as GObject from "@gtkx/ffi/gobject";
3
- import * as Gtk from "@gtkx/ffi/gtk";
4
1
  import { Node } from "../node.js";
5
- const getBufferText = (buffer) => {
6
- const startRef = createRef(new Gtk.TextIter());
7
- const endRef = createRef(new Gtk.TextIter());
8
- buffer.getStartIter(startRef);
9
- buffer.getEndIter(endRef);
10
- return buffer.getText(startRef.value, endRef.value, true);
11
- };
12
- const setBufferText = (buffer, text) => {
13
- buffer.setText(text, -1);
14
- };
15
2
  export class TextViewNode extends Node {
16
3
  static matches(type) {
17
4
  return type === "TextView";
18
5
  }
19
- buffer;
20
- onChanged;
21
- bufferChangedHandlerId;
22
- constructor(type, props, app) {
23
- super(type, props, app);
24
- this.buffer = this.widget.getBuffer();
25
- this.onChanged = props.onChanged;
26
- if (typeof props.text === "string") {
27
- setBufferText(this.buffer, props.text);
28
- }
29
- // Connect after a microtask to avoid signal firing during widget construction
30
- queueMicrotask(() => this.connectBufferSignal());
31
- }
32
- connectBufferSignal() {
33
- if (this.onChanged && this.bufferChangedHandlerId === undefined) {
34
- this.bufferChangedHandlerId = this.buffer.connect("changed", () => {
35
- const text = getBufferText(this.buffer);
36
- this.onChanged?.(text);
37
- });
38
- }
39
- }
40
- disconnectBufferSignal() {
41
- if (this.bufferChangedHandlerId !== undefined) {
42
- GObject.signalHandlerDisconnect(this.buffer, this.bufferChangedHandlerId);
43
- this.bufferChangedHandlerId = undefined;
6
+ constructor(type, props) {
7
+ super(type, props);
8
+ const buffer = props.buffer;
9
+ if (buffer) {
10
+ this.widget.setBuffer(buffer);
44
11
  }
45
12
  }
46
13
  consumedProps() {
47
14
  const consumed = super.consumedProps();
48
- consumed.add("text");
49
- consumed.add("onChanged");
15
+ consumed.add("buffer");
50
16
  return consumed;
51
17
  }
52
18
  updateProps(oldProps, newProps) {
53
- if (this.buffer && oldProps.onChanged !== newProps.onChanged) {
54
- this.disconnectBufferSignal();
55
- this.onChanged = newProps.onChanged;
56
- this.connectBufferSignal();
57
- }
58
- if (this.buffer && oldProps.text !== newProps.text && typeof newProps.text === "string") {
59
- const currentText = getBufferText(this.buffer);
60
- if (currentText !== newProps.text) {
61
- setBufferText(this.buffer, newProps.text);
19
+ if (oldProps.buffer !== newProps.buffer) {
20
+ const buffer = newProps.buffer;
21
+ if (buffer) {
22
+ this.widget.setBuffer(buffer);
62
23
  }
63
24
  }
64
25
  super.updateProps(oldProps, newProps);
@@ -1,12 +1,13 @@
1
- import * as Gtk from "@gtkx/ffi/gtk";
2
- import type { Props } from "../factory.js";
1
+ import type * as Gtk from "@gtkx/ffi/gtk";
3
2
  import { Node } from "../node.js";
3
+ /**
4
+ * Catch-all node for standard GTK widgets that don't need special handling.
5
+ * Specialized widgets (Window, AboutDialog, ActionBar, FlowBox, ListBox, etc.)
6
+ * are handled by their own dedicated Node classes.
7
+ */
4
8
  export declare class WidgetNode extends Node<Gtk.Widget> {
5
9
  static matches(_type: string): boolean;
6
10
  attachToParent(parent: Node): void;
7
11
  attachToParentBefore(parent: Node, before: Node): void;
8
12
  detachFromParent(parent: Node): void;
9
- protected consumedProps(): Set<string>;
10
- updateProps(oldProps: Props, newProps: Props): void;
11
- mount(_app: Gtk.Application): void;
12
13
  }
@@ -1,62 +1,23 @@
1
- import { getObjectId } from "@gtkx/ffi";
2
- import * as GObject from "@gtkx/ffi/gobject";
3
- import * as Gtk from "@gtkx/ffi/gtk";
1
+ import { isChildContainer } from "../container-interfaces.js";
4
2
  import { Node } from "../node.js";
5
- import { OverlayNode } from "./overlay.js";
6
- const isFlowBox = (widget) => widget instanceof Gtk.FlowBox;
7
- const isFlowBoxChild = (widget) => GObject.typeNameFromInstance(getObjectId(widget.ptr)) === "GtkFlowBoxChild";
8
- const isListBox = (widget) => widget instanceof Gtk.ListBox;
9
- const isListBoxRow = (widget) => GObject.typeNameFromInstance(getObjectId(widget.ptr)) === "GtkListBoxRow";
10
- const COMBINED_PROPS = [
11
- {
12
- props: ["defaultWidth", "defaultHeight"],
13
- apply: (widget) => (values) => {
14
- if (widget instanceof Gtk.Window) {
15
- const width = values.defaultWidth ?? -1;
16
- const height = values.defaultHeight ?? -1;
17
- widget.setDefaultSize(width, height);
18
- }
19
- },
20
- },
21
- ];
3
+ /**
4
+ * Catch-all node for standard GTK widgets that don't need special handling.
5
+ * Specialized widgets (Window, AboutDialog, ActionBar, FlowBox, ListBox, etc.)
6
+ * are handled by their own dedicated Node classes.
7
+ */
22
8
  export class WidgetNode extends Node {
23
9
  static matches(_type) {
24
10
  return true;
25
11
  }
26
12
  attachToParent(parent) {
27
- if (this.widget instanceof Gtk.AboutDialog) {
28
- return;
29
- }
30
- if (parent instanceof OverlayNode) {
13
+ if (isChildContainer(parent)) {
31
14
  parent.attachChild(this.widget);
32
15
  return;
33
16
  }
34
- const parentWidget = parent.getWidget();
35
- if (!parentWidget)
36
- return;
37
- if (parentWidget instanceof Gtk.ActionBar) {
38
- parentWidget.packStart(this.widget);
39
- return;
40
- }
41
- if (parentWidget instanceof Gtk.Notebook) {
42
- parentWidget.appendPage(this.widget);
43
- return;
44
- }
45
- if (isFlowBox(parentWidget)) {
46
- parentWidget.append(this.widget);
47
- return;
48
- }
49
- if (isListBox(parentWidget)) {
50
- parentWidget.append(this.widget);
51
- return;
52
- }
53
17
  super.attachToParent(parent);
54
18
  }
55
19
  attachToParentBefore(parent, before) {
56
- if (this.widget instanceof Gtk.AboutDialog) {
57
- return;
58
- }
59
- if (parent instanceof OverlayNode) {
20
+ if (isChildContainer(parent)) {
60
21
  const beforeWidget = before.getWidget();
61
22
  if (beforeWidget) {
62
23
  parent.insertChildBefore(this.widget, beforeWidget);
@@ -66,114 +27,13 @@ export class WidgetNode extends Node {
66
27
  }
67
28
  return;
68
29
  }
69
- const parentWidget = parent.getWidget();
70
- const beforeWidget = before.getWidget();
71
- if (!parentWidget)
72
- return;
73
- if (parentWidget instanceof Gtk.ActionBar) {
74
- parentWidget.packStart(this.widget);
75
- return;
76
- }
77
- if (parentWidget instanceof Gtk.Notebook && beforeWidget) {
78
- const beforePageNum = parentWidget.pageNum(beforeWidget);
79
- if (beforePageNum >= 0) {
80
- parentWidget.insertPage(this.widget, beforePageNum);
81
- }
82
- else {
83
- parentWidget.appendPage(this.widget);
84
- }
85
- return;
86
- }
87
- if (isFlowBox(parentWidget)) {
88
- if (beforeWidget) {
89
- const beforeChild = beforeWidget.getParent();
90
- if (beforeChild && isFlowBoxChild(beforeChild)) {
91
- parentWidget.insert(this.widget, beforeChild.getIndex());
92
- }
93
- else {
94
- parentWidget.append(this.widget);
95
- }
96
- }
97
- else {
98
- parentWidget.append(this.widget);
99
- }
100
- return;
101
- }
102
- if (isListBox(parentWidget)) {
103
- if (beforeWidget && isListBoxRow(beforeWidget)) {
104
- parentWidget.insert(this.widget, beforeWidget.getIndex());
105
- }
106
- else {
107
- parentWidget.append(this.widget);
108
- }
109
- return;
110
- }
111
30
  super.attachToParentBefore(parent, before);
112
31
  }
113
32
  detachFromParent(parent) {
114
- if (this.widget instanceof Gtk.Window) {
115
- this.widget.destroy();
116
- return;
117
- }
118
- if (this.widget instanceof Gtk.AboutDialog) {
119
- return;
120
- }
121
- if (parent instanceof OverlayNode) {
33
+ if (isChildContainer(parent)) {
122
34
  parent.detachChild(this.widget);
123
35
  return;
124
36
  }
125
- const parentWidget = parent.getWidget();
126
- if (!parentWidget)
127
- return;
128
- if (parentWidget instanceof Gtk.ActionBar) {
129
- parentWidget.remove(this.widget);
130
- return;
131
- }
132
- if (parentWidget instanceof Gtk.Notebook) {
133
- const pageNum = parentWidget.pageNum(this.widget);
134
- if (pageNum >= 0) {
135
- parentWidget.removePage(pageNum);
136
- }
137
- return;
138
- }
139
- if (isFlowBox(parentWidget)) {
140
- const flowBoxChild = this.widget.getParent();
141
- if (flowBoxChild) {
142
- parentWidget.remove(flowBoxChild);
143
- }
144
- return;
145
- }
146
- if (isListBox(parentWidget)) {
147
- parentWidget.remove(this.widget);
148
- return;
149
- }
150
37
  super.detachFromParent(parent);
151
38
  }
152
- consumedProps() {
153
- const consumed = super.consumedProps();
154
- for (const handler of COMBINED_PROPS) {
155
- for (const prop of handler.props) {
156
- consumed.add(prop);
157
- }
158
- }
159
- return consumed;
160
- }
161
- updateProps(oldProps, newProps) {
162
- for (const handler of COMBINED_PROPS) {
163
- const hasAnyChanged = handler.props.some((prop) => oldProps[prop] !== newProps[prop]);
164
- if (hasAnyChanged) {
165
- const values = {};
166
- for (const prop of handler.props) {
167
- values[prop] = newProps[prop];
168
- }
169
- handler.apply(this.widget)(values);
170
- }
171
- }
172
- super.updateProps(oldProps, newProps);
173
- }
174
- mount(_app) {
175
- if (this.widget instanceof Gtk.Window) {
176
- this.widget.present();
177
- }
178
- }
179
39
  }
@@ -0,0 +1,11 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import type { Props } from "../factory.js";
3
+ import { Node } from "../node.js";
4
+ export declare class WindowNode extends Node<Gtk.Window> {
5
+ static matches(type: string): boolean;
6
+ protected createWidget(type: string, _props: Props): Gtk.Window;
7
+ detachFromParent(_parent: Node): void;
8
+ mount(): void;
9
+ protected consumedProps(): Set<string>;
10
+ updateProps(oldProps: Props, newProps: Props): void;
11
+ }
@@ -0,0 +1,37 @@
1
+ import { getCurrentApp } from "@gtkx/ffi";
2
+ import * as Gtk from "@gtkx/ffi/gtk";
3
+ import { Node } from "../node.js";
4
+ import { getNumberProp } from "../props.js";
5
+ export class WindowNode extends Node {
6
+ static matches(type) {
7
+ return type === "Window" || type === "ApplicationWindow";
8
+ }
9
+ createWidget(type, _props) {
10
+ if (type === "ApplicationWindow") {
11
+ return new Gtk.ApplicationWindow(getCurrentApp());
12
+ }
13
+ return new Gtk.Window();
14
+ }
15
+ detachFromParent(_parent) {
16
+ this.widget.destroy();
17
+ }
18
+ mount() {
19
+ this.widget.present();
20
+ }
21
+ consumedProps() {
22
+ const consumed = super.consumedProps();
23
+ consumed.add("defaultWidth");
24
+ consumed.add("defaultHeight");
25
+ return consumed;
26
+ }
27
+ updateProps(oldProps, newProps) {
28
+ const widthChanged = oldProps.defaultWidth !== newProps.defaultWidth;
29
+ const heightChanged = oldProps.defaultHeight !== newProps.defaultHeight;
30
+ if (widthChanged || heightChanged) {
31
+ const width = getNumberProp(newProps, "defaultWidth", -1);
32
+ const height = getNumberProp(newProps, "defaultHeight", -1);
33
+ this.widget.setDefaultSize(width, height);
34
+ }
35
+ super.updateProps(oldProps, newProps);
36
+ }
37
+ }
@@ -0,0 +1,5 @@
1
+ import type { Props } from "./factory.js";
2
+ /** Extracts a number property from props with a default value. */
3
+ export declare const getNumberProp: (props: Props, key: string, defaultValue: number) => number;
4
+ /** Extracts a string property from props with a default value. */
5
+ export declare const getStringProp: (props: Props, key: string, defaultValue: string) => string;
package/dist/props.js ADDED
@@ -0,0 +1,10 @@
1
+ /** Extracts a number property from props with a default value. */
2
+ export const getNumberProp = (props, key, defaultValue) => {
3
+ const value = props[key];
4
+ return typeof value === "number" ? value : defaultValue;
5
+ };
6
+ /** Extracts a string property from props with a default value. */
7
+ export const getStringProp = (props, key, defaultValue) => {
8
+ const value = props[key];
9
+ return typeof value === "string" ? value : defaultValue;
10
+ };
@@ -1,4 +1,3 @@
1
- import { getCurrentApp } from "@gtkx/ffi";
2
1
  import React from "react";
3
2
  import ReactReconciler from "react-reconciler";
4
3
  import { beginCommit, endCommit } from "./batch.js";
@@ -30,16 +29,16 @@ class Reconciler {
30
29
  getChildHostContext: (parentHostContext) => parentHostContext,
31
30
  shouldSetTextContent: () => false,
32
31
  createInstance: (type, props) => {
33
- return createNode(type, props, getCurrentApp());
32
+ return createNode(type, props);
34
33
  },
35
- createTextInstance: (text) => createNode("Label.Root", { label: text }, getCurrentApp()),
34
+ createTextInstance: (text) => createNode("Label.Root", { label: text }),
36
35
  appendInitialChild: (parent, child) => parent.appendChild(child),
37
36
  finalizeInitialChildren: () => true,
38
37
  commitUpdate: (instance, _type, oldProps, newProps) => {
39
38
  instance.updateProps(oldProps, newProps);
40
39
  },
41
40
  commitMount: (instance) => {
42
- instance.mount(getCurrentApp());
41
+ instance.mount();
43
42
  },
44
43
  appendChild: (parent, child) => parent.appendChild(child),
45
44
  removeChild: (parent, child) => parent.removeChild(child),
@@ -105,7 +104,7 @@ class Reconciler {
105
104
  return context;
106
105
  }
107
106
  createNodeFromContainer(container) {
108
- return createNode(container.constructor.name, {}, getCurrentApp(), container);
107
+ return createNode(container.constructor.name, {}, container);
109
108
  }
110
109
  }
111
110
  /** The singleton GTKX React reconciler instance. */