@gtkx/react 0.12.0 → 0.13.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 (81) hide show
  1. package/README.md +1 -1
  2. package/dist/generated/jsx.d.ts +32 -18
  3. package/dist/host-config.js +3 -3
  4. package/dist/jsx.d.ts +530 -372
  5. package/dist/jsx.js +401 -353
  6. package/dist/nodes/action-row-child.d.ts +4 -11
  7. package/dist/nodes/action-row-child.js +10 -66
  8. package/dist/nodes/action-row.js +21 -4
  9. package/dist/nodes/application.js +22 -3
  10. package/dist/nodes/autowrapped.js +13 -3
  11. package/dist/nodes/calendar-mark.d.ts +15 -0
  12. package/dist/nodes/calendar-mark.js +29 -0
  13. package/dist/nodes/calendar.d.ts +1 -0
  14. package/dist/nodes/calendar.js +70 -0
  15. package/dist/nodes/column-view-column.d.ts +1 -0
  16. package/dist/nodes/column-view-column.js +4 -0
  17. package/dist/nodes/column-view.js +24 -7
  18. package/dist/nodes/expander-row-child.d.ts +15 -0
  19. package/dist/nodes/expander-row-child.js +20 -0
  20. package/dist/nodes/expander-row.d.ts +1 -0
  21. package/dist/nodes/expander-row.js +54 -0
  22. package/dist/nodes/fixed-child.js +10 -8
  23. package/dist/nodes/grid-child.js +10 -8
  24. package/dist/nodes/index.d.ts +12 -0
  25. package/dist/nodes/index.js +12 -0
  26. package/dist/nodes/internal/list-item-renderer.d.ts +3 -0
  27. package/dist/nodes/internal/list-item-renderer.js +25 -9
  28. package/dist/nodes/internal/list-store.js +2 -2
  29. package/dist/nodes/internal/tree-list-item-renderer.d.ts +8 -0
  30. package/dist/nodes/internal/tree-list-item-renderer.js +68 -24
  31. package/dist/nodes/internal/tree-store.js +3 -4
  32. package/dist/nodes/level-bar-offset.d.ts +13 -0
  33. package/dist/nodes/level-bar-offset.js +35 -0
  34. package/dist/nodes/level-bar.d.ts +1 -0
  35. package/dist/nodes/level-bar.js +82 -0
  36. package/dist/nodes/list-view.js +14 -7
  37. package/dist/nodes/menu.js +4 -4
  38. package/dist/nodes/models/list.d.ts +2 -1
  39. package/dist/nodes/models/list.js +21 -12
  40. package/dist/nodes/models/menu.d.ts +1 -0
  41. package/dist/nodes/models/menu.js +24 -17
  42. package/dist/nodes/models/tree-list.d.ts +2 -1
  43. package/dist/nodes/models/tree-list.js +43 -24
  44. package/dist/nodes/navigation-page.d.ts +16 -0
  45. package/dist/nodes/navigation-page.js +58 -0
  46. package/dist/nodes/navigation-view.d.ts +1 -0
  47. package/dist/nodes/navigation-view.js +105 -0
  48. package/dist/nodes/notebook-page-tab.js +1 -1
  49. package/dist/nodes/notebook-page.js +3 -2
  50. package/dist/nodes/notebook.js +3 -3
  51. package/dist/nodes/overlay-child.js +29 -14
  52. package/dist/nodes/pack-child.d.ts +4 -11
  53. package/dist/nodes/pack-child.js +10 -66
  54. package/dist/nodes/pack.js +21 -4
  55. package/dist/nodes/popover-menu.js +15 -12
  56. package/dist/nodes/scale-mark.d.ts +17 -0
  57. package/dist/nodes/scale-mark.js +38 -0
  58. package/dist/nodes/scale.d.ts +1 -0
  59. package/dist/nodes/scale.js +70 -0
  60. package/dist/nodes/simple-list-view.js +3 -3
  61. package/dist/nodes/slot.d.ts +2 -1
  62. package/dist/nodes/slot.js +2 -2
  63. package/dist/nodes/stack-page.js +7 -7
  64. package/dist/nodes/stack.js +5 -5
  65. package/dist/nodes/toggle-group.d.ts +1 -0
  66. package/dist/nodes/toggle-group.js +48 -0
  67. package/dist/nodes/toggle.d.ts +15 -0
  68. package/dist/nodes/toggle.js +70 -0
  69. package/dist/nodes/toolbar-child.js +18 -16
  70. package/dist/nodes/tree-list-view.js +16 -7
  71. package/dist/nodes/virtual-child.d.ts +18 -0
  72. package/dist/nodes/virtual-child.js +62 -0
  73. package/dist/nodes/widget.js +22 -8
  74. package/dist/nodes/window.d.ts +22 -0
  75. package/dist/nodes/window.js +11 -2
  76. package/dist/render.d.ts +3 -5
  77. package/dist/render.js +3 -5
  78. package/dist/scheduler.d.ts +13 -1
  79. package/dist/scheduler.js +26 -6
  80. package/dist/types.d.ts +25 -0
  81. package/package.json +3 -3
