@gtkx/react 0.19.0 → 0.21.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 (289) hide show
  1. package/README.md +26 -62
  2. package/dist/components/compound.d.ts +40 -0
  3. package/dist/components/compound.d.ts.map +1 -0
  4. package/dist/components/compound.js +46 -0
  5. package/dist/components/compound.js.map +1 -0
  6. package/dist/components/list.d.ts +75 -0
  7. package/dist/components/list.d.ts.map +1 -0
  8. package/dist/components/list.js +81 -0
  9. package/dist/components/list.js.map +1 -0
  10. package/dist/components/slot-widget.d.ts +15 -0
  11. package/dist/components/slot-widget.d.ts.map +1 -0
  12. package/dist/components/slot-widget.js +37 -0
  13. package/dist/components/slot-widget.js.map +1 -0
  14. package/dist/errors.d.ts +6 -0
  15. package/dist/errors.d.ts.map +1 -1
  16. package/dist/errors.js +8 -6
  17. package/dist/errors.js.map +1 -1
  18. package/dist/generated/compounds.d.ts +2672 -0
  19. package/dist/generated/compounds.d.ts.map +1 -0
  20. package/dist/generated/compounds.js +2624 -0
  21. package/dist/generated/compounds.js.map +1 -0
  22. package/dist/generated/internal.d.ts +6 -7
  23. package/dist/generated/internal.d.ts.map +1 -1
  24. package/dist/generated/internal.js +3054 -1838
  25. package/dist/generated/internal.js.map +1 -1
  26. package/dist/generated/jsx.d.ts +2096 -4970
  27. package/dist/generated/jsx.d.ts.map +1 -1
  28. package/dist/generated/jsx.js +979 -3862
  29. package/dist/generated/jsx.js.map +1 -1
  30. package/dist/generated/registry.d.ts +1 -0
  31. package/dist/generated/registry.d.ts.map +1 -1
  32. package/dist/generated/registry.js +0 -1
  33. package/dist/generated/registry.js.map +1 -1
  34. package/dist/host-config.d.ts.map +1 -1
  35. package/dist/host-config.js +2 -0
  36. package/dist/host-config.js.map +1 -1
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +2 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/jsx.d.ts +157 -518
  42. package/dist/jsx.d.ts.map +1 -1
  43. package/dist/jsx.js +6 -393
  44. package/dist/jsx.js.map +1 -1
  45. package/dist/metadata.d.ts +1 -1
  46. package/dist/metadata.d.ts.map +1 -1
  47. package/dist/metadata.js +7 -3
  48. package/dist/metadata.js.map +1 -1
  49. package/dist/node.d.ts +0 -4
  50. package/dist/node.d.ts.map +1 -1
  51. package/dist/node.js +19 -41
  52. package/dist/node.js.map +1 -1
  53. package/dist/nodes/alert-dialog.d.ts +14 -0
  54. package/dist/nodes/alert-dialog.d.ts.map +1 -0
  55. package/dist/nodes/alert-dialog.js +41 -0
  56. package/dist/nodes/alert-dialog.js.map +1 -0
  57. package/dist/nodes/animation.d.ts +5 -4
  58. package/dist/nodes/animation.d.ts.map +1 -1
  59. package/dist/nodes/animation.js +65 -49
  60. package/dist/nodes/animation.js.map +1 -1
  61. package/dist/nodes/application.d.ts.map +1 -1
  62. package/dist/nodes/application.js +4 -0
  63. package/dist/nodes/application.js.map +1 -1
  64. package/dist/nodes/column-view-column.d.ts +19 -19
  65. package/dist/nodes/column-view-column.d.ts.map +1 -1
  66. package/dist/nodes/column-view-column.js +130 -119
  67. package/dist/nodes/column-view-column.js.map +1 -1
  68. package/dist/nodes/container-slot.d.ts +3 -1
  69. package/dist/nodes/container-slot.d.ts.map +1 -1
  70. package/dist/nodes/container-slot.js +28 -16
  71. package/dist/nodes/container-slot.js.map +1 -1
  72. package/dist/nodes/drawing-area.d.ts +3 -1
  73. package/dist/nodes/drawing-area.d.ts.map +1 -1
  74. package/dist/nodes/drawing-area.js +20 -22
  75. package/dist/nodes/drawing-area.js.map +1 -1
  76. package/dist/nodes/event-controller.d.ts.map +1 -1
  77. package/dist/nodes/event-controller.js +6 -16
  78. package/dist/nodes/event-controller.js.map +1 -1
  79. package/dist/nodes/fixed-child.d.ts +1 -0
  80. package/dist/nodes/fixed-child.d.ts.map +1 -1
  81. package/dist/nodes/fixed-child.js +13 -0
  82. package/dist/nodes/fixed-child.js.map +1 -1
  83. package/dist/nodes/grid-child.d.ts +1 -0
  84. package/dist/nodes/grid-child.d.ts.map +1 -1
  85. package/dist/nodes/grid-child.js +13 -0
  86. package/dist/nodes/grid-child.js.map +1 -1
  87. package/dist/nodes/internal/accessible.d.ts.map +1 -1
  88. package/dist/nodes/internal/accessible.js.map +1 -1
  89. package/dist/nodes/internal/bound-item.d.ts +4 -0
  90. package/dist/nodes/internal/bound-item.d.ts.map +1 -0
  91. package/dist/nodes/internal/bound-item.js +2 -0
  92. package/dist/nodes/internal/bound-item.js.map +1 -0
  93. package/dist/nodes/internal/construct.d.ts +1 -8
  94. package/dist/nodes/internal/construct.d.ts.map +1 -1
  95. package/dist/nodes/internal/construct.js +30 -54
  96. package/dist/nodes/internal/construct.js.map +1 -1
  97. package/dist/nodes/internal/widget.d.ts.map +1 -1
  98. package/dist/nodes/internal/widget.js +9 -10
  99. package/dist/nodes/internal/widget.js.map +1 -1
  100. package/dist/nodes/list-item-node.d.ts +12 -0
  101. package/dist/nodes/list-item-node.d.ts.map +1 -0
  102. package/dist/nodes/list-item-node.js +45 -0
  103. package/dist/nodes/list-item-node.js.map +1 -0
  104. package/dist/nodes/list.d.ts +100 -0
  105. package/dist/nodes/list.d.ts.map +1 -0
  106. package/dist/nodes/list.js +950 -0
  107. package/dist/nodes/list.js.map +1 -0
  108. package/dist/nodes/notebook-page.d.ts.map +1 -1
  109. package/dist/nodes/notebook-page.js +6 -2
  110. package/dist/nodes/notebook-page.js.map +1 -1
  111. package/dist/nodes/overlay-child.d.ts +2 -0
  112. package/dist/nodes/overlay-child.d.ts.map +1 -1
  113. package/dist/nodes/overlay-child.js +29 -8
  114. package/dist/nodes/overlay-child.js.map +1 -1
  115. package/dist/nodes/spin-row.d.ts +14 -0
  116. package/dist/nodes/spin-row.d.ts.map +1 -0
  117. package/dist/nodes/spin-row.js +46 -0
  118. package/dist/nodes/spin-row.js.map +1 -0
  119. package/dist/nodes/switch-row.d.ts +11 -0
  120. package/dist/nodes/switch-row.d.ts.map +1 -0
  121. package/dist/nodes/switch-row.js +15 -0
  122. package/dist/nodes/switch-row.js.map +1 -0
  123. package/dist/nodes/text-anchor.d.ts.map +1 -1
  124. package/dist/nodes/text-anchor.js +10 -0
  125. package/dist/nodes/text-anchor.js.map +1 -1
  126. package/dist/nodes/text-tag.d.ts.map +1 -1
  127. package/dist/nodes/text-tag.js +45 -39
  128. package/dist/nodes/text-tag.js.map +1 -1
  129. package/dist/nodes/toggle-group.d.ts +12 -6
  130. package/dist/nodes/toggle-group.d.ts.map +1 -1
  131. package/dist/nodes/toggle-group.js +53 -4
  132. package/dist/nodes/toggle-group.js.map +1 -1
  133. package/dist/nodes/widget.d.ts.map +1 -1
  134. package/dist/nodes/widget.js +16 -22
  135. package/dist/nodes/widget.js.map +1 -1
  136. package/dist/nodes/window.d.ts.map +1 -1
  137. package/dist/nodes/window.js +2 -2
  138. package/dist/nodes/window.js.map +1 -1
  139. package/dist/registry.d.ts +0 -2
  140. package/dist/registry.d.ts.map +1 -1
  141. package/dist/registry.js +11 -18
  142. package/dist/registry.js.map +1 -1
  143. package/dist/types.d.ts +3 -2
  144. package/dist/types.d.ts.map +1 -1
  145. package/dist/use-property.d.ts +29 -0
  146. package/dist/use-property.d.ts.map +1 -0
  147. package/dist/use-property.js +44 -0
  148. package/dist/use-property.js.map +1 -0
  149. package/dist/use-setting.d.ts +36 -0
  150. package/dist/use-setting.d.ts.map +1 -0
  151. package/dist/use-setting.js +68 -0
  152. package/dist/use-setting.js.map +1 -0
  153. package/package.json +5 -4
  154. package/src/components/compound.tsx +57 -0
  155. package/src/components/list.tsx +140 -0
  156. package/src/components/slot-widget.tsx +46 -0
  157. package/src/errors.ts +8 -7
  158. package/src/generated/compounds.ts +2741 -0
  159. package/src/generated/internal.ts +3059 -1840
  160. package/src/generated/jsx.ts +2509 -5350
  161. package/src/generated/registry.ts +2 -1
  162. package/src/host-config.ts +2 -0
  163. package/src/index.ts +2 -0
  164. package/src/jsx.ts +167 -581
  165. package/src/metadata.ts +7 -4
  166. package/src/node.ts +23 -39
  167. package/src/nodes/alert-dialog.ts +55 -0
  168. package/src/nodes/animation.ts +67 -60
  169. package/src/nodes/application.ts +5 -0
  170. package/src/nodes/column-view-column.ts +125 -128
  171. package/src/nodes/container-slot.ts +30 -17
  172. package/src/nodes/drawing-area.ts +23 -32
  173. package/src/nodes/event-controller.ts +6 -18
  174. package/src/nodes/fixed-child.ts +13 -0
  175. package/src/nodes/grid-child.ts +13 -0
  176. package/src/nodes/internal/accessible.ts +0 -1
  177. package/src/nodes/internal/bound-item.ts +4 -0
  178. package/src/nodes/internal/construct.ts +38 -68
  179. package/src/nodes/internal/widget.ts +9 -13
  180. package/src/nodes/list-item-node.ts +53 -0
  181. package/src/nodes/list.ts +1082 -0
  182. package/src/nodes/notebook-page.ts +6 -2
  183. package/src/nodes/overlay-child.ts +30 -9
  184. package/src/nodes/spin-row.ts +72 -0
  185. package/src/nodes/switch-row.ts +26 -0
  186. package/src/nodes/text-anchor.ts +9 -0
  187. package/src/nodes/text-tag.ts +45 -40
  188. package/src/nodes/toggle-group.ts +63 -9
  189. package/src/nodes/widget.ts +14 -26
  190. package/src/nodes/window.ts +2 -2
  191. package/src/registry.ts +18 -24
  192. package/src/types.ts +8 -2
  193. package/src/use-property.ts +58 -0
  194. package/src/use-setting.ts +96 -0
  195. package/dist/fiber-root.d.ts +0 -4
  196. package/dist/fiber-root.d.ts.map +0 -1
  197. package/dist/fiber-root.js +0 -6
  198. package/dist/fiber-root.js.map +0 -1
  199. package/dist/nodes/column-view.d.ts +0 -37
  200. package/dist/nodes/column-view.d.ts.map +0 -1
  201. package/dist/nodes/column-view.js +0 -205
  202. package/dist/nodes/column-view.js.map +0 -1
  203. package/dist/nodes/drop-down.d.ts +0 -37
  204. package/dist/nodes/drop-down.d.ts.map +0 -1
  205. package/dist/nodes/drop-down.js +0 -231
  206. package/dist/nodes/drop-down.js.map +0 -1
  207. package/dist/nodes/grid-view.d.ts +0 -30
  208. package/dist/nodes/grid-view.d.ts.map +0 -1
  209. package/dist/nodes/grid-view.js +0 -90
  210. package/dist/nodes/grid-view.js.map +0 -1
  211. package/dist/nodes/internal/base-item-renderer.d.ts +0 -28
  212. package/dist/nodes/internal/base-item-renderer.d.ts.map +0 -1
  213. package/dist/nodes/internal/base-item-renderer.js +0 -85
  214. package/dist/nodes/internal/base-item-renderer.js.map +0 -1
  215. package/dist/nodes/internal/grid-item-renderer.d.ts +0 -20
  216. package/dist/nodes/internal/grid-item-renderer.d.ts.map +0 -1
  217. package/dist/nodes/internal/grid-item-renderer.js +0 -66
  218. package/dist/nodes/internal/grid-item-renderer.js.map +0 -1
  219. package/dist/nodes/internal/header-item-renderer.d.ts +0 -23
  220. package/dist/nodes/internal/header-item-renderer.d.ts.map +0 -1
  221. package/dist/nodes/internal/header-item-renderer.js +0 -87
  222. package/dist/nodes/internal/header-item-renderer.js.map +0 -1
  223. package/dist/nodes/internal/header-renderer-manager.d.ts +0 -13
  224. package/dist/nodes/internal/header-renderer-manager.d.ts.map +0 -1
  225. package/dist/nodes/internal/header-renderer-manager.js +0 -20
  226. package/dist/nodes/internal/header-renderer-manager.js.map +0 -1
  227. package/dist/nodes/internal/list-item-renderer.d.ts +0 -27
  228. package/dist/nodes/internal/list-item-renderer.d.ts.map +0 -1
  229. package/dist/nodes/internal/list-item-renderer.js +0 -131
  230. package/dist/nodes/internal/list-item-renderer.js.map +0 -1
  231. package/dist/nodes/internal/list-store.d.ts +0 -21
  232. package/dist/nodes/internal/list-store.d.ts.map +0 -1
  233. package/dist/nodes/internal/list-store.js +0 -90
  234. package/dist/nodes/internal/list-store.js.map +0 -1
  235. package/dist/nodes/internal/sectioned-list-store.d.ts +0 -50
  236. package/dist/nodes/internal/sectioned-list-store.d.ts.map +0 -1
  237. package/dist/nodes/internal/sectioned-list-store.js +0 -250
  238. package/dist/nodes/internal/sectioned-list-store.js.map +0 -1
  239. package/dist/nodes/internal/selection-helpers.d.ts +0 -12
  240. package/dist/nodes/internal/selection-helpers.d.ts.map +0 -1
  241. package/dist/nodes/internal/selection-helpers.js +0 -25
  242. package/dist/nodes/internal/selection-helpers.js.map +0 -1
  243. package/dist/nodes/internal/selection-model-controller.d.ts +0 -26
  244. package/dist/nodes/internal/selection-model-controller.d.ts.map +0 -1
  245. package/dist/nodes/internal/selection-model-controller.js +0 -82
  246. package/dist/nodes/internal/selection-model-controller.js.map +0 -1
  247. package/dist/nodes/internal/simple-list-store.d.ts +0 -15
  248. package/dist/nodes/internal/simple-list-store.d.ts.map +0 -1
  249. package/dist/nodes/internal/simple-list-store.js +0 -110
  250. package/dist/nodes/internal/simple-list-store.js.map +0 -1
  251. package/dist/nodes/internal/tree-store.d.ts +0 -37
  252. package/dist/nodes/internal/tree-store.d.ts.map +0 -1
  253. package/dist/nodes/internal/tree-store.js +0 -253
  254. package/dist/nodes/internal/tree-store.js.map +0 -1
  255. package/dist/nodes/list-item.d.ts +0 -24
  256. package/dist/nodes/list-item.d.ts.map +0 -1
  257. package/dist/nodes/list-item.js +0 -83
  258. package/dist/nodes/list-item.js.map +0 -1
  259. package/dist/nodes/list-section.d.ts +0 -27
  260. package/dist/nodes/list-section.d.ts.map +0 -1
  261. package/dist/nodes/list-section.js +0 -43
  262. package/dist/nodes/list-section.js.map +0 -1
  263. package/dist/nodes/list-view.d.ts +0 -32
  264. package/dist/nodes/list-view.d.ts.map +0 -1
  265. package/dist/nodes/list-view.js +0 -123
  266. package/dist/nodes/list-view.js.map +0 -1
  267. package/dist/nodes/models/list.d.ts +0 -39
  268. package/dist/nodes/models/list.d.ts.map +0 -1
  269. package/dist/nodes/models/list.js +0 -207
  270. package/dist/nodes/models/list.js.map +0 -1
  271. package/src/fiber-root.ts +0 -20
  272. package/src/nodes/column-view.ts +0 -262
  273. package/src/nodes/drop-down.ts +0 -284
  274. package/src/nodes/grid-view.ts +0 -119
  275. package/src/nodes/internal/base-item-renderer.ts +0 -107
  276. package/src/nodes/internal/grid-item-renderer.ts +0 -78
  277. package/src/nodes/internal/header-item-renderer.ts +0 -105
  278. package/src/nodes/internal/header-renderer-manager.ts +0 -33
  279. package/src/nodes/internal/list-item-renderer.ts +0 -162
  280. package/src/nodes/internal/list-store.ts +0 -107
  281. package/src/nodes/internal/sectioned-list-store.ts +0 -287
  282. package/src/nodes/internal/selection-helpers.ts +0 -35
  283. package/src/nodes/internal/selection-model-controller.ts +0 -119
  284. package/src/nodes/internal/simple-list-store.ts +0 -116
  285. package/src/nodes/internal/tree-store.ts +0 -289
  286. package/src/nodes/list-item.ts +0 -107
  287. package/src/nodes/list-section.ts +0 -64
  288. package/src/nodes/list-view.ts +0 -164
  289. package/src/nodes/models/list.ts +0 -250
