@gtkx/react 1.0.0-rc.1 → 1.0.0-rc.2

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 (381) hide show
  1. package/dist/adw/config.d.ts +2 -0
  2. package/dist/adw/config.d.ts.map +1 -0
  3. package/dist/adw/config.js +2 -0
  4. package/dist/adw/config.js.map +1 -0
  5. package/dist/{libraries/adw → adw}/dialog.d.ts +2 -2
  6. package/dist/adw/dialog.d.ts.map +1 -0
  7. package/dist/adw/dialog.js +25 -0
  8. package/dist/adw/dialog.js.map +1 -0
  9. package/dist/adw/element-behaviors.d.ts +2 -0
  10. package/dist/adw/element-behaviors.d.ts.map +1 -0
  11. package/dist/adw/element-behaviors.js +299 -0
  12. package/dist/adw/element-behaviors.js.map +1 -0
  13. package/dist/adw/element-config.d.ts +9 -0
  14. package/dist/adw/element-config.d.ts.map +1 -0
  15. package/dist/adw/element-config.js +137 -0
  16. package/dist/adw/element-config.js.map +1 -0
  17. package/dist/adw/index.d.ts +4 -0
  18. package/dist/adw/index.d.ts.map +1 -0
  19. package/dist/adw/index.js +3 -0
  20. package/dist/adw/index.js.map +1 -0
  21. package/dist/adw/prop-types.d.ts +29 -0
  22. package/dist/adw/prop-types.d.ts.map +1 -0
  23. package/dist/adw/prop-types.js +2 -0
  24. package/dist/adw/prop-types.js.map +1 -0
  25. package/dist/bootstrap.d.ts +2 -0
  26. package/dist/bootstrap.d.ts.map +1 -0
  27. package/dist/bootstrap.js +5 -0
  28. package/dist/bootstrap.js.map +1 -0
  29. package/dist/components/application.d.ts +2 -2
  30. package/dist/components/application.d.ts.map +1 -1
  31. package/dist/components/application.js +31 -18
  32. package/dist/components/application.js.map +1 -1
  33. package/dist/components/element.d.ts +6 -0
  34. package/dist/components/element.d.ts.map +1 -0
  35. package/dist/components/element.js +29 -0
  36. package/dist/components/element.js.map +1 -0
  37. package/dist/components/window.d.ts +2 -2
  38. package/dist/components/window.d.ts.map +1 -1
  39. package/dist/components/window.js +10 -11
  40. package/dist/components/window.js.map +1 -1
  41. package/dist/config.d.ts +4 -0
  42. package/dist/config.d.ts.map +1 -0
  43. package/dist/config.js +3 -0
  44. package/dist/config.js.map +1 -0
  45. package/dist/element-behaviors.d.ts +2 -0
  46. package/dist/element-behaviors.d.ts.map +1 -0
  47. package/dist/element-behaviors.js +348 -0
  48. package/dist/element-behaviors.js.map +1 -0
  49. package/dist/element-config.d.ts +10 -0
  50. package/dist/element-config.d.ts.map +1 -0
  51. package/dist/element-config.js +146 -0
  52. package/dist/element-config.js.map +1 -0
  53. package/dist/hooks/use-application.d.ts +4 -3
  54. package/dist/hooks/use-application.d.ts.map +1 -1
  55. package/dist/hooks/use-application.js +5 -4
  56. package/dist/hooks/use-application.js.map +1 -1
  57. package/dist/hooks/use-bind-setting.d.ts +21 -4
  58. package/dist/hooks/use-bind-setting.d.ts.map +1 -1
  59. package/dist/hooks/use-bind-setting.js +27 -16
  60. package/dist/hooks/use-bind-setting.js.map +1 -1
  61. package/dist/hooks/use-merged-refs.d.ts +8 -0
  62. package/dist/hooks/use-merged-refs.d.ts.map +1 -0
  63. package/dist/hooks/use-merged-refs.js +48 -0
  64. package/dist/hooks/use-merged-refs.js.map +1 -0
  65. package/dist/hooks/use-object-value.d.ts +3 -2
  66. package/dist/hooks/use-object-value.d.ts.map +1 -1
  67. package/dist/hooks/use-object-value.js +18 -21
  68. package/dist/hooks/use-object-value.js.map +1 -1
  69. package/dist/hooks/use-parent-window.d.ts +3 -2
  70. package/dist/hooks/use-parent-window.d.ts.map +1 -1
  71. package/dist/hooks/use-parent-window.js +3 -2
  72. package/dist/hooks/use-parent-window.js.map +1 -1
  73. package/dist/hooks/use-property.d.ts +5 -5
  74. package/dist/hooks/use-property.d.ts.map +1 -1
  75. package/dist/hooks/use-property.js +4 -3
  76. package/dist/hooks/use-property.js.map +1 -1
  77. package/dist/hooks/use-setting.d.ts +5 -16
  78. package/dist/hooks/use-setting.d.ts.map +1 -1
  79. package/dist/hooks/use-setting.js +16 -11
  80. package/dist/hooks/use-setting.js.map +1 -1
  81. package/dist/hooks/use-signal.d.ts +10 -7
  82. package/dist/hooks/use-signal.d.ts.map +1 -1
  83. package/dist/hooks/use-signal.js +29 -18
  84. package/dist/hooks/use-signal.js.map +1 -1
  85. package/dist/index.d.ts +7 -8
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +2 -3
  88. package/dist/index.js.map +1 -1
  89. package/dist/internal.d.ts +6 -7
  90. package/dist/internal.d.ts.map +1 -1
  91. package/dist/internal.js +5 -7
  92. package/dist/internal.js.map +1 -1
  93. package/dist/prop-types.d.ts +110 -0
  94. package/dist/prop-types.d.ts.map +1 -0
  95. package/dist/prop-types.js +2 -0
  96. package/dist/prop-types.js.map +1 -0
  97. package/dist/reconciler/apply-props.d.ts +10 -7
  98. package/dist/reconciler/apply-props.d.ts.map +1 -1
  99. package/dist/reconciler/apply-props.js +182 -84
  100. package/dist/reconciler/apply-props.js.map +1 -1
  101. package/dist/reconciler/behaviors.d.ts +59 -0
  102. package/dist/reconciler/behaviors.d.ts.map +1 -0
  103. package/dist/reconciler/behaviors.js +172 -0
  104. package/dist/reconciler/behaviors.js.map +1 -0
  105. package/dist/reconciler/child-routing.d.ts +5 -0
  106. package/dist/reconciler/child-routing.d.ts.map +1 -0
  107. package/dist/reconciler/child-routing.js +156 -0
  108. package/dist/reconciler/child-routing.js.map +1 -0
  109. package/dist/reconciler/host-config.d.ts +8 -12
  110. package/dist/reconciler/host-config.d.ts.map +1 -1
  111. package/dist/reconciler/host-config.js +175 -270
  112. package/dist/reconciler/host-config.js.map +1 -1
  113. package/dist/reconciler/instance.d.ts +4 -5
  114. package/dist/reconciler/instance.d.ts.map +1 -1
  115. package/dist/reconciler/instance.js +44 -22
  116. package/dist/reconciler/instance.js.map +1 -1
  117. package/dist/reconciler/metadata.d.ts +17 -0
  118. package/dist/reconciler/metadata.d.ts.map +1 -0
  119. package/dist/reconciler/metadata.js +82 -0
  120. package/dist/reconciler/metadata.js.map +1 -0
  121. package/dist/reconciler/node.d.ts +76 -0
  122. package/dist/reconciler/node.d.ts.map +1 -0
  123. package/dist/reconciler/node.js +53 -0
  124. package/dist/reconciler/node.js.map +1 -0
  125. package/dist/reconciler/placement.d.ts +5 -0
  126. package/dist/reconciler/placement.d.ts.map +1 -0
  127. package/dist/reconciler/placement.js +175 -0
  128. package/dist/reconciler/placement.js.map +1 -0
  129. package/dist/reconciler/registry.d.ts +92 -0
  130. package/dist/reconciler/registry.d.ts.map +1 -0
  131. package/dist/reconciler/registry.js +64 -0
  132. package/dist/reconciler/registry.js.map +1 -0
  133. package/dist/reconciler/root-element.d.ts +9 -12
  134. package/dist/reconciler/root-element.d.ts.map +1 -1
  135. package/dist/reconciler/root-element.js +6 -6
  136. package/dist/reconciler/root-element.js.map +1 -1
  137. package/dist/reconciler/root.d.ts +56 -0
  138. package/dist/reconciler/root.d.ts.map +1 -0
  139. package/dist/reconciler/root.js +109 -0
  140. package/dist/reconciler/root.js.map +1 -0
  141. package/dist/reconciler/signals.d.ts +10 -0
  142. package/dist/reconciler/signals.d.ts.map +1 -0
  143. package/dist/reconciler/signals.js +70 -0
  144. package/dist/reconciler/signals.js.map +1 -0
  145. package/dist/reconciler/text.d.ts +19 -0
  146. package/dist/reconciler/text.d.ts.map +1 -0
  147. package/dist/reconciler/text.js +276 -0
  148. package/dist/reconciler/text.js.map +1 -0
  149. package/dist/utils/accessible-metadata.d.ts +11 -4
  150. package/dist/utils/accessible-metadata.d.ts.map +1 -1
  151. package/dist/utils/accessible-metadata.js +20 -17
  152. package/dist/utils/accessible-metadata.js.map +1 -1
  153. package/dist/{reconciler/accessible.d.ts → utils/accessible-props.d.ts} +7 -6
  154. package/dist/utils/accessible-props.d.ts.map +1 -0
  155. package/dist/utils/accessible-props.js +181 -0
  156. package/dist/utils/accessible-props.js.map +1 -0
  157. package/dist/utils/ref-prop.d.ts +15 -0
  158. package/dist/utils/ref-prop.d.ts.map +1 -0
  159. package/dist/utils/ref-prop.js +18 -0
  160. package/dist/utils/ref-prop.js.map +1 -0
  161. package/dist/utils/settings.d.ts +17 -0
  162. package/dist/utils/settings.d.ts.map +1 -0
  163. package/dist/utils/settings.js +37 -0
  164. package/dist/utils/settings.js.map +1 -0
  165. package/dist/utils/variant.d.ts +57 -0
  166. package/dist/utils/variant.d.ts.map +1 -0
  167. package/dist/utils/variant.js +197 -0
  168. package/dist/utils/variant.js.map +1 -0
  169. package/env.d.ts +9 -0
  170. package/package.json +36 -11
  171. package/src/adw/config.ts +1 -0
  172. package/src/adw/dialog.tsx +35 -0
  173. package/src/adw/element-behaviors.ts +379 -0
  174. package/src/adw/element-config.ts +140 -0
  175. package/src/adw/index.ts +4 -0
  176. package/src/adw/prop-types.ts +42 -0
  177. package/src/bootstrap.ts +5 -0
  178. package/src/components/application.tsx +42 -23
  179. package/src/components/element.tsx +47 -0
  180. package/src/components/window.tsx +12 -13
  181. package/src/config.ts +3 -0
  182. package/src/element-behaviors.ts +424 -0
  183. package/src/element-config.ts +148 -0
  184. package/src/env.d.ts +1 -0
  185. package/src/hooks/use-application.ts +6 -4
  186. package/src/hooks/use-bind-setting.ts +47 -31
  187. package/src/hooks/use-merged-refs.ts +64 -0
  188. package/src/hooks/use-object-value.ts +27 -23
  189. package/src/hooks/use-parent-window.ts +4 -2
  190. package/src/hooks/use-property.ts +11 -10
  191. package/src/hooks/use-setting.ts +20 -33
  192. package/src/hooks/use-signal.ts +37 -48
  193. package/src/index.ts +7 -8
  194. package/src/internal.ts +7 -18
  195. package/src/prop-types.ts +142 -0
  196. package/src/reconciler/apply-props.ts +233 -85
  197. package/src/reconciler/behaviors.ts +324 -0
  198. package/src/reconciler/child-routing.ts +202 -0
  199. package/src/reconciler/host-config.ts +239 -366
  200. package/src/reconciler/instance.ts +76 -24
  201. package/src/reconciler/metadata.ts +119 -0
  202. package/src/reconciler/node.ts +161 -0
  203. package/src/reconciler/placement.ts +255 -0
  204. package/src/reconciler/registry.ts +161 -0
  205. package/src/reconciler/root-element.ts +9 -11
  206. package/src/reconciler/root.ts +175 -0
  207. package/src/reconciler/signals.ts +113 -0
  208. package/src/reconciler/text.ts +407 -0
  209. package/src/utils/accessible-metadata.ts +23 -18
  210. package/src/utils/accessible-props.ts +279 -0
  211. package/src/utils/ref-prop.ts +30 -0
  212. package/src/utils/settings.ts +69 -0
  213. package/src/utils/variant.ts +368 -0
  214. package/dist/hooks/use-merge-refs.d.ts +0 -3
  215. package/dist/hooks/use-merge-refs.d.ts.map +0 -1
  216. package/dist/hooks/use-merge-refs.js +0 -48
  217. package/dist/hooks/use-merge-refs.js.map +0 -1
  218. package/dist/hooks/use-object-attachment.d.ts +0 -10
  219. package/dist/hooks/use-object-attachment.d.ts.map +0 -1
  220. package/dist/hooks/use-object-attachment.js +0 -24
  221. package/dist/hooks/use-object-attachment.js.map +0 -1
  222. package/dist/libraries/adw/dialog.d.ts.map +0 -1
  223. package/dist/libraries/adw/dialog.js +0 -25
  224. package/dist/libraries/adw/dialog.js.map +0 -1
  225. package/dist/libraries/adw/index.d.ts +0 -2
  226. package/dist/libraries/adw/index.d.ts.map +0 -1
  227. package/dist/libraries/adw/index.js +0 -2
  228. package/dist/libraries/adw/index.js.map +0 -1
  229. package/dist/reconciler/accessible.d.ts.map +0 -1
  230. package/dist/reconciler/accessible.js +0 -143
  231. package/dist/reconciler/accessible.js.map +0 -1
  232. package/dist/reconciler/commit-flush.d.ts +0 -3
  233. package/dist/reconciler/commit-flush.d.ts.map +0 -1
  234. package/dist/reconciler/commit-flush.js +0 -13
  235. package/dist/reconciler/commit-flush.js.map +0 -1
  236. package/dist/reconciler/container-attach.d.ts +0 -10
  237. package/dist/reconciler/container-attach.d.ts.map +0 -1
  238. package/dist/reconciler/container-attach.js +0 -216
  239. package/dist/reconciler/container-attach.js.map +0 -1
  240. package/dist/reconciler/content-rebuild.d.ts +0 -3
  241. package/dist/reconciler/content-rebuild.d.ts.map +0 -1
  242. package/dist/reconciler/content-rebuild.js +0 -15
  243. package/dist/reconciler/content-rebuild.js.map +0 -1
  244. package/dist/reconciler/dispatch.d.ts +0 -6
  245. package/dist/reconciler/dispatch.d.ts.map +0 -1
  246. package/dist/reconciler/dispatch.js +0 -61
  247. package/dist/reconciler/dispatch.js.map +0 -1
  248. package/dist/reconciler/element-prop-appliers.d.ts +0 -5
  249. package/dist/reconciler/element-prop-appliers.d.ts.map +0 -1
  250. package/dist/reconciler/element-prop-appliers.js +0 -104
  251. package/dist/reconciler/element-prop-appliers.js.map +0 -1
  252. package/dist/reconciler/element-props.d.ts +0 -25
  253. package/dist/reconciler/element-props.d.ts.map +0 -1
  254. package/dist/reconciler/element-props.js +0 -157
  255. package/dist/reconciler/element-props.js.map +0 -1
  256. package/dist/reconciler/label-text-rebuild.d.ts +0 -3
  257. package/dist/reconciler/label-text-rebuild.d.ts.map +0 -1
  258. package/dist/reconciler/label-text-rebuild.js +0 -22
  259. package/dist/reconciler/label-text-rebuild.js.map +0 -1
  260. package/dist/reconciler/portal.d.ts +0 -11
  261. package/dist/reconciler/portal.d.ts.map +0 -1
  262. package/dist/reconciler/portal.js +0 -20
  263. package/dist/reconciler/portal.js.map +0 -1
  264. package/dist/reconciler/reconciler-error-handler.d.ts +0 -7
  265. package/dist/reconciler/reconciler-error-handler.d.ts.map +0 -1
  266. package/dist/reconciler/reconciler-error-handler.js +0 -24
  267. package/dist/reconciler/reconciler-error-handler.js.map +0 -1
  268. package/dist/reconciler/reconciler-root.d.ts +0 -19
  269. package/dist/reconciler/reconciler-root.d.ts.map +0 -1
  270. package/dist/reconciler/reconciler-root.js +0 -24
  271. package/dist/reconciler/reconciler-root.js.map +0 -1
  272. package/dist/reconciler/reconciler.d.ts +0 -3
  273. package/dist/reconciler/reconciler.d.ts.map +0 -1
  274. package/dist/reconciler/reconciler.js +0 -12
  275. package/dist/reconciler/reconciler.js.map +0 -1
  276. package/dist/reconciler/render.d.ts +0 -23
  277. package/dist/reconciler/render.d.ts.map +0 -1
  278. package/dist/reconciler/render.js +0 -46
  279. package/dist/reconciler/render.js.map +0 -1
  280. package/dist/reconciler/signal-store.d.ts +0 -22
  281. package/dist/reconciler/signal-store.d.ts.map +0 -1
  282. package/dist/reconciler/signal-store.js +0 -84
  283. package/dist/reconciler/signal-store.js.map +0 -1
  284. package/dist/reconciler/state.d.ts +0 -36
  285. package/dist/reconciler/state.d.ts.map +0 -1
  286. package/dist/reconciler/state.js +0 -38
  287. package/dist/reconciler/state.js.map +0 -1
  288. package/dist/reconciler/text-buffer-controller.d.ts +0 -17
  289. package/dist/reconciler/text-buffer-controller.d.ts.map +0 -1
  290. package/dist/reconciler/text-buffer-controller.js +0 -102
  291. package/dist/reconciler/text-buffer-controller.js.map +0 -1
  292. package/dist/reconciler/text-buffer-rebuild.d.ts +0 -3
  293. package/dist/reconciler/text-buffer-rebuild.d.ts.map +0 -1
  294. package/dist/reconciler/text-buffer-rebuild.js +0 -7
  295. package/dist/reconciler/text-buffer-rebuild.js.map +0 -1
  296. package/dist/reconciler/text-node.d.ts +0 -7
  297. package/dist/reconciler/text-node.d.ts.map +0 -1
  298. package/dist/reconciler/text-node.js +0 -8
  299. package/dist/reconciler/text-node.js.map +0 -1
  300. package/dist/reconciler/types.d.ts +0 -5
  301. package/dist/reconciler/types.d.ts.map +0 -1
  302. package/dist/reconciler/types.js +0 -2
  303. package/dist/reconciler/types.js.map +0 -1
  304. package/dist/reconciler/visibility.d.ts +0 -6
  305. package/dist/reconciler/visibility.d.ts.map +0 -1
  306. package/dist/reconciler/visibility.js +0 -57
  307. package/dist/reconciler/visibility.js.map +0 -1
  308. package/dist/reconciler/wrapper-apply.d.ts +0 -6
  309. package/dist/reconciler/wrapper-apply.d.ts.map +0 -1
  310. package/dist/reconciler/wrapper-apply.js +0 -287
  311. package/dist/reconciler/wrapper-apply.js.map +0 -1
  312. package/dist/reconciler/wrapper-content.d.ts +0 -8
  313. package/dist/reconciler/wrapper-content.d.ts.map +0 -1
  314. package/dist/reconciler/wrapper-content.js +0 -19
  315. package/dist/reconciler/wrapper-content.js.map +0 -1
  316. package/dist/reconciler/wrapper-node.d.ts +0 -8
  317. package/dist/reconciler/wrapper-node.d.ts.map +0 -1
  318. package/dist/reconciler/wrapper-node.js +0 -4
  319. package/dist/reconciler/wrapper-node.js.map +0 -1
  320. package/dist/reconciler/wrapper-protocol.d.ts +0 -13
  321. package/dist/reconciler/wrapper-protocol.d.ts.map +0 -1
  322. package/dist/reconciler/wrapper-protocol.js +0 -20
  323. package/dist/reconciler/wrapper-protocol.js.map +0 -1
  324. package/dist/utils/create-element-component.d.ts +0 -4
  325. package/dist/utils/create-element-component.d.ts.map +0 -1
  326. package/dist/utils/create-element-component.js +0 -54
  327. package/dist/utils/create-element-component.js.map +0 -1
  328. package/dist/utils/gtype.d.ts +0 -16
  329. package/dist/utils/gtype.d.ts.map +0 -1
  330. package/dist/utils/gtype.js +0 -127
  331. package/dist/utils/gtype.js.map +0 -1
  332. package/dist/utils/notify-name.d.ts +0 -5
  333. package/dist/utils/notify-name.d.ts.map +0 -1
  334. package/dist/utils/notify-name.js +0 -6
  335. package/dist/utils/notify-name.js.map +0 -1
  336. package/dist/utils/object-prop.d.ts +0 -8
  337. package/dist/utils/object-prop.d.ts.map +0 -1
  338. package/dist/utils/object-prop.js +0 -9
  339. package/dist/utils/object-prop.js.map +0 -1
  340. package/dist/utils/settings-accessor.d.ts +0 -8
  341. package/dist/utils/settings-accessor.d.ts.map +0 -1
  342. package/dist/utils/settings-accessor.js +0 -69
  343. package/dist/utils/settings-accessor.js.map +0 -1
  344. package/dist/utils/wrapper-node-jsx.d.ts +0 -32
  345. package/dist/utils/wrapper-node-jsx.d.ts.map +0 -1
  346. package/dist/utils/wrapper-node-jsx.js +0 -2
  347. package/dist/utils/wrapper-node-jsx.js.map +0 -1
  348. package/src/hooks/use-merge-refs.ts +0 -53
  349. package/src/hooks/use-object-attachment.ts +0 -35
  350. package/src/libraries/adw/dialog.tsx +0 -34
  351. package/src/libraries/adw/index.ts +0 -1
  352. package/src/reconciler/accessible.ts +0 -232
  353. package/src/reconciler/commit-flush.ts +0 -13
  354. package/src/reconciler/container-attach.ts +0 -219
  355. package/src/reconciler/content-rebuild.ts +0 -19
  356. package/src/reconciler/dispatch.ts +0 -58
  357. package/src/reconciler/element-prop-appliers.ts +0 -110
  358. package/src/reconciler/element-props.ts +0 -192
  359. package/src/reconciler/label-text-rebuild.ts +0 -26
  360. package/src/reconciler/portal.ts +0 -28
  361. package/src/reconciler/reconciler-error-handler.ts +0 -29
  362. package/src/reconciler/reconciler-root.ts +0 -57
  363. package/src/reconciler/reconciler.ts +0 -13
  364. package/src/reconciler/render.ts +0 -61
  365. package/src/reconciler/signal-store.ts +0 -103
  366. package/src/reconciler/state.ts +0 -72
  367. package/src/reconciler/text-buffer-controller.ts +0 -107
  368. package/src/reconciler/text-buffer-rebuild.ts +0 -12
  369. package/src/reconciler/text-node.ts +0 -13
  370. package/src/reconciler/types.ts +0 -6
  371. package/src/reconciler/visibility.ts +0 -52
  372. package/src/reconciler/wrapper-apply.ts +0 -308
  373. package/src/reconciler/wrapper-content.ts +0 -24
  374. package/src/reconciler/wrapper-node.ts +0 -8
  375. package/src/reconciler/wrapper-protocol.ts +0 -32
  376. package/src/utils/create-element-component.ts +0 -77
  377. package/src/utils/gtype.ts +0 -166
  378. package/src/utils/notify-name.ts +0 -10
  379. package/src/utils/object-prop.ts +0 -13
  380. package/src/utils/settings-accessor.ts +0 -89
  381. package/src/utils/wrapper-node-jsx.ts +0 -34