@@ -2,13 +2,21 @@ import "./action-row-child.js";
2
2
  import "./action-row.js";
3
3
  import "./application.js";
4
4
  import "./autowrapped.js";
5
+ import "./calendar-mark.js";
6
+ import "./calendar.js";
5
7
  import "./column-view-column.js";
6
8
  import "./column-view.js";
9
+ import "./expander-row-child.js";
10
+ import "./expander-row.js";
7
11
  import "./fixed-child.js";
8
12
  import "./grid-child.js";
13
+ import "./level-bar-offset.js";
14
+ import "./level-bar.js";
9
15
  import "./list-item.js";
10
16
  import "./list-view.js";
11
17
  import "./menu.js";
18
+ import "./navigation-page.js";
19
+ import "./navigation-view.js";
12
20
  import "./notebook-page-tab.js";
13
21
  import "./notebook-page.js";
14
22
  import "./notebook.js";
@@ -16,11 +24,15 @@ import "./overlay-child.js";
16
24
  import "./pack-child.js";
17
25
  import "./pack.js";
18
26
  import "./popover-menu.js";
27
+ import "./scale-mark.js";
28
+ import "./scale.js";
19
29
  import "./simple-list-item.js";
20
30
  import "./simple-list-view.js";
21
31
  import "./slot.js";
22
32
  import "./stack-page.js";
23
33
  import "./stack.js";
34
+ import "./toggle.js";
35
+ import "./toggle-group.js";
24
36
  import "./toolbar-child.js";
25
37
  import "./tree-list-item.js";
26
38
  import "./tree-list-view.js";
@@ -2,13 +2,21 @@ import "./action-row-child.js";
2
2
  import "./action-row.js";
3
3
  import "./application.js";
4
4
  import "./autowrapped.js";
5
+ import "./calendar-mark.js";
6
+ import "./calendar.js";
5
7
  import "./column-view-column.js";
6
8
  import "./column-view.js";
9
+ import "./expander-row-child.js";
10
+ import "./expander-row.js";
7
11
  import "./fixed-child.js";
8
12
  import "./grid-child.js";
13
+ import "./level-bar-offset.js";
14
+ import "./level-bar.js";
9
15
  import "./list-item.js";
10
16
  import "./list-view.js";
11
17
  import "./menu.js";
18
+ import "./navigation-page.js";
19
+ import "./navigation-view.js";
12
20
  import "./notebook-page-tab.js";
13
21
  import "./notebook-page.js";
14
22
  import "./notebook.js";
@@ -16,11 +24,15 @@ import "./overlay-child.js";
16
24
  import "./pack-child.js";
17
25
  import "./pack.js";
18
26
  import "./popover-menu.js";
27
+ import "./scale-mark.js";
28
+ import "./scale.js";
19
29
  import "./simple-list-item.js";
20
30
  import "./simple-list-view.js";
21
31
  import "./slot.js";
22
32
  import "./stack-page.js";
23
33
  import "./stack.js";
34
+ import "./toggle.js";
35
+ import "./toggle-group.js";
24
36
  import "./toolbar-child.js";
25
37
  import "./tree-list-item.js";
26
38
  import "./tree-list-view.js";
@@ -6,11 +6,14 @@ export declare class ListItemRenderer {
6
6
  private factory;
7
7
  private store?;
8
8
  private fiberRoots;
9
+ private tornDown;
9
10
  private renderFn?;
11
+ private estimatedItemHeight?;
10
12
  constructor();
11
13
  getFactory(): Gtk.SignalListItemFactory;
12
14
  setRenderFn(renderFn?: RenderItemFn<unknown>): void;
13
15
  setStore(store?: ListStore | null): void;
16
+ setEstimatedItemHeight(height?: number): void;
14
17
  private getStore;
15
18
  private initialize;
16
19
  }
