@gtkx/react 0.1.26 → 0.1.28

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/dist/node.d.ts CHANGED
@@ -4,6 +4,7 @@ export declare abstract class Node<T extends Gtk.Widget | undefined = Gtk.Widget
4
4
  static matches(_type: string): boolean;
5
5
  protected signalHandlers: Map<string, number>;
6
6
  protected widget: T;
7
+ protected widgetType: string;
7
8
  protected isVirtual(): boolean;
8
9
  constructor(type: string, props: Props, app: Gtk.Application, existingWidget?: Gtk.Widget);
9
10
  protected createWidget(type: string, props: Props, app: Gtk.Application): T;
@@ -16,8 +17,9 @@ export declare abstract class Node<T extends Gtk.Widget | undefined = Gtk.Widget
16
17
  attachToParentBefore(parent: Node, before: Node): void;
17
18
  protected consumedProps(): Set<string>;
18
19
  updateProps(oldProps: Props, newProps: Props): void;
19
- protected setSignalProperty(widget: Gtk.Widget, key: string, handler: unknown): void;
20
- protected setSignalHandler(widget: Gtk.Widget, eventName: string, handler: (...args: unknown[]) => unknown): void;
20
+ protected propKeyToEventName(key: string): string;
21
+ protected disconnectSignal(eventName: string): void;
22
+ protected connectSignal(widget: Gtk.Widget, eventName: string, handler: (...args: unknown[]) => unknown): void;
21
23
  protected setProperty(widget: Gtk.Widget, key: string, value: unknown): void;
22
24
  mount(_app: Gtk.Application): void;
23
25
  dispose(_app: Gtk.Application): void;
package/dist/node.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as GObject from "@gtkx/ffi/gobject";
2
2
  import * as Gtk from "@gtkx/ffi/gtk";
3
- import { CONSTRUCTOR_PARAMS } from "./generated/jsx.js";
3
+ import { CONSTRUCTOR_PARAMS, SETTER_GETTERS } from "./generated/jsx.js";
4
4
  import { isAppendable, isRemovable, isSingleChild } from "./predicates.js";
5
5
  const extractConstructorArgs = (type, props) => {
6
6
  const params = CONSTRUCTOR_PARAMS[type];
@@ -14,10 +14,12 @@ export class Node {
14
14
  }
15
15
  signalHandlers = new Map();
16
16
  widget;
17
+ widgetType;
17
18
  isVirtual() {
18
19
  return false;
19
20
  }
20
21
  constructor(type, props, app, existingWidget) {
22
+ this.widgetType = type.split(".")[0] || type;
21
23
  if (existingWidget) {
22
24
  this.widget = existingWidget;
23
25
  return;
@@ -94,6 +96,8 @@ export class Node {
94
96
  return;
95
97
  const consumed = this.consumedProps();
96
98
  const allKeys = new Set([...Object.keys(oldProps), ...Object.keys(newProps)]);
99
+ const signalUpdates = [];
100
+ const propertyUpdates = [];
97
101
  for (const key of allKeys) {
98
102
  if (consumed.has(key))
99
103
  continue;
@@ -102,39 +106,64 @@ export class Node {
102
106
  if (oldValue === newValue)
103
107
  continue;
104
108
  if (key.startsWith("on")) {
105
- this.setSignalProperty(widget, key, newValue);
106
- continue;
109
+ signalUpdates.push({ key, newValue });
107
110
  }
108
- if (newValue === undefined)
109
- continue;
111
+ else if (newValue !== undefined) {
112
+ propertyUpdates.push({ key, newValue });
113
+ }
114
+ }
115
+ for (const { key } of signalUpdates) {
116
+ this.disconnectSignal(this.propKeyToEventName(key));
117
+ }
118
+ for (const { key, newValue } of propertyUpdates) {
110
119
  this.setProperty(widget, key, newValue);
111
120
  }
121
+ for (const { key, newValue } of signalUpdates) {
122
+ if (typeof newValue === "function") {
123
+ this.connectSignal(widget, this.propKeyToEventName(key), newValue);
124
+ }
125
+ }
112
126
  }
113
- setSignalProperty(widget, key, handler) {
114
- const eventName = key
127
+ propKeyToEventName(key) {
128
+ return key
115
129
  .slice(2)
116
130
  .replace(/([A-Z])/g, "-$1")
117
131
  .toLowerCase()
118
132
  .replace(/^-/, "");
119
- const oldHandlerId = this.signalHandlers.get(eventName);
120
- if (oldHandlerId !== undefined) {
121
- GObject.signalHandlerDisconnect(widget, oldHandlerId);
133
+ }
134
+ disconnectSignal(eventName) {
135
+ const handlerId = this.signalHandlers.get(eventName);
136
+ if (handlerId !== undefined) {
137
+ const widget = this.getWidget();
138
+ if (widget) {
139
+ GObject.signalHandlerDisconnect(widget, handlerId);
140
+ }
122
141
  this.signalHandlers.delete(eventName);
123
142
  }
124
- if (typeof handler === "function") {
125
- this.setSignalHandler(widget, eventName, handler);
126
- }
127
143
  }
128
- setSignalHandler(widget, eventName, handler) {
144
+ connectSignal(widget, eventName, handler) {
129
145
  const handlerId = widget.connect(eventName, handler);
130
146
  this.signalHandlers.set(eventName, handlerId);
131
147
  }
132
148
  setProperty(widget, key, value) {
133
149
  const setterName = `set${key.charAt(0).toUpperCase()}${key.slice(1)}`;
134
150
  const setter = widget[setterName];
135
- if (typeof setter === "function") {
136
- setter.call(widget, value);
151
+ if (typeof setter !== "function")
152
+ return;
153
+ const getterName = SETTER_GETTERS[this.widgetType]?.[setterName];
154
+ if (getterName) {
155
+ const getter = widget[getterName];
156
+ if (typeof getter === "function") {
157
+ try {
158
+ const currentValue = getter.call(widget);
159
+ if (currentValue === value)
160
+ return;
161
+ }
162
+ catch {
163
+ }
164
+ }
137
165
  }
166
+ setter.call(widget, value);
138
167
  }
139
168
  mount(_app) { }
140
169
  dispose(_app) { }
@@ -48,7 +48,7 @@ export class DropDownNode extends Node {
48
48
  const item = this.store.getItem(index);
49
49
  this.onSelectionChanged?.(item, index);
50
50
  };
51
- this.setSignalHandler(this.widget, "notify::selected", handler);
51
+ this.connectSignal(this.widget, "notify::selected", handler);
52
52
  }
53
53
  }
54
54
  getStore() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/react",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
4
4
  "description": "Build GTK4 desktop applications with React and TypeScript",
5
5
  "keywords": [
6
6
  "gtk",
@@ -40,10 +40,10 @@
40
40
  ],
41
41
  "dependencies": {
42
42
  "react-reconciler": "0.33.0",
43
- "@gtkx/ffi": "0.1.26"
43
+ "@gtkx/ffi": "0.1.28"
44
44
  },
45
45
  "devDependencies": {
46
- "@gtkx/gir": "0.1.26"
46
+ "@gtkx/gir": "0.1.28"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "react": "^19"