@@ -0,0 +1,161 @@
1
+ import type * as GObject from "@gtkx/gi/gobject";
2
+
3
+ /** The props of a host element or node, as React passes them through the reconciler. */
4
+ type Props = Record<string, unknown>;
5
+
6
+ /** Per-child values a slot hook receives while placing or moving one child. */
7
+ type PlaceInfo = {
8
+ slot: string;
9
+ index: number;
10
+ sibling: GObject.Object | null;
11
+ adopted: GObject.Object | null;
12
+ props: Props;
13
+ context: unknown;
14
+ };
15
+
16
+ /** Per-child values a slot hook receives while removing one child. */
17
+ type DetachInfo = {
18
+ slot: string;
19
+ adopted: GObject.Object | null;
20
+ props: Props;
21
+ context: unknown;
22
+ };
23
+
24
+ /**
25
+ * Customizes how one element type places children and applies props. Every hook receives the
26
+ * GObject instance and a private per-node `context` built once by `createContext`. A slot hook
27
+ * claims a child by returning a non-`undefined` value; that value, or `resolve`, is the object
28
+ * the container adopts for the child. `update` returns the prop names it consumed so those props
29
+ * are not also set as plain GObject properties. `create` builds the GObject for types whose
30
+ * constructor does more than set properties, and is consulted for its own type only, never
31
+ * inherited by subtypes.
32
+ */
33
+ type ElementBehavior<T extends GObject.Object = GObject.Object> = {
34
+ create?: (props: Props) => GObject.Object;
35
+ createContext?: (object: T) => unknown;
36
+ attach?: (object: T, child: GObject.Object, info: PlaceInfo) => unknown;
37
+ reorder?: (object: T, child: GObject.Object, info: PlaceInfo) => unknown;
38
+ detach?: (object: T, child: GObject.Object, info: DetachInfo) => void;
39
+ resolve?: (object: T, child: GObject.Object) => GObject.Object | null;
40
+ update?: (object: T, prev: Props, next: Props, context: unknown) => Iterable<string> | undefined;
41
+ flush?: (object: T, context: unknown) => void;
42
+ mount?: (object: T, context: unknown) => void;
43
+ unmount?: (object: T, context: unknown) => void;
44
+ deferred?: string[];
45
+ };
46
+
47
+ /** A named export in a module, referenced as plain data (the module is never imported at runtime). */
48
+ type ModuleExport = { module: string; export: string };
49
+
50
+ /**
51
+ * Per-element configuration keyed by GLib type name: whether the element is lazy (its GObject is
52
+ * created by its parent container, as pages and layout children are), the custom behaviors bound to
53
+ * its type, an optional component that wraps the generated element, and the base props interface its
54
+ * generated props extend. `component` and `props` are inert at runtime; they are read only by codegen.
55
+ */
56
+ type ElementConfig<T extends GObject.Object = GObject.Object> = {
57
+ lazy?: boolean;
58
+ behaviors?: ElementBehavior<T>[];
59
+ component?: ModuleExport;
60
+ props?: ModuleExport;
61
+ };
62
+
63
+ /**
64
+ * Every registered element config, keyed by GLib type name. Adwaita entries appear once `@gtkx/react/adw`
65
+ * is loaded.
66
+ */
67
+ const ELEMENTS: Record<string, ElementConfig> = {};
68
+
69
+ /** Props a behavior applies after construction; the constructor is never given them. */
70
+ const deferredProps = (behavior: ElementBehavior): string[] => behavior.deferred ?? [];
71
+
72
+ const mergeBehaviors = (base: ElementConfig, added: ElementBehavior[], isPrepended: boolean): ElementBehavior[] => {
73
+ const baseBehaviors = base.behaviors ?? [];
74
+
75
+ return isPrepended ? [...added, ...baseBehaviors] : [...baseBehaviors, ...added];
76
+ };
77
+
78
+ const mergeConfigEntry = (base: ElementConfig, added: ElementConfig<never>, isPrepended = false): ElementConfig => {
79
+ const entry: ElementConfig = { ...base };
80
+
81
+ if (added.behaviors !== undefined) {
82
+ entry.behaviors = mergeBehaviors(entry, added.behaviors as ElementBehavior[], isPrepended);
83
+ }
84
+
85
+ if (added.lazy === true) {
86
+ entry.lazy = true;
87
+ }
88
+
89
+ if (added.component !== undefined) {
90
+ entry.component = added.component;
91
+ }
92
+
93
+ if (added.props !== undefined) {
94
+ entry.props = added.props;
95
+ }
96
+
97
+ return entry;
98
+ };
99
+
100
+ /**
101
+ * Merges maps of {@link ElementConfig} keyed by GLib type name into one, concatenating each type's
102
+ * behaviors in the order the maps are given (an earlier map's behaviors come first) and taking the last
103
+ * lazy flag, component, and props seen. Use it to combine an app's element config with its behaviors.
104
+ */
105
+ const mergeElementConfigs = (...maps: Record<string, ElementConfig<never>>[]): Record<string, ElementConfig> => {
106
+ const merged: Record<string, ElementConfig> = {};
107
+
108
+ for (const map of maps) {
109
+ for (const [type, config] of Object.entries(map)) {
110
+ merged[type] = mergeConfigEntry(merged[type] ?? {}, config);
111
+ }
112
+ }
113
+
114
+ return merged;
115
+ };
116
+
117
+ /**
118
+ * Registers a map of {@link ElementConfig} keyed by GLib type name, merging each entry into the
119
+ * registry. Behaviors are appended by default (the framework's built-ins register this way); pass
120
+ * `{ prepend: true }` for an app's own configuration so its behaviors are consulted before the
121
+ * built-ins for the same slot, letting it override them regardless of registration order.
122
+ */
123
+ const registerElements = (
124
+ map: Record<string, ElementConfig<never>>,
125
+ options: { prepend?: boolean } = {},
126
+ ): void => {
127
+ for (const [type, config] of Object.entries(map)) {
128
+ ELEMENTS[type] = mergeConfigEntry(ELEMENTS[type] ?? {}, config, options.prepend === true);
129
+ }
130
+ };
131
+
132
+ /**
133
+ * Identity helper that types the module named by the `elements` entry of `gtkx.config.ts`, enabling
134
+ * editor autocompletion and type checking. Key each entry by GLib type name and annotate each hook's
135
+ * object parameter with the concrete GObject class the behavior applies to.
136
+ */
137
+ const defineElements = (elements: Record<string, ElementConfig<never>>): Record<string, ElementConfig<never>> =>
138
+ elements;
139
+
140
+ /** Spreads one config across many GLib type names. */
141
+ const forTypes = (types: string[], config: ElementConfig<never>): Record<string, ElementConfig<never>> =>
142
+ Object.fromEntries(types.map((type) => [type, config]));
143
+
144
+ /** References a base props interface exported from `@gtkx/react/internal`. */
145
+ const internal = (name: string): ModuleExport => ({ module: "@gtkx/react/internal", export: name });
146
+
147
+ export {
148
+ ELEMENTS,
149
+ deferredProps,
150
+ mergeElementConfigs,
151
+ registerElements,
152
+ defineElements,
153
+ forTypes,
154
+ internal,
155
+ type Props,
156
+ type PlaceInfo,
157
+ type DetachInfo,
158
+ type ElementBehavior,
159
+ type ModuleExport,
160
+ type ElementConfig,
161
+ };
@@ -1,14 +1,12 @@
1
- const ROOT_ELEMENT: unique symbol = Symbol.for("gtkx.rootElement");
1
+ /** The type of the shared {@link rootElement} marker used as a default top-level container. */
2
+ type RootElement = { [ROOT_ELEMENT_BRAND]: true };
2
3
 
