@gtkx/react 0.15.0 → 0.17.1

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 (172) hide show
  1. package/README.md +1 -0
  2. package/dist/animation/css-builder.d.ts +3 -0
  3. package/dist/animation/css-builder.js +53 -0
  4. package/dist/animation/types.d.ts +120 -0
  5. package/dist/errors.js +3 -0
  6. package/dist/factory.d.ts +3 -2
  7. package/dist/factory.js +1 -1
  8. package/dist/fiber-root.js +1 -1
  9. package/dist/generated/internal.d.ts +28 -1
  10. package/dist/generated/internal.js +93 -18
  11. package/dist/generated/jsx.d.ts +1672 -1483
  12. package/dist/generated/jsx.js +475 -0
  13. package/dist/host-config.d.ts +3 -1
  14. package/dist/host-config.js +26 -11
  15. package/dist/jsx.d.ts +136 -166
  16. package/dist/jsx.js +58 -69
  17. package/dist/node.d.ts +4 -1
  18. package/dist/node.js +14 -3
  19. package/dist/nodes/abstract/positional-child.d.ts +9 -0
  20. package/dist/nodes/abstract/positional-child.js +29 -0
  21. package/dist/nodes/abstract/virtual-container.d.ts +21 -0
  22. package/dist/nodes/abstract/virtual-container.js +68 -0
  23. package/dist/nodes/abstract/virtual-single-child.d.ts +18 -0
  24. package/dist/nodes/abstract/virtual-single-child.js +55 -0
  25. package/dist/nodes/action-row-child.d.ts +0 -13
  26. package/dist/nodes/action-row-child.js +22 -12
  27. package/dist/nodes/adjustable.d.ts +23 -0
  28. package/dist/nodes/adjustable.js +62 -0
  29. package/dist/nodes/alert-dialog-response.js +86 -0
  30. package/dist/nodes/animation.js +252 -0
  31. package/dist/nodes/application.js +17 -7
  32. package/dist/nodes/autowrapped.js +37 -43
  33. package/dist/nodes/calendar.js +17 -43
  34. package/dist/nodes/color-dialog-button.d.ts +1 -0
  35. package/dist/nodes/color-dialog-button.js +70 -0
  36. package/dist/nodes/column-view-column.d.ts +3 -3
  37. package/dist/nodes/column-view-column.js +1 -1
  38. package/dist/nodes/column-view.js +36 -39
  39. package/dist/nodes/dialog.d.ts +11 -0
  40. package/dist/nodes/dialog.js +20 -0
  41. package/dist/nodes/drawing-area.js +24 -7
  42. package/dist/nodes/event-controller.d.ts +22 -0
  43. package/dist/nodes/event-controller.js +96 -0
  44. package/dist/nodes/expander-row-child.d.ts +0 -14
  45. package/dist/nodes/expander-row-child.js +22 -12
  46. package/dist/nodes/fixed-child.js +52 -36
  47. package/dist/nodes/font-dialog-button.d.ts +1 -0
  48. package/dist/nodes/font-dialog-button.js +90 -0
  49. package/dist/nodes/grid-child.js +43 -45
  50. package/dist/nodes/grid.d.ts +1 -0
  51. package/dist/nodes/grid.js +41 -0
  52. package/dist/nodes/index.d.ts +18 -12
  53. package/dist/nodes/index.js +18 -12
  54. package/dist/nodes/internal/base-item-renderer.d.ts +29 -0
  55. package/dist/nodes/internal/base-item-renderer.js +88 -0
  56. package/dist/nodes/internal/child-attachment.d.ts +26 -0
  57. package/dist/nodes/internal/child-attachment.js +48 -0
  58. package/dist/nodes/internal/deferred-action.d.ts +9 -0
  59. package/dist/nodes/internal/deferred-action.js +22 -0
  60. package/dist/nodes/internal/list-item-renderer.d.ts +14 -15
  61. package/dist/nodes/internal/list-item-renderer.js +51 -77
  62. package/dist/nodes/internal/list-store.d.ts +5 -6
  63. package/dist/nodes/internal/list-store.js +29 -38
  64. package/dist/nodes/internal/predicates.d.ts +25 -2
  65. package/dist/nodes/internal/predicates.js +53 -41
  66. package/dist/nodes/internal/selection-model.d.ts +30 -0
  67. package/dist/nodes/internal/selection-model.js +87 -0
  68. package/dist/nodes/internal/signal-store.d.ts +9 -5
  69. package/dist/nodes/internal/signal-store.js +31 -31
  70. package/dist/nodes/internal/simple-list-store.js +6 -9
  71. package/dist/nodes/internal/text-buffer-controller.d.ts +43 -0
  72. package/dist/nodes/internal/text-buffer-controller.js +287 -0
  73. package/dist/nodes/internal/text-tag-styles.d.ts +43 -0
  74. package/dist/nodes/internal/text-tag-styles.js +52 -0
  75. package/dist/nodes/internal/tree-list-item-renderer.d.ts +15 -14
  76. package/dist/nodes/internal/tree-list-item-renderer.js +85 -96
  77. package/dist/nodes/internal/tree-store.d.ts +8 -11
  78. package/dist/nodes/internal/tree-store.js +70 -72
  79. package/dist/nodes/internal/utils.d.ts +7 -4
  80. package/dist/nodes/internal/utils.js +50 -5
  81. package/dist/nodes/level-bar.js +19 -54
  82. package/dist/nodes/list-item.d.ts +6 -3
  83. package/dist/nodes/list-item.js +7 -4
  84. package/dist/nodes/list-view.js +17 -12
  85. package/dist/nodes/menu.d.ts +3 -3
  86. package/dist/nodes/menu.js +3 -3
  87. package/dist/nodes/models/list.d.ts +11 -13
  88. package/dist/nodes/models/list.js +16 -73
  89. package/dist/nodes/models/menu.d.ts +8 -7
  90. package/dist/nodes/models/menu.js +43 -50
  91. package/dist/nodes/models/tree-list.d.ts +6 -12
  92. package/dist/nodes/models/tree-list.js +30 -93
  93. package/dist/nodes/navigation-page.d.ts +1 -0
  94. package/dist/nodes/navigation-page.js +27 -32
  95. package/dist/nodes/navigation-view.js +17 -28
  96. package/dist/nodes/notebook-page-tab.d.ts +3 -3
  97. package/dist/nodes/notebook-page-tab.js +11 -14
  98. package/dist/nodes/notebook-page.d.ts +7 -5
  99. package/dist/nodes/notebook-page.js +45 -25
  100. package/dist/nodes/notebook.js +2 -2
  101. package/dist/nodes/overlay-child.js +90 -30
  102. package/dist/nodes/pack-child.d.ts +0 -13
  103. package/dist/nodes/pack-child.js +22 -12
  104. package/dist/nodes/popover-menu.js +2 -2
  105. package/dist/nodes/scale.js +15 -45
  106. package/dist/nodes/scrolled-window.js +7 -6
  107. package/dist/nodes/search-bar.d.ts +1 -0
  108. package/dist/nodes/search-bar.js +40 -0
  109. package/dist/nodes/shortcut-controller.d.ts +1 -37
  110. package/dist/nodes/shortcut-controller.js +8 -47
  111. package/dist/nodes/shortcut.d.ts +5 -4
  112. package/dist/nodes/shortcut.js +11 -5
  113. package/dist/nodes/simple-list-view.js +2 -3
  114. package/dist/nodes/slot.d.ts +6 -9
  115. package/dist/nodes/slot.js +27 -42
  116. package/dist/nodes/source-view.js +80 -29
  117. package/dist/nodes/stack-page.js +20 -22
  118. package/dist/nodes/stack.js +19 -5
  119. package/dist/nodes/text-anchor.d.ts +41 -0
  120. package/dist/nodes/text-anchor.js +59 -0
  121. package/dist/nodes/text-content.d.ts +10 -0
  122. package/dist/nodes/text-content.js +1 -0
  123. package/dist/nodes/text-paintable.d.ts +17 -0
  124. package/dist/nodes/text-paintable.js +34 -0
  125. package/dist/nodes/text-segment.d.ts +15 -0
  126. package/dist/nodes/text-segment.js +29 -0
  127. package/dist/nodes/text-tag.d.ts +136 -0
  128. package/dist/nodes/text-tag.js +202 -0
  129. package/dist/nodes/text-view.d.ts +30 -0
  130. package/dist/nodes/text-view.js +49 -21
  131. package/dist/nodes/toggle-group.js +24 -32
  132. package/dist/nodes/toggle.d.ts +1 -15
  133. package/dist/nodes/toggle.js +40 -32
  134. package/dist/nodes/toolbar-child.js +22 -31
  135. package/dist/nodes/tree-list-item.d.ts +7 -5
  136. package/dist/nodes/tree-list-item.js +24 -36
  137. package/dist/nodes/tree-list-view.js +9 -7
  138. package/dist/nodes/virtual.d.ts +1 -1
  139. package/dist/nodes/web-view.d.ts +1 -0
  140. package/dist/nodes/web-view.js +29 -0
  141. package/dist/nodes/widget.d.ts +2 -16
  142. package/dist/nodes/widget.js +105 -294
  143. package/dist/nodes/window.d.ts +9 -3
  144. package/dist/nodes/window.js +29 -15
  145. package/dist/registry.d.ts +1 -1
  146. package/dist/render.js +9 -7
  147. package/dist/scheduler.d.ts +11 -1
  148. package/dist/scheduler.js +16 -4
  149. package/dist/types.d.ts +2 -136
  150. package/package.json +4 -4
  151. package/dist/nodes/action-row.js +0 -46
  152. package/dist/nodes/adjustment.d.ts +0 -48
  153. package/dist/nodes/adjustment.js +0 -70
  154. package/dist/nodes/calendar-mark.d.ts +0 -15
  155. package/dist/nodes/calendar-mark.js +0 -29
  156. package/dist/nodes/expander-row.js +0 -55
  157. package/dist/nodes/internal/constants.d.ts +0 -1
  158. package/dist/nodes/internal/constants.js +0 -24
  159. package/dist/nodes/level-bar-offset.d.ts +0 -13
  160. package/dist/nodes/level-bar-offset.js +0 -35
  161. package/dist/nodes/pack.js +0 -46
  162. package/dist/nodes/scale-mark.d.ts +0 -17
  163. package/dist/nodes/scale-mark.js +0 -38
  164. package/dist/nodes/source-buffer.d.ts +0 -73
  165. package/dist/nodes/source-buffer.js +0 -149
  166. package/dist/nodes/text-buffer.d.ts +0 -43
  167. package/dist/nodes/text-buffer.js +0 -81
  168. package/dist/nodes/virtual-child.d.ts +0 -18
  169. package/dist/nodes/virtual-child.js +0 -62
  170. /package/dist/{nodes/action-row.d.ts → animation/types.js} +0 -0
  171. /package/dist/nodes/{expander-row.d.ts → alert-dialog-response.d.ts} +0 -0
  172. /package/dist/nodes/{pack.d.ts → animation.d.ts} +0 -0
