@gtkx/react 0.13.3 → 0.15.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.
- package/README.md +8 -7
- package/dist/generated/internal.js +98 -0
- package/dist/generated/jsx.d.ts +908 -1572
- package/dist/host-config.js +2 -2
- package/dist/jsx.d.ts +176 -36
- package/dist/jsx.js +96 -5
- package/dist/nodes/adjustment.d.ts +48 -0
- package/dist/nodes/adjustment.js +70 -0
- package/dist/nodes/application.js +6 -6
- package/dist/nodes/calendar.js +3 -16
- package/dist/nodes/column-view-column.d.ts +1 -0
- package/dist/nodes/column-view-column.js +4 -0
- package/dist/nodes/column-view.js +6 -6
- package/dist/nodes/drawing-area.d.ts +1 -0
- package/dist/nodes/drawing-area.js +19 -0
- package/dist/nodes/expander-row.js +1 -0
- package/dist/nodes/index.d.ts +9 -0
- package/dist/nodes/index.js +9 -0
- package/dist/nodes/internal/constants.js +14 -0
- package/dist/nodes/internal/list-item-renderer.d.ts +1 -0
- package/dist/nodes/internal/list-item-renderer.js +6 -1
- package/dist/nodes/internal/predicates.d.ts +4 -0
- package/dist/nodes/internal/predicates.js +3 -0
- package/dist/nodes/internal/signal-store.d.ts +1 -0
- package/dist/nodes/internal/signal-store.js +7 -0
- package/dist/nodes/internal/tree-list-item-renderer.d.ts +1 -0
- package/dist/nodes/internal/tree-list-item-renderer.js +9 -1
- package/dist/nodes/level-bar.js +3 -16
- package/dist/nodes/list-view.js +11 -2
- package/dist/nodes/models/list.d.ts +6 -1
- package/dist/nodes/models/list.js +21 -6
- package/dist/nodes/models/tree-list.d.ts +6 -1
- package/dist/nodes/models/tree-list.js +21 -7
- package/dist/nodes/navigation-page.js +32 -23
- package/dist/nodes/notebook-page-tab.d.ts +1 -0
- package/dist/nodes/notebook-page-tab.js +15 -9
- package/dist/nodes/notebook-page.js +9 -6
- package/dist/nodes/scale.js +3 -16
- package/dist/nodes/scrolled-window.d.ts +1 -0
- package/dist/nodes/scrolled-window.js +22 -0
- package/dist/nodes/shortcut-controller.d.ts +37 -0
- package/dist/nodes/shortcut-controller.js +74 -0
- package/dist/nodes/shortcut.d.ts +38 -0
- package/dist/nodes/shortcut.js +46 -0
- package/dist/nodes/slot.js +11 -2
- package/dist/nodes/source-buffer.d.ts +73 -0
- package/dist/nodes/source-buffer.js +149 -0
- package/dist/nodes/source-view.d.ts +1 -0
- package/dist/nodes/source-view.js +42 -0
- package/dist/nodes/stack-page.js +15 -9
- package/dist/nodes/text-buffer.d.ts +43 -0
- package/dist/nodes/text-buffer.js +81 -0
- package/dist/nodes/text-view.d.ts +1 -0
- package/dist/nodes/text-view.js +45 -0
- package/dist/nodes/tree-list-view.js +11 -2
- package/dist/nodes/widget.d.ts +9 -0
- package/dist/nodes/widget.js +166 -13
- package/dist/nodes/window.js +7 -5
- package/dist/render.d.ts +14 -14
- package/dist/render.js +14 -14
- package/dist/types.d.ts +110 -1
- package/package.json +3 -3
package/dist/nodes/stack-page.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isObjectEqual } from "@gtkx/ffi";
|
|
1
|
+
import { batch, isObjectEqual } from "@gtkx/ffi";
|
|
2
2
|
import * as Adw from "@gtkx/ffi/adw";
|
|
3
3
|
import { registerNodeClass } from "../registry.js";
|
|
4
4
|
import { SlotNode } from "./slot.js";
|
|
@@ -13,11 +13,15 @@ class StackPageNode extends SlotNode {
|
|
|
13
13
|
if (!this.page) {
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
|
-
if (
|
|
17
|
-
|
|
16
|
+
if (!oldProps || oldProps.title !== newProps.title) {
|
|
17
|
+
if (newProps.title !== undefined) {
|
|
18
|
+
this.page.setTitle(newProps.title);
|
|
19
|
+
}
|
|
18
20
|
}
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
+
if (!oldProps || oldProps.iconName !== newProps.iconName) {
|
|
22
|
+
if (newProps.iconName !== undefined) {
|
|
23
|
+
this.page.setIconName(newProps.iconName);
|
|
24
|
+
}
|
|
21
25
|
}
|
|
22
26
|
if (!oldProps || oldProps.needsAttention !== newProps.needsAttention) {
|
|
23
27
|
this.page.setNeedsAttention(newProps.needsAttention ?? false);
|
|
@@ -75,10 +79,12 @@ class StackPageNode extends SlotNode {
|
|
|
75
79
|
}
|
|
76
80
|
}
|
|
77
81
|
onChildChange(oldChild) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
this.
|
|
81
|
-
|
|
82
|
+
batch(() => {
|
|
83
|
+
this.removePage(oldChild);
|
|
84
|
+
if (this.child) {
|
|
85
|
+
this.addPage();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
82
88
|
}
|
|
83
89
|
}
|
|
84
90
|
registerNodeClass(StackPageNode);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import { VirtualNode } from "./virtual.js";
|
|
3
|
+
/**
|
|
4
|
+
* Props for the TextBuffer virtual element.
|
|
5
|
+
*
|
|
6
|
+
* Used to declaratively configure the text buffer for a GtkTextView.
|
|
7
|
+
* For GtkSourceView with syntax highlighting, use {@link SourceBufferProps} instead.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <GtkTextView>
|
|
12
|
+
* <x.TextBuffer
|
|
13
|
+
* text="Hello, World!"
|
|
14
|
+
* enableUndo
|
|
15
|
+
* onTextChanged={(text) => console.log("Text:", text)}
|
|
16
|
+
* />
|
|
17
|
+
* </GtkTextView>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export type TextBufferProps = {
|
|
21
|
+
/** Text content */
|
|
22
|
+
text?: string;
|
|
23
|
+
/** Whether to enable undo/redo */
|
|
24
|
+
enableUndo?: boolean;
|
|
25
|
+
/** Callback when the text content changes */
|
|
26
|
+
onTextChanged?: (text: string) => void;
|
|
27
|
+
/** Callback when can-undo state changes */
|
|
28
|
+
onCanUndoChanged?: (canUndo: boolean) => void;
|
|
29
|
+
/** Callback when can-redo state changes */
|
|
30
|
+
onCanRedoChanged?: (canRedo: boolean) => void;
|
|
31
|
+
};
|
|
32
|
+
export declare class TextBufferNode extends VirtualNode<TextBufferProps> {
|
|
33
|
+
static priority: number;
|
|
34
|
+
private textView?;
|
|
35
|
+
private buffer?;
|
|
36
|
+
static matches(type: string): boolean;
|
|
37
|
+
setTextView(textView: Gtk.TextView): void;
|
|
38
|
+
private setupBuffer;
|
|
39
|
+
private getBufferText;
|
|
40
|
+
private updateSignalHandlers;
|
|
41
|
+
updateProps(oldProps: TextBufferProps | null, newProps: TextBufferProps): void;
|
|
42
|
+
unmount(): void;
|
|
43
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { batch } from "@gtkx/ffi";
|
|
2
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
|
+
import { registerNodeClass } from "../registry.js";
|
|
4
|
+
import { signalStore } from "./internal/signal-store.js";
|
|
5
|
+
import { VirtualNode } from "./virtual.js";
|
|
6
|
+
export class TextBufferNode extends VirtualNode {
|
|
7
|
+
static priority = 1;
|
|
8
|
+
textView;
|
|
9
|
+
buffer;
|
|
10
|
+
static matches(type) {
|
|
11
|
+
return type === "TextBuffer";
|
|
12
|
+
}
|
|
13
|
+
setTextView(textView) {
|
|
14
|
+
this.textView = textView;
|
|
15
|
+
this.setupBuffer();
|
|
16
|
+
}
|
|
17
|
+
setupBuffer() {
|
|
18
|
+
if (!this.textView)
|
|
19
|
+
return;
|
|
20
|
+
this.buffer = new Gtk.TextBuffer();
|
|
21
|
+
this.textView.setBuffer(this.buffer);
|
|
22
|
+
if (this.props.enableUndo !== undefined) {
|
|
23
|
+
this.buffer.setEnableUndo(this.props.enableUndo);
|
|
24
|
+
}
|
|
25
|
+
if (this.props.text !== undefined) {
|
|
26
|
+
this.buffer.setText(this.props.text, -1);
|
|
27
|
+
}
|
|
28
|
+
this.updateSignalHandlers();
|
|
29
|
+
}
|
|
30
|
+
getBufferText() {
|
|
31
|
+
const buffer = this.buffer;
|
|
32
|
+
if (!buffer)
|
|
33
|
+
return "";
|
|
34
|
+
const startIter = new Gtk.TextIter();
|
|
35
|
+
const endIter = new Gtk.TextIter();
|
|
36
|
+
batch(() => {
|
|
37
|
+
buffer.getStartIter(startIter);
|
|
38
|
+
buffer.getEndIter(endIter);
|
|
39
|
+
});
|
|
40
|
+
return buffer.getText(startIter, endIter, true);
|
|
41
|
+
}
|
|
42
|
+
updateSignalHandlers() {
|
|
43
|
+
if (!this.buffer)
|
|
44
|
+
return;
|
|
45
|
+
const buffer = this.buffer;
|
|
46
|
+
const { onTextChanged, onCanUndoChanged, onCanRedoChanged } = this.props;
|
|
47
|
+
signalStore.set(this, buffer, "changed", onTextChanged ? () => onTextChanged(this.getBufferText()) : null);
|
|
48
|
+
signalStore.set(this, buffer, "notify::can-undo", onCanUndoChanged ? () => onCanUndoChanged(buffer.getCanUndo()) : null);
|
|
49
|
+
signalStore.set(this, buffer, "notify::can-redo", onCanRedoChanged ? () => onCanRedoChanged(buffer.getCanRedo()) : null);
|
|
50
|
+
}
|
|
51
|
+
updateProps(oldProps, newProps) {
|
|
52
|
+
super.updateProps(oldProps, newProps);
|
|
53
|
+
if (!this.buffer)
|
|
54
|
+
return;
|
|
55
|
+
if (!oldProps || oldProps.enableUndo !== newProps.enableUndo) {
|
|
56
|
+
if (newProps.enableUndo !== undefined) {
|
|
57
|
+
this.buffer.setEnableUndo(newProps.enableUndo);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!oldProps || oldProps.text !== newProps.text) {
|
|
61
|
+
if (newProps.text !== undefined) {
|
|
62
|
+
const currentText = this.getBufferText();
|
|
63
|
+
if (currentText !== newProps.text) {
|
|
64
|
+
this.buffer.setText(newProps.text, -1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!oldProps ||
|
|
69
|
+
oldProps.onTextChanged !== newProps.onTextChanged ||
|
|
70
|
+
oldProps.onCanUndoChanged !== newProps.onCanUndoChanged ||
|
|
71
|
+
oldProps.onCanRedoChanged !== newProps.onCanRedoChanged) {
|
|
72
|
+
this.updateSignalHandlers();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
unmount() {
|
|
76
|
+
this.buffer = undefined;
|
|
77
|
+
this.textView = undefined;
|
|
78
|
+
super.unmount();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
registerNodeClass(TextBufferNode);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/ffi/gtk";
|
|
2
|
+
import * as GtkSource from "@gtkx/ffi/gtksource";
|
|
3
|
+
import { registerNodeClass } from "../registry.js";
|
|
4
|
+
import { isContainerType } from "./internal/utils.js";
|
|
5
|
+
import { TextBufferNode } from "./text-buffer.js";
|
|
6
|
+
import { WidgetNode } from "./widget.js";
|
|
7
|
+
class TextViewNode extends WidgetNode {
|
|
8
|
+
static priority = 1;
|
|
9
|
+
bufferChild;
|
|
10
|
+
static matches(_type, containerOrClass) {
|
|
11
|
+
if (isContainerType(GtkSource.View, containerOrClass))
|
|
12
|
+
return false;
|
|
13
|
+
return isContainerType(Gtk.TextView, containerOrClass);
|
|
14
|
+
}
|
|
15
|
+
appendChild(child) {
|
|
16
|
+
if (this.tryAttachTextBuffer(child))
|
|
17
|
+
return;
|
|
18
|
+
super.appendChild(child);
|
|
19
|
+
}
|
|
20
|
+
insertBefore(child, before) {
|
|
21
|
+
if (this.tryAttachTextBuffer(child))
|
|
22
|
+
return;
|
|
23
|
+
super.insertBefore(child, before);
|
|
24
|
+
}
|
|
25
|
+
removeChild(child) {
|
|
26
|
+
if (child instanceof TextBufferNode) {
|
|
27
|
+
if (this.bufferChild === child) {
|
|
28
|
+
this.bufferChild = undefined;
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
super.removeChild(child);
|
|
33
|
+
}
|
|
34
|
+
tryAttachTextBuffer(child) {
|
|
35
|
+
if (!(child instanceof TextBufferNode))
|
|
36
|
+
return false;
|
|
37
|
+
if (this.bufferChild) {
|
|
38
|
+
throw new Error("TextView can only have one TextBuffer child");
|
|
39
|
+
}
|
|
40
|
+
this.bufferChild = child;
|
|
41
|
+
child.setTextView(this.container);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
registerNodeClass(TextViewNode);
|
|
@@ -34,6 +34,10 @@ class TreeListViewNode extends WidgetNode {
|
|
|
34
34
|
super.mount();
|
|
35
35
|
this.container.setModel(this.treeList.getSelectionModel());
|
|
36
36
|
}
|
|
37
|
+
unmount() {
|
|
38
|
+
this.itemRenderer.dispose();
|
|
39
|
+
super.unmount();
|
|
40
|
+
}
|
|
37
41
|
appendChild(child) {
|
|
38
42
|
if (!(child instanceof TreeListItemNode)) {
|
|
39
43
|
throw new Error(`Cannot append '${child.typeName}' to 'TreeListView': expected x.TreeListItem`);
|
|
@@ -59,8 +63,13 @@ class TreeListViewNode extends WidgetNode {
|
|
|
59
63
|
if (!oldProps || oldProps.estimatedItemHeight !== newProps.estimatedItemHeight) {
|
|
60
64
|
this.itemRenderer.setEstimatedItemHeight(newProps.estimatedItemHeight);
|
|
61
65
|
}
|
|
62
|
-
this.treeList.
|
|
63
|
-
|
|
66
|
+
const previousModel = this.treeList.getSelectionModel();
|
|
67
|
+
this.treeList.updateProps(filterProps(oldProps ?? {}, RENDERER_PROP_NAMES), filterProps(newProps, RENDERER_PROP_NAMES));
|
|
68
|
+
const currentModel = this.treeList.getSelectionModel();
|
|
69
|
+
if (previousModel !== currentModel) {
|
|
70
|
+
this.container.setModel(currentModel);
|
|
71
|
+
}
|
|
72
|
+
super.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
75
|
registerNodeClass(TreeListViewNode);
|
package/dist/nodes/widget.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ export declare class WidgetNode<T extends Gtk.Widget = Gtk.Widget, P extends Pro
|
|
|
7
7
|
private clickController?;
|
|
8
8
|
private keyController?;
|
|
9
9
|
private scrollController?;
|
|
10
|
+
private dragSourceController?;
|
|
11
|
+
private dropTargetController?;
|
|
12
|
+
private gestureDragController?;
|
|
13
|
+
private adjustmentChild?;
|
|
10
14
|
static matches(_type: string, containerOrClass?: Container | ContainerClass | null): boolean;
|
|
11
15
|
static createContainer(props: Props, containerClass: typeof Gtk.Widget): Container | null;
|
|
12
16
|
appendChild(child: Node): void;
|
|
@@ -15,7 +19,12 @@ export declare class WidgetNode<T extends Gtk.Widget = Gtk.Widget, P extends Pro
|
|
|
15
19
|
private insertBeforeReorderable;
|
|
16
20
|
private insertBeforeInsertable;
|
|
17
21
|
updateProps(oldProps: P | null, newProps: P): void;
|
|
22
|
+
private updateSizeRequest;
|
|
23
|
+
private updateGrabFocus;
|
|
18
24
|
private updateEventControllerProp;
|
|
25
|
+
private ensureDragSource;
|
|
26
|
+
private ensureDropTarget;
|
|
27
|
+
private ensureGestureDrag;
|
|
19
28
|
private updateNotifyHandler;
|
|
20
29
|
private propNameToSignalName;
|
|
21
30
|
private getProperty;
|
package/dist/nodes/widget.js
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
import { batch, isObjectEqual, NativeObject } from "@gtkx/ffi";
|
|
2
|
+
import * as Gdk from "@gtkx/ffi/gdk";
|
|
2
3
|
import * as Gtk from "@gtkx/ffi/gtk";
|
|
3
4
|
import { CONSTRUCTOR_PROPS } from "../generated/internal.js";
|
|
4
5
|
import { Node } from "../node.js";
|
|
5
6
|
import { registerNodeClass } from "../registry.js";
|
|
7
|
+
import { AdjustmentNode } from "./adjustment.js";
|
|
6
8
|
import { EVENT_CONTROLLER_PROPS } from "./internal/constants.js";
|
|
7
|
-
import { hasSingleContent, isAddable, isAppendable, isEditable, isInsertable, isRemovable, isReorderable, isSingleChild, } from "./internal/predicates.js";
|
|
9
|
+
import { hasSingleContent, isAddable, isAdjustable, isAppendable, isEditable, isInsertable, isRemovable, isReorderable, isSingleChild, } from "./internal/predicates.js";
|
|
8
10
|
import { signalStore } from "./internal/signal-store.js";
|
|
9
11
|
import { filterProps, isContainerType, resolvePropMeta, resolveSignal } from "./internal/utils.js";
|
|
12
|
+
import { ShortcutControllerNode } from "./shortcut-controller.js";
|
|
10
13
|
import { SlotNode } from "./slot.js";
|
|
14
|
+
const PROPS = ["children", "widthRequest", "heightRequest", "grabFocus"];
|
|
11
15
|
export class WidgetNode extends Node {
|
|
12
16
|
static priority = 3;
|
|
13
17
|
motionController;
|
|
14
18
|
clickController;
|
|
15
19
|
keyController;
|
|
16
20
|
scrollController;
|
|
21
|
+
dragSourceController;
|
|
22
|
+
dropTargetController;
|
|
23
|
+
gestureDragController;
|
|
24
|
+
adjustmentChild;
|
|
17
25
|
static matches(_type, containerOrClass) {
|
|
18
26
|
return isContainerType(Gtk.Widget, containerOrClass);
|
|
19
27
|
}
|
|
@@ -24,10 +32,25 @@ export class WidgetNode extends Node {
|
|
|
24
32
|
return new WidgetClass(...args);
|
|
25
33
|
}
|
|
26
34
|
appendChild(child) {
|
|
35
|
+
if (child instanceof ShortcutControllerNode) {
|
|
36
|
+
child.setParent(this.container);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
27
39
|
if (child instanceof SlotNode) {
|
|
28
40
|
child.setParent(this.container);
|
|
29
41
|
return;
|
|
30
42
|
}
|
|
43
|
+
if (child instanceof AdjustmentNode) {
|
|
44
|
+
if (!isAdjustable(this.container)) {
|
|
45
|
+
throw new Error(`Cannot add Adjustment to '${this.typeName}': widget does not support adjustments`);
|
|
46
|
+
}
|
|
47
|
+
if (this.adjustmentChild) {
|
|
48
|
+
throw new Error(`${this.typeName} can only have one Adjustment child`);
|
|
49
|
+
}
|
|
50
|
+
this.adjustmentChild = child;
|
|
51
|
+
child.setWidget(this.container);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
31
54
|
if (!(child instanceof WidgetNode)) {
|
|
32
55
|
throw new Error(`Cannot append '${child.typeName}' to 'Widget': expected WidgetNode child`);
|
|
33
56
|
}
|
|
@@ -37,9 +60,19 @@ export class WidgetNode extends Node {
|
|
|
37
60
|
batch(() => this.attachChild(child));
|
|
38
61
|
}
|
|
39
62
|
removeChild(child) {
|
|
63
|
+
if (child instanceof ShortcutControllerNode) {
|
|
64
|
+
child.setParent(undefined);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
40
67
|
if (child instanceof SlotNode) {
|
|
41
68
|
return;
|
|
42
69
|
}
|
|
70
|
+
if (child instanceof AdjustmentNode) {
|
|
71
|
+
if (this.adjustmentChild === child) {
|
|
72
|
+
this.adjustmentChild = undefined;
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
43
76
|
if (!(child instanceof WidgetNode)) {
|
|
44
77
|
throw new Error(`Cannot remove '${child.typeName}' from 'Widget': expected WidgetNode child`);
|
|
45
78
|
}
|
|
@@ -49,10 +82,25 @@ export class WidgetNode extends Node {
|
|
|
49
82
|
batch(() => this.detachChild(child));
|
|
50
83
|
}
|
|
51
84
|
insertBefore(child, before) {
|
|
85
|
+
if (child instanceof ShortcutControllerNode) {
|
|
86
|
+
child.setParent(this.container);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
52
89
|
if (child instanceof SlotNode) {
|
|
53
90
|
child.setParent(this.container);
|
|
54
91
|
return;
|
|
55
92
|
}
|
|
93
|
+
if (child instanceof AdjustmentNode) {
|
|
94
|
+
if (!isAdjustable(this.container)) {
|
|
95
|
+
throw new Error(`Cannot add Adjustment to '${this.typeName}': widget does not support adjustments`);
|
|
96
|
+
}
|
|
97
|
+
if (this.adjustmentChild) {
|
|
98
|
+
throw new Error(`${this.typeName} can only have one Adjustment child`);
|
|
99
|
+
}
|
|
100
|
+
this.adjustmentChild = child;
|
|
101
|
+
child.setWidget(this.container);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
56
104
|
if (!(child instanceof WidgetNode) || !(before instanceof WidgetNode)) {
|
|
57
105
|
throw new Error(`Cannot insert '${child.typeName}' before '${before.typeName}': expected WidgetNode children`);
|
|
58
106
|
}
|
|
@@ -89,11 +137,14 @@ export class WidgetNode extends Node {
|
|
|
89
137
|
container.insert(child.container, position);
|
|
90
138
|
}
|
|
91
139
|
updateProps(oldProps, newProps) {
|
|
140
|
+
this.updateSizeRequest(oldProps, newProps);
|
|
141
|
+
this.updateGrabFocus(oldProps, newProps);
|
|
92
142
|
const propNames = new Set([
|
|
93
|
-
...Object.keys(filterProps(oldProps ?? {},
|
|
94
|
-
...Object.keys(filterProps(newProps ?? {},
|
|
143
|
+
...Object.keys(filterProps(oldProps ?? {}, PROPS)),
|
|
144
|
+
...Object.keys(filterProps(newProps ?? {}, PROPS)),
|
|
95
145
|
]);
|
|
96
146
|
const pendingSignals = [];
|
|
147
|
+
const pendingProperties = [];
|
|
97
148
|
for (const name of propNames) {
|
|
98
149
|
const oldValue = oldProps?.[name];
|
|
99
150
|
const newValue = newProps[name];
|
|
@@ -112,14 +163,7 @@ export class WidgetNode extends Node {
|
|
|
112
163
|
pendingSignals.push({ name, newValue });
|
|
113
164
|
}
|
|
114
165
|
else if (newValue !== undefined) {
|
|
115
|
-
|
|
116
|
-
if (isEditableText && oldValue !== undefined) {
|
|
117
|
-
const currentValue = this.getProperty(name);
|
|
118
|
-
if (oldValue !== currentValue) {
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
this.setProperty(name, newValue);
|
|
166
|
+
pendingProperties.push({ name, oldValue, newValue });
|
|
123
167
|
}
|
|
124
168
|
}
|
|
125
169
|
for (const { name, newValue } of pendingSignals) {
|
|
@@ -135,9 +179,37 @@ export class WidgetNode extends Node {
|
|
|
135
179
|
signalStore.set(this, this.container, signalName, handler);
|
|
136
180
|
}
|
|
137
181
|
}
|
|
182
|
+
for (const { name, oldValue, newValue } of pendingProperties) {
|
|
183
|
+
const isEditableText = name === "text" && isEditable(this.container);
|
|
184
|
+
if (isEditableText && oldValue !== undefined) {
|
|
185
|
+
const currentValue = this.getProperty(name);
|
|
186
|
+
if (oldValue !== currentValue) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
this.setProperty(name, newValue);
|
|
191
|
+
}
|
|
138
192
|
}
|
|
139
|
-
|
|
140
|
-
const
|
|
193
|
+
updateSizeRequest(oldProps, newProps) {
|
|
194
|
+
const oldWidth = oldProps?.widthRequest;
|
|
195
|
+
const oldHeight = oldProps?.heightRequest;
|
|
196
|
+
const newWidth = newProps.widthRequest;
|
|
197
|
+
const newHeight = newProps.heightRequest;
|
|
198
|
+
if (oldWidth !== newWidth || oldHeight !== newHeight) {
|
|
199
|
+
this.container.setSizeRequest(newWidth ?? -1, newHeight ?? -1);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
updateGrabFocus(oldProps, newProps) {
|
|
203
|
+
const oldGrabFocus = oldProps?.grabFocus;
|
|
204
|
+
const newGrabFocus = newProps.grabFocus;
|
|
205
|
+
if (!oldGrabFocus && newGrabFocus) {
|
|
206
|
+
this.container.grabFocus();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
updateEventControllerProp(propName, handlerOrValue) {
|
|
210
|
+
const wrappedHandler = typeof handlerOrValue === "function"
|
|
211
|
+
? (_self, ...args) => handlerOrValue(...args)
|
|
212
|
+
: undefined;
|
|
141
213
|
switch (propName) {
|
|
142
214
|
case "onEnter":
|
|
143
215
|
case "onLeave":
|
|
@@ -178,7 +250,88 @@ export class WidgetNode extends Node {
|
|
|
178
250
|
signalStore.set(this, this.scrollController, "scroll", wrappedHandler);
|
|
179
251
|
break;
|
|
180
252
|
}
|
|
253
|
+
case "onDragPrepare":
|
|
254
|
+
case "onDragBegin":
|
|
255
|
+
case "onDragEnd":
|
|
256
|
+
case "onDragCancel":
|
|
257
|
+
case "dragActions": {
|
|
258
|
+
const dragSource = this.ensureDragSource();
|
|
259
|
+
if (propName === "dragActions") {
|
|
260
|
+
dragSource.setActions(handlerOrValue ?? Gdk.DragAction.COPY);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const signalName = propName === "onDragPrepare"
|
|
264
|
+
? "prepare"
|
|
265
|
+
: propName === "onDragBegin"
|
|
266
|
+
? "drag-begin"
|
|
267
|
+
: propName === "onDragEnd"
|
|
268
|
+
? "drag-end"
|
|
269
|
+
: "drag-cancel";
|
|
270
|
+
signalStore.set(this, dragSource, signalName, wrappedHandler);
|
|
271
|
+
}
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
case "onDrop":
|
|
275
|
+
case "onDropEnter":
|
|
276
|
+
case "onDropLeave":
|
|
277
|
+
case "onDropMotion":
|
|
278
|
+
case "dropActions":
|
|
279
|
+
case "dropTypes": {
|
|
280
|
+
const dropTarget = this.ensureDropTarget();
|
|
281
|
+
if (propName === "dropActions") {
|
|
282
|
+
dropTarget.setActions(handlerOrValue ?? Gdk.DragAction.COPY);
|
|
283
|
+
}
|
|
284
|
+
else if (propName === "dropTypes") {
|
|
285
|
+
const types = handlerOrValue ?? [];
|
|
286
|
+
dropTarget.setGtypes(types.length, types);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
const signalName = propName === "onDrop"
|
|
290
|
+
? "drop"
|
|
291
|
+
: propName === "onDropEnter"
|
|
292
|
+
? "enter"
|
|
293
|
+
: propName === "onDropLeave"
|
|
294
|
+
? "leave"
|
|
295
|
+
: "motion";
|
|
296
|
+
signalStore.set(this, dropTarget, signalName, wrappedHandler);
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
case "onGestureDragBegin":
|
|
301
|
+
case "onGestureDragUpdate":
|
|
302
|
+
case "onGestureDragEnd": {
|
|
303
|
+
const gestureDrag = this.ensureGestureDrag();
|
|
304
|
+
const signalName = propName === "onGestureDragBegin"
|
|
305
|
+
? "drag-begin"
|
|
306
|
+
: propName === "onGestureDragUpdate"
|
|
307
|
+
? "drag-update"
|
|
308
|
+
: "drag-end";
|
|
309
|
+
signalStore.set(this, gestureDrag, signalName, wrappedHandler);
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
ensureDragSource() {
|
|
315
|
+
if (!this.dragSourceController) {
|
|
316
|
+
this.dragSourceController = new Gtk.DragSource();
|
|
317
|
+
this.dragSourceController.setActions(Gdk.DragAction.COPY);
|
|
318
|
+
this.container.addController(this.dragSourceController);
|
|
319
|
+
}
|
|
320
|
+
return this.dragSourceController;
|
|
321
|
+
}
|
|
322
|
+
ensureDropTarget() {
|
|
323
|
+
if (!this.dropTargetController) {
|
|
324
|
+
this.dropTargetController = new Gtk.DropTarget(0, Gdk.DragAction.COPY);
|
|
325
|
+
this.container.addController(this.dropTargetController);
|
|
326
|
+
}
|
|
327
|
+
return this.dropTargetController;
|
|
328
|
+
}
|
|
329
|
+
ensureGestureDrag() {
|
|
330
|
+
if (!this.gestureDragController) {
|
|
331
|
+
this.gestureDragController = new Gtk.GestureDrag();
|
|
332
|
+
this.container.addController(this.gestureDragController);
|
|
181
333
|
}
|
|
334
|
+
return this.gestureDragController;
|
|
182
335
|
}
|
|
183
336
|
updateNotifyHandler(handler) {
|
|
184
337
|
const wrappedHandler = handler
|
package/dist/nodes/window.js
CHANGED
|
@@ -68,12 +68,14 @@ export class WindowNode extends WidgetNode {
|
|
|
68
68
|
const height = newProps.defaultHeight ?? -1;
|
|
69
69
|
this.container.setDefaultSize(width, height);
|
|
70
70
|
}
|
|
71
|
-
if (oldProps
|
|
71
|
+
if (!oldProps || oldProps.onClose !== newProps.onClose) {
|
|
72
72
|
const userHandler = newProps.onClose;
|
|
73
|
-
const wrappedHandler =
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
const wrappedHandler = userHandler
|
|
74
|
+
? () => {
|
|
75
|
+
userHandler();
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
: undefined;
|
|
77
79
|
signalStore.set(this, this.container, "close-request", wrappedHandler);
|
|
78
80
|
}
|
|
79
81
|
super.updateProps(filterProps(oldProps ?? {}, PROPS), filterProps(newProps, PROPS));
|
package/dist/render.d.ts
CHANGED
|
@@ -9,9 +9,9 @@ import { type ReactNode } from "react";
|
|
|
9
9
|
* @example
|
|
10
10
|
* ```tsx
|
|
11
11
|
* const App = () => {
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* const app = useApplication();
|
|
13
|
+
* console.log(app.applicationId);
|
|
14
|
+
* return <GtkLabel label="Hello" />;
|
|
15
15
|
* };
|
|
16
16
|
* ```
|
|
17
17
|
*/
|
|
@@ -27,8 +27,8 @@ export declare const ApplicationContext: React.Context<Gtk.Application | null>;
|
|
|
27
27
|
* @example
|
|
28
28
|
* ```tsx
|
|
29
29
|
* const MyComponent = () => {
|
|
30
|
-
*
|
|
31
|
-
*
|
|
30
|
+
* const app = useApplication();
|
|
31
|
+
* return <GtkLabel label={app.applicationId} />;
|
|
32
32
|
* };
|
|
33
33
|
* ```
|
|
34
34
|
*
|
|
@@ -69,9 +69,9 @@ export declare const setHotReloading: (value: boolean) => void;
|
|
|
69
69
|
* import { render, quit } from "@gtkx/react";
|
|
70
70
|
*
|
|
71
71
|
* const App = () => (
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
72
|
+
* <GtkApplicationWindow title="My App" onClose={quit}>
|
|
73
|
+
* <GtkLabel label="Hello, GTKX!" />
|
|
74
|
+
* </GtkApplicationWindow>
|
|
75
75
|
* );
|
|
76
76
|
*
|
|
77
77
|
* render(<App />, "com.example.myapp");
|
|
@@ -94,9 +94,9 @@ export declare const render: (element: ReactNode, appId: string, flags?: Gio.App
|
|
|
94
94
|
* ```tsx
|
|
95
95
|
* // In HMR handler
|
|
96
96
|
* if (import.meta.hot) {
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
97
|
+
* import.meta.hot.accept(() => {
|
|
98
|
+
* update(<App />);
|
|
99
|
+
* });
|
|
100
100
|
* }
|
|
101
101
|
* ```
|
|
102
102
|
*
|
|
@@ -114,9 +114,9 @@ export declare const update: (element: ReactNode) => Promise<void>;
|
|
|
114
114
|
* import { quit } from "@gtkx/react";
|
|
115
115
|
*
|
|
116
116
|
* const App = () => (
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
117
|
+
* <GtkApplicationWindow title="My App" onClose={quit}>
|
|
118
|
+
* <GtkButton label="Quit" onClicked={quit} />
|
|
119
|
+
* </GtkApplicationWindow>
|
|
120
120
|
* );
|
|
121
121
|
* ```
|
|
122
122
|
*
|
package/dist/render.js
CHANGED
|
@@ -11,9 +11,9 @@ import { reconciler } from "./reconciler.js";
|
|
|
11
11
|
* @example
|
|
12
12
|
* ```tsx
|
|
13
13
|
* const App = () => {
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* const app = useApplication();
|
|
15
|
+
* console.log(app.applicationId);
|
|
16
|
+
* return <GtkLabel label="Hello" />;
|
|
17
17
|
* };
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
@@ -29,8 +29,8 @@ export const ApplicationContext = createContext(null);
|
|
|
29
29
|
* @example
|
|
30
30
|
* ```tsx
|
|
31
31
|
* const MyComponent = () => {
|
|
32
|
-
*
|
|
33
|
-
*
|
|
32
|
+
* const app = useApplication();
|
|
33
|
+
* return <GtkLabel label={app.applicationId} />;
|
|
34
34
|
* };
|
|
35
35
|
* ```
|
|
36
36
|
*
|
|
@@ -84,9 +84,9 @@ export const setHotReloading = (value) => {
|
|
|
84
84
|
* import { render, quit } from "@gtkx/react";
|
|
85
85
|
*
|
|
86
86
|
* const App = () => (
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
87
|
+
* <GtkApplicationWindow title="My App" onClose={quit}>
|
|
88
|
+
* <GtkLabel label="Hello, GTKX!" />
|
|
89
|
+
* </GtkApplicationWindow>
|
|
90
90
|
* );
|
|
91
91
|
*
|
|
92
92
|
* render(<App />, "com.example.myapp");
|
|
@@ -121,9 +121,9 @@ export const render = (element, appId, flags) => {
|
|
|
121
121
|
* ```tsx
|
|
122
122
|
* // In HMR handler
|
|
123
123
|
* if (import.meta.hot) {
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
124
|
+
* import.meta.hot.accept(() => {
|
|
125
|
+
* update(<App />);
|
|
126
|
+
* });
|
|
127
127
|
* }
|
|
128
128
|
* ```
|
|
129
129
|
*
|
|
@@ -147,9 +147,9 @@ export const update = (element) => {
|
|
|
147
147
|
* import { quit } from "@gtkx/react";
|
|
148
148
|
*
|
|
149
149
|
* const App = () => (
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
150
|
+
* <GtkApplicationWindow title="My App" onClose={quit}>
|
|
151
|
+
* <GtkButton label="Quit" onClicked={quit} />
|
|
152
|
+
* </GtkApplicationWindow>
|
|
153
153
|
* );
|
|
154
154
|
* ```
|
|
155
155
|
*
|