@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-setting.js","sourceRoot":"","sources":["../src/use-setting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,OAAO,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAYlE,MAAM,OAAO,GAAgC;IACzC,OAAO,EAAE,YAAY;IACrB,GAAG,EAAE,QAAQ;IACb,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,IAAI,EAAE,SAAS;CAClB,CAAC;AAEF,MAAM,OAAO,GAAgC;IACzC,OAAO,EAAE,YAAY;IACrB,GAAG,EAAE,QAAQ;IACb,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,IAAI,EAAE,SAAS;CAClB,CAAC;AAIF,SAAS,WAAW,CAAC,QAAsB,EAAE,GAAW,EAAE,IAAiB;IACvE,MAAM,MAAM,GAAI,QAAuD,CAAC,OAAO,CAAC,IAAI,CAAC,CAAoB,CAAC;IAC1G,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,YAAY,CAAC,QAAsB,EAAE,GAAW,EAAE,IAAiB,EAAE,KAAc;IACxF,MAAM,MAAM,GAAI,QAAuD,CAAC,OAAO,CAAC,IAAI,CAAC,CAAoB,CAAC;IAC1G,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,UAAU,CACtB,QAAgB,EAChB,GAAW,EACX,IAAO;IAEP,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAoB,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAsB,CAAC,CAAC;IAEnH,SAAS,CAAC,GAAG,EAAE;QACX,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAsB,CAAC,CAAC;QAEhE,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,GAAG,EAAE,EAAE,GAAG,EAAE;YACvD,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAsB,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACR,OAAO,CAAC,uBAAuB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACzD,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAE1B,MAAM,GAAG,GAAG,WAAW,CACnB,CAAC,QAA2B,EAAE,EAAE;QAC5B,YAAY,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChD,CAAC,EACD,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,CACxB,CAAC;IAEF,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACxB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/react",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "description": "Build GTK4 desktop applications with React and TypeScript",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -39,8 +39,8 @@
39
39
  ],
40
40
  "dependencies": {
41
41
  "react-reconciler": "^0.33.0",
42
- "@gtkx/ffi": "0.19.0",
43
- "@gtkx/gir": "0.19.0"
42
+ "@gtkx/ffi": "0.21.0",
43
+ "@gtkx/gir": "0.21.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/react-reconciler": "^0.33.0"
@@ -49,6 +49,7 @@
49
49
  "react": "^19"
50
50
  },
51
51
  "scripts": {
52
- "build": "tsc -b && cp ../../README.md ."
52
+ "build": "tsc -b && cp ../../README.md .",
53
+ "typecheck": "tsc -b --emitDeclarationOnly"
53
54
  }
54
55
  }