@@ -1,284 +0,0 @@
1
- import * as Gtk from "@gtkx/ffi/gtk";
2
- import type { ReactNode } from "react";
3
- import type Reconciler from "react-reconciler";
4
- import { createFiberRoot } from "../fiber-root.js";
5
- import type { AdwComboRowProps, GtkDropDownProps } from "../jsx.js";
6
- import type { Node } from "../node.js";
7
- import { reconciler } from "../reconciler.js";
8
- import type { DropDownWidget } from "../registry.js";
9
- import type { Container } from "../types.js";
10
- import { ContainerSlotNode } from "./container-slot.js";
11
- import { EventControllerNode } from "./event-controller.js";
12
- import type { HeaderItemRenderer } from "./internal/header-item-renderer.js";
13
- import { updateHeaderRenderer } from "./internal/header-renderer-manager.js";
14
- import { filterProps, hasChanged } from "./internal/props.js";
15
- import { SimpleListStore } from "./internal/simple-list-store.js";
16
- import { ListItemNode } from "./list-item.js";
17
- import { ListSectionNode } from "./list-section.js";
18
- import { SlotNode } from "./slot.js";
19
- import { WidgetNode } from "./widget.js";
20
-
21
- const OWN_PROPS = ["selectedId", "onSelectionChanged", "renderItem", "renderListItem", "renderHeader"] as const;
22
-
23
- type DropDownProps = Pick<GtkDropDownProps | AdwComboRowProps, (typeof OWN_PROPS)[number]>;
24
-
25
- type DropDownChild = ListItemNode | ListSectionNode | EventControllerNode | SlotNode | ContainerSlotNode;
26
-
27
- type RenderItemFn = (item: string | null) => ReactNode;
28
-
29
- interface FactoryState {
30
- factory: Gtk.SignalListItemFactory;
31
- fiberRoots: Map<object, Reconciler.FiberRoot>;
32
- tornDown: Set<object>;
33
- boundLabels: Map<string, object>;
34
- }
35
-
36
- export class DropDownNode extends WidgetNode<DropDownWidget, DropDownProps, DropDownChild> {
37
- private store = new SimpleListStore();
38
- private initialSelectedId: string | null | undefined;
39
-
40
- private itemState: FactoryState | null = null;
41
- private renderItemFn: RenderItemFn | null = null;
42
-
43
- private listItemState: FactoryState | null = null;
44
- private renderListItemFn: RenderItemFn | null = null;
45
-
46
- private headerRenderer: HeaderItemRenderer | null = null;
47
-
48
- public override isValidChild(child: Node): boolean {
49
- return (
50
- child instanceof ListItemNode ||
51
- child instanceof ListSectionNode ||
52
- child instanceof EventControllerNode ||
53
- child instanceof SlotNode ||
54
- child instanceof ContainerSlotNode
55
- );
56
- }
57
-
58
- constructor(typeName: string, props: DropDownProps, container: DropDownWidget, rootContainer: Container) {
59
- super(typeName, props, container, rootContainer);
60
- this.store.beginBatch();
61
- this.initialSelectedId = props.selectedId;
62
- }
63
-
64
- public override finalizeInitialChildren(props: DropDownProps): boolean {
65
- super.finalizeInitialChildren(props);
66
- this.store.flushBatch();
67
- this.container.setModel(this.store.getModel());
68
- this.reapplyInitialSelectedId();
69
- return false;
70
- }
71
-
72
- private reapplyInitialSelectedId(): void {
73
- if (this.initialSelectedId == null) return;
74
- const index = this.store.getIndexById(this.initialSelectedId);
75
- this.initialSelectedId = undefined;
76
- if (index !== null) {
77
- this.container.setSelected(index);
78
- }
79
- }
80
-
81
- public override appendChild(child: DropDownChild): void {
82
- super.appendChild(child);
83
- if (child instanceof ListSectionNode) {
84
- this.store.addSection(child.props.id, child.props.value);
85
- child.setStore(this.store);
86
- } else if (child instanceof ListItemNode) {
87
- child.setStore(this.store);
88
- this.store.addItem(child.props.id, child.props.value as string);
89
- }
90
- }
91
-
92
- public override insertBefore(child: DropDownChild, before: DropDownChild): void {
93
- super.insertBefore(child, before);
94
- if (child instanceof ListSectionNode) {
95
- this.store.addSection(child.props.id, child.props.value);
96
- child.setStore(this.store);
97
- } else if (child instanceof ListItemNode && before instanceof ListItemNode) {
98
- child.setStore(this.store);
99
- this.store.insertItemBefore(child.props.id, before.props.id, child.props.value as string);
100
- } else if (child instanceof ListItemNode) {
101
- child.setStore(this.store);
102
- this.store.addItem(child.props.id, child.props.value as string);
103
- }
104
- }
105
-
106
- public override removeChild(child: DropDownChild): void {
107
- if (child instanceof ListSectionNode) {
108
- this.store.removeSection(child.props.id);
109
- child.setStore(null);
110
- } else if (child instanceof ListItemNode) {
111
- this.store.removeItem(child.props.id);
112
- child.setStore(null);
113
- }
114
- super.removeChild(child);
115
- }
116
-
117
- public override commitUpdate(oldProps: DropDownProps | null, newProps: DropDownProps): void {
118
- super.commitUpdate(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
119
- this.applyOwnProps(oldProps, newProps);
120
- }
121
-
122
- public override detachDeletedInstance(): void {
123
- this.disposeFactory(this.itemState);
124
- this.itemState = null;
125
- this.disposeFactory(this.listItemState);
126
- this.listItemState = null;
127
- this.headerRenderer?.dispose();
128
- super.detachDeletedInstance();
129
- }
130
-
131
- private applyOwnProps(oldProps: DropDownProps | null, newProps: DropDownProps): void {
132
- if (hasChanged(oldProps, newProps, "onSelectionChanged")) {
133
- const onSelectionChanged = newProps.onSelectionChanged;
134
-
135
- const handleSelectionChange = onSelectionChanged
136
- ? () => {
137
- const selectedIndex = this.container.getSelected();
138
- const id = this.store.getIdAtIndex(selectedIndex);
139
- if (id !== null) {
140
- onSelectionChanged(id);
141
- }
142
- }
143
- : undefined;
144
-
145
- this.signalStore.set(this, this.container, "notify::selected", handleSelectionChange);
146
- }
147
-
148
- if (hasChanged(oldProps, newProps, "selectedId")) {
149
- const index = newProps.selectedId != null ? this.store.getIndexById(newProps.selectedId) : null;
150
-
151
- if (index !== null) {
152
- this.container.setSelected(index);
153
- }
154
- }
155
-
156
- if (hasChanged(oldProps, newProps, "renderItem")) {
157
- if (newProps.renderItem) {
158
- if (!this.itemState) {
159
- this.itemState = this.createFactory(
160
- () => this.renderItemFn,
161
- (f) => this.container.setFactory(f),
162
- );
163
- }
164
- this.renderItemFn = newProps.renderItem;
165
- this.rebindAll(this.itemState, this.renderItemFn);
166
- } else if (this.itemState) {
167
- this.disposeFactory(this.itemState);
168
- this.itemState = null;
169
- this.container.setFactory(null);
170
- this.renderItemFn = null;
171
- }
172
- }
173
-
174
- if (hasChanged(oldProps, newProps, "renderListItem")) {
175
- if (newProps.renderListItem) {
176
- if (!this.listItemState) {
177
- this.listItemState = this.createFactory(
178
- () => this.renderListItemFn,
179
- (f) => this.container.setListFactory(f),
180
- );
181
- }
182
- this.renderListItemFn = newProps.renderListItem;
183
- this.rebindAll(this.listItemState, this.renderListItemFn);
184
- } else if (this.listItemState) {
185
- this.disposeFactory(this.listItemState);
186
- this.listItemState = null;
187
- this.container.setListFactory(null);
188
- this.renderListItemFn = null;
189
- }
190
- }
191
-
192
- if (hasChanged(oldProps, newProps, "renderHeader")) {
193
- this.headerRenderer = updateHeaderRenderer(
194
- this.headerRenderer,
195
- {
196
- signalStore: this.signalStore,
197
- isEnabled: () => this.store.isSectioned(),
198
- resolveItem: (label) => this.store.getHeaderValueByLabel(label),
199
- setFactory: (factory) => this.container.setHeaderFactory(factory),
200
- },
201
- newProps.renderHeader,
202
- );
203
- }
204
- }
205
-
206
- private createFactory(
207
- getRenderFn: () => RenderItemFn | null,
208
- applyFactory: (factory: Gtk.SignalListItemFactory) => void,
209
- ): FactoryState {
210
- const state: FactoryState = {
211
- factory: new Gtk.SignalListItemFactory(),
212
- fiberRoots: new Map(),
213
- tornDown: new Set(),
214
- boundLabels: new Map(),
215
- };
216
-
217
- this.signalStore.set(this, state.factory, "setup", (listItem: Gtk.ListItem) => {
218
- const box = new Gtk.Box(Gtk.Orientation.HORIZONTAL);
219
- box.setValign(Gtk.Align.CENTER);
220
- listItem.setChild(box);
221
- const fiberRoot = createFiberRoot(box);
222
- state.fiberRoots.set(listItem, fiberRoot);
223
- const element = getRenderFn()?.(null);
224
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {});
225
- });
226
-
227
- this.signalStore.set(this, state.factory, "bind", (listItem: Gtk.ListItem) => {
228
- const fiberRoot = state.fiberRoots.get(listItem);
229
- if (!fiberRoot) return;
230
- const stringObject = listItem.getItem();
231
- const label = stringObject instanceof Gtk.StringObject ? stringObject.getString() : null;
232
- if (label !== null) state.boundLabels.set(label, listItem);
233
- const element = getRenderFn()?.(label);
234
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {});
235
- });
236
-
237
- this.signalStore.set(this, state.factory, "unbind", (listItem: Gtk.ListItem) => {
238
- const stringObject = listItem.getItem();
239
- if (stringObject instanceof Gtk.StringObject) {
240
- state.boundLabels.delete(stringObject.getString());
241
- }
242
- });
243
-
244
- this.signalStore.set(this, state.factory, "teardown", (listItem: Gtk.ListItem) => {
245
- const fiberRoot = state.fiberRoots.get(listItem);
246
- if (fiberRoot) {
247
- state.tornDown.add(listItem);
248
- reconciler.getInstance().updateContainer(null, fiberRoot, null, () => {});
249
- queueMicrotask(() => {
250
- state.fiberRoots.delete(listItem);
251
- state.tornDown.delete(listItem);
252
- });
253
- }
254
- });
255
-
256
- applyFactory(state.factory);
257
- return state;
258
- }
259
-
260
- private rebindAll(state: FactoryState, renderFn: RenderItemFn): void {
261
- for (const [label, listItem] of state.boundLabels) {
262
- const fiberRoot = state.fiberRoots.get(listItem);
263
- if (!fiberRoot) continue;
264
- const element = renderFn(label);
265
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {});
266
- }
267
- }
268
-
269
- private disposeFactory(state: FactoryState | null): void {
270
- if (!state) return;
271
- this.signalStore.set(this, state.factory, "setup", undefined);
272
- this.signalStore.set(this, state.factory, "bind", undefined);
273
- this.signalStore.set(this, state.factory, "unbind", undefined);
274
- this.signalStore.set(this, state.factory, "teardown", undefined);
275
- for (const [listItem, fiberRoot] of state.fiberRoots) {
276
- if (!state.tornDown.has(listItem)) {
277
- reconciler.getInstance().updateContainer(null, fiberRoot, null, () => {});
278
- }
279
- }
280
- state.fiberRoots.clear();
281
- state.tornDown.clear();
282
- state.boundLabels.clear();
283
- }
284
- }
@@ -1,119 +0,0 @@
1
- import type * as Gtk from "@gtkx/ffi/gtk";
2
- import type { GtkGridViewProps } from "../jsx.js";
3
- import type { Node } from "../node.js";
4
- import type { Container } from "../types.js";
5
- import { ContainerSlotNode } from "./container-slot.js";
6
- import { EventControllerNode } from "./event-controller.js";
7
- import { GridItemRenderer } from "./internal/grid-item-renderer.js";
8
- import { filterProps, hasChanged } from "./internal/props.js";
9
- import { ListItemNode } from "./list-item.js";
10
- import { ListSectionNode } from "./list-section.js";
11
- import { ListModel, type ListModelProps } from "./models/list.js";
12
- import { SlotNode } from "./slot.js";
13
- import { WidgetNode } from "./widget.js";
14
-
15
- const RENDERER_PROPS = ["renderItem", "estimatedItemHeight"] as const;
16
- const OWN_PROPS = [...RENDERER_PROPS, "selectionMode", "selected", "onSelectionChanged"] as const;
17
-
18
- type GridViewProps = Pick<GtkGridViewProps, (typeof RENDERER_PROPS)[number]> & ListModelProps;
19
-
20
- type GridViewChild = ListItemNode | ListSectionNode | EventControllerNode | SlotNode | ContainerSlotNode;
21
-
22
- export class GridViewNode extends WidgetNode<Gtk.GridView, GridViewProps, GridViewChild> {
23
- private itemRenderer: GridItemRenderer;
24
- private list: ListModel;
25
-
26
- constructor(typeName: string, props: GridViewProps, container: Gtk.GridView, rootContainer: Container) {
27
- super(typeName, props, container, rootContainer);
28
- this.list = new ListModel(
29
- { owner: this, signalStore: this.signalStore },
30
- {
31
- selectionMode: props.selectionMode,
32
- selected: props.selected,
33
- onSelectionChanged: props.onSelectionChanged,
34
- },
35
- true,
36
- );
37
- this.itemRenderer = new GridItemRenderer(this.signalStore);
38
- this.itemRenderer.setStore(this.list.getFlatStore());
39
- this.list.setOnItemUpdated((id) => this.itemRenderer.rebindItem(id));
40
- this.container.setFactory(this.itemRenderer.getFactory());
41
- }
42
-
43
- public override isValidChild(child: Node): boolean {
44
- if (child instanceof EventControllerNode || child instanceof SlotNode || child instanceof ContainerSlotNode)
45
- return true;
46
- if (child instanceof ListSectionNode) return true;
47
- if (!(child instanceof ListItemNode)) return false;
48
- if (child.getChildNodes().length > 0) {
49
- throw new Error("GtkGridView does not support nested ListItems. Use GtkListView for tree lists.");
50
- }
51
- return true;
52
- }
53
-
54
- public override appendChild(child: GridViewChild): void {
55
- super.appendChild(child);
56
- if (child instanceof ListItemNode || child instanceof ListSectionNode) {
57
- this.list.appendChild(child);
58
- }
59
- }
60
-
61
- public override insertBefore(child: GridViewChild, before: GridViewChild): void {
62
- super.insertBefore(child, before);
63
- if (
64
- (child instanceof ListItemNode || child instanceof ListSectionNode) &&
65
- (before instanceof ListItemNode || before instanceof ListSectionNode)
66
- ) {
67
- this.list.insertBefore(child, before);
68
- }
69
- }
70
-
71
- public override removeChild(child: GridViewChild): void {
72
- if (child instanceof ListItemNode || child instanceof ListSectionNode) {
73
- this.list.removeChild(child);
74
- }
75
- super.removeChild(child);
76
- }
77
-
78
- public override finalizeInitialChildren(props: GridViewProps): boolean {
79
- super.finalizeInitialChildren(props);
80
- return true;
81
- }
82
-
83
- public override commitUpdate(oldProps: GridViewProps | null, newProps: GridViewProps): void {
84
- super.commitUpdate(oldProps ? filterProps(oldProps, OWN_PROPS) : null, filterProps(newProps, OWN_PROPS));
85
- this.applyOwnProps(oldProps, newProps);
86
- }
87
-
88
- public override commitMount(): void {
89
- super.commitMount();
90
- this.list.flushBatch();
91
- this.container.setModel(this.list.getSelectionModel());
92
- }
93
-
94
- public override detachDeletedInstance(): void {
95
- this.itemRenderer.dispose();
96
- super.detachDeletedInstance();
97
- }
98
-
99
- private applyOwnProps(oldProps: GridViewProps | null, newProps: GridViewProps): void {
100
- if (hasChanged(oldProps, newProps, "renderItem")) {
101
- this.itemRenderer.setRenderFn(newProps.renderItem ?? null);
102
- }
103
-
104
- if (hasChanged(oldProps, newProps, "estimatedItemHeight")) {
105
- this.itemRenderer.setEstimatedItemHeight(newProps.estimatedItemHeight ?? null);
106
- }
107
-
108
- const previousModel = this.list.getSelectionModel();
109
- this.list.updateProps(
110
- oldProps ? filterProps(oldProps, RENDERER_PROPS) : null,
111
- filterProps(newProps, RENDERER_PROPS),
112
- );
113
- const currentModel = this.list.getSelectionModel();
114
-
115
- if (previousModel !== currentModel) {
116
- this.container.setModel(currentModel);
117
- }
118
- }
119
- }
@@ -1,107 +0,0 @@
1
- import * as Gtk from "@gtkx/ffi/gtk";
2
- import type { ReactNode } from "react";
3
- import type Reconciler from "react-reconciler";
4
- import { createFiberRoot } from "../../fiber-root.js";
5
- import { reconciler } from "../../reconciler.js";
6
- import type { SignalStore } from "./signal-store.js";
7
-
8
- export abstract class BaseItemRenderer<TStore = unknown> {
9
- protected factory: Gtk.SignalListItemFactory;
10
- protected fiberRoots = new Map<Gtk.ListItem, Reconciler.FiberRoot>();
11
- protected tornDown = new Set<Gtk.ListItem>();
12
- protected estimatedItemHeight: number | null = null;
13
- private store: TStore | null = null;
14
- protected signalStore: SignalStore;
15
-
16
- constructor(signalStore: SignalStore) {
17
- this.signalStore = signalStore;
18
- this.factory = new Gtk.SignalListItemFactory();
19
- this.initializeFactory();
20
- }
21
-
22
- public getFactory(): Gtk.SignalListItemFactory {
23
- return this.factory;
24
- }
25
-
26
- public setEstimatedItemHeight(height: number | null): void {
27
- this.estimatedItemHeight = height;
28
- }
29
-
30
- public setStore(store: TStore | null): void {
31
- this.store = store;
32
- }
33
-
34
- protected getStore(): TStore {
35
- if (!this.store) {
36
- throw new Error(`Expected store to be set on ${this.constructor.name}`);
37
- }
38
- return this.store;
39
- }
40
-
41
- public dispose(): void {
42
- this.signalStore.clear(this);
43
- this.fiberRoots.clear();
44
- this.tornDown.clear();
45
- }
46
-
47
- protected abstract renderItem(listItem: Gtk.ListItem): ReactNode;
48
- protected abstract onSetup(listItem: Gtk.ListItem): Gtk.Widget;
49
- protected abstract onBind(listItem: Gtk.ListItem, fiberRoot: Reconciler.FiberRoot): void;
50
- protected abstract onUnbind(listItem: Gtk.ListItem): void;
51
-
52
- protected onSetupComplete(_listItem: Gtk.ListItem): void {}
53
- protected onTeardown(_listItem: Gtk.ListItem): void {}
54
-
55
- protected createBox(): Gtk.Box {
56
- const box = new Gtk.Box(Gtk.Orientation.HORIZONTAL);
57
-
58
- if (this.estimatedItemHeight !== null) {
59
- box.setSizeRequest(-1, this.estimatedItemHeight);
60
- }
61
-
62
- return box;
63
- }
64
-
65
- protected clearBoxSizeRequest(box: Gtk.Widget): void {
66
- if (box instanceof Gtk.Box) {
67
- box.setSizeRequest(-1, -1);
68
- }
69
- }
70
-
71
- private initializeFactory(): void {
72
- this.signalStore.set(this, this.factory, "setup", (listItem: Gtk.ListItem) => {
73
- const container = this.onSetup(listItem);
74
- const fiberRoot = createFiberRoot(container);
75
- this.fiberRoots.set(listItem, fiberRoot);
76
- const element = this.renderItem(listItem);
77
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {
78
- if (this.tornDown.has(listItem)) return;
79
- this.onSetupComplete(listItem);
80
- });
81
- });
82
-
83
- this.signalStore.set(this, this.factory, "bind", (listItem: Gtk.ListItem) => {
84
- const fiberRoot = this.fiberRoots.get(listItem);
85
- if (!fiberRoot) return;
86
- this.onBind(listItem, fiberRoot);
87
- });
88
-
89
- this.signalStore.set(this, this.factory, "unbind", (listItem: Gtk.ListItem) => {
90
- this.onUnbind(listItem);
91
- });
92
-
93
- this.signalStore.set(this, this.factory, "teardown", (listItem: Gtk.ListItem) => {
94
- const fiberRoot = this.fiberRoots.get(listItem);
95
-
96
- if (fiberRoot) {
97
- this.tornDown.add(listItem);
98
- this.onTeardown(listItem);
99
- reconciler.getInstance().updateContainer(null, fiberRoot, null, () => {});
100
- queueMicrotask(() => {
101
- this.fiberRoots.delete(listItem);
102
- this.tornDown.delete(listItem);
103
- });
104
- }
105
- });
106
- }
107
- }
@@ -1,78 +0,0 @@
1
- import * as Gtk from "@gtkx/ffi/gtk";
2
- import type { ReactNode } from "react";
3
- import type Reconciler from "react-reconciler";
4
- import { reconciler } from "../../reconciler.js";
5
- import { BaseItemRenderer } from "./base-item-renderer.js";
6
- import type { ListStore } from "./list-store.js";
7
-
8
- type GridRenderItemFn<T> = (item: T | null) => ReactNode;
9
-
10
- export class GridItemRenderer extends BaseItemRenderer<ListStore> {
11
- private renderFn: GridRenderItemFn<unknown> | null = () => null;
12
- private boundItems = new Map<string, Gtk.ListItem>();
13
-
14
- public setRenderFn(renderFn: GridRenderItemFn<unknown> | null): void {
15
- this.renderFn = renderFn;
16
- this.rebindAllItems();
17
- }
18
-
19
- public rebindAllItems(): void {
20
- for (const id of this.boundItems.keys()) {
21
- this.rebindItem(id);
22
- }
23
- }
24
-
25
- public rebindItem(id: string): void {
26
- const listItem = this.boundItems.get(id);
27
- if (!listItem) return;
28
-
29
- const fiberRoot = this.fiberRoots.get(listItem);
30
- if (!fiberRoot) return;
31
-
32
- const item = this.getStore().getItem(id);
33
- const element = this.renderFn?.(item);
34
-
35
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {});
36
- }
37
-
38
- protected override renderItem(_listItem: Gtk.ListItem): ReactNode {
39
- return this.renderFn?.(null);
40
- }
41
-
42
- private getItemFromListItem(listItem: Gtk.ListItem): string | null {
43
- const stringObject = listItem.getItem();
44
- if (!(stringObject instanceof Gtk.StringObject)) return null;
45
- return stringObject.getString();
46
- }
47
-
48
- protected override onSetup(listItem: Gtk.ListItem): Gtk.Widget {
49
- const box = this.createBox();
50
- listItem.setChild(box);
51
- return box;
52
- }
53
-
54
- protected override onBind(listItem: Gtk.ListItem, fiberRoot: Reconciler.FiberRoot): void {
55
- const id = this.getItemFromListItem(listItem);
56
- if (id !== null) {
57
- this.boundItems.set(id, listItem);
58
- }
59
-
60
- const item = id !== null ? this.getStore().getItem(id) : null;
61
- const element = this.renderFn?.(item);
62
-
63
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {
64
- if (this.tornDown.has(listItem)) return;
65
- if (this.estimatedItemHeight !== null) return;
66
- const currentFiberRoot = this.fiberRoots.get(listItem);
67
- if (!currentFiberRoot) return;
68
- this.clearBoxSizeRequest(currentFiberRoot.containerInfo);
69
- });
70
- }
71
-
72
- protected override onUnbind(listItem: Gtk.ListItem): void {
73
- const id = this.getItemFromListItem(listItem);
74
- if (id !== null) {
75
- this.boundItems.delete(id);
76
- }
77
- }
78
- }
@@ -1,105 +0,0 @@
1
- import * as Gtk from "@gtkx/ffi/gtk";
2
- import type { ReactNode } from "react";
3
- import type Reconciler from "react-reconciler";
4
- import { createFiberRoot } from "../../fiber-root.js";
5
- import { reconciler } from "../../reconciler.js";
6
- import type { SignalStore } from "./signal-store.js";
7
-
8
- type RenderHeaderFn = (item: unknown) => ReactNode;
9
-
10
- type ItemResolver = (id: string) => unknown;
11
-
12
- export class HeaderItemRenderer {
13
- private factory: Gtk.SignalListItemFactory;
14
- private fiberRoots = new Map<object, Reconciler.FiberRoot>();
15
- private tornDown = new Set<object>();
16
- private renderFn: RenderHeaderFn | null = () => null;
17
- private boundHeaders = new Map<string, object>();
18
- private signalStore: SignalStore;
19
- private resolveItem: ItemResolver | null = null;
20
-
21
- constructor(signalStore: SignalStore) {
22
- this.signalStore = signalStore;
23
- this.factory = new Gtk.SignalListItemFactory();
24
- this.initializeFactory();
25
- }
26
-
27
- public getFactory(): Gtk.SignalListItemFactory {
28
- return this.factory;
29
- }
30
-
31
- public setResolveItem(resolver: ItemResolver | null): void {
32
- this.resolveItem = resolver;
33
- }
34
-
35
- public setRenderFn(renderFn: RenderHeaderFn | null): void {
36
- this.renderFn = renderFn;
37
- this.rebindAllHeaders();
38
- }
39
-
40
- public dispose(): void {
41
- this.signalStore.clear(this);
42
- this.fiberRoots.clear();
43
- this.tornDown.clear();
44
- this.boundHeaders.clear();
45
- }
46
-
47
- private rebindAllHeaders(): void {
48
- for (const [id, header] of this.boundHeaders) {
49
- const fiberRoot = this.fiberRoots.get(header);
50
- if (!fiberRoot) continue;
51
- const item = this.resolveItem?.(id) ?? null;
52
- const element = this.renderFn?.(item);
53
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {});
54
- }
55
- }
56
-
57
- private initializeFactory(): void {
58
- this.signalStore.set(this, this.factory, "setup", (listHeader: Gtk.ListHeader) => {
59
- const box = new Gtk.Box(Gtk.Orientation.HORIZONTAL);
60
- listHeader.setChild(box);
61
- const fiberRoot = createFiberRoot(box);
62
- this.fiberRoots.set(listHeader, fiberRoot);
63
- const element = this.renderFn?.(null);
64
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {});
65
- });
66
-
67
- this.signalStore.set(this, this.factory, "bind", (listHeader: Gtk.ListHeader) => {
68
- const fiberRoot = this.fiberRoots.get(listHeader);
69
- if (!fiberRoot) return;
70
-
71
- const stringObject = listHeader.getItem();
72
- let id: string | null = null;
73
- if (stringObject instanceof Gtk.StringObject) {
74
- id = stringObject.getString();
75
- }
76
-
77
- if (id !== null) {
78
- this.boundHeaders.set(id, listHeader);
79
- }
80
-
81
- const item = id !== null && this.resolveItem ? this.resolveItem(id) : null;
82
- const element = this.renderFn?.(item);
83
- reconciler.getInstance().updateContainer(element, fiberRoot, null, () => {});
84
- });
85
-
86
- this.signalStore.set(this, this.factory, "unbind", (listHeader: Gtk.ListHeader) => {
87
- const stringObject = listHeader.getItem();
88
- if (stringObject instanceof Gtk.StringObject) {
89
- this.boundHeaders.delete(stringObject.getString());
90
- }
91
- });
92
-
93
- this.signalStore.set(this, this.factory, "teardown", (listHeader: Gtk.ListHeader) => {
94
- const fiberRoot = this.fiberRoots.get(listHeader);
95
- if (fiberRoot) {
96
- this.tornDown.add(listHeader);
97
- reconciler.getInstance().updateContainer(null, fiberRoot, null, () => {});
98
- queueMicrotask(() => {
99
- this.fiberRoots.delete(listHeader);
100
- this.tornDown.delete(listHeader);
101
- });
102
- }
103
- });
104
- }
105
- }