@gjsify/adwaita-web 0.54.0 → 0.56.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 (479) hide show
  1. package/README.md +8 -0
  2. package/dist/adwaita-web.css +8146 -3011
  3. package/dist/adwaita-web.css.map +1 -1
  4. package/lib/types/adw-application-window.spec.d.ts +1 -0
  5. package/lib/types/adw-bin.spec.d.ts +1 -0
  6. package/lib/types/adw-breakpoint-bin.spec.d.ts +1 -0
  7. package/lib/types/adw-clamp-scrollable.spec.d.ts +1 -0
  8. package/lib/types/adw-multi-layout-view.spec.d.ts +1 -0
  9. package/lib/types/adw-preferences-row.spec.d.ts +1 -0
  10. package/lib/types/adw-shortcuts.spec.d.ts +1 -0
  11. package/lib/types/adw-status-page.spec.d.ts +1 -0
  12. package/lib/types/adw-tab-bar.spec.d.ts +1 -0
  13. package/lib/types/adw-tab-button.spec.d.ts +1 -0
  14. package/lib/types/adw-tab-overview.spec.d.ts +1 -0
  15. package/lib/types/adw-view-switcher-sidebar.spec.d.ts +1 -0
  16. package/lib/types/adw-window.spec.d.ts +1 -0
  17. package/lib/types/attributes.d.ts +19 -0
  18. package/lib/types/breakpoints.d.ts +14 -3
  19. package/lib/types/construct-vectors.spec.d.ts +1 -0
  20. package/lib/types/elements/adw-action-row.d.ts +4 -0
  21. package/lib/types/elements/adw-application-window.d.ts +27 -0
  22. package/lib/types/elements/adw-bin.d.ts +17 -0
  23. package/lib/types/elements/adw-breakpoint-bin.d.ts +67 -0
  24. package/lib/types/elements/adw-clamp-scrollable.d.ts +38 -0
  25. package/lib/types/elements/adw-combo-row.d.ts +4 -0
  26. package/lib/types/elements/adw-dialog.d.ts +10 -0
  27. package/lib/types/elements/adw-entry-row.d.ts +6 -0
  28. package/lib/types/elements/adw-expander-row.d.ts +2 -0
  29. package/lib/types/elements/adw-header-bar.d.ts +6 -0
  30. package/lib/types/elements/adw-layout-slot.d.ts +19 -0
  31. package/lib/types/elements/adw-multi-layout-view.d.ts +101 -0
  32. package/lib/types/elements/adw-overlay-split-view.d.ts +13 -0
  33. package/lib/types/elements/adw-preferences-row.d.ts +31 -0
  34. package/lib/types/elements/adw-shortcuts-dialog.d.ts +13 -0
  35. package/lib/types/elements/adw-shortcuts-item.d.ts +36 -0
  36. package/lib/types/elements/adw-shortcuts-section.d.ts +14 -0
  37. package/lib/types/elements/adw-sidebar.d.ts +8 -2
  38. package/lib/types/elements/adw-spin-row.d.ts +6 -0
  39. package/lib/types/elements/adw-switch-row.d.ts +7 -0
  40. package/lib/types/elements/adw-tab-bar.d.ts +108 -0
  41. package/lib/types/elements/adw-tab-button.d.ts +32 -0
  42. package/lib/types/elements/adw-tab-overview.d.ts +199 -0
  43. package/lib/types/elements/adw-tab-view.d.ts +19 -23
  44. package/lib/types/elements/adw-toggle-group.d.ts +17 -0
  45. package/lib/types/elements/adw-view-switcher-sidebar.d.ts +84 -0
  46. package/lib/types/elements/adw-window.d.ts +40 -0
  47. package/lib/types/elements/gtk-about-dialog.d.ts +146 -0
  48. package/lib/types/elements/gtk-application-window.d.ts +34 -0
  49. package/lib/types/elements/gtk-aspect-frame.d.ts +27 -0
  50. package/lib/types/elements/gtk-button.d.ts +9 -0
  51. package/lib/types/elements/gtk-calendar.d.ts +159 -0
  52. package/lib/types/elements/gtk-center-box.d.ts +39 -0
  53. package/lib/types/elements/gtk-color-dialog-button.d.ts +69 -0
  54. package/lib/types/elements/gtk-column-view.d.ts +50 -0
  55. package/lib/types/elements/gtk-drag-icon.d.ts +78 -0
  56. package/lib/types/elements/gtk-drawing-area.d.ts +95 -0
  57. package/lib/types/elements/gtk-editable-label.d.ts +33 -0
  58. package/lib/types/elements/gtk-emoji-chooser.d.ts +84 -0
  59. package/lib/types/elements/gtk-entry.d.ts +20 -1
  60. package/lib/types/elements/gtk-expander.d.ts +49 -0
  61. package/lib/types/elements/gtk-fixed.d.ts +13 -0
  62. package/lib/types/elements/gtk-flow-box-child.d.ts +14 -0
  63. package/lib/types/elements/gtk-flow-box.d.ts +87 -0
  64. package/lib/types/elements/gtk-font-dialog-button.d.ts +83 -0
  65. package/lib/types/elements/gtk-frame.d.ts +24 -0
  66. package/lib/types/elements/gtk-gl-area.d.ts +136 -0
  67. package/lib/types/elements/gtk-graphics-offload.d.ts +24 -0
  68. package/lib/types/elements/gtk-grid-view.d.ts +39 -0
  69. package/lib/types/elements/gtk-grid.d.ts +27 -0
  70. package/lib/types/elements/gtk-header-bar.d.ts +60 -0
  71. package/lib/types/elements/gtk-inscription.d.ts +64 -0
  72. package/lib/types/elements/gtk-label.d.ts +3 -0
  73. package/lib/types/elements/gtk-level-bar.d.ts +59 -0
  74. package/lib/types/elements/gtk-link-button.d.ts +29 -0
  75. package/lib/types/elements/gtk-list-box-row.d.ts +54 -0
  76. package/lib/types/elements/gtk-list-box.d.ts +100 -0
  77. package/lib/types/elements/gtk-list-view.d.ts +73 -0
  78. package/lib/types/elements/gtk-media-controls.d.ts +142 -0
  79. package/lib/types/elements/gtk-notebook.d.ts +148 -0
  80. package/lib/types/elements/gtk-overlay.d.ts +22 -0
  81. package/lib/types/elements/gtk-page-setup-unix-dialog.d.ts +87 -0
  82. package/lib/types/elements/gtk-paned.d.ts +121 -0
  83. package/lib/types/elements/gtk-password-entry.d.ts +27 -0
  84. package/lib/types/elements/gtk-picture.d.ts +66 -0
  85. package/lib/types/elements/gtk-popover-bin.d.ts +82 -0
  86. package/lib/types/elements/gtk-popover-menu-bar.d.ts +66 -0
  87. package/lib/types/elements/gtk-popover-menu.d.ts +83 -0
  88. package/lib/types/elements/gtk-popover.d.ts +28 -3
  89. package/lib/types/elements/gtk-print-unix-dialog.d.ts +167 -0
  90. package/lib/types/elements/gtk-revealer.d.ts +55 -0
  91. package/lib/types/elements/gtk-scale-button.d.ts +59 -0
  92. package/lib/types/elements/gtk-scale.d.ts +98 -0
  93. package/lib/types/elements/gtk-scrollbar.d.ts +124 -0
  94. package/lib/types/elements/gtk-scrolled-window.d.ts +129 -0
  95. package/lib/types/elements/gtk-search-bar.d.ts +39 -0
  96. package/lib/types/elements/gtk-search-entry.d.ts +27 -0
  97. package/lib/types/elements/gtk-separator.d.ts +10 -0
  98. package/lib/types/elements/gtk-spin-button.d.ts +94 -0
  99. package/lib/types/elements/gtk-spinner.d.ts +14 -0
  100. package/lib/types/elements/gtk-stack-sidebar.d.ts +43 -0
  101. package/lib/types/elements/gtk-stack-switcher.d.ts +58 -0
  102. package/lib/types/elements/gtk-stack.d.ts +154 -0
  103. package/lib/types/elements/gtk-switch.d.ts +4 -1
  104. package/lib/types/elements/gtk-text-view.d.ts +62 -0
  105. package/lib/types/elements/gtk-text.d.ts +45 -0
  106. package/lib/types/elements/gtk-toggle-button.d.ts +45 -0
  107. package/lib/types/elements/gtk-tree-expander.d.ts +38 -0
  108. package/lib/types/elements/gtk-video.d.ts +97 -0
  109. package/lib/types/elements/gtk-viewport.d.ts +84 -0
  110. package/lib/types/elements/gtk-window-controls.d.ts +80 -0
  111. package/lib/types/elements/gtk-window-handle.d.ts +39 -0
  112. package/lib/types/elements/gtk-window.d.ts +103 -0
  113. package/lib/types/elements/justification.d.ts +2 -0
  114. package/lib/types/elements/popover-menu.d.ts +18 -0
  115. package/lib/types/elements/roving-focus.d.ts +29 -1
  116. package/lib/types/emoji-data.d.ts +38 -0
  117. package/lib/types/font-description.d.ts +96 -0
  118. package/lib/types/gtk-about-dialog.spec.d.ts +1 -0
  119. package/lib/types/gtk-action-bar.spec.d.ts +1 -0
  120. package/lib/types/gtk-application-window.spec.d.ts +1 -0
  121. package/lib/types/gtk-aspect-frame.spec.d.ts +1 -0
  122. package/lib/types/gtk-calendar.spec.d.ts +1 -0
  123. package/lib/types/gtk-center-box.spec.d.ts +1 -0
  124. package/lib/types/gtk-color-dialog-button.spec.d.ts +1 -0
  125. package/lib/types/gtk-column-view.spec.d.ts +1 -0
  126. package/lib/types/gtk-drag-icon.spec.d.ts +1 -0
  127. package/lib/types/gtk-drawing-area.spec.d.ts +1 -0
  128. package/lib/types/gtk-editable-label.spec.d.ts +1 -0
  129. package/lib/types/gtk-emoji-chooser.spec.d.ts +1 -0
  130. package/lib/types/gtk-expander.spec.d.ts +1 -0
  131. package/lib/types/gtk-fixed.spec.d.ts +1 -0
  132. package/lib/types/gtk-flow-box.spec.d.ts +1 -0
  133. package/lib/types/gtk-font-dialog-button.spec.d.ts +1 -0
  134. package/lib/types/gtk-frame.spec.d.ts +1 -0
  135. package/lib/types/gtk-gl-area.spec.d.ts +1 -0
  136. package/lib/types/gtk-graphics-offload.spec.d.ts +1 -0
  137. package/lib/types/gtk-grid-view.spec.d.ts +1 -0
  138. package/lib/types/gtk-grid.spec.d.ts +1 -0
  139. package/lib/types/gtk-header-bar.spec.d.ts +1 -0
  140. package/lib/types/gtk-inscription.spec.d.ts +1 -0
  141. package/lib/types/gtk-level-bar.spec.d.ts +1 -0
  142. package/lib/types/gtk-link-button.spec.d.ts +1 -0
  143. package/lib/types/gtk-list-box.spec.d.ts +1 -0
  144. package/lib/types/gtk-list-view.spec.d.ts +1 -0
  145. package/lib/types/gtk-media-controls.spec.d.ts +1 -0
  146. package/lib/types/gtk-notebook.spec.d.ts +1 -0
  147. package/lib/types/gtk-overlay.spec.d.ts +1 -0
  148. package/lib/types/gtk-paned.spec.d.ts +1 -0
  149. package/lib/types/gtk-password-entry.spec.d.ts +1 -0
  150. package/lib/types/gtk-picture.spec.d.ts +1 -0
  151. package/lib/types/gtk-popover-bin.spec.d.ts +1 -0
  152. package/lib/types/gtk-popover-menu-bar.spec.d.ts +1 -0
  153. package/lib/types/gtk-popover-menu.spec.d.ts +1 -0
  154. package/lib/types/gtk-popover-role.spec.d.ts +1 -0
  155. package/lib/types/gtk-popover.spec.d.ts +1 -0
  156. package/lib/types/gtk-print-dialogs.spec.d.ts +1 -0
  157. package/lib/types/gtk-revealer.spec.d.ts +1 -0
  158. package/lib/types/gtk-scale-button.spec.d.ts +1 -0
  159. package/lib/types/gtk-scale.spec.d.ts +1 -0
  160. package/lib/types/gtk-scrollbar.spec.d.ts +1 -0
  161. package/lib/types/gtk-scrolled-window.spec.d.ts +1 -0
  162. package/lib/types/gtk-search-bar.spec.d.ts +1 -0
  163. package/lib/types/gtk-search-entry.spec.d.ts +1 -0
  164. package/lib/types/gtk-separator.spec.d.ts +1 -0
  165. package/lib/types/gtk-spin-button.spec.d.ts +1 -0
  166. package/lib/types/gtk-spinner.spec.d.ts +1 -0
  167. package/lib/types/gtk-stack-sidebar.spec.d.ts +1 -0
  168. package/lib/types/gtk-stack-switcher.spec.d.ts +1 -0
  169. package/lib/types/gtk-stack.spec.d.ts +1 -0
  170. package/lib/types/gtk-text-view.spec.d.ts +1 -0
  171. package/lib/types/gtk-text.spec.d.ts +1 -0
  172. package/lib/types/gtk-toggle-button.spec.d.ts +1 -0
  173. package/lib/types/gtk-tree-expander.spec.d.ts +1 -0
  174. package/lib/types/gtk-video.spec.d.ts +1 -0
  175. package/lib/types/gtk-viewport.spec.d.ts +1 -0
  176. package/lib/types/gtk-window-controls.spec.d.ts +1 -0
  177. package/lib/types/gtk-window-handle.spec.d.ts +1 -0
  178. package/lib/types/gtk-window.spec.d.ts +1 -0
  179. package/lib/types/index.d.ts +4 -1
  180. package/lib/types/list-view-dom.d.ts +44 -0
  181. package/lib/types/namespace/adw.d.ts +12 -0
  182. package/lib/types/namespace/gtk.d.ts +61 -0
  183. package/lib/types/page-setup.d.ts +100 -0
  184. package/lib/types/row-line-clamp.d.ts +20 -0
  185. package/lib/types/row-tooltip.d.ts +8 -0
  186. package/lib/types/row-tooltip.spec.d.ts +1 -0
  187. package/lib/types/scroll-shading.d.ts +15 -1
  188. package/lib/types/shared-tree-builder.d.ts +75 -17
  189. package/lib/types/shared-tree-mount.spec.d.ts +1 -0
  190. package/lib/types/signals.d.ts +4 -0
  191. package/lib/types/styles.generated.d.ts +1 -1
  192. package/lib/types/tab-chip.d.ts +73 -0
  193. package/lib/types/template-classes.d.ts +11 -0
  194. package/lib/types/widget-size.spec.d.ts +1 -0
  195. package/package.json +12 -8
  196. package/scss/_action_row.scss +41 -17
  197. package/scss/_application_window.scss +26 -0
  198. package/scss/_aspect_frame.scss +25 -0
  199. package/scss/_bin.scss +26 -0
  200. package/scss/_button.scss +45 -0
  201. package/scss/_button_row.scss +5 -0
  202. package/scss/_calendar.scss +176 -0
  203. package/scss/_center_box.scss +25 -0
  204. package/scss/_checks.scss +6 -1
  205. package/scss/_clamp_scrollable.scss +28 -0
  206. package/scss/_color_button.scss +67 -0
  207. package/scss/_column_view.scss +126 -0
  208. package/scss/_drag_icon.scss +55 -0
  209. package/scss/_drawing.scss +85 -0
  210. package/scss/_emoji_chooser.scss +213 -0
  211. package/scss/_entry.scss +13 -5
  212. package/scss/_entry_row.scss +1 -1
  213. package/scss/_expander.scss +113 -0
  214. package/scss/_expander_row.scss +36 -3
  215. package/scss/_fixed.scss +29 -0
  216. package/scss/_flow_box.scss +94 -0
  217. package/scss/_font_button.scss +63 -0
  218. package/scss/_frame.scss +41 -0
  219. package/scss/_grid.scss +19 -0
  220. package/scss/_grid_view.scss +46 -0
  221. package/scss/_gtk_about_dialog.scss +186 -0
  222. package/scss/_headerbar.scss +134 -1
  223. package/scss/_icons.generated.scss +186 -0
  224. package/scss/_inscription.scss +125 -0
  225. package/scss/_level_bar.scss +190 -0
  226. package/scss/_link.scss +82 -0
  227. package/scss/_list_box.scss +88 -0
  228. package/scss/_list_view.scss +96 -0
  229. package/scss/_media_controls.scss +139 -0
  230. package/scss/_overlay.scss +68 -0
  231. package/scss/_paned.scss +130 -0
  232. package/scss/_password_entry.scss +83 -0
  233. package/scss/_picture.scss +80 -0
  234. package/scss/_popover_bin.scss +53 -0
  235. package/scss/_popover_menu_bar.scss +104 -0
  236. package/scss/_preferences_row.scss +60 -0
  237. package/scss/_print_dialogs.scss +328 -0
  238. package/scss/_reset.scss +21 -19
  239. package/scss/_revealer.scss +37 -0
  240. package/scss/_row.scss +36 -5
  241. package/scss/_scale.scss +298 -0
  242. package/scss/_scale_button.scss +167 -0
  243. package/scss/_scrollbar.scss +230 -0
  244. package/scss/_scrolled_window.scss +131 -0
  245. package/scss/_search_bar.scss +118 -0
  246. package/scss/_search_entry.scss +86 -0
  247. package/scss/_separator.scss +44 -0
  248. package/scss/_shortcuts_dialog.scss +100 -0
  249. package/scss/_spin_button.scss +172 -0
  250. package/scss/_spin_row.scss +56 -8
  251. package/scss/_spinner.scss +85 -4
  252. package/scss/_stack.scss +729 -0
  253. package/scss/_status_page.scss +1 -1
  254. package/scss/_switch.scss +13 -5
  255. package/scss/_switch_row.scss +10 -0
  256. package/scss/_tab_bar.scss +317 -0
  257. package/scss/_tab_button.scss +98 -0
  258. package/scss/_tab_overview.scss +483 -0
  259. package/scss/_text.scss +182 -0
  260. package/scss/_theme.scss +1 -1
  261. package/scss/_toggle_group.scss +28 -0
  262. package/scss/_tree_expander.scss +62 -0
  263. package/scss/_variables.scss +1 -1
  264. package/scss/_video.scss +146 -0
  265. package/scss/_view_switcher_sidebar.scss +112 -0
  266. package/scss/_viewport.scss +50 -0
  267. package/scss/_widget.scss +14 -3
  268. package/scss/_window.scss +131 -2
  269. package/scss/_window_handle.scss +20 -0
  270. package/scss/adwaita-skin.scss +109 -0
  271. package/src/adw-action-rows.spec.ts +331 -0
  272. package/src/adw-application-window.spec.ts +118 -0
  273. package/src/adw-bin.spec.ts +75 -0
  274. package/src/adw-breakpoint-bin.spec.ts +324 -0
  275. package/src/adw-clamp-scrollable.spec.ts +189 -0
  276. package/src/adw-header-bar.spec.ts +18 -0
  277. package/src/adw-multi-layout-view.spec.ts +243 -0
  278. package/src/adw-preferences-row.spec.ts +164 -0
  279. package/src/adw-row-state.spec.ts +142 -0
  280. package/src/adw-shortcuts.spec.ts +155 -0
  281. package/src/adw-status-page.spec.ts +124 -0
  282. package/src/adw-tab-bar.spec.ts +287 -0
  283. package/src/adw-tab-button.spec.ts +101 -0
  284. package/src/adw-tab-overview.spec.ts +443 -0
  285. package/src/adw-view-switcher-sidebar.spec.ts +281 -0
  286. package/src/adw-window.spec.ts +129 -0
  287. package/src/attributes.ts +52 -0
  288. package/src/breakpoints.ts +25 -8
  289. package/src/capabilities.d.mts +3 -0
  290. package/src/capabilities.mjs +21 -0
  291. package/src/connect-lifecycle.spec.ts +12 -0
  292. package/src/construct-vectors.spec.ts +175 -0
  293. package/src/elements/adw-action-row.ts +31 -2
  294. package/src/elements/adw-alert-dialog.ts +4 -1
  295. package/src/elements/adw-application-window.ts +154 -0
  296. package/src/elements/adw-bin.ts +101 -0
  297. package/src/elements/adw-breakpoint-bin.ts +287 -0
  298. package/src/elements/adw-button-row.ts +7 -1
  299. package/src/elements/adw-clamp-scrollable.ts +207 -0
  300. package/src/elements/adw-combo-row.ts +26 -1
  301. package/src/elements/adw-dialog.ts +19 -0
  302. package/src/elements/adw-entry-row.ts +22 -12
  303. package/src/elements/adw-expander-row.ts +34 -1
  304. package/src/elements/adw-header-bar.ts +18 -4
  305. package/src/elements/adw-layout-slot.ts +95 -0
  306. package/src/elements/adw-multi-layout-view.ts +326 -0
  307. package/src/elements/adw-overlay-split-view.ts +29 -6
  308. package/src/elements/adw-preferences-row.ts +153 -0
  309. package/src/elements/adw-shortcuts-dialog.ts +52 -0
  310. package/src/elements/adw-shortcuts-item.ts +171 -0
  311. package/src/elements/adw-shortcuts-section.ts +86 -0
  312. package/src/elements/adw-sidebar.ts +74 -7
  313. package/src/elements/adw-spin-row.ts +37 -2
  314. package/src/elements/adw-status-page.ts +10 -2
  315. package/src/elements/adw-switch-row.ts +53 -2
  316. package/src/elements/adw-tab-bar.ts +529 -0
  317. package/src/elements/adw-tab-button.ts +194 -0
  318. package/src/elements/adw-tab-overview.ts +1011 -0
  319. package/src/elements/adw-tab-view.ts +66 -145
  320. package/src/elements/adw-toggle-group.ts +138 -14
  321. package/src/elements/adw-view-stack.ts +18 -0
  322. package/src/elements/adw-view-switcher-sidebar.ts +332 -0
  323. package/src/elements/adw-window.ts +190 -11
  324. package/src/elements/checks.ts +35 -8
  325. package/src/elements/gtk-about-dialog.ts +811 -0
  326. package/src/elements/gtk-application-window.ts +108 -0
  327. package/src/elements/gtk-aspect-frame.ts +160 -0
  328. package/src/elements/gtk-button.ts +12 -0
  329. package/src/elements/gtk-calendar.ts +757 -0
  330. package/src/elements/gtk-center-box.ts +184 -0
  331. package/src/elements/gtk-color-dialog-button.ts +278 -0
  332. package/src/elements/gtk-column-view.ts +320 -0
  333. package/src/elements/gtk-drag-icon.ts +257 -0
  334. package/src/elements/gtk-drawing-area.ts +303 -0
  335. package/src/elements/gtk-editable-label.ts +204 -0
  336. package/src/elements/gtk-emoji-chooser.ts +542 -0
  337. package/src/elements/gtk-entry.ts +39 -5
  338. package/src/elements/gtk-expander.ts +301 -0
  339. package/src/elements/gtk-fixed.ts +99 -0
  340. package/src/elements/gtk-flow-box-child.ts +68 -0
  341. package/src/elements/gtk-flow-box.ts +480 -0
  342. package/src/elements/gtk-font-dialog-button.ts +432 -0
  343. package/src/elements/gtk-frame.ts +174 -0
  344. package/src/elements/gtk-gl-area.ts +476 -0
  345. package/src/elements/gtk-graphics-offload.ts +130 -0
  346. package/src/elements/gtk-grid-view.ts +168 -0
  347. package/src/elements/gtk-grid.ts +127 -0
  348. package/src/elements/gtk-header-bar.ts +273 -0
  349. package/src/elements/gtk-inscription.ts +387 -0
  350. package/src/elements/gtk-label.ts +19 -11
  351. package/src/elements/gtk-level-bar.ts +323 -0
  352. package/src/elements/gtk-link-button.ts +138 -0
  353. package/src/elements/gtk-list-box-row.ts +195 -0
  354. package/src/elements/gtk-list-box.ts +413 -0
  355. package/src/elements/gtk-list-view.ts +370 -0
  356. package/src/elements/gtk-media-controls.ts +509 -0
  357. package/src/elements/gtk-notebook.ts +664 -0
  358. package/src/elements/gtk-overlay.ts +149 -0
  359. package/src/elements/gtk-page-setup-unix-dialog.ts +420 -0
  360. package/src/elements/gtk-paned.ts +597 -0
  361. package/src/elements/gtk-password-entry.ts +170 -0
  362. package/src/elements/gtk-picture.ts +254 -0
  363. package/src/elements/gtk-popover-bin.ts +332 -0
  364. package/src/elements/gtk-popover-menu-bar.ts +355 -0
  365. package/src/elements/gtk-popover-menu.ts +339 -0
  366. package/src/elements/gtk-popover.ts +92 -10
  367. package/src/elements/gtk-print-unix-dialog.ts +989 -0
  368. package/src/elements/gtk-progress-bar.ts +24 -11
  369. package/src/elements/gtk-revealer.ts +406 -0
  370. package/src/elements/gtk-scale-button.ts +358 -0
  371. package/src/elements/gtk-scale.ts +492 -0
  372. package/src/elements/gtk-scrollbar.ts +528 -0
  373. package/src/elements/gtk-scrolled-window.ts +653 -0
  374. package/src/elements/gtk-search-bar.ts +200 -0
  375. package/src/elements/gtk-search-entry.ts +172 -0
  376. package/src/elements/gtk-separator.ts +52 -0
  377. package/src/elements/gtk-spin-button.ts +475 -0
  378. package/src/elements/gtk-spinner.ts +126 -0
  379. package/src/elements/gtk-stack-sidebar.ts +212 -0
  380. package/src/elements/gtk-stack-switcher.ts +279 -0
  381. package/src/elements/gtk-stack.ts +748 -0
  382. package/src/elements/gtk-switch.ts +52 -19
  383. package/src/elements/gtk-text-view.ts +290 -0
  384. package/src/elements/gtk-text.ts +219 -0
  385. package/src/elements/gtk-toggle-button.ts +239 -0
  386. package/src/elements/gtk-tree-expander.ts +243 -0
  387. package/src/elements/gtk-video.ts +423 -0
  388. package/src/elements/gtk-viewport.ts +277 -0
  389. package/src/elements/gtk-window-controls.ts +341 -0
  390. package/src/elements/gtk-window-handle.ts +221 -0
  391. package/src/elements/gtk-window.ts +372 -0
  392. package/src/elements/justification.ts +24 -0
  393. package/src/elements/popover-menu.ts +24 -0
  394. package/src/elements/roving-focus.ts +53 -21
  395. package/src/emoji-data.ts +577 -0
  396. package/src/entry-rows.spec.ts +31 -0
  397. package/src/font-description.ts +238 -0
  398. package/src/gtk-about-dialog.spec.ts +250 -0
  399. package/src/gtk-action-bar.spec.ts +89 -0
  400. package/src/gtk-application-window.spec.ts +107 -0
  401. package/src/gtk-aspect-frame.spec.ts +114 -0
  402. package/src/gtk-calendar.spec.ts +589 -0
  403. package/src/gtk-center-box.spec.ts +125 -0
  404. package/src/gtk-color-dialog-button.spec.ts +141 -0
  405. package/src/gtk-column-view.spec.ts +154 -0
  406. package/src/gtk-drag-icon.spec.ts +190 -0
  407. package/src/gtk-drawing-area.spec.ts +211 -0
  408. package/src/gtk-editable-label.spec.ts +190 -0
  409. package/src/gtk-emoji-chooser.spec.ts +173 -0
  410. package/src/gtk-entry.spec.ts +23 -0
  411. package/src/gtk-expander.spec.ts +170 -0
  412. package/src/gtk-fixed.spec.ts +97 -0
  413. package/src/gtk-flow-box.spec.ts +289 -0
  414. package/src/gtk-font-dialog-button.spec.ts +166 -0
  415. package/src/gtk-frame.spec.ts +119 -0
  416. package/src/gtk-gl-area.spec.ts +361 -0
  417. package/src/gtk-graphics-offload.spec.ts +119 -0
  418. package/src/gtk-grid-view.spec.ts +106 -0
  419. package/src/gtk-grid.spec.ts +122 -0
  420. package/src/gtk-header-bar.spec.ts +202 -0
  421. package/src/gtk-inscription.spec.ts +235 -0
  422. package/src/gtk-level-bar.spec.ts +199 -0
  423. package/src/gtk-link-button.spec.ts +117 -0
  424. package/src/gtk-list-box.spec.ts +422 -0
  425. package/src/gtk-list-view.spec.ts +203 -0
  426. package/src/gtk-media-controls.spec.ts +295 -0
  427. package/src/gtk-notebook.spec.ts +546 -0
  428. package/src/gtk-overlay.spec.ts +141 -0
  429. package/src/gtk-paned.spec.ts +267 -0
  430. package/src/gtk-password-entry.spec.ts +150 -0
  431. package/src/gtk-picture.spec.ts +172 -0
  432. package/src/gtk-popover-bin.spec.ts +229 -0
  433. package/src/gtk-popover-menu-bar.spec.ts +296 -0
  434. package/src/gtk-popover-menu.spec.ts +261 -0
  435. package/src/gtk-popover-role.spec.ts +138 -0
  436. package/src/gtk-popover.spec.ts +264 -0
  437. package/src/gtk-print-dialogs.spec.ts +251 -0
  438. package/src/gtk-revealer.spec.ts +164 -0
  439. package/src/gtk-scale-button.spec.ts +218 -0
  440. package/src/gtk-scale.spec.ts +213 -0
  441. package/src/gtk-scrollbar.spec.ts +244 -0
  442. package/src/gtk-scrolled-window.spec.ts +262 -0
  443. package/src/gtk-search-bar.spec.ts +179 -0
  444. package/src/gtk-search-entry.spec.ts +142 -0
  445. package/src/gtk-separator.spec.ts +74 -0
  446. package/src/gtk-spin-button.spec.ts +186 -0
  447. package/src/gtk-spinner.spec.ts +130 -0
  448. package/src/gtk-stack-sidebar.spec.ts +217 -0
  449. package/src/gtk-stack-switcher.spec.ts +249 -0
  450. package/src/gtk-stack.spec.ts +432 -0
  451. package/src/gtk-text-view.spec.ts +189 -0
  452. package/src/gtk-text.spec.ts +163 -0
  453. package/src/gtk-toggle-button.spec.ts +186 -0
  454. package/src/gtk-tree-expander.spec.ts +201 -0
  455. package/src/gtk-video.spec.ts +240 -0
  456. package/src/gtk-viewport.spec.ts +140 -0
  457. package/src/gtk-window-controls.spec.ts +232 -0
  458. package/src/gtk-window-handle.spec.ts +158 -0
  459. package/src/gtk-window.spec.ts +202 -0
  460. package/src/index.ts +9 -1
  461. package/src/keyboard-operable.spec.ts +77 -9
  462. package/src/list-view-dom.ts +121 -0
  463. package/src/namespace/adw.ts +12 -0
  464. package/src/namespace/gtk.ts +61 -0
  465. package/src/page-setup.ts +222 -0
  466. package/src/row-line-clamp.ts +74 -0
  467. package/src/row-tooltip.spec.ts +313 -0
  468. package/src/row-tooltip.ts +52 -0
  469. package/src/scroll-shading.ts +18 -1
  470. package/src/shared-tree-builder.ts +336 -41
  471. package/src/shared-tree-mount.spec.ts +130 -0
  472. package/src/shared-trees.spec.ts +15 -0
  473. package/src/signals.ts +15 -0
  474. package/src/style-classes.spec.ts +9 -8
  475. package/src/styles.generated.ts +1 -1
  476. package/src/tab-chip.ts +200 -0
  477. package/src/template-classes.ts +45 -0
  478. package/src/test.browser.mts +160 -0
  479. package/src/widget-size.spec.ts +117 -0