@@ -0,0 +1,57 @@
1
+ import { createElement, type ReactNode } from "react";
2
+
3
+ type ContainerSlotChild = (props: { children?: ReactNode }) => ReactNode;
4
+
5
+ /**
6
+ * Creates a compound child component that delegates to a ContainerSlot
7
+ * with a specific method name.
8
+ *
9
+ * @param methodName - The container slot method name (e.g., "packStart", "addPrefix")
10
+ */
11
+ export function createContainerSlotChild(methodName: string): ContainerSlotChild {
12
+ return (props: { children?: ReactNode }): ReactNode => {
13
+ return createElement("ContainerSlot", { id: methodName }, props.children);
14
+ };
15
+ }
16
+
17
+ /**
18
+ * Creates a compound child component that delegates to an existing
19
+ * virtual node intrinsic element.
20
+ *
21
+ * @param intrinsicName - The intrinsic element name (e.g., "StackPage", "GridChild")
22
+ */
23
+ export function createVirtualChild<P extends Record<string, unknown>>(
24
+ intrinsicName: string,
25
+ ): (props: P & { children?: ReactNode }) => ReactNode {
26
+ return (props: P & { children?: ReactNode }): ReactNode => {
27
+ return createElement(intrinsicName, props, props.children);
28
+ };
29
+ }
30
+
31
+ /**
32
+ * Creates a compound child component for NavigationPage that automatically
33
+ * sets the `for` discriminant based on the parent widget type.
34
+ *
35
+ * @param forValue - The `for` discriminant value (e.g., "AdwNavigationView")
36
+ */
37
+ export function createNavigationPageChild<P extends Record<string, unknown>>(
38
+ forValue: string,
39
+ ): (props: P & { children?: ReactNode }) => ReactNode {
40
+ return (props: P & { children?: ReactNode }): ReactNode => {
41
+ return createElement("NavigationPage", { ...props, for: forValue }, props.children);
42
+ };
43
+ }
44
+
45
+ /**
46
+ * Creates a compound child component for menu items that delegates to
47
+ * an existing menu intrinsic element.
48
+ *
49
+ * @param intrinsicName - "MenuItem", "MenuSection", or "MenuSubmenu"
50
+ */
51
+ export function createMenuChild<P extends Record<string, unknown>>(
52
+ intrinsicName: string,
53
+ ): (props: P & { children?: ReactNode }) => ReactNode {
54
+ return (props: P & { children?: ReactNode }): ReactNode => {
55
+ return createElement(intrinsicName, props, props.children);
56
+ };
57
+ }
@@ -0,0 +1,140 @@
1
+ import type * as Adw from "@gtkx/ffi/adw";
2
+ import type * as Gtk from "@gtkx/ffi/gtk";
3
+ import { createElement, Fragment, type ReactNode, type Ref, useReducer, useRef } from "react";
4
+ import type {
5
+ AdwComboRowProps,
6
+ GtkColumnViewProps,
7
+ GtkDropDownProps,
8
+ GtkGridViewProps,
9
+ GtkListViewProps,
10
+ } from "../generated/jsx.js";
11
+ import type {
12
+ ColumnViewColumnProps,
13
+ DropDownProps,
14
+ GridViewProps,
15
+ ListItem,
16
+ ListViewProps,
17
+ MenuItemProps,
18
+ MenuSectionProps,
19
+ MenuSubmenuProps,
20
+ } from "../jsx.js";
21
+ import type { BoundItem } from "../nodes/internal/bound-item.js";
22
+ import { createPortal } from "../portal.js";
23
+ import { createMenuChild } from "./compound.js";
24
+
25
+ type GenericListViewProps<T, S> = Omit<GtkListViewProps, keyof ListViewProps> & ListViewProps<T, S>;
26
+ type GenericGridViewProps<T> = Omit<GtkGridViewProps, keyof GridViewProps> & GridViewProps<T>;
27
+ type GenericDropDownProps<T, S> = Omit<GtkDropDownProps, keyof DropDownProps> & DropDownProps<T, S>;
28
+ type GenericComboRowProps<T, S> = Omit<AdwComboRowProps, keyof DropDownProps> & DropDownProps<T, S>;
29
+ type GenericColumnViewProps<T, S> = Omit<GtkColumnViewProps, "items" | "renderHeader"> & {
30
+ items?: ListItem<T, S>[];
31
+ renderHeader?: ((item: S) => ReactNode) | null;
32
+ };
33
+
34
+ function useListHandle() {
35
+ const [, rerender] = useReducer((x: number) => x + 1, 0);
36
+ const boundItemsRef = useRef<BoundItem[]>([]);
37
+ const headerBoundItemsRef = useRef<BoundItem[]>([]);
38
+ return { rerender, boundItemsRef, headerBoundItemsRef };
39
+ }
40
+
41
+ function renderListElement(intrinsicName: string, handle: ReturnType<typeof useListHandle>, props: object): ReactNode {
42
+ const { rerender, boundItemsRef, headerBoundItemsRef } = handle;
43
+
44
+ const portals: ReactNode[] = [];
45
+ for (const [content, container, key] of boundItemsRef.current) {
46
+ portals.push(createPortal(content, container, key));
47
+ }
48
+ for (const [content, container, key] of headerBoundItemsRef.current) {
49
+ portals.push(createPortal(content, container, key));
50
+ }
51
+
52
+ return createElement(
53
+ Fragment,
54
+ null,
55
+ createElement(intrinsicName, {
56
+ ...(props as Record<string, unknown>),
57
+ __boundItemsRef: boundItemsRef,
58
+ __rerender: rerender,
59
+ __headerBoundItemsRef: headerBoundItemsRef,
60
+ }),
61
+ ...portals,
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Virtualized scrollable list that renders items from a flat or tree data model.
67
+ *
68
+ * Wraps `GtkListView` with React-managed item rendering via portals,
69
+ * supporting single/multi selection, section headers, and tree expansion.
70
+ */
71
+ export function GtkListView<T = unknown, S = unknown>(
72
+ props: GenericListViewProps<T, S> & { children?: ReactNode; ref?: Ref<Gtk.ListView> },
73
+ ): ReactNode {
74
+ return renderListElement("GtkListView", useListHandle(), props);
75
+ }
76
+
77
+ /**
78
+ * Virtualized scrollable grid that renders items in a multi-column layout.
79
+ *
80
+ * Wraps `GtkGridView` with React-managed item rendering via portals,
81
+ * supporting single/multi selection.
82
+ */
83
+ export function GtkGridView<T = unknown>(
84
+ props: GenericGridViewProps<T> & { children?: ReactNode; ref?: Ref<Gtk.GridView> },
85
+ ): ReactNode {
86
+ return renderListElement("GtkGridView", useListHandle(), props);
87
+ }
88
+
89
+ /** @internal */
90
+ function GtkColumnViewBase<T = unknown, S = unknown>(
91
+ props: GenericColumnViewProps<T, S> & { children?: ReactNode; ref?: Ref<Gtk.ColumnView> },
92
+ ): ReactNode {
93
+ return renderListElement("GtkColumnView", useListHandle(), props);
94
+ }
95
+
96
+ /**
97
+ * Multi-column sortable list with React-managed cell rendering.
98
+ *
99
+ * Wraps `GtkColumnView` with portal-based factories. Use the
100
+ * `GtkColumnView.Column` compound component to define columns,
101
+ * and the `MenuItem` / `MenuSection` / `MenuSubmenu` compounds
102
+ * for the column header context menu.
103
+ */
104
+ export const GtkColumnView: typeof GtkColumnViewBase & {
105
+ Column: <T = unknown>(props: ColumnViewColumnProps<T>) => ReactNode;
106
+ MenuItem: (props: MenuItemProps) => ReactNode;
107
+ MenuSection: (props: MenuSectionProps) => ReactNode;
108
+ MenuSubmenu: (props: MenuSubmenuProps) => ReactNode;
109
+ } = Object.assign(GtkColumnViewBase, {
110
+ Column: <T = unknown>(props: ColumnViewColumnProps<T>): ReactNode =>
111
+ createElement("ColumnViewColumn", props, props.children),
112
+ MenuItem: createMenuChild<MenuItemProps>("MenuItem"),
113
+ MenuSection: createMenuChild<MenuSectionProps>("MenuSection"),
114
+ MenuSubmenu: createMenuChild<MenuSubmenuProps>("MenuSubmenu"),
115
+ });
116
+
117
+ /**
118
+ * Single-selection dropdown widget with React-managed item rendering.
119
+ *
120
+ * Wraps `GtkDropDown` with portal-based factories, supporting custom
121
+ * item templates, separate list-item templates, and section headers.
122
+ */
123
+ export function GtkDropDown<T = unknown, S = unknown>(
124
+ props: GenericDropDownProps<T, S> & { children?: ReactNode; ref?: Ref<Gtk.DropDown> },
125
+ ): ReactNode {
126
+ return renderListElement("GtkDropDown", useListHandle(), props);
127
+ }
128
+
129
+ /**
130
+ * Libadwaita combo row with React-managed item rendering.
131
+ *
132
+ * Wraps `AdwComboRow` with portal-based factories, providing a
133
+ * preferences-style dropdown row with custom item templates and
134
+ * section headers.
135
+ */
136
+ export function AdwComboRow<T = unknown, S = unknown>(
137
+ props: GenericComboRowProps<T, S> & { children?: ReactNode; ref?: Ref<Adw.ComboRow> },
138
+ ): ReactNode {
139
+ return renderListElement("AdwComboRow", useListHandle(), props);
140
+ }
@@ -0,0 +1,46 @@
1
+ import { createElement, type ReactNode } from "react";
2
+
3
+ type SlotPropValue = ReactNode | null | undefined;
4
+
5
+ /**
6
+ * Creates a function component for a widget that has named property slots.
7
+ *
8
+ * The returned component extracts slot props (ReactNode values), forwards
9
+ * remaining props to the underlying intrinsic element, and appends internal
10
+ * Slot children for each non-null slot prop.
11
+ *
12
+ * @param intrinsicName - The intrinsic element name (e.g., "GtkWindow")
13
+ * @param slotNames - Array of camelCase slot prop names (e.g., ["titlebar", "startChild"])
14
+ */
15
+ // biome-ignore lint/suspicious/noExplicitAny: Props interfaces don't satisfy Record<string, unknown>
16
+ export function createSlotWidget<P = any>(
17
+ intrinsicName: string,
18
+ slotNames: readonly string[],
19
+ ): (props: P & { children?: ReactNode }) => ReactNode {
20
+ const slotSet = new Set(slotNames);
21
+
22
+ return (props: P & { children?: ReactNode }): ReactNode => {
23
+ const forwardedProps: Record<string, unknown> = {};
24
+ const slotChildren: ReactNode[] = [];
25
+ const propsRecord = props as Record<string, unknown>;
26
+
27
+ for (const key in propsRecord) {
28
+ if (slotSet.has(key)) {
29
+ const value = propsRecord[key] as SlotPropValue;
30
+ if (value != null) {
31
+ slotChildren.push(createElement("Slot", { key: `__slot_${key}`, id: key }, value));
32
+ }
33
+ } else {
34
+ forwardedProps[key] = propsRecord[key];
35
+ }
36
+ }
37
+
38
+ const { children } = props;
39
+
40
+ if (slotChildren.length > 0) {
41
+ return createElement(intrinsicName, forwardedProps, children, ...slotChildren);
42
+ }
43
+
44
+ return createElement(intrinsicName, forwardedProps, children);
45
+ };
46
+ }
package/src/errors.ts CHANGED
@@ -1,3 +1,9 @@
1
+ /**
2
+ * Error subclass thrown by the GTKX reconciler and rendering pipeline.
3
+ *
4
+ * Carries optional context about the widget type that failed and the
5
+ * React component stack at the point of failure.
6
+ */
1
7
  export class GtkxError extends Error {
2
8
  constructor(
3
9
  message: string,
@@ -32,14 +38,9 @@ export function formatRenderError(error: unknown, widgetType?: string): GtkxErro
32
38
  return error;
33
39
  }
34
40
 
35
- if (error instanceof Error) {
36
- console.error("[formatRenderError] Original error stack:", error.stack);
37
- }
38
-
39
41
  const message = error instanceof Error ? error.message : String(error);
40
- const formattedMessage = widgetType ? `Failed to render ${widgetType}: ${message}` : `Render error: ${message}`;
41
42
 
42
- return new GtkxError(formattedMessage, widgetType);
43
+ return new GtkxError(message, widgetType);
43
44
  }
44
45
 
45
46
  export function formatBoundaryError(error: unknown): GtkxError {
@@ -48,5 +49,5 @@ export function formatBoundaryError(error: unknown): GtkxError {
48
49
  }
49
50
 
50
51
  const message = error instanceof Error ? error.message : String(error);
51
- return new GtkxError(`Error caught by boundary: ${message}`);
52
+ return new GtkxError(message);
52
53
  }