@gtkx/react 0.1.50 → 0.1.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/batch.js +8 -3
- package/dist/codegen/jsx-generator.js +92 -5
- package/dist/container-interfaces.d.ts +21 -0
- package/dist/container-interfaces.js +1 -0
- package/dist/factory.js +13 -1
- package/dist/generated/jsx.d.ts +42 -6
- package/dist/generated/jsx.js +56 -3
- package/dist/node.d.ts +11 -2
- package/dist/node.js +23 -4
- package/dist/nodes/column-view.d.ts +36 -26
- package/dist/nodes/column-view.js +122 -125
- package/dist/nodes/dropdown.d.ts +2 -2
- package/dist/nodes/dropdown.js +4 -4
- package/dist/nodes/grid.d.ts +1 -1
- package/dist/nodes/grid.js +6 -6
- package/dist/nodes/list.d.ts +19 -10
- package/dist/nodes/list.js +45 -40
- package/dist/nodes/menu.d.ts +84 -0
- package/dist/nodes/menu.js +279 -0
- package/dist/nodes/notebook.d.ts +1 -1
- package/dist/nodes/notebook.js +3 -3
- package/dist/nodes/root.js +1 -1
- package/dist/nodes/slot.d.ts +1 -2
- package/dist/nodes/slot.js +2 -2
- package/dist/nodes/stack.d.ts +35 -0
- package/dist/nodes/stack.js +178 -0
- package/dist/nodes/text-view.d.ts +0 -1
- package/dist/nodes/text-view.js +0 -7
- package/dist/types.d.ts +76 -0
- package/package.json +3 -3
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { isStackPageContainer, } from "../container-interfaces.js";
|
|
2
|
+
import { Node } from "../node.js";
|
|
3
|
+
export class StackNode extends Node {
|
|
4
|
+
static matches(type) {
|
|
5
|
+
return type === "Stack" || type === "Stack.Root";
|
|
6
|
+
}
|
|
7
|
+
pendingVisibleChildName = null;
|
|
8
|
+
addStackPage(child, props) {
|
|
9
|
+
const { name, title } = props;
|
|
10
|
+
let stackPage;
|
|
11
|
+
if (title !== undefined) {
|
|
12
|
+
stackPage = this.widget.addTitled(child, title, name ?? null);
|
|
13
|
+
}
|
|
14
|
+
else if (name !== undefined) {
|
|
15
|
+
stackPage = this.widget.addNamed(child, name);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
stackPage = this.widget.addChild(child);
|
|
19
|
+
}
|
|
20
|
+
this.applyStackPageProps(stackPage, props);
|
|
21
|
+
this.applyPendingVisibleChild();
|
|
22
|
+
}
|
|
23
|
+
applyPendingVisibleChild() {
|
|
24
|
+
if (this.pendingVisibleChildName !== null) {
|
|
25
|
+
const child = this.widget.getChildByName(this.pendingVisibleChildName);
|
|
26
|
+
if (child) {
|
|
27
|
+
this.widget.setVisibleChild(child);
|
|
28
|
+
this.pendingVisibleChildName = null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
insertStackPageBefore(child, props, _beforeChild) {
|
|
33
|
+
// Stack doesn't have insertBefore, so we add and rely on order
|
|
34
|
+
// For now, just add at the end - GTK Stack doesn't support insertion at position
|
|
35
|
+
this.addStackPage(child, props);
|
|
36
|
+
}
|
|
37
|
+
removeStackPage(child) {
|
|
38
|
+
this.widget.remove(child);
|
|
39
|
+
}
|
|
40
|
+
updateStackPageProps(child, props) {
|
|
41
|
+
const stackPage = this.widget.getPage(child);
|
|
42
|
+
this.applyStackPageProps(stackPage, props);
|
|
43
|
+
}
|
|
44
|
+
applyStackPageProps(stackPage, props) {
|
|
45
|
+
if (props.name !== undefined) {
|
|
46
|
+
stackPage.setName(props.name);
|
|
47
|
+
}
|
|
48
|
+
if (props.title !== undefined) {
|
|
49
|
+
stackPage.setTitle(props.title);
|
|
50
|
+
}
|
|
51
|
+
if (props.iconName !== undefined) {
|
|
52
|
+
stackPage.setIconName(props.iconName);
|
|
53
|
+
}
|
|
54
|
+
if (props.needsAttention !== undefined) {
|
|
55
|
+
stackPage.setNeedsAttention(props.needsAttention);
|
|
56
|
+
}
|
|
57
|
+
if (props.visible !== undefined) {
|
|
58
|
+
stackPage.setVisible(props.visible);
|
|
59
|
+
}
|
|
60
|
+
if (props.useUnderline !== undefined) {
|
|
61
|
+
stackPage.setUseUnderline(props.useUnderline);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
attachChild(child) {
|
|
65
|
+
this.widget.addChild(child);
|
|
66
|
+
}
|
|
67
|
+
insertChildBefore(child, _before) {
|
|
68
|
+
// Stack doesn't support insertion at position
|
|
69
|
+
this.widget.addChild(child);
|
|
70
|
+
}
|
|
71
|
+
detachChild(child) {
|
|
72
|
+
this.widget.remove(child);
|
|
73
|
+
}
|
|
74
|
+
consumedProps() {
|
|
75
|
+
const consumed = super.consumedProps();
|
|
76
|
+
consumed.add("visibleChildName");
|
|
77
|
+
return consumed;
|
|
78
|
+
}
|
|
79
|
+
updateProps(oldProps, newProps) {
|
|
80
|
+
if (newProps.visibleChildName !== undefined) {
|
|
81
|
+
const name = newProps.visibleChildName;
|
|
82
|
+
const child = this.widget.getChildByName(name);
|
|
83
|
+
if (child) {
|
|
84
|
+
this.widget.setVisibleChild(child);
|
|
85
|
+
this.pendingVisibleChildName = null;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Child not yet added, defer until it's added
|
|
89
|
+
this.pendingVisibleChildName = name;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
super.updateProps(oldProps, newProps);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export class StackPageNode extends Node {
|
|
96
|
+
static matches(type) {
|
|
97
|
+
return type === "Stack.Page";
|
|
98
|
+
}
|
|
99
|
+
isVirtual() {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
pageProps = {};
|
|
103
|
+
childWidget = null;
|
|
104
|
+
parentContainer = null;
|
|
105
|
+
initialize(props) {
|
|
106
|
+
this.pageProps = this.extractPageProps(props);
|
|
107
|
+
super.initialize(props);
|
|
108
|
+
}
|
|
109
|
+
extractPageProps(props) {
|
|
110
|
+
return {
|
|
111
|
+
name: typeof props.name === "string" ? props.name : undefined,
|
|
112
|
+
title: typeof props.title === "string" ? props.title : undefined,
|
|
113
|
+
iconName: typeof props.iconName === "string" ? props.iconName : undefined,
|
|
114
|
+
needsAttention: typeof props.needsAttention === "boolean" ? props.needsAttention : undefined,
|
|
115
|
+
visible: typeof props.visible === "boolean" ? props.visible : undefined,
|
|
116
|
+
useUnderline: typeof props.useUnderline === "boolean" ? props.useUnderline : undefined,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
getChildWidget() {
|
|
120
|
+
return this.childWidget;
|
|
121
|
+
}
|
|
122
|
+
appendChild(child) {
|
|
123
|
+
const childWidget = child.getWidget();
|
|
124
|
+
if (childWidget) {
|
|
125
|
+
this.childWidget = childWidget;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
attachToParent(parent) {
|
|
129
|
+
if (isStackPageContainer(parent) && this.childWidget) {
|
|
130
|
+
this.parentContainer = parent;
|
|
131
|
+
parent.addStackPage(this.childWidget, this.pageProps);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
attachToParentBefore(parent, before) {
|
|
135
|
+
if (isStackPageContainer(parent) && this.childWidget) {
|
|
136
|
+
this.parentContainer = parent;
|
|
137
|
+
const beforePage = before instanceof StackPageNode ? before.getChildWidget() : before.getWidget();
|
|
138
|
+
if (beforePage) {
|
|
139
|
+
parent.insertStackPageBefore(this.childWidget, this.pageProps, beforePage);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
parent.addStackPage(this.childWidget, this.pageProps);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
detachFromParent(parent) {
|
|
147
|
+
if (isStackPageContainer(parent) && this.childWidget) {
|
|
148
|
+
parent.removeStackPage(this.childWidget);
|
|
149
|
+
this.parentContainer = null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
consumedProps() {
|
|
153
|
+
const consumed = super.consumedProps();
|
|
154
|
+
consumed.add("name");
|
|
155
|
+
consumed.add("title");
|
|
156
|
+
consumed.add("iconName");
|
|
157
|
+
consumed.add("needsAttention");
|
|
158
|
+
consumed.add("visible");
|
|
159
|
+
consumed.add("useUnderline");
|
|
160
|
+
return consumed;
|
|
161
|
+
}
|
|
162
|
+
updateProps(oldProps, newProps) {
|
|
163
|
+
const newPageProps = this.extractPageProps(newProps);
|
|
164
|
+
const propsChanged = oldProps.name !== newProps.name ||
|
|
165
|
+
oldProps.title !== newProps.title ||
|
|
166
|
+
oldProps.iconName !== newProps.iconName ||
|
|
167
|
+
oldProps.needsAttention !== newProps.needsAttention ||
|
|
168
|
+
oldProps.visible !== newProps.visible ||
|
|
169
|
+
oldProps.useUnderline !== newProps.useUnderline;
|
|
170
|
+
if (propsChanged) {
|
|
171
|
+
this.pageProps = newPageProps;
|
|
172
|
+
if (this.parentContainer && this.childWidget) {
|
|
173
|
+
this.parentContainer.updateStackPageProps(this.childWidget, this.pageProps);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
super.updateProps(oldProps, newProps);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -3,7 +3,6 @@ import type { Props } from "../factory.js";
|
|
|
3
3
|
import { Node } from "../node.js";
|
|
4
4
|
export declare class TextViewNode extends Node<Gtk.TextView> {
|
|
5
5
|
static matches(type: string): boolean;
|
|
6
|
-
constructor(type: string, props: Props);
|
|
7
6
|
protected consumedProps(): Set<string>;
|
|
8
7
|
updateProps(oldProps: Props, newProps: Props): void;
|
|
9
8
|
}
|
package/dist/nodes/text-view.js
CHANGED
|
@@ -3,13 +3,6 @@ export class TextViewNode extends Node {
|
|
|
3
3
|
static matches(type) {
|
|
4
4
|
return type === "TextView";
|
|
5
5
|
}
|
|
6
|
-
constructor(type, props) {
|
|
7
|
-
super(type, props);
|
|
8
|
-
const buffer = props.buffer;
|
|
9
|
-
if (buffer) {
|
|
10
|
-
this.widget.setBuffer(buffer);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
6
|
consumedProps() {
|
|
14
7
|
const consumed = super.consumedProps();
|
|
15
8
|
consumed.add("buffer");
|
package/dist/types.d.ts
CHANGED
|
@@ -7,7 +7,12 @@ import type { ReactElement, ReactNode } from "react";
|
|
|
7
7
|
export interface SlotProps {
|
|
8
8
|
children?: ReactNode;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Props passed to list item components.
|
|
12
|
+
* @typeParam I - The type of the data item
|
|
13
|
+
*/
|
|
10
14
|
export interface ListItemProps<I = unknown> {
|
|
15
|
+
/** The data item to render. */
|
|
11
16
|
item: I;
|
|
12
17
|
}
|
|
13
18
|
export interface GridChildProps extends SlotProps {
|
|
@@ -21,7 +26,12 @@ export interface GridChildProps extends SlotProps {
|
|
|
21
26
|
* Called with null during setup (for loading state) and with the actual item during bind.
|
|
22
27
|
*/
|
|
23
28
|
export type RenderItemFn<T> = (item: T | null) => ReactElement;
|
|
29
|
+
/**
|
|
30
|
+
* Props for ListView and GridView components.
|
|
31
|
+
* @typeParam T - The type of the data items in the list
|
|
32
|
+
*/
|
|
24
33
|
export interface ListViewRenderProps<T = unknown> {
|
|
34
|
+
/** Render function called for each item in the list. */
|
|
25
35
|
renderItem: RenderItemFn<T>;
|
|
26
36
|
}
|
|
27
37
|
/**
|
|
@@ -32,11 +42,20 @@ export interface ListViewRenderProps<T = unknown> {
|
|
|
32
42
|
* @param columnId - The ID of the column being sorted
|
|
33
43
|
*/
|
|
34
44
|
export type ColumnSortFn<T, C extends string = string> = (a: T, b: T, columnId: C) => number;
|
|
45
|
+
/**
|
|
46
|
+
* Props for individual columns in a ColumnView.
|
|
47
|
+
* @typeParam T - The type of the data items displayed in the column
|
|
48
|
+
*/
|
|
35
49
|
export interface ColumnViewColumnProps<T = unknown> {
|
|
50
|
+
/** The column header title. */
|
|
36
51
|
title?: string;
|
|
52
|
+
/** Whether the column should expand to fill available space. */
|
|
37
53
|
expand?: boolean;
|
|
54
|
+
/** Whether the column can be resized by the user. */
|
|
38
55
|
resizable?: boolean;
|
|
56
|
+
/** Fixed width in pixels. Overrides automatic sizing. */
|
|
39
57
|
fixedWidth?: number;
|
|
58
|
+
/** Unique identifier for the column. Used for sorting. */
|
|
40
59
|
id?: string;
|
|
41
60
|
/**
|
|
42
61
|
* Render function for column cells.
|
|
@@ -45,12 +64,69 @@ export interface ColumnViewColumnProps<T = unknown> {
|
|
|
45
64
|
*/
|
|
46
65
|
renderCell: (item: T | null) => ReactElement;
|
|
47
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Props for the ColumnView root component.
|
|
69
|
+
* @typeParam T - The type of the data items in the view
|
|
70
|
+
* @typeParam C - The union type of column IDs
|
|
71
|
+
*/
|
|
48
72
|
export interface ColumnViewRootProps<T = unknown, C extends string = string> {
|
|
73
|
+
/** The ID of the currently sorted column, or null if unsorted. */
|
|
49
74
|
sortColumn?: C | null;
|
|
75
|
+
/** The current sort direction. */
|
|
50
76
|
sortOrder?: SortType;
|
|
77
|
+
/** Callback fired when the user changes the sort column or order. */
|
|
51
78
|
onSortChange?: (column: C | null, order: SortType) => void;
|
|
79
|
+
/** Custom comparison function for sorting items. */
|
|
52
80
|
sortFn?: ColumnSortFn<T, C>;
|
|
53
81
|
}
|
|
54
82
|
export interface NotebookPageProps extends SlotProps {
|
|
55
83
|
label: string;
|
|
56
84
|
}
|
|
85
|
+
export interface StackRootProps extends SlotProps {
|
|
86
|
+
visibleChildName?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface StackPageProps extends SlotProps {
|
|
89
|
+
name?: string;
|
|
90
|
+
title?: string;
|
|
91
|
+
iconName?: string;
|
|
92
|
+
needsAttention?: boolean;
|
|
93
|
+
visible?: boolean;
|
|
94
|
+
useUnderline?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Props for the Menu.Root component.
|
|
98
|
+
* Root container for declarative menu structures.
|
|
99
|
+
*/
|
|
100
|
+
export interface MenuRootProps {
|
|
101
|
+
children?: ReactNode;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Props for Menu.Item components.
|
|
105
|
+
* Represents a single menu item with an action.
|
|
106
|
+
*/
|
|
107
|
+
export interface MenuItemProps {
|
|
108
|
+
/** The visible label for the menu item. */
|
|
109
|
+
label: string;
|
|
110
|
+
/** Callback invoked when the menu item is activated. */
|
|
111
|
+
onActivate?: () => void;
|
|
112
|
+
/** Keyboard accelerators for this menu item (e.g., `"<Control>q"` or `["<Control>q", "<Control>w"]`). */
|
|
113
|
+
accels?: string | string[];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Props for Menu.Section components.
|
|
117
|
+
* Groups related menu items with optional label.
|
|
118
|
+
*/
|
|
119
|
+
export interface MenuSectionProps {
|
|
120
|
+
/** Optional section label displayed as a header. */
|
|
121
|
+
label?: string;
|
|
122
|
+
children?: ReactNode;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Props for Menu.Submenu components.
|
|
126
|
+
* Creates a nested submenu with its own items.
|
|
127
|
+
*/
|
|
128
|
+
export interface MenuSubmenuProps {
|
|
129
|
+
/** The submenu label shown in parent menu. */
|
|
130
|
+
label: string;
|
|
131
|
+
children?: ReactNode;
|
|
132
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.52",
|
|
4
4
|
"description": "Build GTK4 desktop applications with React and TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtk",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"react-reconciler": "0.33.0",
|
|
39
|
-
"@gtkx/ffi": "0.1.
|
|
39
|
+
"@gtkx/ffi": "0.1.52"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@gtkx/gir": "0.1.
|
|
42
|
+
"@gtkx/gir": "0.1.52"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"react": "^19"
|