@gtkx/react 0.14.0 → 0.16.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 (182) hide show
  1. package/README.md +28 -27
  2. package/dist/errors.js +3 -0
  3. package/dist/factory.d.ts +3 -2
  4. package/dist/factory.js +1 -1
  5. package/dist/generated/internal.d.ts +28 -1
  6. package/dist/generated/internal.js +93 -18
  7. package/dist/generated/jsx.d.ts +1712 -1516
  8. package/dist/generated/jsx.js +475 -0
  9. package/dist/host-config.d.ts +3 -1
  10. package/dist/host-config.js +31 -11
  11. package/dist/jsx.d.ts +147 -97
  12. package/dist/jsx.js +89 -21
  13. package/dist/node.d.ts +3 -1
  14. package/dist/node.js +5 -3
  15. package/dist/nodes/abstract/positional-child.d.ts +9 -0
  16. package/dist/nodes/abstract/positional-child.js +29 -0
  17. package/dist/nodes/abstract/positional-parent.d.ts +18 -0
  18. package/dist/nodes/abstract/positional-parent.js +48 -0
  19. package/dist/nodes/abstract/virtual-container.d.ts +17 -0
  20. package/dist/nodes/abstract/virtual-container.js +59 -0
  21. package/dist/nodes/abstract/virtual-single-child.d.ts +18 -0
  22. package/dist/nodes/abstract/virtual-single-child.js +54 -0
  23. package/dist/nodes/action-row-child.d.ts +0 -13
  24. package/dist/nodes/action-row-child.js +14 -12
  25. package/dist/nodes/action-row.d.ts +6 -1
  26. package/dist/nodes/action-row.js +4 -37
  27. package/dist/nodes/adjustable.d.ts +23 -0
  28. package/dist/nodes/adjustable.js +62 -0
  29. package/dist/nodes/alert-dialog-response.d.ts +1 -0
  30. package/dist/nodes/alert-dialog-response.js +86 -0
  31. package/dist/nodes/animation/animation-controller.d.ts +17 -0
  32. package/dist/nodes/animation/animation-controller.js +107 -0
  33. package/dist/nodes/animation/animation-factory.d.ts +15 -0
  34. package/dist/nodes/animation/animation-factory.js +25 -0
  35. package/dist/nodes/animation/animation-node.d.ts +9 -0
  36. package/dist/nodes/animation/animation-node.js +126 -0
  37. package/dist/nodes/animation/animation-style-sheet.d.ts +16 -0
  38. package/dist/nodes/animation/animation-style-sheet.js +74 -0
  39. package/dist/nodes/animation/index.d.ts +4 -0
  40. package/dist/nodes/animation/index.js +1 -0
  41. package/dist/nodes/animation/property-mapper.d.ts +11 -0
  42. package/dist/nodes/animation/property-mapper.js +36 -0
  43. package/dist/nodes/animation/transform-state.d.ts +11 -0
  44. package/dist/nodes/animation/transform-state.js +57 -0
  45. package/dist/nodes/animation/widget-registry.d.ts +5 -0
  46. package/dist/nodes/animation/widget-registry.js +42 -0
  47. package/dist/nodes/application.js +17 -7
  48. package/dist/nodes/autowrapped.js +37 -43
  49. package/dist/nodes/calendar.js +16 -55
  50. package/dist/nodes/color-dialog-button.d.ts +1 -0
  51. package/dist/nodes/color-dialog-button.js +70 -0
  52. package/dist/nodes/column-view-column.d.ts +4 -3
  53. package/dist/nodes/column-view-column.js +5 -1
  54. package/dist/nodes/column-view.js +40 -43
  55. package/dist/nodes/dialog.d.ts +11 -0
  56. package/dist/nodes/dialog.js +20 -0
  57. package/dist/nodes/drawing-area.d.ts +1 -0
  58. package/dist/nodes/drawing-area.js +36 -0
  59. package/dist/nodes/event-controller.d.ts +1 -0
  60. package/dist/nodes/event-controller.js +96 -0
  61. package/dist/nodes/expander-row-child.d.ts +0 -14
  62. package/dist/nodes/expander-row-child.js +14 -12
  63. package/dist/nodes/expander-row.d.ts +6 -1
  64. package/dist/nodes/expander-row.js +11 -47
  65. package/dist/nodes/fixed-child.js +48 -36
  66. package/dist/nodes/font-dialog-button.d.ts +1 -0
  67. package/dist/nodes/font-dialog-button.js +90 -0
  68. package/dist/nodes/grid-child.js +39 -45
  69. package/dist/nodes/grid.d.ts +1 -0
  70. package/dist/nodes/grid.js +41 -0
  71. package/dist/nodes/index.d.ts +22 -6
  72. package/dist/nodes/index.js +22 -6
  73. package/dist/nodes/internal/base-item-renderer.d.ts +29 -0
  74. package/dist/nodes/internal/base-item-renderer.js +88 -0
  75. package/dist/nodes/internal/base-store.d.ts +9 -0
  76. package/dist/nodes/internal/base-store.js +20 -0
  77. package/dist/nodes/internal/child-attachment.d.ts +26 -0
  78. package/dist/nodes/internal/child-attachment.js +48 -0
  79. package/dist/nodes/internal/deferred-action.d.ts +8 -0
  80. package/dist/nodes/internal/deferred-action.js +19 -0
  81. package/dist/nodes/internal/list-item-renderer.d.ts +14 -14
  82. package/dist/nodes/internal/list-item-renderer.js +49 -70
  83. package/dist/nodes/internal/list-store.d.ts +7 -6
  84. package/dist/nodes/internal/list-store.js +20 -24
  85. package/dist/nodes/internal/predicates.d.ts +28 -1
  86. package/dist/nodes/internal/predicates.js +53 -38
  87. package/dist/nodes/internal/selection-model.d.ts +30 -0
  88. package/dist/nodes/internal/selection-model.js +91 -0
  89. package/dist/nodes/internal/signal-store.d.ts +5 -3
  90. package/dist/nodes/internal/signal-store.js +30 -21
  91. package/dist/nodes/internal/simple-list-store.js +6 -9
  92. package/dist/nodes/internal/text-buffer-controller.d.ts +43 -0
  93. package/dist/nodes/internal/text-buffer-controller.js +287 -0
  94. package/dist/nodes/internal/text-tag-styles.d.ts +43 -0
  95. package/dist/nodes/internal/text-tag-styles.js +52 -0
  96. package/dist/nodes/internal/tree-list-item-renderer.d.ts +16 -14
  97. package/dist/nodes/internal/tree-list-item-renderer.js +88 -91
  98. package/dist/nodes/internal/tree-store.d.ts +10 -9
  99. package/dist/nodes/internal/tree-store.js +31 -35
  100. package/dist/nodes/internal/utils.d.ts +7 -4
  101. package/dist/nodes/internal/utils.js +50 -5
  102. package/dist/nodes/level-bar.js +18 -66
  103. package/dist/nodes/list-item.d.ts +6 -3
  104. package/dist/nodes/list-item.js +7 -4
  105. package/dist/nodes/list-view.js +19 -11
  106. package/dist/nodes/menu.d.ts +3 -3
  107. package/dist/nodes/menu.js +3 -3
  108. package/dist/nodes/models/list.d.ts +11 -13
  109. package/dist/nodes/models/list.js +16 -73
  110. package/dist/nodes/models/menu.d.ts +8 -7
  111. package/dist/nodes/models/menu.js +43 -50
  112. package/dist/nodes/models/tree-list.d.ts +6 -12
  113. package/dist/nodes/models/tree-list.js +30 -93
  114. package/dist/nodes/navigation-page.d.ts +1 -0
  115. package/dist/nodes/navigation-page.js +7 -3
  116. package/dist/nodes/navigation-view.js +17 -28
  117. package/dist/nodes/notebook-page-tab.d.ts +4 -3
  118. package/dist/nodes/notebook-page-tab.js +5 -2
  119. package/dist/nodes/notebook-page.d.ts +7 -5
  120. package/dist/nodes/notebook-page.js +39 -16
  121. package/dist/nodes/notebook.js +2 -2
  122. package/dist/nodes/overlay-child.js +90 -30
  123. package/dist/nodes/pack-child.d.ts +0 -13
  124. package/dist/nodes/pack-child.js +14 -12
  125. package/dist/nodes/pack.d.ts +6 -1
  126. package/dist/nodes/pack.js +4 -37
  127. package/dist/nodes/popover-menu.js +2 -2
  128. package/dist/nodes/scale.js +15 -58
  129. package/dist/nodes/scrolled-window.js +7 -5
  130. package/dist/nodes/search-bar.d.ts +1 -0
  131. package/dist/nodes/search-bar.js +40 -0
  132. package/dist/nodes/shortcut-controller.d.ts +1 -0
  133. package/dist/nodes/shortcut-controller.js +90 -0
  134. package/dist/nodes/shortcut.d.ts +39 -0
  135. package/dist/nodes/shortcut.js +52 -0
  136. package/dist/nodes/simple-list-view.js +2 -3
  137. package/dist/nodes/slot.d.ts +6 -9
  138. package/dist/nodes/slot.js +27 -42
  139. package/dist/nodes/source-view.d.ts +1 -0
  140. package/dist/nodes/source-view.js +93 -0
  141. package/dist/nodes/stack-page.js +17 -13
  142. package/dist/nodes/stack.js +19 -5
  143. package/dist/nodes/text-anchor.d.ts +41 -0
  144. package/dist/nodes/text-anchor.js +59 -0
  145. package/dist/nodes/text-content.d.ts +10 -0
  146. package/dist/nodes/text-content.js +1 -0
  147. package/dist/nodes/text-paintable.d.ts +17 -0
  148. package/dist/nodes/text-paintable.js +34 -0
  149. package/dist/nodes/text-segment.d.ts +15 -0
  150. package/dist/nodes/text-segment.js +29 -0
  151. package/dist/nodes/text-tag.d.ts +136 -0
  152. package/dist/nodes/text-tag.js +202 -0
  153. package/dist/nodes/text-view.d.ts +31 -0
  154. package/dist/nodes/text-view.js +73 -0
  155. package/dist/nodes/toggle-group.js +24 -32
  156. package/dist/nodes/toggle.d.ts +1 -15
  157. package/dist/nodes/toggle.js +40 -32
  158. package/dist/nodes/toolbar-child.js +14 -16
  159. package/dist/nodes/tree-list-item.d.ts +7 -5
  160. package/dist/nodes/tree-list-item.js +24 -36
  161. package/dist/nodes/tree-list-view.js +9 -4
  162. package/dist/nodes/virtual.d.ts +1 -1
  163. package/dist/nodes/widget.d.ts +3 -13
  164. package/dist/nodes/widget.js +117 -231
  165. package/dist/nodes/window.d.ts +9 -3
  166. package/dist/nodes/window.js +35 -19
  167. package/dist/registry.d.ts +1 -1
  168. package/dist/render.js +8 -6
  169. package/dist/scheduler.d.ts +11 -1
  170. package/dist/scheduler.js +16 -4
  171. package/dist/types.d.ts +2 -110
  172. package/package.json +3 -3
  173. package/dist/nodes/calendar-mark.d.ts +0 -15
  174. package/dist/nodes/calendar-mark.js +0 -29
  175. package/dist/nodes/internal/constants.d.ts +0 -1
  176. package/dist/nodes/internal/constants.js +0 -21
  177. package/dist/nodes/level-bar-offset.d.ts +0 -13
  178. package/dist/nodes/level-bar-offset.js +0 -35
  179. package/dist/nodes/scale-mark.d.ts +0 -17
  180. package/dist/nodes/scale-mark.js +0 -38
  181. package/dist/nodes/virtual-child.d.ts +0 -18
  182. package/dist/nodes/virtual-child.js +0 -62