@@ -0,0 +1,757 @@
1
+ // <gtk-calendar> — the month grid: a heading with four navigation arrows, the day-name row, an
2
+ // optional week-number column and 42 day cells, the web counterpart of `Gtk.Calendar`.
3
+ //
4
+ // THE GRID IS `calendarDays` AND FRIENDS, in `@gjsify/adwaita-core` (ADR 0004), because every
5
+ // part of it is arithmetic the C does in integers: which days lead the month, which trail it,
6
+ // what ISO week each row is, and what a month step lands on when the source day does not exist
7
+ // in the target. `calendar.ts` carries the derivations and the vectors; this element holds the
8
+ // marks, the focus cell and the date.
9
+ //
10
+ // `date` IS AN ISO `YYYY-MM-DD` STRING, which is what `GDateTime` is written as in every GTK
11
+ // binding and what `Date.parse` reads, so the markup door is the object's own ISO 8601
12
+ // serialisation rather than a port-specific encoding. The three DEPRECATED `year` / `month` /
13
+ // `day` properties are observed as attributes and kept in step with `date` exactly as
14
+ // upstream's setters do — `gtk_calendar_set_year` calls `calendar_select_day_internal` with
15
+ // the same day in the new year (gtkcalendar.c:860-880), so a write to `year` and a write to
16
+ // `date` are the same operation. They are deprecated in 4.20 in favour of `date` and this
17
+ // element says so rather than hiding them.
18
+ //
19
+ // `month` IS 0-11 HERE, because the attribute is the GIR property and GIR's property is
20
+ // 0-indexed — the ONE place this element departs from `GDateTime`'s own 1-12 numbering, and
21
+ // the property's own documentation states the range (:419-429). Core functions take 1-12 and
22
+ // say so; the boundary is exactly the two attribute readers below.
23
+ //
24
+ // SHOW-HEADING AND SHOW-DAY-NAMES DEFAULT TRUE, SHOW-WEEK-NUMBERS FALSE (:440-460), so the
25
+ // two are INVERTED flags read as `="false"`. The week-number column is a real grid COLUMN and
26
+ // not a decoration: upstream the day numbers are attached at column `1 + i` and the week
27
+ // numbers at column 0 (gtkcalendar.c:776-790), which is why turning the numbers on narrows
28
+ // the days rather than overlaying them.
29
+ //
30
+ // THE THREE ARROWS' SENSE. A cell belonging to the PREVIOUS month, activated with Space,
31
+ // pages BACK and selects that day (`calendar_set_month_prev`, gtkcalendar.c:1521-1534), and
32
+ // likewise forwards for the next month. The month and year arrows go through
33
+ // `calendar_select_day_internal` with `emit_day_signal = FALSE` (:868-919), so paging the
34
+ // calendar repaints without telling an application the user picked a day.
35
+ //
36
+ // WHAT IS NOT HERE: `gtk_calendar_select_day` is a deprecated METHOD in favour of the
37
+ // `date` property, so it is `date` here; `GtkDragSource` / `GtkDropTarget` (:543-560, :820-830)
38
+ // have no browser counterpart this element can reach for; and the `focus_row` / `focus_col`
39
+ // cursor is INTERNAL state upstream with no property, so it is the roving focus of the grid
40
+ // here — arrows move it, `Space` acts on the cell it is on, which is the C's `move_focus` +
41
+ // Space branch (gtkcalendar.c:1386-1534).
42
+ //
43
+ // Reference: refs/gtk/gtk/gtkcalendar.c:134-178 (the tables), :372-540 (properties, signals,
44
+ // css name), :564-861 (the widget tree and the defaults), :923-1084 (the grid, the labels, the
45
+ // navigation buttons), :1089-1192 (select_day_internal), :1311-1353 (the click), :1386-1534
46
+ // (move_focus and the key table), :1564-1782 (the public API)
47
+ // Reference: refs/libadwaita/src/stylesheet/widgets/_calendar.scss:1-58
48
+ // Copyright (c) GNOME contributors (GTK/libadwaita). LGPLv2.1+.
49
+ // Modifications: Implemented as a Web Component for @gjsify/adwaita-web; the date arithmetic
50
+ // composed from @gjsify/adwaita-core.
51
+
52
+ import {
53
+ CALENDAR_YEAR_MAX,
54
+ CALENDAR_YEAR_MIN,
55
+ calendarClearMarks,
56
+ calendarDayIsMarked,
57
+ calendarDays,
58
+ calendarMarkDay,
59
+ calendarNavigationButtons,
60
+ calendarSelectDay,
61
+ calendarStep,
62
+ calendarWeekNumber,
63
+ calendarWeekStart,
64
+ type AdwCalendarCell,
65
+ type AdwCalendarSelectResult,
66
+ type AdwCalendarDate,
67
+ type AdwCalendarStep,
68
+ } from '@gjsify/adwaita-core';
69
+
70
+ import { createGtkImage } from './gtk-image.js';
71
+
72
+ /** The seven abbreviated day names, Sunday first — `default_abbreviated_dayname` (:745-757). */
73
+ const DAY_NAMES = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
74
+
75
+ /** The twelve month names — `default_monthname` (:759-786), which strftime-falls-back to `%B`. */
76
+ const MONTH_NAMES = [
77
+ 'January',
78
+ 'February',
79
+ 'March',
80
+ 'April',
81
+ 'May',
82
+ 'June',
83
+ 'July',
84
+ 'August',
85
+ 'September',
86
+ 'October',
87
+ 'November',
88
+ 'December',
89
+ ];
90
+
91
+ /** The four arrows, in the order `gtk_calendar_init` appends them (:600-616). */
92
+ const ARROWS: readonly { step: AdwCalendarStep; icon: string; tooltip: string }[] = [
93
+ { step: 'previous-month', icon: 'go-previous', tooltip: 'Previous Month' },
94
+ { step: 'next-month', icon: 'go-next', tooltip: 'Next Month' },
95
+ { step: 'previous-year', icon: 'go-up', tooltip: 'Previous Year' },
96
+ { step: 'next-year', icon: 'go-down', tooltip: 'Next Year' },
97
+ ];
98
+
99
+ /** The arrow a cell's disabled state keys off — `calendar_update_navigation_buttons` (:1055-1084). */
100
+ type ArrowName = 'previousMonth' | 'nextMonth' | 'previousYear' | 'nextYear';
101
+
102
+ export class GtkCalendar extends HTMLElement {
103
+ private _headerEl!: HTMLDivElement;
104
+ private _monthEl!: HTMLSpanElement;
105
+ private _yearEl!: HTMLSpanElement;
106
+ private _arrowEls: Record<ArrowName, HTMLButtonElement> = {} as Record<ArrowName, HTMLButtonElement>;
107
+ private _gridEl!: HTMLDivElement;
108
+ private _dayNameEls: HTMLSpanElement[] = [];
109
+ private _weekNumberEls: HTMLSpanElement[] = [];
110
+ private _cellEls: HTMLButtonElement[] = [];
111
+ private _marked: boolean[] = calendarClearMarks();
112
+ private _date: AdwCalendarDate;
113
+ /** `focus_row` / `focus_col` collapsed into one index into the 42 cells, -1 for neither. */
114
+ private _focus = -1;
115
+ private _initialized = false;
116
+
117
+ static get observedAttributes() {
118
+ return ['date', 'year', 'month', 'day', 'show-heading', 'show-day-names', 'show-week-numbers', 'week-start'];
119
+ }
120
+
121
+ /**
122
+ * `GtkCalendar:date` — the selected date as `YYYY-MM-DD`, `GDateTime`'s own ISO form.
123
+ *
124
+ * Unset means TODAY, which is what `gtk_calendar_init` seeds it with
125
+ * (`g_date_time_new_now_local`, gtkcalendar.c:851) — so the getter answers today when no
126
+ * attribute is present, rather than the epoch the C starts from before its first select.
127
+ */
128
+ get date(): string {
129
+ return toIsoDate(this._date);
130
+ }
131
+
132
+ set date(value: string) {
133
+ this.setAttribute('date', value);
134
+ }
135
+
136
+ /** `GtkCalendar:year` — DEPRECATED in 4.20 in favour of `date` (:396-403). */
137
+ get year(): number {
138
+ return this._date.year;
139
+ }
140
+
141
+ set year(value: number) {
142
+ this.setAttribute('year', String(value));
143
+ }
144
+
145
+ /**
146
+ * `GtkCalendar:month` — DEPRECATED in 4.20, and 0-11, not 1-12 (:405-417). The one place
147
+ * this element is not in `GDateTime`'s own numbering, and it is the attribute that says so.
148
+ */
149
+ get month(): number {
150
+ return this._date.month - 1;
151
+ }
152
+
153
+ set month(value: number) {
154
+ this.setAttribute('month', String(value));
155
+ }
156
+
157
+ /** `GtkCalendar:day` — DEPRECATED in 4.20 in favour of `date` (:419-428). */
158
+ get day(): number {
159
+ return this._date.day;
160
+ }
161
+
162
+ set day(value: number) {
163
+ this.setAttribute('day', String(value));
164
+ }
165
+
166
+ /** Default TRUE (:441-443), so the attribute is the OFF switch. */
167
+ get showHeading(): boolean {
168
+ return this.getAttribute('show-heading') !== 'false';
169
+ }
170
+
171
+ set showHeading(value: boolean) {
172
+ this.setAttribute('show-heading', String(!!value));
173
+ }
174
+
175
+ /** Default TRUE (:450-452), read the same way. */
176
+ get showDayNames(): boolean {
177
+ return this.getAttribute('show-day-names') !== 'false';
178
+ }
179
+
180
+ set showDayNames(value: boolean) {
181
+ this.setAttribute('show-day-names', String(!!value));
182
+ }
183
+
184
+ /** Default FALSE (:458-460), read the same way. */
185
+ get showWeekNumbers(): boolean {
186
+ return this.hasAttribute('show-week-numbers');
187
+ }
188
+
189
+ set showWeekNumbers(value: boolean) {
190
+ this.toggleAttribute('show-week-numbers', !!value);
191
+ }
192
+
193
+ /**
194
+ * Which day the grid's first column is — `calendar->week_start`, PORT-ONLY.
195
+ *
196
+ * The C reads it out of the locale (`_NL_TIME_FIRST_WEEKDAY` plus `_NL_TIME_WEEK_1STDAY`,
197
+ * gtkcalendar.c:700-718) and has no property for it, and this port does the same by
198
+ * default through `Intl.Locale.getWeekInfo()`. The ATTRIBUTE is the addition, and it is
199
+ * what makes a gallery preview reproducible: a grid whose leading blanks follow the
200
+ * machine's locale is a screenshot that differs per reader, and the C's own
201
+ * `calendar:week_start:0` translatable string (gtkcalendar.c:712-719) is the same
202
+ * override upstream.
203
+ *
204
+ * 0 is Sunday and 6 is Saturday — `GDateTime`'s own numbering, so it is the value
205
+ * `calendarDays` subtracts with and the value every vector table carries.
206
+ */
207
+ get weekStart(): number {
208
+ const authored = this.getAttribute('week-start');
209
+ if (authored !== null) {
210
+ const parsed = Number.parseInt(authored, 10);
211
+ if (Number.isFinite(parsed) && parsed >= 0 && parsed <= 6) return parsed;
212
+ }
213
+ return localeWeekStart();
214
+ }
215
+
216
+ set weekStart(value: number) {
217
+ this.setAttribute('week-start', String(value));
218
+ }
219
+
220
+ /** The 31-slot table — `gtk_calendar_get_day_is_marked`, so a mark does not change state. */
221
+ get markedDays(): number[] {
222
+ return this._marked.flatMap((mark, index) => (mark ? [index + 1] : []));
223
+ }
224
+
225
+ constructor() {
226
+ super();
227
+ this._date = today();
228
+ }
229
+
230
+ connectedCallback() {
231
+ if (this._initialized) return;
232
+ this._initialized = true;
233
+
234
+ this._buildHeader();
235
+ this._buildGrid();
236
+ // The C parents the header and then the grid onto the widget itself
237
+ // (gtkcalendar.c:620, :816) under a vertical `Gtk.BoxLayout` (:849-850), which is the
238
+ // `flex-direction: column` in `_calendar.scss`.
239
+ this.replaceChildren(this._headerEl, this._gridEl);
240
+
241
+ this.addEventListener('keydown', (event) => this._onKeyDown(event));
242
+
243
+ // Every write goes through `selectDay`, so the early return that makes a no-op write
244
+ // silent (gtkcalendar.c:1103-1104) applies to the ATTRIBUTE door too.
245
+ this._adoptAttributes();
246
+ this._render();
247
+ }
248
+
249
+ attributeChangedCallback(name?: string) {
250
+ if (!this._initialized) return;
251
+ // The RESULT, not just the date: `calendar_select_day_internal` (:1103-1104) returns
252
+ // EARLY when nothing changed, so the notify and the signal are gated on the three
253
+ // booleans it computes — and an element UPGRADED with attributes already on it runs
254
+ // through here for each of them, which is exactly that "nothing changed" case.
255
+ const result = this._adoptAttributes(name);
256
+ this._render();
257
+ if (name === 'date' || name === 'year' || name === 'month' || name === 'day') {
258
+ this._emitDaySelected(result);
259
+ }
260
+ }
261
+
262
+ /** `gtk_calendar_mark_day` (:1650-1666). */
263
+ markDay(day: number): void {
264
+ const next = calendarMarkDay(this._marked, day, true);
265
+ if (next === this._marked) return;
266
+ this._marked = next;
267
+ this._paintStates();
268
+ this.dispatchEvent(
269
+ new CustomEvent('notify::marked-days', { bubbles: true, detail: { markedDays: this.markedDays } }),
270
+ );
271
+ }
272
+
273
+ /** `gtk_calendar_unmark_day` (:1686-1704). */
274
+ unmarkDay(day: number): void {
275
+ const next = calendarMarkDay(this._marked, day, false);
276
+ if (next === this._marked) return;
277
+ this._marked = next;
278
+ this._paintStates();
279
+ this.dispatchEvent(
280
+ new CustomEvent('notify::marked-days', { bubbles: true, detail: { markedDays: this.markedDays } }),
281
+ );
282
+ }
283
+
284
+ /** `gtk_calendar_get_day_is_marked` (:1668-1682). */
285
+ dayIsMarked(day: number): boolean {
286
+ return calendarDayIsMarked(this._marked, day);
287
+ }
288
+
289
+ /** `gtk_calendar_clear_marks` (:1589-1613). */
290
+ clearMarks(): void {
291
+ this._marked = calendarClearMarks();
292
+ this._paintStates();
293
+ this.dispatchEvent(new CustomEvent('notify::marked-days', { bubbles: true, detail: { markedDays: [] } }));
294
+ }
295
+
296
+ /** The six rows of seven, as the C's `day[row][col]` pair. */
297
+ get cells(): readonly AdwCalendarCell[] {
298
+ return calendarDays(this._date.year, this._date.month, this.weekStart);
299
+ }
300
+
301
+ /** The date every write resolves against. */
302
+ get selectedDate(): AdwCalendarDate {
303
+ return { ...this._date };
304
+ }
305
+
306
+ private _buildHeader(): void {
307
+ this._headerEl = document.createElement('div');
308
+ this._headerEl.className = 'adw-calendar-header';
309
+
310
+ const names: Record<ArrowName, { icon: string; tooltip: string }> = {
311
+ previousMonth: { icon: ARROWS[0]!.icon, tooltip: ARROWS[0]!.tooltip },
312
+ nextMonth: { icon: ARROWS[1]!.icon, tooltip: ARROWS[1]!.tooltip },
313
+ previousYear: { icon: ARROWS[2]!.icon, tooltip: ARROWS[2]!.tooltip },
314
+ nextYear: { icon: ARROWS[3]!.icon, tooltip: ARROWS[3]!.tooltip },
315
+ };
316
+
317
+ const button = (name: ArrowName, expand: boolean, align: 'start' | 'center' | 'end') => {
318
+ const el = document.createElement('button');
319
+ el.type = 'button';
320
+ el.className = 'adw-calendar-nav-button flat';
321
+ el.title = names[name].tooltip;
322
+ el.setAttribute('aria-label', names[name].tooltip);
323
+ if (expand) el.classList.add('expand');
324
+ el.style.justifySelf = align;
325
+ el.addEventListener('click', () => this._onArrow(name));
326
+ el.appendChild(createGtkImage(names[name].icon, 'adw-calendar-nav-icon'));
327
+ this._arrowEls[name] = el;
328
+ return el;
329
+ };
330
+
331
+ this._monthEl = document.createElement('span');
332
+ this._monthEl.className = 'adw-calendar-month';
333
+ this._yearEl = document.createElement('span');
334
+ this._yearEl.className = 'adw-calendar-year';
335
+
336
+ // The C's order is prev-month, month-name, next-month, prev-year, year-label,
337
+ // next-year (gtkcalendar.c:618-622), and the middle month name EXPANDS.
338
+ this._headerEl.append(
339
+ button('previousMonth', false, 'start'),
340
+ this._monthEl,
341
+ button('nextMonth', true, 'start'),
342
+ button('previousYear', false, 'center'),
343
+ this._yearEl,
344
+ button('nextYear', false, 'end'),
345
+ );
346
+ // Only the month-name stack hexpands; the year label gets a fixed slot so changing the
347
+ // year does not change the calendar's width (gtkcalendar.c:854-858).
348
+ this._monthEl.style.flex = '1';
349
+ this._yearEl.style.paddingInline = '6px';
350
+ }
351
+
352
+ private _buildGrid(): void {
353
+ this._gridEl = document.createElement('div');
354
+ this._gridEl.className = 'adw-calendar-grid';
355
+
356
+ for (let index = 0; index < 7; index++) {
357
+ const label = document.createElement('span');
358
+ label.className = 'adw-calendar-day-name';
359
+ this._dayNameEls.push(label);
360
+ this._gridEl.appendChild(label);
361
+ }
362
+ // A leading spacer, so the week-number column exists even while the numbers are off:
363
+ // upstream the week numbers are grid column 0 whether or not they are VISIBLE
364
+ // (gtkcalendar.c:786-790), and the day numbers stay at `1 + i`.
365
+ const spacer = document.createElement('span');
366
+ spacer.className = 'adw-calendar-week-spacer';
367
+ spacer.setAttribute('aria-hidden', 'true');
368
+ this._gridEl.appendChild(spacer);
369
+
370
+ for (let index = 0; index < 6; index++) {
371
+ const week = document.createElement('span');
372
+ week.className = 'adw-calendar-week-number';
373
+ this._weekNumberEls.push(week);
374
+ this._gridEl.appendChild(week);
375
+
376
+ for (let column = 0; column < 7; column++) {
377
+ const cell = document.createElement('button');
378
+ cell.type = 'button';
379
+ cell.className = 'adw-calendar-cell day-number';
380
+ cell.addEventListener('click', () => this._onCellClick(Number(cell.dataset.index ?? '0')));
381
+ this._cellEls.push(cell);
382
+ this._gridEl.appendChild(cell);
383
+ }
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Resolve the attributes into the one date they all name.
389
+ *
390
+ * THE ATTRIBUTE THAT CHANGED WINS, which is the C's own rule:
391
+ * `gtk_calendar_set_year` builds a new `GDateTime` from the same day in the new year and
392
+ * hands it to the same `calendar_select_day_internal` (gtkcalendar.c:860-880), so a write
393
+ * to a deprecated half AFTER a `date` write MOVES the date rather than being ignored for
394
+ * one being on the element. Reading `date` unconditionally would pin the element to its
395
+ * first write.
396
+ *
397
+ * At connect no attribute has "changed" and `date` wins, because it is the one the three
398
+ * halves are deprecated IN FAVOUR of. With none of them the answer is today, which is what
399
+ * `gtk_calendar_init` seeds (:849-851).
400
+ */
401
+ private _adoptAttributes(changed?: string): AdwCalendarSelectResult {
402
+ const iso = this.getAttribute('date');
403
+ const half = changed === 'year' || changed === 'month' || changed === 'day';
404
+ if (iso !== null && !half) {
405
+ const parsed = parseIsoDate(iso);
406
+ if (parsed !== null) {
407
+ const result = calendarSelectDay(this._date, parsed, false);
408
+ this._date = result.date;
409
+ return result;
410
+ }
411
+ }
412
+ const target = {
413
+ // Each half is read only when present, so `year` alone keeps the current month and
414
+ // day — as `gtk_calendar_set_year` does.
415
+ year: integer(this.getAttribute('year'), this._date.year),
416
+ // The GIR property is 0-11 (gtkcalendar.c:419-429); the core functions are 1-12.
417
+ month: integer(this.getAttribute('month'), this._date.month - 1) + 1,
418
+ day: integer(this.getAttribute('day'), this._date.day),
419
+ };
420
+ const result = calendarSelectDay(this._date, target, false);
421
+ this._date = result.date;
422
+ return result;
423
+ }
424
+
425
+ /**
426
+ * Repaint everything the date decides: the heading, the 42 cells' text and classes, the six
427
+ * week numbers and the four arrows' sensitivity.
428
+ *
429
+ * The cells are NOT rebuilt — the same 42 buttons are reused and re-pointed, so a focus
430
+ * cell and its scroll position survive a month change, which is what `calendar_queue_refresh`
431
+ * gets from the widget layer upstream.
432
+ */
433
+ private _render(): void {
434
+ this._monthEl.textContent = MONTH_NAMES[this._date.month - 1]!;
435
+ this._yearEl.textContent = String(this._date.year);
436
+
437
+ const cells = calendarDays(this._date.year, this._date.month, this.weekStart);
438
+ cells.forEach((cell, index) => {
439
+ const el = this._cellEls[index]!;
440
+ el.dataset.index = String(index);
441
+ el.textContent = String(cell.date.day);
442
+ el.setAttribute('aria-label', `${MONTH_NAMES[cell.date.month - 1]} ${cell.date.day}, ${cell.date.year}`);
443
+ el.classList.toggle('other-month', cell.month !== 'current');
444
+ });
445
+
446
+ this._paintWeekNumbers(cells);
447
+ this._paintStates();
448
+ this._paintArrows();
449
+ this._paintDayNames();
450
+ this._paintVisibility();
451
+ }
452
+
453
+ /**
454
+ * The six week numbers — `week_of_year` of the LAST cell of each row, which is the C's own
455
+ * rule (gtkcalendar.c:1143-1165): the row's week is the week its Sunday-through-Saturday
456
+ * run belongs to, and the row's last cell is its Saturday.
457
+ */
458
+ private _paintWeekNumbers(cells: readonly AdwCalendarCell[]): void {
459
+ for (let row = 0; row < 6; row++) {
460
+ const last = cells[row * 7 + 6]!;
461
+ this._weekNumberEls[row]!.textContent = String(calendarWeekNumber(last.date));
462
+ }
463
+ }
464
+
465
+ /** The per-cell state flags `calendar_update_day_labels` raises (:979-1053). */
466
+ private _paintStates(): void {
467
+ const cells = calendarDays(this._date.year, this._date.month, this.weekStart);
468
+ const now = today();
469
+ const todayDay = now.year === this._date.year && now.month === this._date.month ? now.day : -1;
470
+ cells.forEach((cell, index) => {
471
+ const el = this._cellEls[index]!;
472
+ const isSelected = cell.month === 'current' && cell.date.day === this._date.day;
473
+ // `lower_limit_reached` / `upper_limit_reached` (:1002-1003) blank the cells that
474
+ // would leave the supported year range entirely.
475
+ const beyondRange =
476
+ (cell.month === 'previous' && this._date.year === CALENDAR_YEAR_MIN && this._date.month === 1) ||
477
+ (cell.month === 'next' && this._date.year === CALENDAR_YEAR_MAX && this._date.month === 12);
478
+ el.classList.toggle('selected', isSelected);
479
+ el.classList.toggle('marked', cell.month === 'current' && calendarDayIsMarked(this._marked, cell.date.day));
480
+ el.classList.toggle('today', cell.date.day === todayDay && cell.month === 'current');
481
+ el.classList.toggle('focused', index === this._focus);
482
+ el.disabled = beyondRange;
483
+ if (beyondRange) el.textContent = '';
484
+ else el.textContent = String(cell.date.day);
485
+ });
486
+ }
487
+
488
+ /** `calendar_update_navigation_buttons` (:1055-1084). */
489
+ private _paintArrows(): void {
490
+ const live = calendarNavigationButtons(this._date);
491
+ for (const name of ['previousMonth', 'nextMonth', 'previousYear', 'nextYear'] as const) {
492
+ this._arrowEls[name].disabled = !live[name];
493
+ }
494
+ }
495
+
496
+ private _paintDayNames(): void {
497
+ for (let index = 0; index < 7; index++) {
498
+ // `day = (i + calendar->week_start) % 7` (gtkcalendar.c:773).
499
+ this._dayNameEls[index]!.textContent = DAY_NAMES[(index + this.weekStart) % 7]!;
500
+ }
501
+ }
502
+
503
+ /**
504
+ * `show_heading`, `show_day_names` and `show_week_numbers` — the three visibility flags
505
+ * `gtk_calendar_init` and the setters flip (gtkcalendar.c:815-816, :1690-1700,
506
+ * :1756-1762). One of them hides the whole header BOX and the other two a row of labels,
507
+ * which is why they are one method rather than three writes.
508
+ */
509
+ private _paintVisibility(): void {
510
+ this._headerEl.hidden = !this.showHeading;
511
+ for (const label of this._dayNameEls) label.hidden = !this.showDayNames;
512
+ for (const label of this._weekNumberEls) label.hidden = !this.showWeekNumbers;
513
+ }
514
+
515
+ private _onArrow(name: ArrowName): void {
516
+ const step = ARROWS.find((arrow) => arrowNameOf(arrow.step) === name)?.step;
517
+ if (step === undefined || this._arrowEls[name].disabled) return;
518
+ this._navigate(step);
519
+ }
520
+
521
+ /**
522
+ * `calendar_set_month_prev` and its three siblings: step the date, select it WITHOUT
523
+ * `emit_day_signal`, then emit the arrow's own signal (:868-919).
524
+ */
525
+ private _navigate(step: AdwCalendarStep): void {
526
+ const before = this._date;
527
+ this._date = calendarSelectDay(before, calendarStep(before, step), false).date;
528
+ if (this._focus >= 0) {
529
+ const cells = this.cells;
530
+ const focus = cells[this._focus];
531
+ // The cursor follows the month when the day it was on is still in the grid, which
532
+ // upstream happens by the focus CELL surviving the repaint (gtkcalendar.c:1017-1020).
533
+ const moved = cells.findIndex((cell) => cell.month === focus?.month && cell.date.day === focus.date.day);
534
+ this._focus = moved >= 0 ? moved : -1;
535
+ }
536
+ this._render();
537
+ this.dispatchEvent(new CustomEvent('notify::date', { bubbles: true, detail: { date: this.date } }));
538
+ const signals: Record<AdwCalendarStep, string> = {
539
+ 'previous-month': 'prev-month',
540
+ 'next-month': 'next-month',
541
+ 'previous-year': 'prev-year',
542
+ 'next-year': 'next-year',
543
+ };
544
+ this.dispatchEvent(new CustomEvent(signals[step], { bubbles: true }));
545
+ }
546
+
547
+ /**
548
+ * The C's tail, line for line (:1169-1190): `::day-selected` and the `day` notify INSIDE
549
+ * `if (day_changed)`, the `month` and `year` notifies each inside its own, and `date`
550
+ * unconditionally — because the function that got here changed something.
551
+ */
552
+ private _emitDaySelected(result: AdwCalendarSelectResult): void {
553
+ const notify = (attribute: string, value: number | string) =>
554
+ this.dispatchEvent(
555
+ new CustomEvent(`notify::${attribute}`, { bubbles: true, detail: { [attribute]: value } }),
556
+ );
557
+ if (result.dayChanged) {
558
+ this.dispatchEvent(new CustomEvent('day-selected', { bubbles: true }));
559
+ notify('day', this._date.day);
560
+ }
561
+ if (result.monthChanged) notify('month', this._date.month - 1);
562
+ if (result.yearChanged) notify('year', this._date.year);
563
+ notify('date', this.date);
564
+ }
565
+
566
+ /**
567
+ * A click on a cell — `calendar_select_and_focus_day` reached from
568
+ * `gtk_calendar_button_press` (:1311-1353).
569
+ *
570
+ * A cell from another month PAGES first: that is the `MONTH_PREV` / `MONTH_NEXT` branch of
571
+ * the Space handler (:1521-1534), and a click lands on the same cell either way.
572
+ */
573
+ private _onCellClick(index: number): void {
574
+ const cell = this.cells[index];
575
+ if (cell === undefined) return;
576
+ this._focus = index;
577
+ if (cell.month === 'previous') this._navigate('previous-month');
578
+ else if (cell.month === 'next') this._navigate('next-month');
579
+ this._selectDate(cell.date, true);
580
+ }
581
+
582
+ /**
583
+ * `calendar_select_and_focus_day` (:1195-1213) — the date, WITH `::day-selected`, and the
584
+ * cursor on it.
585
+ */
586
+ private _selectDate(date: AdwCalendarDate, interactive: boolean): void {
587
+ const result = calendarSelectDay(this._date, date, interactive);
588
+ if (!result.dayChanged && !result.monthChanged && !result.yearChanged) {
589
+ this._render();
590
+ return;
591
+ }
592
+ this._date = result.date;
593
+ const cell = this.cells.findIndex(
594
+ (candidate) => candidate.month === 'current' && candidate.date.day === this._date.day,
595
+ );
596
+ if (cell >= 0) this._focus = cell;
597
+ this._render();
598
+ this._emitDaySelected(result);
599
+ }
600
+
601
+ /**
602
+ * The key table: arrows move the cursor (`move_focus`, :1386-1452) and Space selects the
603
+ * cell it is on; `Ctrl` with any arrow is the MONTH and YEAR walk (:1454-1534).
604
+ */
605
+ private _onKeyDown(event: KeyboardEvent): void {
606
+ const arrow: Record<string, [number, number]> = {
607
+ ArrowLeft: [-1, 0],
608
+ ArrowRight: [1, 0],
609
+ ArrowUp: [0, 1],
610
+ ArrowDown: [0, -1],
611
+ };
612
+ if (event.ctrlKey) {
613
+ const steps: Record<string, AdwCalendarStep> = {
614
+ ArrowLeft: 'previous-month',
615
+ ArrowRight: 'next-month',
616
+ ArrowUp: 'previous-year',
617
+ ArrowDown: 'next-year',
618
+ };
619
+ const step = steps[event.key];
620
+ if (step === undefined) return;
621
+ event.preventDefault();
622
+ // The C refuses the keyboard when the MOUSE would be refused (:1492-1494).
623
+ if (!calendarNavigationButtons(this._date)[arrowNameOf(step)]) return;
624
+ this._navigate(step);
625
+ return;
626
+ }
627
+ if (event.altKey || event.metaKey) return;
628
+
629
+ if (event.key === ' ') {
630
+ if (this._focus < 0) return;
631
+ event.preventDefault();
632
+ const cell = this.cells[this._focus];
633
+ if (cell === undefined) return;
634
+ if (cell.month === 'previous') this._navigate('previous-month');
635
+ else if (cell.month === 'next') this._navigate('next-month');
636
+ this._selectDate(cell.date, true);
637
+ return;
638
+ }
639
+
640
+ const move = arrow[event.key];
641
+ if (move === undefined) return;
642
+ event.preventDefault();
643
+ this._moveFocus(move[0], move[1]);
644
+ }
645
+
646
+ /**
647
+ * `move_focus` (:1386-1452) over the 6x7 grid, wrapping at the edges exactly as the C does
648
+ * (`focus_row < 0 → 5`, `focus_col < 0 → 6`).
649
+ */
650
+ private _moveFocus(direction: number, updown: number): void {
651
+ const cells = this.cells;
652
+ if (cells.length === 0) return;
653
+ // `focus_row` / `focus_col` start at -1 (gtkcalendar.c:817-818), NOT at 0 — and the
654
+ // difference is the only place the wrap branches are reachable: an ArrowUp from an
655
+ // untouched cursor lands on row 5 column 6, the LAST cell, because of exactly those
656
+ // two `if (focus_row < 0) focus_row = 5` / `focus_col < 0 → 6` lines.
657
+ let row = this._focus < 0 ? -1 : Math.trunc(this._focus / 7);
658
+ let column = this._focus < 0 ? -1 : this._focus % 7;
659
+
660
+ if (updown === 1) {
661
+ if (row > 0) row--;
662
+ if (row < 0) row = 5;
663
+ if (column < 0) column = 6;
664
+ } else if (updown === -1) {
665
+ if (row < 5) row++;
666
+ if (column < 0) column = 0;
667
+ } else if (direction === -1) {
668
+ if (column > 0) column--;
669
+ else if (row > 0) {
670
+ column = 6;
671
+ row--;
672
+ }
673
+ if (column < 0) column = 6;
674
+ if (row < 0) row = 5;
675
+ } else {
676
+ if (column < 6) column++;
677
+ else if (row < 5) {
678
+ column = 0;
679
+ row++;
680
+ }
681
+ if (column < 0) column = 0;
682
+ if (row < 0) row = 0;
683
+ }
684
+
685
+ const next = row * 7 + column;
686
+ // "Not sensitive, not reachable" (:1444-1445) — a cell past the year range is skipped.
687
+ if (this._cellEls[next]?.disabled === true) return;
688
+ this._focus = next;
689
+ this._paintStates();
690
+ this._cellEls[next]?.focus();
691
+ }
692
+ }
693
+
694
+ /** Which of the four arrows a step names — the order `gtk_calendar_init` appends them in (:618-622). */
695
+ function arrowNameOf(step: AdwCalendarStep): ArrowName {
696
+ switch (step) {
697
+ case 'previous-month':
698
+ return 'previousMonth';
699
+ case 'next-month':
700
+ return 'nextMonth';
701
+ case 'previous-year':
702
+ return 'previousYear';
703
+ default:
704
+ return 'nextYear';
705
+ }
706
+ }
707
+
708
+ /**
709
+ * The locale's first day of the week — `calendar->week_start`, from `Intl`.
710
+ *
711
+ * `Intl.Locale.prototype.getWeekInfo()` reports `firstDay` as 1 (Monday) through 7 (Sunday),
712
+ * which is exactly the numbering `_NL_TIME_FIRST_WEEKDAY` uses, so `calendarWeekStart`'s own
713
+ * formula applies to it unchanged — there is no second arithmetic here on purpose. A runtime
714
+ * without `getWeekInfo` answers 0 (Sunday), which is what the C's fallback lands on too
715
+ * (gtkcalendar.c:716-718).
716
+ */
717
+ function localeWeekStart(): number {
718
+ const language = globalThis.navigator?.language;
719
+ if (typeof language !== 'string') return calendarWeekStart(0, 0);
720
+ const Locale = (Intl as { Locale?: { new (tag: string): { getWeekInfo?: () => { firstDay: number } } } }).Locale;
721
+ if (Locale === undefined) return calendarWeekStart(0, 0);
722
+ const weekInfo = new Locale(language).getWeekInfo?.();
723
+ if (weekInfo === undefined) return calendarWeekStart(0, 0);
724
+ // `firstDay` is 1-7 Monday-to-Sunday; `_NL_TIME_FIRST_WEEKDAY` is 0-6 Sunday-first, and
725
+ // `7 % 7` is the Sunday the two numberings disagree about.
726
+ return calendarWeekStart(weekInfo.firstDay % 7, weekInfo.firstDay === 7 ? 0 : 1);
727
+ }
728
+
729
+ /** Today's date in the local zone — `g_date_time_new_now_local` (:851). */
730
+ function today(): AdwCalendarDate {
731
+ const now = new Date();
732
+ return { year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate() };
733
+ }
734
+
735
+ function toIsoDate(date: AdwCalendarDate): string {
736
+ return `${String(date.year).padStart(4, '0')}-${String(date.month).padStart(2, '0')}-${String(date.day).padStart(2, '0')}`;
737
+ }
738
+
739
+ /** `YYYY-MM-DD` → a date, or null. A malformed attribute leaves the widget where it was. */
740
+ function parseIsoDate(raw: string): AdwCalendarDate | null {
741
+ const match = /^(-?\d{1,6})-(\d{1,2})-(\d{1,2})$/.exec(raw.trim());
742
+ if (match === null) return null;
743
+ const year = Number(match[1]);
744
+ const month = Number(match[2]);
745
+ const day = Number(match[3]);
746
+ if (month < 1 || month > 12 || day < 1 || day > 31) return null;
747
+ if (year < CALENDAR_YEAR_MIN || year > CALENDAR_YEAR_MAX) return null;
748
+ return { year, month, day };
749
+ }
750
+
751
+ /** A `gint` property read, with the caller's own value standing in for an absent attribute. */
752
+ function integer(raw: string | null, fallback: number): number {
753
+ const parsed = Number.parseInt(raw ?? '', 10);
754
+ return Number.isFinite(parsed) ? parsed : fallback;
755
+ }
756
+
757
+ customElements.define('gtk-calendar', GtkCalendar);