@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,90 +1,60 @@
1
- import { type Arg, call, type NativeHandle, registerNativeObject, setInstantiating, type Type } from "@gtkx/ffi";
2
- import { typeFromName } from "@gtkx/ffi/gobject";
3
- import { CONSTRUCT_ONLY_PROPS, CONSTRUCTOR_PROPS } from "../../generated/internal.js";
1
+ import type { NativeClass, Type } from "@gtkx/ffi";
2
+ import { Object as GObject, Value } from "@gtkx/ffi/gobject";
3
+ import { CONSTRUCTION_META } from "../../generated/internal.js";
4
4
  import type { Container, ContainerClass, Props } from "../../types.js";
5
5
 
6
- type ConstructOnlyPropInfo = { girName: string; ffiType: Type };
6
+ type ConstructionPropMeta = {
7
+ girName: string;
8
+ ffiType: Type;
9
+ constructOnly?: true;
10
+ };
7
11
 
8
- /**
9
- * Collects construct-only property metadata by walking the class hierarchy.
10
- * Returns all active construct-only props (those with values set in the initial props)
11
- * that are NOT already handled by the designated constructor parameters.
12
- */
13
- function collectActiveConstructOnlyProps(
12
+ function collectConstructionProps(
14
13
  containerClass: ContainerClass,
15
14
  props: Props,
16
15
  ): Array<{ girName: string; ffiType: Type; value: unknown }> {
17
16
  const result: Array<{ girName: string; ffiType: Type; value: unknown }> = [];
18
- const constructorParams = new Set(CONSTRUCTOR_PROPS[containerClass.glibTypeName] ?? []);
19
-
20
- // biome-ignore lint/suspicious/noExplicitAny: Walking static prototype chain
21
- let current: any = containerClass;
22
- while (current?.glibTypeName) {
23
- const propsForType: Record<string, ConstructOnlyPropInfo> | undefined =
24
- CONSTRUCT_ONLY_PROPS[current.glibTypeName as string];
25
- if (propsForType) {
26
- for (const [camelName, meta] of Object.entries(propsForType)) {
27
- if (constructorParams.has(camelName)) continue;
17
+ const seen = new Set<string>();
18
+
19
+ // biome-ignore lint/complexity/noBannedTypes: Walking prototype chain requires Function type
20
+ let current: Function | null = containerClass;
21
+ while (current) {
22
+ const typeName = (current as NativeClass).glibTypeName;
23
+ if (!typeName) break;
24
+
25
+ const meta: Record<string, ConstructionPropMeta> | undefined = CONSTRUCTION_META[typeName];
26
+ if (meta) {
27
+ for (const [camelName, propMeta] of Object.entries(meta)) {
28
+ if (seen.has(camelName)) continue;
29
+ seen.add(camelName);
28
30
  if (props[camelName] !== undefined) {
29
- const rawValue = props[camelName];
30
- const value =
31
- meta.ffiType.type === "gobject" &&
32
- rawValue &&
33
- typeof rawValue === "object" &&
34
- "handle" in rawValue
35
- ? (rawValue as { handle: NativeHandle }).handle
36
- : rawValue;
37
- result.push({ girName: meta.girName, ffiType: meta.ffiType, value });
31
+ result.push({
32
+ girName: propMeta.girName,
33
+ ffiType: propMeta.ffiType,
34
+ value: props[camelName],
35
+ });
38
36
  }
39
37
  }
40
38
  }
39
+
41
40
  current = Object.getPrototypeOf(current);
41
+ if (current === Object || current === Function) break;
42
42
  }
43
43
 
44
44
  return result;
45
45
  }
46
46
 
47
- /**
48
- * Creates a container (widget or controller) with construct-only properties.
49
- *
50
- * When construct-only props are present that aren't handled by the designated
51
- * constructor, uses `g_object_new` to set them during object construction.
52
- * Otherwise falls back to the normal constructor.
53
- */
54
- export function createContainerWithConstructOnly(
55
- containerClass: ContainerClass,
56
- props: Props,
57
- normalConstructor: () => Container,
58
- ): Container {
59
- const constructOnlyArgs = collectActiveConstructOnlyProps(containerClass, props);
60
-
61
- if (constructOnlyArgs.length === 0) {
62
- return normalConstructor();
63
- }
64
-
65
- const typeName = containerClass.glibTypeName;
66
- const gtype = typeFromName(typeName);
47
+ export function createContainerWithProperties(containerClass: ContainerClass, props: Props): Container {
48
+ const gtype = containerClass.getGType();
49
+ const constructionProps = collectConstructionProps(containerClass, props);
67
50
 
68
- const args: Arg[] = [{ type: { type: "int", size: 64, unsigned: true }, value: gtype, optional: false }];
51
+ const names: string[] = [];
52
+ const values: Value[] = [];
69
53
 
70
- for (const { girName, ffiType, value } of constructOnlyArgs) {
71
- args.push({ type: { type: "string", ownership: "borrowed" }, value: girName, optional: false });
72
- args.push({ type: ffiType, value, optional: false });
54
+ for (const { girName, ffiType, value } of constructionProps) {
55
+ names.push(girName);
56
+ values.push(Value.newFrom(ffiType, value));
73
57
  }
74
58
 
75
- args.push({ type: { type: "null" }, value: null, optional: false });
76
-
77
- const handle = call("libgobject-2.0.so.0", "g_object_new", args, {
78
- type: "gobject",
79
- ownership: "full",
80
- }) as NativeHandle;
81
-
82
- setInstantiating(true);
83
- // biome-ignore lint/suspicious/noExplicitAny: Dynamic instantiation with isInstantiating flag
84
- const instance = new (containerClass as any)() as Container & { handle: NativeHandle };
85
- setInstantiating(false);
86
- instance.handle = handle;
87
- registerNativeObject(instance);
88
-
89
- return instance;
59
+ return GObject.newWithProperties(gtype, names, values) as unknown as Container;
90
60
  }
@@ -1,6 +1,6 @@
1
1
  import type * as Gtk from "@gtkx/ffi/gtk";
2
2
  import { resolvePropMeta } from "../../metadata.js";
3
- import type { ContainerClass } from "../../types.js";
3
+
4
4
  import { isAddable, isAppendable, isContentWidget, isRemovable, isSingleChild } from "./predicates.js";
5
5
 
6
6
  export function detachChild(child: Gtk.Widget, container: Gtk.Widget): void {
@@ -14,6 +14,8 @@ export function detachChild(child: Gtk.Widget, container: Gtk.Widget): void {
14
14
  container.setChild(null);
15
15
  } else if (isRemovable(container)) {
16
16
  container.remove(child);
17
+ } else {
18
+ child.unparent();
17
19
  }
18
20
  }
19
21
 
@@ -27,7 +29,7 @@ export function attachChild(child: Gtk.Widget, container: Gtk.Widget): void {
27
29
  } else if (isSingleChild(container)) {
28
30
  container.setChild(child);
29
31
  } else {
30
- throw new Error(`Cannot attach child to '${container.constructor.name}': container does not support children`);
32
+ child.setParent(container);
31
33
  }
32
34
  }
33
35
 
@@ -60,19 +62,13 @@ export function resolvePropertySetter(
60
62
  parentWidget: Gtk.Widget,
61
63
  propId: string,
62
64
  ): ((child: Gtk.Widget | null) => void) | null {
63
- const propMeta = resolvePropMeta(parentWidget, propId);
65
+ const propName = resolvePropMeta(parentWidget, propId);
64
66
 
65
- if (!propMeta) {
67
+ if (!propName) {
66
68
  return null;
67
69
  }
68
70
 
69
- const [, setterName] = propMeta;
70
- const setter = parentWidget[setterName as keyof Gtk.Widget];
71
-
72
- if (typeof setter !== "function") {
73
- const parentType = (parentWidget.constructor as ContainerClass).glibTypeName;
74
- throw new Error(`Expected setter function for property '${propId}' on type '${parentType}'`);
75
- }
76
-
77
- return setter.bind(parentWidget) as (child: Gtk.Widget | null) => void;
71
+ return (child: Gtk.Widget | null) => {
72
+ (parentWidget as unknown as Record<string, unknown>)[propName] = child;
73
+ };
78
74
  }
@@ -0,0 +1,53 @@
1
+ import type * as Gtk from "@gtkx/ffi/gtk";
2
+ import { Node } from "../node.js";
3
+ import type { Container, Props } from "../types.js";
4
+ import { isRemovable } from "./internal/predicates.js";
5
+ import { WidgetNode } from "./widget.js";
6
+
7
+ export class ListItemNode extends Node<Gtk.ListItem | Gtk.ListHeader, Props, Node, Node> {
8
+ public override isValidChild(_child: Node): boolean {
9
+ return true;
10
+ }
11
+
12
+ public override appendChild(child: Node): void {
13
+ super.appendChild(child);
14
+
15
+ if (child instanceof WidgetNode) {
16
+ this.detachFromGtkParent(child);
17
+ this.container.setChild(child.container);
18
+ }
19
+ }
20
+
21
+ public override removeChild(child: Node): void {
22
+ if (child instanceof WidgetNode) {
23
+ this.container.setChild(null);
24
+ }
25
+
26
+ super.removeChild(child);
27
+ }
28
+
29
+ public override insertBefore(child: Node, before: Node): void {
30
+ super.insertBefore(child, before);
31
+
32
+ if (child instanceof WidgetNode) {
33
+ this.detachFromGtkParent(child);
34
+ this.container.setChild(child.container);
35
+ }
36
+ }
37
+
38
+ private detachFromGtkParent(child: Node): void {
39
+ if (!(child instanceof WidgetNode)) return;
40
+ const currentParent = child.container.getParent();
41
+ if (currentParent !== null) {
42
+ if (isRemovable(currentParent)) {
43
+ currentParent.remove(child.container);
44
+ } else {
45
+ child.container.unparent();
46
+ }
47
+ }
48
+ }
49
+
50
+ public static override createContainer(): Container {
51
+ throw new Error("ListItemNode does not support container creation");
52
+ }
53
+ }