@@ -7,7 +7,9 @@ export class ListItemRenderer {
7
7
  factory;
8
8
  store;
9
9
  fiberRoots = new Map();
10
+ tornDown = new Set();
10
11
  renderFn = () => null;
12
+ estimatedItemHeight;
11
13
  constructor() {
12
14
  this.factory = new Gtk.SignalListItemFactory();
13
15
  this.initialize();
@@ -21,6 +23,9 @@ export class ListItemRenderer {
21
23
  setStore(store) {
22
24
  this.store = store;
23
25
  }
26
+ setEstimatedItemHeight(height) {
27
+ this.estimatedItemHeight = height;
28
+ }
24
29
  getStore() {
25
30
  if (!this.store) {
26
31
  throw new Error("Expected list store to be set on ListItemRenderer");
@@ -31,6 +36,9 @@ export class ListItemRenderer {
31
36
  signalStore.set(this, this.factory, "setup", (_self, listItem) => {
32
37
  const ptr = getNativeId(listItem.handle);
33
38
  const box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
39
+ if (this.estimatedItemHeight !== undefined) {
40
+ box.setSizeRequest(-1, this.estimatedItemHeight);
41
+ }
34
42
  listItem.setChild(box);
35
43
  const fiberRoot = createFiberRoot(box);
36
44
  this.fiberRoots.set(ptr, fiberRoot);
@@ -47,21 +55,29 @@ export class ListItemRenderer {
47
55
  return;
48
56
  const item = this.getStore().getItem(stringObject.getString());
49
57
  const element = this.renderFn?.(item);
50
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => { });
51
- });
52
- signalStore.set(this, this.factory, "unbind", (_self, listItem) => {
53
- const ptr = getNativeId(listItem.handle);
54
- const fiberRoot = this.fiberRoots.get(ptr);
55
- if (!fiberRoot)
56
- return;
57
- reconciler.getInstance().updateContainer(null, fiberRoot, null, () => { });
58
+ reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {
59
+ if (this.tornDown.has(ptr))
60
+ return;
61
+ const currentFiberRoot = this.fiberRoots.get(ptr);
62
+ if (!currentFiberRoot)
63
+ return;
64
+ const box = currentFiberRoot.containerInfo;
65
+ if (box instanceof Gtk.Box) {
66
+ box.setSizeRequest(-1, -1);
67
+ }
68
+ });
58
69
  });
70
+ signalStore.set(this, this.factory, "unbind", () => { });
59
71
  signalStore.set(this, this.factory, "teardown", (_self, listItem) => {
60
72
  const ptr = getNativeId(listItem.handle);
61
73
  const fiberRoot = this.fiberRoots.get(ptr);
62
74
  if (fiberRoot) {
75
+ this.tornDown.add(ptr);
63
76
  reconciler.getInstance().updateContainer(null, fiberRoot, null, () => { });
64
- queueMicrotask(() => this.fiberRoots.delete(ptr));
77
+ queueMicrotask(() => {
78
+ this.fiberRoots.delete(ptr);
79
+ this.tornDown.delete(ptr);
80
+ });
65
81
  }
66
82
  });
67
83
  }
@@ -1,5 +1,5 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
- import { scheduleAfterCommit } from "../../scheduler.js";
2
+ import { CommitPriority, scheduleAfterCommit } from "../../scheduler.js";
3
3
  export class ListStore {
4
4
  items = new Map();
5
5
  model = new Gtk.StringList();
@@ -57,7 +57,7 @@ export class ListStore {
57
57
  return;
58
58
  }
59
59
  this.shouldSync = true;
60
- scheduleAfterCommit(() => this.sync());
60
+ scheduleAfterCommit(() => this.sync(), CommitPriority.LOW);
61
61
  }
62
62
  sync() {
63
63
  this.shouldSync = false;
@@ -6,11 +6,19 @@ export declare class TreeListItemRenderer {
6
6
  private factory;
7
7
  private store?;
8
8
  private fiberRoots;
9
+ private expanders;
10
+ private setupComplete;
11
+ private pendingBinds;
12
+ private tornDown;
9
13
  private renderFn?;
14
+ private estimatedItemHeight?;
10
15
  constructor();
11
16
  getFactory(): Gtk.SignalListItemFactory;
12
17
  setRenderFn(renderFn?: TreeRenderItemFn<unknown>): void;
13
18
  setStore(store?: TreeStore | null): void;
19
+ setEstimatedItemHeight(height?: number): void;
14
20
  private getStore;
15
21
  private initialize;
22
+ private processPendingBind;
23
+ private renderBind;
16
24
  }
@@ -7,7 +7,12 @@ export class TreeListItemRenderer {
7
7
  factory;
8
8
  store;
9
9
  fiberRoots = new Map();
10
+ expanders = new Map();
11
+ setupComplete = new Set();
12
+ pendingBinds = new Map();
13
+ tornDown = new Set();
10
14
  renderFn = () => null;
15
+ estimatedItemHeight;
11
16
  constructor() {
12
17
  this.factory = new Gtk.SignalListItemFactory();
13
18
  this.initialize();
@@ -21,6 +26,9 @@ export class TreeListItemRenderer {
21
26
  setStore(store) {
22
27
  this.store = store;
23
28
  }
29
+ setEstimatedItemHeight(height) {
30
+ this.estimatedItemHeight = height;
31
+ }
24
32
  getStore() {
25
33
  if (!this.store) {
26
34
  throw new Error("Expected tree store to be set on TreeListItemRenderer");
@@ -32,61 +40,97 @@ export class TreeListItemRenderer {
32
40
  const ptr = getNativeId(listItem.handle);
33
41
  const expander = new Gtk.TreeExpander();
34
42
  const box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
43
+ if (this.estimatedItemHeight !== undefined) {
44
+ box.setSizeRequest(-1, this.estimatedItemHeight);
45
+ }
35
46
  expander.setChild(box);
36
47
  listItem.setChild(expander);
37
48
  const fiberRoot = createFiberRoot(box);
38
49
  this.fiberRoots.set(ptr, fiberRoot);
50
+ this.expanders.set(ptr, expander);
39
51
  const element = this.renderFn?.(null, null);
40
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => { });
52
+ reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {
53
+ if (this.tornDown.has(ptr))
54
+ return;
55
+ this.setupComplete.add(ptr);
56
+ this.processPendingBind(ptr);
57
+ });
41
58
  });
42
59
  signalStore.set(this, this.factory, "bind", (_self, listItem) => {
43
60
  const ptr = getNativeId(listItem.handle);
44
61
  const fiberRoot = this.fiberRoots.get(ptr);
45
- if (!fiberRoot)
62
+ const expander = this.expanders.get(ptr);
63
+ if (!fiberRoot || !expander)
46
64
  return;
47
65
  const treeListRow = listItem.getItem();
48
66
  if (!(treeListRow instanceof Gtk.TreeListRow))
49
67
  return;
50
- const expander = listItem.getChild();
51
- if (!(expander instanceof Gtk.TreeExpander))
52
- return;
53
68
  expander.setListRow(treeListRow);
54
69
  const stringObject = treeListRow.getItem();
55
70
  if (!(stringObject instanceof Gtk.StringObject))
56
71
  return;
57
72
  const id = stringObject.getString();
58
- const itemData = this.getStore().getItem(id);
59
- if (itemData) {
60
- if (itemData.indentForDepth !== undefined) {
61
- expander.setIndentForDepth(itemData.indentForDepth);
62
- }
63
- if (itemData.indentForIcon !== undefined) {
64
- expander.setIndentForIcon(itemData.indentForIcon);
65
- }
66
- if (itemData.hideExpander !== undefined) {
67
- expander.setHideExpander(itemData.hideExpander);
68
- }
73
+ if (!this.setupComplete.has(ptr)) {
74
+ this.pendingBinds.set(ptr, { treeListRow, expander, id });
75
+ return;
69
76
  }
70
- const element = this.renderFn?.(itemData?.value ?? null, treeListRow);
71
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => { });
77
+ this.renderBind(ptr, expander, treeListRow, id);
72
78
  });
73
79
  signalStore.set(this, this.factory, "unbind", (_self, listItem) => {
74
- const ptr = getNativeId(listItem.handle);
75
- const fiberRoot = this.fiberRoots.get(ptr);
76
- if (!fiberRoot)
77
- return;
78
80
  const expander = listItem.getChild();
79
81
  if (expander instanceof Gtk.TreeExpander) {
80
82
  expander.setListRow(null);
81
83
  }
82
- reconciler.getInstance().updateContainer(null, fiberRoot, null, () => { });
83
84
  });
84
85
  signalStore.set(this, this.factory, "teardown", (_self, listItem) => {
85
86
  const ptr = getNativeId(listItem.handle);
86
87
  const fiberRoot = this.fiberRoots.get(ptr);
87
88
  if (fiberRoot) {
89
+ this.tornDown.add(ptr);
88
90
  reconciler.getInstance().updateContainer(null, fiberRoot, null, () => { });
89
- queueMicrotask(() => this.fiberRoots.delete(ptr));
91
+ queueMicrotask(() => {
92
+ this.fiberRoots.delete(ptr);
93
+ this.expanders.delete(ptr);
94
+ this.setupComplete.delete(ptr);
95
+ this.pendingBinds.delete(ptr);
96
+ this.tornDown.delete(ptr);
97
+ });
98
+ }
99
+ });
100
+ }
101
+ processPendingBind(ptr) {
102
+ const pending = this.pendingBinds.get(ptr);
103
+ if (!pending)
104
+ return;
105
+ this.pendingBinds.delete(ptr);
106
+ this.renderBind(ptr, pending.expander, pending.treeListRow, pending.id);
107
+ }
108
+ renderBind(ptr, expander, treeListRow, id) {
109
+ const fiberRoot = this.fiberRoots.get(ptr);
110
+ if (!fiberRoot)
111
+ return;
112
+ const itemData = this.getStore().getItem(id);
113
+ if (itemData) {
114
+ if (itemData.indentForDepth !== undefined) {
115
+ expander.setIndentForDepth(itemData.indentForDepth);
116
+ }
117
+ if (itemData.indentForIcon !== undefined) {
118
+ expander.setIndentForIcon(itemData.indentForIcon);
119
+ }
120
+ if (itemData.hideExpander !== undefined) {
121
+ expander.setHideExpander(itemData.hideExpander);
122
+ }
123
+ }
124
+ const element = this.renderFn?.(itemData?.value ?? null, treeListRow);
125
+ reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {
126
+ if (this.tornDown.has(ptr))
127
+ return;
128
+ const currentExpander = this.expanders.get(ptr);
129
+ if (!currentExpander)
130
+ return;
131
+ const box = currentExpander.getChild();
132
+ if (box instanceof Gtk.Box) {
133
+ box.setSizeRequest(-1, -1);
90
134
  }
91
135
  });
92
136
  }
@@ -1,6 +1,6 @@
1
1
  import { batch } from "@gtkx/ffi";
2
2
  import * as Gtk from "@gtkx/ffi/gtk";
3
- import { scheduleAfterCommit } from "../../scheduler.js";
3
+ import { CommitPriority, scheduleAfterCommit } from "../../scheduler.js";
4
4
  export class TreeStore {
5
5
  items = new Map();
6
6
  rootIds = [];
@@ -126,7 +126,7 @@ export class TreeStore {
126
126
  return;
127
127
  }
128
128
  this.shouldSync = true;
129
- scheduleAfterCommit(() => this.sync());
129
+ scheduleAfterCommit(() => this.sync(), CommitPriority.LOW);
130
130
  }
131
131
  sync() {
132
132
  this.shouldSync = false;
@@ -135,10 +135,9 @@ export class TreeStore {
135
135
  this.rootModel.splice(0, oldRootLength, this.newRootIds.length > 0 ? this.newRootIds : undefined);
136
136
  this.rootIds = [...this.newRootIds];
137
137
  for (const [parentId, newChildIds] of this.newChildren) {
138
- const oldChildIds = this.children.get(parentId) ?? [];
139
138
  const model = this.childModels.get(parentId);
140
139
  if (model) {
141
- const oldLength = oldChildIds.length;
140
+ const oldLength = model.getNItems();
142
141
  model.splice(0, oldLength, newChildIds.length > 0 ? newChildIds : undefined);
143
142
  }
144
143
  }
@@ -0,0 +1,13 @@
1
+ import type * as Gtk from "@gtkx/ffi/gtk";
2
+ import type { LevelBarOffsetProps } from "../jsx.js";
3
+ import { VirtualNode } from "./virtual.js";
4
+ export declare class LevelBarOffsetNode extends VirtualNode<LevelBarOffsetProps> {
5
+ static priority: number;
6
+ private levelBar?;
7
+ private onRebuild?;
8
+ static matches(type: string): boolean;
9
+ setLevelBar(levelBar: Gtk.LevelBar, onRebuild: () => void): void;
10
+ addOffset(): string | undefined;
11
+ updateProps(oldProps: LevelBarOffsetProps | null, newProps: LevelBarOffsetProps): void;
12
+ unmount(): void;
13
+ }
@@ -0,0 +1,35 @@
1
+ import { registerNodeClass } from "../registry.js";
2
+ import { VirtualNode } from "./virtual.js";
3
+ export class LevelBarOffsetNode extends VirtualNode {
4
+ static priority = 1;
5
+ levelBar;
6
+ onRebuild;
7
+ static matches(type) {
8
+ return type === "LevelBarOffset";
9
+ }
10
+ setLevelBar(levelBar, onRebuild) {
11
+ this.levelBar = levelBar;
12
+ this.onRebuild = onRebuild;
13
+ }
14
+ addOffset() {
15
+ if (!this.levelBar)
16
+ return undefined;
17
+ this.levelBar.addOffsetValue(this.props.id, this.props.value);
18
+ return this.props.id;
19
+ }
20
+ updateProps(oldProps, newProps) {
21
+ super.updateProps(oldProps, newProps);
22
+ if (oldProps && this.levelBar) {
23
+ const changed = oldProps.id !== newProps.id || oldProps.value !== newProps.value;
24
+ if (changed) {
25
+ this.onRebuild?.();
26
+ }
27
+ }
28
+ }
29
+ unmount() {
30
+ this.levelBar = undefined;
31
+ this.onRebuild = undefined;
32
+ super.unmount();
33
+ }
34
+ }
35
+ registerNodeClass(LevelBarOffsetNode);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,82 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { registerNodeClass } from "../registry.js";
3
+ import { CommitPriority, scheduleAfterCommit } from "../scheduler.js";
4
+ import { isContainerType } from "./internal/utils.js";
5
+ import { LevelBarOffsetNode } from "./level-bar-offset.js";
6
+ import { SlotNode } from "./slot.js";
7
+ import { WidgetNode } from "./widget.js";
8
+ class LevelBarNode extends WidgetNode {
9
+ static priority = 1;
10
+ offsetChildren = [];
11
+ appliedOffsetIds = new Set();
12
+ static matches(_type, containerOrClass) {
13
+ return isContainerType(Gtk.LevelBar, containerOrClass);
14
+ }
15
+ appendChild(child) {
16
+ if (child instanceof LevelBarOffsetNode) {
17
+ child.setLevelBar(this.container, () => this.scheduleRebuildAllOffsets());
18
+ this.offsetChildren.push(child);
19
+ scheduleAfterCommit(() => {
20
+ const id = child.addOffset();
21
+ if (id) {
22
+ this.appliedOffsetIds.add(id);
23
+ }
24
+ });
25
+ return;
26
+ }
27
+ if (child instanceof SlotNode || child instanceof WidgetNode) {
28
+ super.appendChild(child);
29
+ return;
30
+ }
31
+ throw new Error(`Cannot append '${child.typeName}' to 'LevelBar': expected x.LevelBarOffset or Widget`);
32
+ }
33
+ insertBefore(child, before) {
34
+ if (child instanceof LevelBarOffsetNode) {
35
+ child.setLevelBar(this.container, () => this.scheduleRebuildAllOffsets());
36
+ const beforeIndex = this.offsetChildren.indexOf(before);
37
+ if (beforeIndex >= 0) {
38
+ this.offsetChildren.splice(beforeIndex, 0, child);
39
+ }
40
+ else {
41
+ this.offsetChildren.push(child);
42
+ }
43
+ this.scheduleRebuildAllOffsets();
44
+ return;
45
+ }
46
+ if (child instanceof SlotNode || child instanceof WidgetNode) {
47
+ super.insertBefore(child, before);
48
+ return;
49
+ }
50
+ throw new Error(`Cannot insert '${child.typeName}' into 'LevelBar': expected x.LevelBarOffset or Widget`);
51
+ }
52
+ removeChild(child) {
53
+ if (child instanceof LevelBarOffsetNode) {
54
+ const index = this.offsetChildren.indexOf(child);
55
+ if (index >= 0) {
56
+ this.offsetChildren.splice(index, 1);
57
+ }
58
+ this.scheduleRebuildAllOffsets(CommitPriority.HIGH);
59
+ return;
60
+ }
61
+ if (child instanceof SlotNode || child instanceof WidgetNode) {
62
+ super.removeChild(child);
63
+ return;
64
+ }
65
+ throw new Error(`Cannot remove '${child.typeName}' from 'LevelBar': expected x.LevelBarOffset or Widget`);
66
+ }
67
+ scheduleRebuildAllOffsets(priority = CommitPriority.NORMAL) {
68
+ scheduleAfterCommit(() => {
69
+ for (const id of this.appliedOffsetIds) {
70
+ this.container.removeOffsetValue(id);
71
+ }
72
+ this.appliedOffsetIds.clear();
73
+ for (const offset of this.offsetChildren) {
74
+ const id = offset.addOffset();
75
+ if (id) {
76
+ this.appliedOffsetIds.add(id);
77
+ }
78
+ }
79
+ }, priority);
80
+ }
81
+ }
82
+ registerNodeClass(LevelBarNode);
@@ -5,7 +5,7 @@ import { filterProps, matchesAnyClass } from "./internal/utils.js";
5
5
  import { ListItemNode } from "./list-item.js";
6
6
  import { List } from "./models/list.js";
7
7
  import { WidgetNode } from "./widget.js";
8
- const PROP_NAMES = ["renderItem"];
8
+ const PROP_NAMES = ["renderItem", "estimatedItemHeight"];
9
9
  class ListViewNode extends WidgetNode {
10
10
  static priority = 1;
11
11
  itemRenderer;
@@ -15,7 +15,11 @@ class ListViewNode extends WidgetNode {
15
15
  }
16
16
  constructor(typeName, props, container, rootContainer) {
17
17
  super(typeName, props, container, rootContainer);
18
- this.list = new List();
18
+ this.list = new List({
19
+ selectionMode: props.selectionMode,
20
+ selected: props.selected,
21
+ onSelectionChanged: props.onSelectionChanged,
22
+ });
19
23
  this.itemRenderer = new ListItemRenderer();
20
24
  this.itemRenderer.setStore(this.list.getStore());
21
25
  this.container.setFactory(this.itemRenderer.getFactory());
@@ -26,19 +30,19 @@ class ListViewNode extends WidgetNode {
26
30
  }
27
31
  appendChild(child) {
28
32
  if (!(child instanceof ListItemNode)) {
29
- throw new Error(`Cannot append '${child.typeName}' to 'ListView': expected ListItem`);
33
+ throw new Error(`Cannot append '${child.typeName}' to 'ListView': expected x.ListItem`);
30
34
  }
31
35
  this.list.appendChild(child);
32
36
  }
33
37
  insertBefore(child, before) {
34
38
  if (!(child instanceof ListItemNode) || !(before instanceof ListItemNode)) {
35
- throw new Error(`Cannot insert '${child.typeName}' to 'ListView': expected ListItem`);
39
+ throw new Error(`Cannot insert '${child.typeName}' into 'ListView': expected x.ListItem`);
36
40
  }
37
41
  this.list.insertBefore(child, before);
38
42
  }
39
43
  removeChild(child) {
40
44
  if (!(child instanceof ListItemNode)) {
41
- throw new Error(`Cannot remove '${child.typeName}' from 'ListView': expected ListItem`);
45
+ throw new Error(`Cannot remove '${child.typeName}' from 'ListView': expected x.ListItem`);
42
46
  }
43
47
  this.list.removeChild(child);
44
48
  }
@@ -46,8 +50,11 @@ class ListViewNode extends WidgetNode {
46
50
  if (!oldProps || oldProps.renderItem !== newProps.renderItem) {
47
51
  this.itemRenderer.setRenderFn(newProps.renderItem);
48
52
  }
49
- this.list.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
50
- super.updateProps(filterProps(oldProps ?? {}, PROP_NAMES), filterProps(newProps, PROP_NAMES));
53
+ if (!oldProps || oldProps.estimatedItemHeight !== newProps.estimatedItemHeight) {
54
+ this.itemRenderer.setEstimatedItemHeight(newProps.estimatedItemHeight);
55
+ }
56
+ this.list.updateProps(oldProps ? filterProps(oldProps, PROP_NAMES) : null, filterProps(newProps, PROP_NAMES));
57
+ super.updateProps(oldProps ? filterProps(oldProps, PROP_NAMES) : null, filterProps(newProps, PROP_NAMES));
51
58
  }
52
59
  }
53
60
  registerNodeClass(ListViewNode);
@@ -4,16 +4,16 @@ import { Menu } from "./models/menu.js";
4
4
  export class MenuNode extends Menu {
5
5
  static priority = 1;
6
6
  static matches(type) {
7
- return type === "Menu.Item" || type === "Menu.Section" || type === "Menu.Submenu";
7
+ return type === "MenuItem" || type === "MenuSection" || type === "MenuSubmenu";
8
8
  }
9
9
  static getType(typeName) {
10
- if (typeName === "Menu.Item") {
10
+ if (typeName === "MenuItem") {
11
11
  return "item";
12
12
  }
13
- else if (typeName === "Menu.Section") {
13
+ else if (typeName === "MenuSection") {
14
14
  return "section";
15
15
  }
16
- else if (typeName === "Menu.Submenu") {
16
+ else if (typeName === "MenuSubmenu") {
17
17
  return "submenu";
18
18
  }
19
19
  throw new Error(`Unable to find menu type '${typeName}'`);
@@ -11,7 +11,8 @@ export declare class List extends VirtualNode<ListProps> {
11
11
  private store;
12
12
  private selectionModel;
13
13
  private handleSelectionChange?;
14
- constructor(selectionMode?: Gtk.SelectionMode);
14
+ constructor(props?: ListProps);
15
+ private initSelectionHandler;
15
16
  getStore(): ListStore;
16
17
  getSelectionModel(): Gtk.SingleSelection | Gtk.MultiSelection;
17
18
  appendChild(child: Node): void;
@@ -7,11 +7,22 @@ export class List extends VirtualNode {
7
7
  store;
8
8
  selectionModel;
9
9
  handleSelectionChange;
10
- constructor(selectionMode) {
10
+ constructor(props = {}) {
11
11
  super("", {}, undefined);
12
12
  this.store = new ListStore();
13
- this.selectionModel = this.createSelectionModel(selectionMode);
13
+ this.selectionModel = this.createSelectionModel(props.selectionMode);
14
14
  this.selectionModel.setModel(this.store.getModel());
15
+ this.initSelectionHandler(props.onSelectionChanged);
16
+ }
17
+ initSelectionHandler(onSelectionChanged) {
18
+ if (!onSelectionChanged) {
19
+ signalStore.set(this, this.selectionModel, "selection-changed", null);
20
+ return;
21
+ }
22
+ this.handleSelectionChange = () => {
23
+ onSelectionChanged(this.getSelection());
24
+ };
25
+ signalStore.set(this, this.selectionModel, "selection-changed", this.handleSelectionChange);
15
26
  }
16
27
  getStore() {
17
28
  return this.store;
@@ -42,20 +53,18 @@ export class List extends VirtualNode {
42
53
  }
43
54
  updateProps(oldProps, newProps) {
44
55
  super.updateProps(oldProps, newProps);
45
- if (!oldProps || oldProps.selectionMode !== newProps.selectionMode) {
56
+ if (oldProps && oldProps.selectionMode !== newProps.selectionMode) {
46
57
  signalStore.set(this, this.selectionModel, "selection-changed", null);
47
58
  this.selectionModel = this.createSelectionModel(newProps.selectionMode);
59
+ this.selectionModel.setModel(this.store.getModel());
60
+ this.initSelectionHandler(newProps.onSelectionChanged);
61
+ this.setSelection(newProps.selected);
62
+ return;
48
63
  }
49
- if (!oldProps ||
50
- oldProps.onSelectionChanged !== newProps.onSelectionChanged ||
51
- oldProps.selectionMode !== newProps.selectionMode) {
52
- const onSelectionChanged = newProps.onSelectionChanged;
53
- this.handleSelectionChange = () => {
54
- onSelectionChanged?.(this.getSelection());
55
- };
56
- signalStore.set(this, this.selectionModel, "selection-changed", newProps.onSelectionChanged ? this.handleSelectionChange : null);
64
+ if (!oldProps || oldProps.onSelectionChanged !== newProps.onSelectionChanged) {
65
+ this.initSelectionHandler(newProps.onSelectionChanged);
57
66
  }
58
- if (!oldProps || oldProps.selected !== newProps.selected || oldProps.selectionMode !== newProps.selectionMode) {
67
+ if (!oldProps || oldProps.selected !== newProps.selected) {
59
68
  this.setSelection(newProps.selected);
60
69
  }
61
70
  }
@@ -29,6 +29,7 @@ export declare class Menu extends VirtualNode<MenuProps> {
29
29
  createAction(): void;
30
30
  private removeAction;
31
31
  private getPosition;
32
+ private findPositionIn;
32
33
  private setParent;
33
34
  getMenu(): Gio.Menu;
34
35
  private getAction;