@@ -0,0 +1,252 @@
1
+ import { isObjectEqual } from "@gtkx/ffi";
2
+ import * as Adw from "@gtkx/ffi/adw";
3
+ import * as Gdk from "@gtkx/ffi/gdk";
4
+ import * as Gtk from "@gtkx/ffi/gtk";
5
+ import { buildCss, interpolate } from "../animation/css-builder.js";
6
+ import { registerNodeClass } from "../registry.js";
7
+ import { CommitPriority, scheduleAfterCommit } from "../scheduler.js";
8
+ import { VirtualSingleChildNode } from "./abstract/virtual-single-child.js";
9
+ import { attachChild, detachChild, getAttachmentStrategy } from "./internal/child-attachment.js";
10
+ import { isRemovable } from "./internal/predicates.js";
11
+ let animationCounter = 0;
12
+ const DEFAULT_TIMED_DURATION = 300;
13
+ const DEFAULT_SPRING_DAMPING = 1;
14
+ const DEFAULT_SPRING_MASS = 1;
15
+ const DEFAULT_SPRING_STIFFNESS = 100;
16
+ class AnimationNode extends VirtualSingleChildNode {
17
+ static priority = 2;
18
+ static matches(type) {
19
+ return type === "Animation";
20
+ }
21
+ className;
22
+ provider = null;
23
+ display = null;
24
+ currentAnimation = null;
25
+ currentValues = {};
26
+ isExiting = false;
27
+ constructor(typeName, props, container, rootContainer) {
28
+ super(typeName, props, container, rootContainer);
29
+ this.className = `gtkx-anim-${animationCounter++}`;
30
+ }
31
+ updateProps(oldProps, newProps) {
32
+ super.updateProps(oldProps, newProps);
33
+ if (this.isExiting) {
34
+ return;
35
+ }
36
+ if (oldProps && newProps.animate && !this.arePropsEqual(oldProps.animate, newProps.animate)) {
37
+ const target = newProps.animate;
38
+ scheduleAfterCommit(() => {
39
+ if (this.child && !this.isExiting) {
40
+ this.animateTo(target);
41
+ }
42
+ }, CommitPriority.LOW);
43
+ }
44
+ }
45
+ onChildChange(oldChild) {
46
+ if (oldChild && this.provider) {
47
+ oldChild.removeCssClass(this.className);
48
+ }
49
+ if (oldChild && this.parent && this.isWidgetAttachedTo(oldChild, this.parent)) {
50
+ const strategy = getAttachmentStrategy(this.parent);
51
+ if (strategy) {
52
+ detachChild(oldChild, strategy);
53
+ }
54
+ else if (isRemovable(this.parent)) {
55
+ this.parent.remove(oldChild);
56
+ }
57
+ }
58
+ if (this.child && this.parent) {
59
+ const strategy = getAttachmentStrategy(this.parent);
60
+ if (strategy) {
61
+ attachChild(this.child, strategy);
62
+ }
63
+ this.setupCssProvider();
64
+ this.child.addCssClass(this.className);
65
+ scheduleAfterCommit(() => {
66
+ if (!this.child)
67
+ return;
68
+ const initial = this.props.initial;
69
+ const animate = this.props.animate;
70
+ if (initial === false || !this.props.animateOnMount) {
71
+ if (animate) {
72
+ this.currentValues = { ...animate };
73
+ this.applyValues(this.currentValues);
74
+ }
75
+ }
76
+ else {
77
+ const initialValues = initial ?? animate ?? {};
78
+ this.currentValues = { ...initialValues };
79
+ this.applyValues(this.currentValues);
80
+ if (this.props.animateOnMount && animate) {
81
+ this.animateTo(animate);
82
+ }
83
+ }
84
+ }, CommitPriority.LOW);
85
+ }
86
+ }
87
+ unmount() {
88
+ if (this.isExiting) {
89
+ return;
90
+ }
91
+ if (this.props.exit && this.child) {
92
+ this.isExiting = true;
93
+ this.animateTo(this.props.exit, () => {
94
+ this.detachChildFromParent();
95
+ this.cleanup();
96
+ super.unmount();
97
+ });
98
+ }
99
+ else {
100
+ this.detachChildFromParent();
101
+ this.cleanup();
102
+ super.unmount();
103
+ }
104
+ }
105
+ detachChildFromParent() {
106
+ if (this.child && this.parent && this.isChildAttachedToParent()) {
107
+ const strategy = getAttachmentStrategy(this.parent);
108
+ if (strategy) {
109
+ detachChild(this.child, strategy);
110
+ }
111
+ else if (isRemovable(this.parent)) {
112
+ this.parent.remove(this.child);
113
+ }
114
+ }
115
+ }
116
+ isChildAttachedToParent() {
117
+ return this.isWidgetAttachedTo(this.child, this.parent);
118
+ }
119
+ isWidgetAttachedTo(child, parent) {
120
+ if (!child || !parent)
121
+ return false;
122
+ const childParent = child.getParent();
123
+ return childParent !== null && isObjectEqual(childParent, parent);
124
+ }
125
+ setupCssProvider() {
126
+ if (this.provider || !this.child)
127
+ return;
128
+ this.provider = new Gtk.CssProvider();
129
+ this.display = Gdk.DisplayManager.get().getDefaultDisplay();
130
+ if (this.display) {
131
+ Gtk.StyleContext.addProviderForDisplay(this.display, this.provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
132
+ }
133
+ }
134
+ cleanup() {
135
+ if (this.currentAnimation) {
136
+ this.currentAnimation.skip();
137
+ this.currentAnimation = null;
138
+ }
139
+ if (this.provider && this.display) {
140
+ Gtk.StyleContext.removeProviderForDisplay(this.display, this.provider);
141
+ }
142
+ if (this.child) {
143
+ this.child.removeCssClass(this.className);
144
+ }
145
+ this.provider = null;
146
+ this.display = null;
147
+ }
148
+ animateTo(target, onComplete) {
149
+ if (!this.child)
150
+ return;
151
+ if (this.currentAnimation) {
152
+ this.currentAnimation.skip();
153
+ this.currentAnimation = null;
154
+ }
155
+ const from = { ...this.currentValues };
156
+ const to = { ...target };
157
+ this.props.onAnimationStart?.();
158
+ const callback = new Adw.CallbackAnimationTarget((progress) => {
159
+ const interpolated = interpolate(from, to, progress);
160
+ this.currentValues = interpolated;
161
+ this.applyValues(interpolated);
162
+ });
163
+ const animation = this.createAnimation(this.child, callback);
164
+ animation.connect("done", () => {
165
+ this.currentValues = { ...to };
166
+ this.currentAnimation = null;
167
+ this.props.onAnimationComplete?.();
168
+ onComplete?.();
169
+ });
170
+ this.currentAnimation = animation;
171
+ const transition = this.props.transition;
172
+ const delay = transition?.delay ?? 0;
173
+ if (delay > 0) {
174
+ setTimeout(() => {
175
+ if (this.currentAnimation === animation) {
176
+ animation.play();
177
+ }
178
+ }, delay);
179
+ }
180
+ else {
181
+ animation.play();
182
+ }
183
+ }
184
+ createAnimation(widget, target) {
185
+ const mode = this.props.mode;
186
+ if (mode === "spring") {
187
+ return this.createSpringAnimation(widget, target);
188
+ }
189
+ return this.createTimedAnimation(widget, target);
190
+ }
191
+ createTimedAnimation(widget, target) {
192
+ const transition = this.props.transition;
193
+ const duration = transition?.duration ?? DEFAULT_TIMED_DURATION;
194
+ const animation = new Adw.TimedAnimation(widget, 0, 1, duration, target);
195
+ if (transition?.easing !== undefined) {
196
+ animation.setEasing(transition.easing);
197
+ }
198
+ if (transition?.repeat !== undefined) {
199
+ animation.setRepeatCount(transition.repeat);
200
+ }
201
+ if (transition?.reverse !== undefined) {
202
+ animation.setReverse(transition.reverse);
203
+ }
204
+ if (transition?.alternate !== undefined) {
205
+ animation.setAlternate(transition.alternate);
206
+ }
207
+ return animation;
208
+ }
209
+ createSpringAnimation(widget, target) {
210
+ const transition = this.props.transition;
211
+ const damping = transition?.damping ?? DEFAULT_SPRING_DAMPING;
212
+ const mass = transition?.mass ?? DEFAULT_SPRING_MASS;
213
+ const stiffness = transition?.stiffness ?? DEFAULT_SPRING_STIFFNESS;
214
+ const springParams = new Adw.SpringParams(damping, mass, stiffness);
215
+ const animation = new Adw.SpringAnimation(widget, 0, 1, springParams, target);
216
+ if (transition?.initialVelocity !== undefined) {
217
+ animation.setInitialVelocity(transition.initialVelocity);
218
+ }
219
+ if (transition?.clamp !== undefined) {
220
+ animation.setClamp(transition.clamp);
221
+ }
222
+ return animation;
223
+ }
224
+ applyValues(values) {
225
+ if (!this.provider) {
226
+ return;
227
+ }
228
+ if (this.child && !this.child.getCssClasses()?.includes(this.className)) {
229
+ this.child.addCssClass(this.className);
230
+ }
231
+ const css = buildCss(this.className, values);
232
+ if (css) {
233
+ this.provider.loadFromString(css);
234
+ }
235
+ }
236
+ arePropsEqual(a, b) {
237
+ if (a === b)
238
+ return true;
239
+ if (!a || !b)
240
+ return false;
241
+ const keysA = Object.keys(a);
242
+ const keysB = Object.keys(b);
243
+ if (keysA.length !== keysB.length)
244
+ return false;
245
+ for (const key of keysA) {
246
+ if (a[key] !== b[key])
247
+ return false;
248
+ }
249
+ return true;
250
+ }
251
+ }
252
+ registerNodeClass(AnimationNode);
@@ -2,20 +2,21 @@ import * as Gtk from "@gtkx/ffi/gtk";
2
2
  import { Node } from "../node.js";
3
3
  import { registerNodeClass } from "../registry.js";
4
4
  import { CommitPriority, scheduleAfterCommit } from "../scheduler.js";
5
- import { isContainerType } from "./internal/utils.js";
5
+ import { DialogNode } from "./dialog.js";
6
+ import { matchesAnyClass } from "./internal/utils.js";
6
7
  import { MenuNode } from "./menu.js";
7
- import { Menu } from "./models/menu.js";
8
+ import { MenuModel } from "./models/menu.js";
8
9
  import { WindowNode } from "./window.js";
9
10
  class ApplicationNode extends Node {
10
11
  static priority = 0;
11
12
  menu;
12
13
  static matches(_type, containerOrClass) {
13
- return isContainerType(Gtk.Application, containerOrClass);
14
+ return matchesAnyClass([Gtk.Application], containerOrClass);
14
15
  }
15
16
  constructor(typeName, props, container, rootContainer) {
16
17
  super(typeName, props, container, rootContainer);
17
18
  const application = rootContainer instanceof Gtk.Application ? rootContainer : undefined;
18
- this.menu = new Menu("root", {}, container, application);
19
+ this.menu = new MenuModel("root", {}, rootContainer, container, application);
19
20
  }
20
21
  appendChild(child) {
21
22
  if (child instanceof MenuNode) {
@@ -26,7 +27,10 @@ class ApplicationNode extends Node {
26
27
  if (child instanceof WindowNode && child.container instanceof Gtk.ApplicationWindow) {
27
28
  return;
28
29
  }
29
- throw new Error(`Cannot append '${child.typeName}' to 'Application': expected ApplicationWindow or MenuItem`);
30
+ if (child instanceof DialogNode) {
31
+ return;
32
+ }
33
+ throw new Error(`Cannot append '${child.typeName}' to 'Application': expected ApplicationWindow, Dialog, or MenuItem`);
30
34
  }
31
35
  insertBefore(child, before) {
32
36
  if (child instanceof MenuNode) {
@@ -36,7 +40,10 @@ class ApplicationNode extends Node {
36
40
  if (child instanceof WindowNode && child.container instanceof Gtk.ApplicationWindow) {
37
41
  return;
38
42
  }
39
- throw new Error(`Cannot insert '${child.typeName}' into 'Application': expected ApplicationWindow or MenuItem`);
43
+ if (child instanceof DialogNode) {
44
+ return;
45
+ }
46
+ throw new Error(`Cannot insert '${child.typeName}' into 'Application': expected ApplicationWindow, Dialog, or MenuItem`);
40
47
  }
41
48
  removeChild(child) {
42
49
  if (child instanceof MenuNode) {
@@ -51,7 +58,10 @@ class ApplicationNode extends Node {
51
58
  if (child instanceof WindowNode && child.container instanceof Gtk.ApplicationWindow) {
52
59
  return;
53
60
  }
54
- throw new Error(`Cannot remove '${child.typeName}' from 'Application': expected ApplicationWindow or MenuItem`);
61
+ if (child instanceof DialogNode) {
62
+ return;
63
+ }
64
+ throw new Error(`Cannot remove '${child.typeName}' from 'Application': expected ApplicationWindow, Dialog, or MenuItem`);
55
65
  }
56
66
  }
57
67
  registerNodeClass(ApplicationNode);
@@ -1,4 +1,4 @@
1
- import { batch, isObjectEqual } from "@gtkx/ffi";
1
+ import { isObjectEqual } from "@gtkx/ffi";
2
2
  import * as Gtk from "@gtkx/ffi/gtk";
3
3
  import { AUTOWRAP_CLASSES } from "../generated/internal.js";
4
4
  import { registerNodeClass } from "../registry.js";
@@ -10,7 +10,7 @@ const isAutowrappedChild = (obj) => {
10
10
  return obj instanceof Gtk.ListBoxRow || obj instanceof Gtk.FlowBoxChild;
11
11
  };
12
12
  class AutowrappedNode extends WidgetNode {
13
- static priority = 2;
13
+ static priority = 1;
14
14
  static matches(_type, containerOrClass) {
15
15
  return matchesAnyClass(AUTOWRAP_CLASSES, containerOrClass);
16
16
  }
@@ -22,18 +22,16 @@ class AutowrappedNode extends WidgetNode {
22
22
  if (!(child instanceof WidgetNode)) {
23
23
  throw new Error(`Cannot append '${child.typeName}' to 'ListBox/FlowBox': expected Widget`);
24
24
  }
25
- batch(() => {
26
- if (isAutowrappedChild(child.container)) {
27
- const currentParent = child.container.getParent();
28
- if (currentParent !== null && isRemovable(currentParent)) {
29
- currentParent.remove(child.container);
30
- }
31
- }
32
- else {
33
- this.removeExistingWrapper(child.container);
25
+ if (isAutowrappedChild(child.container)) {
26
+ const currentParent = child.container.getParent();
27
+ if (currentParent !== null && isRemovable(currentParent)) {
28
+ currentParent.remove(child.container);
34
29
  }
35
- this.container.append(child.container);
36
- });
30
+ }
31
+ else {
32
+ this.removeExistingWrapper(child.container);
33
+ }
34
+ this.container.append(child.container);
37
35
  }
38
36
  removeChild(child) {
39
37
  if (child instanceof SlotNode) {
@@ -43,17 +41,15 @@ class AutowrappedNode extends WidgetNode {
43
41
  if (!(child instanceof WidgetNode)) {
44
42
  throw new Error(`Cannot remove '${child.typeName}' from 'ListBox/FlowBox': expected Widget`);
45
43
  }
46
- batch(() => {
47
- if (!isAutowrappedChild(child.container)) {
48
- const wrapper = child.container.getParent();
49
- if (wrapper && isSingleChild(wrapper)) {
50
- wrapper.setChild(null);
51
- this.container.remove(wrapper);
52
- return;
53
- }
44
+ if (!isAutowrappedChild(child.container)) {
45
+ const wrapper = child.container.getParent();
46
+ if (wrapper && isSingleChild(wrapper)) {
47
+ wrapper.setChild(null);
48
+ this.container.remove(wrapper);
49
+ return;
54
50
  }
55
- this.container.remove(child.container);
56
- });
51
+ }
52
+ this.container.remove(child.container);
57
53
  }
58
54
  insertBefore(child, before) {
59
55
  if (child instanceof SlotNode) {
@@ -61,31 +57,29 @@ class AutowrappedNode extends WidgetNode {
61
57
  return;
62
58
  }
63
59
  if (!(child instanceof WidgetNode) || !(before instanceof WidgetNode)) {
64
- throw new Error(`Cannot insert '${child.typeName}' before '${before.typeName}' in 'ListBox/FlowBox': expected Widget`);
60
+ throw new Error(`Cannot insert '${child.typeName}' into 'ListBox/FlowBox': expected Widget`);
65
61
  }
66
- batch(() => {
67
- const currentParent = child.container.getParent();
68
- if (currentParent !== null) {
69
- if (isAutowrappedChild(child.container)) {
70
- if (isRemovable(currentParent)) {
71
- currentParent.remove(child.container);
72
- }
73
- }
74
- else {
75
- this.removeExistingWrapper(child.container);
62
+ const currentParent = child.container.getParent();
63
+ if (currentParent !== null) {
64
+ if (isAutowrappedChild(child.container)) {
65
+ if (isRemovable(currentParent)) {
66
+ currentParent.remove(child.container);
76
67
  }
77
68
  }
78
- else if (!isAutowrappedChild(child.container)) {
79
- this.removeExistingWrapper(child.container);
80
- }
81
- const position = this.findChildPosition(before);
82
- if (position !== null) {
83
- this.container.insert(child.container, position);
84
- }
85
69
  else {
86
- this.container.append(child.container);
70
+ this.removeExistingWrapper(child.container);
87
71
  }
88
- });
72
+ }
73
+ else if (!isAutowrappedChild(child.container)) {
74
+ this.removeExistingWrapper(child.container);
75
+ }
76
+ const position = this.findChildPosition(before);
77
+ if (position !== null) {
78
+ this.container.insert(child.container, position);
79
+ }
80
+ else {
81
+ this.container.append(child.container);
82
+ }
89
83
  }
90
84
  removeExistingWrapper(childWidget) {
91
85
  const existingWrapper = childWidget.getParent();
@@ -1,57 +1,31 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
2
  import { registerNodeClass } from "../registry.js";
3
- import { CommitPriority, scheduleAfterCommit } from "../scheduler.js";
4
- import { CalendarMarkNode } from "./calendar-mark.js";
5
- import { isContainerType } from "./internal/utils.js";
3
+ import { filterProps, matchesAnyClass, primitiveArrayEqual } from "./internal/utils.js";
6
4
  import { WidgetNode } from "./widget.js";
5
+ const OWN_PROPS = ["markedDays"];
7
6
  class CalendarNode extends WidgetNode {
8
7
  static priority = 1;
9
- markChildren = [];
8
+ appliedMarks = [];
10
9
  static matches(_type, containerOrClass) {
11
- return isContainerType(Gtk.Calendar, containerOrClass);
10
+ return matchesAnyClass([Gtk.Calendar], containerOrClass);
12
11
  }
13
- appendChild(child) {
14
- if (child instanceof CalendarMarkNode) {
15
- child.setCalendar(this.container, () => this.scheduleRebuildAllMarks());
16
- this.markChildren.push(child);
17
- scheduleAfterCommit(() => child.addMark());
18
- return;
19
- }
20
- super.appendChild(child);
12
+ updateProps(oldProps, newProps) {
13
+ super.updateProps(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
14
+ this.applyOwnProps(oldProps, newProps);
21
15
  }
22
- insertBefore(child, before) {
23
- if (child instanceof CalendarMarkNode) {
24
- child.setCalendar(this.container, () => this.scheduleRebuildAllMarks());
25
- const beforeIndex = this.markChildren.indexOf(before);
26
- if (beforeIndex >= 0) {
27
- this.markChildren.splice(beforeIndex, 0, child);
28
- }
29
- else {
30
- this.markChildren.push(child);
31
- }
32
- this.scheduleRebuildAllMarks();
33
- return;
34
- }
35
- super.insertBefore(child, before);
16
+ applyOwnProps(_oldProps, newProps) {
17
+ this.applyMarkedDays(newProps);
36
18
  }
37
- removeChild(child) {
38
- if (child instanceof CalendarMarkNode) {
39
- const index = this.markChildren.indexOf(child);
40
- if (index >= 0) {
41
- this.markChildren.splice(index, 1);
42
- }
43
- this.scheduleRebuildAllMarks(CommitPriority.HIGH);
19
+ applyMarkedDays(newProps) {
20
+ const newMarkedDays = newProps.markedDays ?? [];
21
+ if (primitiveArrayEqual(this.appliedMarks, newMarkedDays)) {
44
22
  return;
45
23
  }
46
- super.removeChild(child);
47
- }
48
- scheduleRebuildAllMarks(priority = CommitPriority.NORMAL) {
49
- scheduleAfterCommit(() => {
50
- this.container.clearMarks();
51
- for (const mark of this.markChildren) {
52
- mark.addMark();
53
- }
54
- }, priority);
24
+ this.container.clearMarks();
25
+ for (const day of newMarkedDays) {
26
+ this.container.markDay(day);
27
+ }
28
+ this.appliedMarks = [...newMarkedDays];
55
29
  }
56
30
  }
57
31
  registerNodeClass(CalendarNode);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { registerNodeClass } from "../registry.js";
3
+ import { filterProps, hasChanged, matchesAnyClass } from "./internal/utils.js";
4
+ import { WidgetNode } from "./widget.js";
5
+ const OWN_PROPS = ["rgba", "onRgbaChanged", "title", "modal", "withAlpha"];
6
+ class ColorDialogButtonNode extends WidgetNode {
7
+ static priority = 1;
8
+ dialog;
9
+ notifyHandler = null;
10
+ static matches(_type, containerOrClass) {
11
+ return matchesAnyClass([Gtk.ColorDialogButton], containerOrClass);
12
+ }
13
+ static createContainer(_props, containerClass) {
14
+ const dialog = new Gtk.ColorDialog();
15
+ const button = new containerClass(dialog);
16
+ return button;
17
+ }
18
+ constructor(type, props, container, rootContainer) {
19
+ super(type, props, container, rootContainer);
20
+ const dialog = container.getDialog();
21
+ if (!dialog) {
22
+ throw new Error("ColorDialogButton must have a dialog");
23
+ }
24
+ this.dialog = dialog;
25
+ }
26
+ updateProps(oldProps, newProps) {
27
+ super.updateProps(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
28
+ this.applyOwnProps(oldProps, newProps);
29
+ }
30
+ applyOwnProps(oldProps, newProps) {
31
+ if (hasChanged(oldProps, newProps, "title") && newProps.title !== undefined) {
32
+ this.dialog.setTitle(newProps.title);
33
+ }
34
+ if (hasChanged(oldProps, newProps, "modal")) {
35
+ this.dialog.setModal(newProps.modal ?? true);
36
+ }
37
+ if (hasChanged(oldProps, newProps, "withAlpha")) {
38
+ this.dialog.setWithAlpha(newProps.withAlpha ?? true);
39
+ }
40
+ if (hasChanged(oldProps, newProps, "rgba") && newProps.rgba) {
41
+ this.container.setRgba(newProps.rgba);
42
+ }
43
+ if (hasChanged(oldProps, newProps, "onRgbaChanged")) {
44
+ this.setupNotifyHandler(newProps.onRgbaChanged);
45
+ }
46
+ }
47
+ setupNotifyHandler(callback) {
48
+ if (this.notifyHandler) {
49
+ this.signalStore.set(this, this.container, "notify", undefined);
50
+ this.notifyHandler = null;
51
+ }
52
+ if (callback) {
53
+ this.notifyHandler = (_button, pspec) => {
54
+ if (pspec.getName() === "rgba") {
55
+ const rgba = this.container.getRgba();
56
+ callback(rgba);
57
+ }
58
+ };
59
+ this.signalStore.set(this, this.container, "notify", this.notifyHandler);
60
+ }
61
+ }
62
+ unmount() {
63
+ if (this.notifyHandler) {
64
+ this.signalStore.set(this, this.container, "notify", undefined);
65
+ this.notifyHandler = null;
66
+ }
67
+ super.unmount();
68
+ }
69
+ }
70
+ registerNodeClass(ColorDialogButtonNode);
@@ -9,10 +9,10 @@ export declare class ColumnViewColumnNode extends VirtualNode<Props> {
9
9
  static matches(type: string): boolean;
10
10
  column: Gtk.ColumnViewColumn;
11
11
  private itemRenderer;
12
- constructor(typeName: string, props: Props, container: undefined, rootContainer?: Container);
12
+ constructor(typeName: string, props: Props, container: undefined, rootContainer: Container);
13
13
  unmount(): void;
14
- setStore(model?: ListStore): void;
15
- setEstimatedRowHeight(height?: number): void;
14
+ setStore(model: ListStore | null): void;
15
+ setEstimatedRowHeight(height: number | null): void;
16
16
  updateProps(oldProps: Props | null, newProps: Props): void;
17
17
  }
18
18
  export {};
@@ -11,7 +11,7 @@ export class ColumnViewColumnNode extends VirtualNode {
11
11
  itemRenderer;
12
12
  constructor(typeName, props, container, rootContainer) {
13
13
  super(typeName, props, container, rootContainer);
14
- this.itemRenderer = new ListItemRenderer();
14
+ this.itemRenderer = new ListItemRenderer(this.signalStore);
15
15
  this.column = new Gtk.ColumnViewColumn();
16
16
  this.column.setFactory(this.itemRenderer.getFactory());
17
17
  }