3
- /**
4
- * The type of the singleton marker used as the top-level render container.
5
- */
6
- export type RootElement = { [ROOT_ELEMENT]: true };
4
+ const ROOT_ELEMENT_BRAND: unique symbol = Symbol.for("gtkx:root-element");
5
+ /** A shared marker value used as the default top-level container for rendering and portals. */
6
+ const rootElement: RootElement = { [ROOT_ELEMENT_BRAND]: true };
7
7
 
8
- /**
9
- * The shared root element used as the default container for `createRoot`.
10
- */
11
- export const rootElement: RootElement = { [ROOT_ELEMENT]: true };
8
+ /** Reports whether an arbitrary value is a {@link rootElement} marker. */
9
+ const isRootElement = (value: unknown): value is RootElement =>
10
+ typeof value === "object" && value !== null && Object.hasOwn(value, ROOT_ELEMENT_BRAND);
12
11
 
13
- export const isRootElement = (value: unknown): value is RootElement =>
14
- typeof value === "object" && value !== null && ROOT_ELEMENT in value;
12
+ export { rootElement, isRootElement, type RootElement };
@@ -0,0 +1,175 @@
1
+ import type { ErrorInfo, ReactNode } from "react";
2
+ import * as Gdk from "@gtkx/gi/gdk";
3
+ import { createLogger, type Logger } from "@gtkx/utils";
4
+ import { ConcurrentRoot } from "react-reconciler/constants.js";
5
+ import { type Container, reconciler } from "./host-config.js";
6
+ import { rootElement } from "./root-element.js";
7
+ import { endSuppressionNow } from "./signals.js";
8
+
9
+ type OpaqueRoot = { [opaqueRoot]: true };
10
+
11
+ type RootErrorCallbacks = {
12
+ onUncaughtError?: (error: unknown, info: ErrorInfo) => void;
13
+ onCaughtError?: (error: unknown, info: ErrorInfo) => void;
14
+ onRecoverableError?: (error: unknown, info: ErrorInfo) => void;
15
+ };
16
+
17
+ type ReconcilerRootOptions = RootErrorCallbacks & { containerInfo: Container };
18
+
19
+ /** A root that mounts an element tree into an explicit container and reports render errors. */
20
+ type ReconcilerRoot = {
21
+ update: (element: ReactNode) => void;
22
+ unmount: (teardown: (root: ReconcilerRoot) => Promise<void>) => Promise<void>;
23
+ };
24
+
25
+ /** The object {@link createRoot} returns: it renders an element tree into a container and can tear it down. */
26
+ type Root = {
27
+ render: (element: ReactNode) => void;
28
+ unmount: () => void;
29
+ };
30
+
31
+ type ErrorHandler = (error: unknown) => void;
32
+ type ErrorHandlerSlot = { get: () => ErrorHandler | null; set: (handler: ErrorHandler) => ErrorHandler | null };
33
+
34
+ declare const opaqueRoot: unique symbol;
35
+ const log: Logger = createLogger("react");
36
+ const activeRoots: Set<OpaqueRoot> = new Set();
37
+ const errorHandlerSlot = createErrorHandlerSlot();
38
+
39
+ function createErrorHandlerSlot(): ErrorHandlerSlot {
40
+ let current: ErrorHandler | null = null;
41
+
42
+ return {
43
+ get: () => current,
44
+ set: (handler) => {
45
+ const previous = current;
46
+ current = handler;
47
+
48
+ return previous;
49
+ },
50
+ };
51
+ }
52
+
53
+ /**
54
+ * Installs a process-wide handler for errors thrown while rendering or applying an update.
55
+ *
56
+ * @param handler The handler to install.
57
+ * @returns The previously installed handler, or null.
58
+ */
59
+ const setReconcilerErrorHandler = (handler: ErrorHandler): ErrorHandler | null => errorHandlerSlot.set(handler);
60
+
61
+ const rethrowUncaughtRenderError = (error: unknown): never => {
62
+ endSuppressionNow();
63
+ throw error;
64
+ };
65
+
66
+ const logCaughtRenderError = (error: unknown): void => {
67
+ endSuppressionNow();
68
+ log.error("caught render error", error);
69
+ };
70
+
71
+ const openContainer = (containerInfo: Container, callbacks: RootErrorCallbacks): OpaqueRoot => {
72
+ const container = reconciler.createContainer(
73
+ containerInfo,
74
+ ConcurrentRoot,
75
+ null,
76
+ false,
77
+ null,
78
+ "",
79
+ (error, info) => {
80
+ errorHandlerSlot.get()?.(error);
81
+ callbacks.onUncaughtError?.(error, info);
82
+ },
83
+ (error, info) => {
84
+ errorHandlerSlot.get()?.(error);
85
+ callbacks.onCaughtError?.(error, info);
86
+ },
87
+ (error, info) => {
88
+ callbacks.onRecoverableError?.(error, info);
89
+ },
90
+ (): void => undefined,
91
+ ) as OpaqueRoot;
92
+
93
+ activeRoots.add(container);
94
+
95
+ return container;
96
+ };
97
+
98
+ const unmountContainer = (container: OpaqueRoot): void => {
99
+ reconciler.updateContainer(null, container, null, null);
100
+ activeRoots.delete(container);
101
+ };
102
+
103
+ /**
104
+ * Creates a root that mounts an element tree into a container, routing render errors to the supplied callbacks.
105
+ *
106
+ * @param options The container to render into and the error callbacks to route failures to.
107
+ * @returns A {@link ReconcilerRoot}.
108
+ */
109
+ const createReconcilerRoot = (options: ReconcilerRootOptions): ReconcilerRoot => {
110
+ const container = openContainer(options.containerInfo, options);
111
+
112
+ const root: ReconcilerRoot = {
113
+ update: (element) => {
114
+ reconciler.updateContainer(element, container, null, null);
115
+ },
116
+ unmount: async (teardown) => {
117
+ await teardown(root);
118
+ activeRoots.delete(container);
119
+ },
120
+ };
121
+
122
+ return root;
123
+ };
124
+
125
+ /**
126
+ * Creates a render root for a GTKX application.
127
+ *
128
+ * @param container The top-level container to render into; defaults to the shared {@link rootElement}.
129
+ * @returns A {@link Root} exposing render and unmount.
130
+ */
131
+ const createRoot = (container: Container = rootElement): Root => {
132
+ const opaque = openContainer(container, {
133
+ onUncaughtError: rethrowUncaughtRenderError,
134
+ onCaughtError: logCaughtRenderError,
135
+ });
136
+
137
+ return {
138
+ render: (element) => {
139
+ reconciler.updateContainer(element, opaque, null, null);
140
+ },
141
+ unmount: () => {
142
+ unmountContainer(opaque);
143
+ },
144
+ };
145
+ };
146
+
147
+ /** Unmounts every active render root and stops the originating signal from propagating further. */
148
+ const quit = (): typeof Gdk.EVENT_STOP => {
149
+ for (const container of activeRoots) {
150
+ unmountContainer(container);
151
+ }
152
+
153
+ return Gdk.EVENT_STOP;
154
+ };
155
+
156
+ /**
157
+ * Renders children into a container other than the surrounding tree.
158
+ *
159
+ * @param children The element tree to render.
160
+ * @param container The GObject, application, or {@link rootElement} to render into.
161
+ * @param key An optional stable key.
162
+ * @returns A React portal.
163
+ */
164
+ const createPortal = (children: ReactNode, container: Container, key?: string): ReactNode =>
165
+ Object.assign(reconciler.createPortal(children, container, null, key ?? null), { type: "gtkx-portal", props: {} });
166
+
167
+ export {
168
+ setReconcilerErrorHandler,
169
+ createReconcilerRoot,
170
+ createRoot,
171
+ quit,
172
+ createPortal,
173
+ type ReconcilerRoot,
174
+ type Root,
175
+ };
@@ -0,0 +1,113 @@
1
+ import { getSignalBaseName, type SignalHandler } from "@gtkx/runtime";
2
+ import { camelCase } from "@gtkx/utils";
3
+ import type { HandlerRecord, SignalTarget } from "./node.js";
4
+ import { type TypeInfo, typeInfoFor } from "./metadata.js";
5
+
6
+ type SuppressionCounter = {
7
+ beginSuppression: () => void;
8
+ endSuppression: () => void;
9
+ endSuppressionNow: () => void;
10
+ isSuppressed: () => boolean;
11
+ };
12
+
13
+ const NOTIFY_DETAIL_PREFIX = "notify::";
14
+ const suppressionCounter: SuppressionCounter = createSuppressionCounter();
15
+ const beginSuppression: () => void = suppressionCounter.beginSuppression;
16
+ const endSuppression: () => void = suppressionCounter.endSuppression;
17
+ const endSuppressionNow: () => void = suppressionCounter.endSuppressionNow;
18
+ const isSuppressed: () => boolean = suppressionCounter.isSuppressed;
19
+
20
+ function createSuppressionCounter(): SuppressionCounter {
21
+ let depth = 0;
22
+
23
+ const release = (): void => {
24
+ if (depth > 0) {
25
+ depth -= 1;
26
+ }
27
+ };
28
+
29
+ return {
30
+ beginSuppression: () => {
31
+ depth += 1;
32
+ },
33
+ endSuppression: () => {
34
+ queueMicrotask(release);
35
+ },
36
+ endSuppressionNow: release,
37
+ isSuppressed: () => depth > 0,
38
+ };
39
+ }
40
+
41
+ const getNotifyProperty = (signal: string): string | null =>
42
+ signal.startsWith(NOTIFY_DETAIL_PREFIX) ? camelCase(signal.slice(NOTIFY_DETAIL_PREFIX.length)) : null;
43
+
44
+ const isBlockableSignal = (info: TypeInfo, signal: string): boolean =>
45
+ info.userEventSignals.has(getSignalBaseName(signal));
46
+
47
+ const invokeHandler = (
48
+ target: SignalTarget,
49
+ record: HandlerRecord,
50
+ notifyProperty: string | null,
51
+ args: unknown[],
52
+ ): unknown =>
53
+ notifyProperty === null
54
+ ? record.handler(...args, target.object)
55
+ : record.handler(Reflect.get(target.object, notifyProperty), target.object);
56
+
57
+ const wrapHandler = (target: SignalTarget, record: HandlerRecord, notifyProperty: string | null): SignalHandler =>
58
+ (...args: unknown[]): unknown => {
59
+ if (record.blockable && isSuppressed()) {
60
+ return undefined;
61
+ }
62
+
63
+ return target.dispatch(() => invokeHandler(target, record, notifyProperty, args));
64
+ };
65
+
66
+ const connectHandler = (target: SignalTarget, prop: string, signal: string, handler: SignalHandler): void => {
67
+ const existing = target.handlers.get(prop);
68
+
69
+ if (existing?.signal === signal) {
70
+ existing.handler = handler;
71
+
72
+ return;
73
+ }
74
+
75
+ if (existing !== undefined) {
76
+ target.object.off(existing.signal, existing.wrapped);
77
+ }
78
+
79
+ const isBlockable = isBlockableSignal(typeInfoFor(target.typeName), signal);
80
+ const notifyProperty = getNotifyProperty(signal);
81
+ const record: HandlerRecord = { signal, handler, wrapped: (): undefined => undefined, blockable: isBlockable };
82
+ record.wrapped = wrapHandler(target, record, notifyProperty);
83
+ target.object.on(signal, record.wrapped);
84
+ target.handlers.set(prop, record);
85
+ };
86
+
87
+ const disconnectHandler = (target: SignalTarget, prop: string): void => {
88
+ const record = target.handlers.get(prop);
89
+
90
+ if (record === undefined) {
91
+ return;
92
+ }
93
+
94
+ target.object.off(record.signal, record.wrapped);
95
+ target.handlers.delete(prop);
96
+ };
97
+
98
+ const disconnectAllHandlers = (target: SignalTarget): void => {
99
+ for (const record of target.handlers.values()) {
100
+ target.object.off(record.signal, record.wrapped);
101
+ }
102
+
103
+ target.handlers.clear();
104
+ };
105
+
106
+ export {
107
+ beginSuppression,
108
+ endSuppression,
109
+ endSuppressionNow,
110
+ connectHandler,
111
+ disconnectHandler,
112
+ disconnectAllHandlers,
113
+ };