@@ -0,0 +1,126 @@
1
+ import { registerNodeClass } from "../../registry.js";
2
+ import { CommitPriority, scheduleAfterCommit } from "../../scheduler.js";
3
+ import { VirtualSingleChildNode } from "../abstract/virtual-single-child.js";
4
+ import { attachChild, detachChild, getAttachmentStrategy } from "../internal/child-attachment.js";
5
+ import { isRemovable } from "../internal/predicates.js";
6
+ import { WidgetNode } from "../widget.js";
7
+ import { AnimationController } from "./animation-controller.js";
8
+ class AnimationNode extends VirtualSingleChildNode {
9
+ static priority = 2;
10
+ controller = new AnimationController();
11
+ hasAppliedInitial = false;
12
+ hasStartedAnimation = false;
13
+ static matches(type) {
14
+ return type === "Animation";
15
+ }
16
+ appendChild(child) {
17
+ if (!(child instanceof WidgetNode)) {
18
+ throw new Error(`Cannot append '${child.typeName}' to 'x.Animation': expected Widget`);
19
+ }
20
+ const oldChild = this.child;
21
+ this.child = child.container;
22
+ scheduleAfterCommit(() => {
23
+ if (this.parent) {
24
+ this.onChildChange(oldChild);
25
+ }
26
+ }, CommitPriority.NORMAL);
27
+ }
28
+ removeChild(child) {
29
+ if (!(child instanceof WidgetNode)) {
30
+ throw new Error(`Cannot remove '${child.typeName}' from 'x.Animation': expected Widget`);
31
+ }
32
+ const oldChild = this.child;
33
+ scheduleAfterCommit(() => {
34
+ if (oldChild === this.child) {
35
+ this.child = null;
36
+ this.controller.setWidget(null);
37
+ }
38
+ if (this.parent && oldChild) {
39
+ this.onChildChange(oldChild);
40
+ }
41
+ }, CommitPriority.HIGH);
42
+ }
43
+ updateProps(oldProps, newProps) {
44
+ super.updateProps(oldProps, newProps);
45
+ const animateChanged = !shallowObjectEqual(oldProps?.animate, newProps.animate);
46
+ if (animateChanged) {
47
+ this.hasStartedAnimation = false;
48
+ }
49
+ if (this.child) {
50
+ this.controller.setWidget(this.child);
51
+ if (!this.hasAppliedInitial && newProps.initial) {
52
+ this.controller.applyImmediate(newProps.initial);
53
+ this.hasAppliedInitial = true;
54
+ }
55
+ if (!this.hasStartedAnimation && newProps.animate) {
56
+ this.hasStartedAnimation = true;
57
+ this.startAnimation();
58
+ }
59
+ }
60
+ }
61
+ unmount() {
62
+ if (this.parent && this.child) {
63
+ const strategy = getAttachmentStrategy(this.parent);
64
+ if (strategy) {
65
+ detachChild(this.child, strategy);
66
+ }
67
+ }
68
+ this.controller.dispose();
69
+ this.hasAppliedInitial = false;
70
+ this.child = null;
71
+ super.unmount();
72
+ }
73
+ onChildChange(oldChild) {
74
+ if (!this.parent)
75
+ return;
76
+ const strategy = getAttachmentStrategy(this.parent);
77
+ if (!strategy)
78
+ return;
79
+ if (oldChild && !this.child) {
80
+ detachChild(oldChild, strategy);
81
+ }
82
+ else if (oldChild && this.child && oldChild !== this.child) {
83
+ if (isRemovable(this.parent)) {
84
+ this.parent.remove(oldChild);
85
+ }
86
+ attachChild(this.child, strategy);
87
+ }
88
+ else if (!oldChild && this.child) {
89
+ attachChild(this.child, strategy);
90
+ }
91
+ if (!this.child)
92
+ return;
93
+ this.controller.setWidget(this.child);
94
+ if (!this.hasAppliedInitial && this.props.initial) {
95
+ this.controller.applyImmediate(this.props.initial);
96
+ this.hasAppliedInitial = true;
97
+ }
98
+ if (!this.hasStartedAnimation && this.props.animate) {
99
+ this.hasStartedAnimation = true;
100
+ this.startAnimation();
101
+ }
102
+ }
103
+ startAnimation() {
104
+ const from = this.props.initial ?? {};
105
+ const to = this.props.animate ?? {};
106
+ const transition = this.props.transition ?? {};
107
+ const onComplete = this.props.onAnimationComplete;
108
+ this.controller.animate(from, to, transition, onComplete);
109
+ }
110
+ }
111
+ function shallowObjectEqual(a, b) {
112
+ if (a === b)
113
+ return true;
114
+ if (!a || !b)
115
+ return false;
116
+ const keysA = Object.keys(a);
117
+ const keysB = Object.keys(b);
118
+ if (keysA.length !== keysB.length)
119
+ return false;
120
+ for (const key of keysA) {
121
+ if (a[key] !== b[key])
122
+ return false;
123
+ }
124
+ return true;
125
+ }
126
+ registerNodeClass(AnimationNode);
@@ -0,0 +1,16 @@
1
+ export declare function getAnimationStyleSheet(): AnimationStyleSheet;
2
+ declare class AnimationStyleSheet {
3
+ private provider;
4
+ private display;
5
+ private rules;
6
+ private dirty;
7
+ private flushScheduled;
8
+ setRule(widgetId: string, transformCss: string): void;
9
+ removeRule(widgetId: string): void;
10
+ private markDirty;
11
+ private scheduleFlush;
12
+ private flush;
13
+ private ensureProvider;
14
+ dispose(): void;
15
+ }
16
+ export {};
@@ -0,0 +1,74 @@
1
+ import { isStarted } from "@gtkx/ffi";
2
+ import * as Gdk from "@gtkx/ffi/gdk";
3
+ import * as Gtk from "@gtkx/ffi/gtk";
4
+ const STYLE_PROVIDER_PRIORITY_ANIMATIONS = 700;
5
+ let instance = null;
6
+ export function getAnimationStyleSheet() {
7
+ if (!instance) {
8
+ instance = new AnimationStyleSheet();
9
+ }
10
+ return instance;
11
+ }
12
+ class AnimationStyleSheet {
13
+ provider = null;
14
+ display = null;
15
+ rules = new Map();
16
+ dirty = false;
17
+ flushScheduled = false;
18
+ setRule(widgetId, transformCss) {
19
+ const rule = `#${widgetId} { transform-origin: center center; transform: ${transformCss}; }`;
20
+ this.rules.set(widgetId, rule);
21
+ this.markDirty();
22
+ }
23
+ removeRule(widgetId) {
24
+ if (this.rules.delete(widgetId)) {
25
+ this.markDirty();
26
+ }
27
+ }
28
+ markDirty() {
29
+ this.dirty = true;
30
+ this.scheduleFlush();
31
+ }
32
+ scheduleFlush() {
33
+ if (this.flushScheduled)
34
+ return;
35
+ this.flushScheduled = true;
36
+ if (isStarted) {
37
+ queueMicrotask(() => this.flush());
38
+ }
39
+ }
40
+ flush() {
41
+ this.flushScheduled = false;
42
+ if (!this.dirty)
43
+ return;
44
+ this.dirty = false;
45
+ if (!isStarted)
46
+ return;
47
+ this.ensureProvider();
48
+ if (this.rules.size === 0) {
49
+ this.provider?.loadFromString("");
50
+ return;
51
+ }
52
+ const css = [...this.rules.values()].join("\n");
53
+ this.provider?.loadFromString(css);
54
+ }
55
+ ensureProvider() {
56
+ if (this.provider)
57
+ return;
58
+ this.provider = new Gtk.CssProvider();
59
+ this.display = Gdk.DisplayManager.get().getDefaultDisplay();
60
+ if (this.display) {
61
+ Gtk.StyleContext.addProviderForDisplay(this.display, this.provider, STYLE_PROVIDER_PRIORITY_ANIMATIONS);
62
+ }
63
+ }
64
+ dispose() {
65
+ if (this.provider && this.display) {
66
+ Gtk.StyleContext.removeProviderForDisplay(this.display, this.provider);
67
+ }
68
+ this.provider = null;
69
+ this.display = null;
70
+ this.rules.clear();
71
+ this.dirty = false;
72
+ this.flushScheduled = false;
73
+ }
74
+ }
@@ -0,0 +1,4 @@
1
+ import "./animation-node.js";
2
+ export type { AnimatableProperties } from "./animation-controller.js";
3
+ export type { SpringTransition, TimedTransition, Transition } from "./animation-factory.js";
4
+ export type { AnimationProps } from "./animation-node.js";
@@ -0,0 +1 @@
1
+ import "./animation-node.js";
@@ -0,0 +1,11 @@
1
+ import type * as Gtk from "@gtkx/ffi/gtk";
2
+ import type { TransformProperty } from "./transform-state.js";
3
+ export type AnimatableProperty = TransformProperty | "opacity";
4
+ type PropertyAccessor = {
5
+ get: (widget: Gtk.Widget) => number;
6
+ set: (widget: Gtk.Widget, value: number) => void;
7
+ };
8
+ export declare function getPropertyAccessor(property: AnimatableProperty): PropertyAccessor;
9
+ export declare function isAnimatableProperty(property: string): property is AnimatableProperty;
10
+ export declare function isTransformProperty(property: string): property is TransformProperty;
11
+ export {};
@@ -0,0 +1,36 @@
1
+ import { getTransformState } from "./widget-registry.js";
2
+ const TRANSFORM_DEFAULTS = {
3
+ x: 0,
4
+ y: 0,
5
+ scale: 1,
6
+ scaleX: 1,
7
+ scaleY: 1,
8
+ rotate: 0,
9
+ };
10
+ function createTransformAccessor(property) {
11
+ return {
12
+ get: (widget) => getTransformState(widget)?.get(property) ?? TRANSFORM_DEFAULTS[property],
13
+ set: (widget, value) => getTransformState(widget)?.set(property, value),
14
+ };
15
+ }
16
+ const propertyAccessors = {
17
+ opacity: {
18
+ get: (widget) => widget.getOpacity(),
19
+ set: (widget, value) => widget.setOpacity(value),
20
+ },
21
+ x: createTransformAccessor("x"),
22
+ y: createTransformAccessor("y"),
23
+ scale: createTransformAccessor("scale"),
24
+ scaleX: createTransformAccessor("scaleX"),
25
+ scaleY: createTransformAccessor("scaleY"),
26
+ rotate: createTransformAccessor("rotate"),
27
+ };
28
+ export function getPropertyAccessor(property) {
29
+ return propertyAccessors[property];
30
+ }
31
+ export function isAnimatableProperty(property) {
32
+ return property in propertyAccessors;
33
+ }
34
+ export function isTransformProperty(property) {
35
+ return property in TRANSFORM_DEFAULTS;
36
+ }
@@ -0,0 +1,11 @@
1
+ export type TransformProperty = "x" | "y" | "scale" | "scaleX" | "scaleY" | "rotate";
2
+ export declare class TransformState {
3
+ private values;
4
+ private onChangeCallback;
5
+ constructor(onChange?: () => void);
6
+ get(property: TransformProperty): number;
7
+ set(property: TransformProperty, value: number): void;
8
+ isDefault(): boolean;
9
+ toCss(): string;
10
+ reset(): void;
11
+ }
@@ -0,0 +1,57 @@
1
+ const DEFAULT_VALUES = {
2
+ x: 0,
3
+ y: 0,
4
+ scale: 1,
5
+ scaleX: 1,
6
+ scaleY: 1,
7
+ rotate: 0,
8
+ };
9
+ export class TransformState {
10
+ values = { ...DEFAULT_VALUES };
11
+ onChangeCallback = null;
12
+ constructor(onChange) {
13
+ this.onChangeCallback = onChange ?? null;
14
+ }
15
+ get(property) {
16
+ return this.values[property];
17
+ }
18
+ set(property, value) {
19
+ if (this.values[property] !== value) {
20
+ this.values[property] = value;
21
+ this.onChangeCallback?.();
22
+ }
23
+ }
24
+ isDefault() {
25
+ return (this.values.x === 0 &&
26
+ this.values.y === 0 &&
27
+ this.values.scale === 1 &&
28
+ this.values.scaleX === 1 &&
29
+ this.values.scaleY === 1 &&
30
+ this.values.rotate === 0);
31
+ }
32
+ toCss() {
33
+ const transforms = [];
34
+ if (this.values.x !== 0 || this.values.y !== 0) {
35
+ transforms.push(`translate(${this.values.x}px, ${this.values.y}px)`);
36
+ }
37
+ const hasUniformScale = this.values.scale !== 1;
38
+ const hasAxisScale = this.values.scaleX !== 1 || this.values.scaleY !== 1;
39
+ if (hasUniformScale) {
40
+ transforms.push(`scale(${this.values.scale})`);
41
+ }
42
+ else if (hasAxisScale) {
43
+ transforms.push(`scale(${this.values.scaleX}, ${this.values.scaleY})`);
44
+ }
45
+ if (this.values.rotate !== 0) {
46
+ transforms.push(`rotate(${this.values.rotate}deg)`);
47
+ }
48
+ return transforms.length > 0 ? transforms.join(" ") : "none";
49
+ }
50
+ reset() {
51
+ const wasDefault = this.isDefault();
52
+ this.values = { ...DEFAULT_VALUES };
53
+ if (!wasDefault) {
54
+ this.onChangeCallback?.();
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,5 @@
1
+ import type * as Gtk from "@gtkx/ffi/gtk";
2
+ import { TransformState } from "./transform-state.js";
3
+ export declare function registerWidget(widget: Gtk.Widget): TransformState;
4
+ export declare function unregisterWidget(widget: Gtk.Widget): void;
5
+ export declare function getTransformState(widget: Gtk.Widget): TransformState | null;
@@ -0,0 +1,42 @@
1
+ import { getNativeId } from "@gtkx/ffi";
2
+ import { getAnimationStyleSheet } from "./animation-style-sheet.js";
3
+ import { TransformState } from "./transform-state.js";
4
+ const widgets = new WeakMap();
5
+ const styleSheet = getAnimationStyleSheet();
6
+ export function registerWidget(widget) {
7
+ const existing = widgets.get(widget);
8
+ if (existing) {
9
+ return existing.transformState;
10
+ }
11
+ const nativeId = getNativeId(widget.handle);
12
+ const cssId = `gtkx-anim-${nativeId}`;
13
+ const originalName = widget.getName();
14
+ widget.setName(cssId);
15
+ const transformState = new TransformState(() => {
16
+ if (transformState.isDefault()) {
17
+ styleSheet.removeRule(cssId);
18
+ }
19
+ else {
20
+ styleSheet.setRule(cssId, transformState.toCss());
21
+ }
22
+ });
23
+ widgets.set(widget, {
24
+ cssId,
25
+ originalName,
26
+ transformState,
27
+ });
28
+ return transformState;
29
+ }
30
+ export function unregisterWidget(widget) {
31
+ const entry = widgets.get(widget);
32
+ if (!entry)
33
+ return;
34
+ styleSheet.removeRule(entry.cssId);
35
+ if (entry.originalName !== null) {
36
+ widget.setName(entry.originalName);
37
+ }
38
+ widgets.delete(widget);
39
+ }
40
+ export function getTransformState(widget) {
41
+ return widgets.get(widget)?.transformState ?? null;
42
+ }
@@ -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,70 +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";
6
- import { SlotNode } from "./slot.js";
3
+ import { filterProps, matchesAnyClass, primitiveArrayEqual } from "./internal/utils.js";
7
4
  import { WidgetNode } from "./widget.js";
5
+ const OWN_PROPS = ["markedDays"];
8
6
  class CalendarNode extends WidgetNode {
9
7
  static priority = 1;
10
- markChildren = [];
8
+ appliedMarks = [];
11
9
  static matches(_type, containerOrClass) {
12
- return isContainerType(Gtk.Calendar, containerOrClass);
10
+ return matchesAnyClass([Gtk.Calendar], containerOrClass);
13
11
  }
14
- appendChild(child) {
15
- if (child instanceof CalendarMarkNode) {
16
- child.setCalendar(this.container, () => this.scheduleRebuildAllMarks());
17
- this.markChildren.push(child);
18
- scheduleAfterCommit(() => child.addMark());
19
- return;
20
- }
21
- if (child instanceof SlotNode || child instanceof WidgetNode) {
22
- super.appendChild(child);
23
- return;
24
- }
25
- throw new Error(`Cannot append '${child.typeName}' to 'Calendar': expected x.CalendarMark or Widget`);
12
+ updateProps(oldProps, newProps) {
13
+ super.updateProps(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
14
+ this.applyOwnProps(oldProps, newProps);
26
15
  }
27
- insertBefore(child, before) {
28
- if (child instanceof CalendarMarkNode) {
29
- child.setCalendar(this.container, () => this.scheduleRebuildAllMarks());
30
- const beforeIndex = this.markChildren.indexOf(before);
31
- if (beforeIndex >= 0) {
32
- this.markChildren.splice(beforeIndex, 0, child);
33
- }
34
- else {
35
- this.markChildren.push(child);
36
- }
37
- this.scheduleRebuildAllMarks();
38
- return;
39
- }
40
- if (child instanceof SlotNode || child instanceof WidgetNode) {
41
- super.insertBefore(child, before);
42
- return;
43
- }
44
- throw new Error(`Cannot insert '${child.typeName}' into 'Calendar': expected x.CalendarMark or Widget`);
16
+ applyOwnProps(_oldProps, newProps) {
17
+ this.applyMarkedDays(newProps);
45
18
  }
46
- removeChild(child) {
47
- if (child instanceof CalendarMarkNode) {
48
- const index = this.markChildren.indexOf(child);
49
- if (index >= 0) {
50
- this.markChildren.splice(index, 1);
51
- }
52
- this.scheduleRebuildAllMarks(CommitPriority.HIGH);
19
+ applyMarkedDays(newProps) {
20
+ const newMarkedDays = newProps.markedDays ?? [];
21
+ if (primitiveArrayEqual(this.appliedMarks, newMarkedDays)) {
53
22
  return;
54
23
  }
55
- if (child instanceof SlotNode || child instanceof WidgetNode) {
56
- super.removeChild(child);
57
- return;
24
+ this.container.clearMarks();
25
+ for (const day of newMarkedDays) {
26
+ this.container.markDay(day);
58
27
  }
59
- throw new Error(`Cannot remove '${child.typeName}' from 'Calendar': expected x.CalendarMark or Widget`);
60
- }
61
- scheduleRebuildAllMarks(priority = CommitPriority.NORMAL) {
62
- scheduleAfterCommit(() => {
63
- this.container.clearMarks();
64
- for (const mark of this.markChildren) {
65
- mark.addMark();
66
- }
67
- }, priority);
28
+ this.appliedMarks = [...newMarkedDays];
68
29
  }
69
30
  }
70
31
  registerNodeClass(CalendarNode);
@@ -0,0 +1 @@
1
+ export {};