@gjsify/adwaita-web 0.53.0 → 0.55.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.
- package/dist/adwaita-web.css +8070 -3037
- package/dist/adwaita-web.css.map +1 -1
- package/lib/types/adw-application-window.spec.d.ts +1 -0
- package/lib/types/adw-bin.spec.d.ts +1 -0
- package/lib/types/adw-breakpoint-bin.spec.d.ts +1 -0
- package/lib/types/adw-clamp-scrollable.spec.d.ts +1 -0
- package/lib/types/adw-multi-layout-view.spec.d.ts +1 -0
- package/lib/types/adw-preferences-row.spec.d.ts +1 -0
- package/lib/types/adw-shortcuts.spec.d.ts +1 -0
- package/lib/types/adw-tab-bar.spec.d.ts +1 -0
- package/lib/types/adw-tab-button.spec.d.ts +1 -0
- package/lib/types/adw-tab-overview.spec.d.ts +1 -0
- package/lib/types/adw-view-switcher-sidebar.spec.d.ts +1 -0
- package/lib/types/adw-window.spec.d.ts +1 -0
- package/lib/types/breakpoints.d.ts +14 -3
- package/lib/types/construct-vectors.spec.d.ts +1 -0
- package/lib/types/elements/adw-application-window.d.ts +27 -0
- package/lib/types/elements/adw-bin.d.ts +17 -0
- package/lib/types/elements/adw-breakpoint-bin.d.ts +67 -0
- package/lib/types/elements/adw-clamp-scrollable.d.ts +38 -0
- package/lib/types/elements/adw-dialog.d.ts +10 -0
- package/lib/types/elements/adw-layout-slot.d.ts +19 -0
- package/lib/types/elements/adw-multi-layout-view.d.ts +101 -0
- package/lib/types/elements/adw-preferences-row.d.ts +31 -0
- package/lib/types/elements/adw-shortcuts-dialog.d.ts +13 -0
- package/lib/types/elements/adw-shortcuts-item.d.ts +36 -0
- package/lib/types/elements/adw-shortcuts-section.d.ts +14 -0
- package/lib/types/elements/adw-sidebar.d.ts +5 -0
- package/lib/types/elements/adw-switch-row.d.ts +3 -0
- package/lib/types/elements/adw-tab-bar.d.ts +108 -0
- package/lib/types/elements/adw-tab-button.d.ts +32 -0
- package/lib/types/elements/adw-tab-overview.d.ts +199 -0
- package/lib/types/elements/adw-tab-view.d.ts +19 -23
- package/lib/types/elements/adw-view-switcher-sidebar.d.ts +84 -0
- package/lib/types/elements/adw-window.d.ts +40 -0
- package/lib/types/elements/gtk-about-dialog.d.ts +146 -0
- package/lib/types/elements/gtk-application-window.d.ts +34 -0
- package/lib/types/elements/gtk-aspect-frame.d.ts +27 -0
- package/lib/types/elements/gtk-button.d.ts +9 -0
- package/lib/types/elements/gtk-calendar.d.ts +159 -0
- package/lib/types/elements/gtk-center-box.d.ts +39 -0
- package/lib/types/elements/gtk-color-dialog-button.d.ts +69 -0
- package/lib/types/elements/gtk-column-view.d.ts +50 -0
- package/lib/types/elements/gtk-drag-icon.d.ts +78 -0
- package/lib/types/elements/gtk-drawing-area.d.ts +95 -0
- package/lib/types/elements/gtk-editable-label.d.ts +33 -0
- package/lib/types/elements/gtk-emoji-chooser.d.ts +84 -0
- package/lib/types/elements/gtk-entry.d.ts +20 -1
- package/lib/types/elements/gtk-expander.d.ts +49 -0
- package/lib/types/elements/gtk-fixed.d.ts +13 -0
- package/lib/types/elements/gtk-flow-box-child.d.ts +14 -0
- package/lib/types/elements/gtk-flow-box.d.ts +87 -0
- package/lib/types/elements/gtk-font-dialog-button.d.ts +83 -0
- package/lib/types/elements/gtk-frame.d.ts +24 -0
- package/lib/types/elements/gtk-gl-area.d.ts +136 -0
- package/lib/types/elements/gtk-graphics-offload.d.ts +24 -0
- package/lib/types/elements/gtk-grid-view.d.ts +39 -0
- package/lib/types/elements/gtk-grid.d.ts +27 -0
- package/lib/types/elements/gtk-header-bar.d.ts +60 -0
- package/lib/types/elements/gtk-inscription.d.ts +64 -0
- package/lib/types/elements/gtk-label.d.ts +3 -0
- package/lib/types/elements/gtk-level-bar.d.ts +59 -0
- package/lib/types/elements/gtk-link-button.d.ts +29 -0
- package/lib/types/elements/gtk-list-box-row.d.ts +54 -0
- package/lib/types/elements/gtk-list-box.d.ts +100 -0
- package/lib/types/elements/gtk-list-view.d.ts +73 -0
- package/lib/types/elements/gtk-media-controls.d.ts +142 -0
- package/lib/types/elements/gtk-notebook.d.ts +148 -0
- package/lib/types/elements/gtk-overlay.d.ts +22 -0
- package/lib/types/elements/gtk-page-setup-unix-dialog.d.ts +87 -0
- package/lib/types/elements/gtk-paned.d.ts +121 -0
- package/lib/types/elements/gtk-password-entry.d.ts +27 -0
- package/lib/types/elements/gtk-picture.d.ts +66 -0
- package/lib/types/elements/gtk-popover-bin.d.ts +82 -0
- package/lib/types/elements/gtk-popover-menu-bar.d.ts +66 -0
- package/lib/types/elements/gtk-popover-menu.d.ts +83 -0
- package/lib/types/elements/gtk-popover.d.ts +28 -3
- package/lib/types/elements/gtk-print-unix-dialog.d.ts +167 -0
- package/lib/types/elements/gtk-revealer.d.ts +55 -0
- package/lib/types/elements/gtk-scale-button.d.ts +59 -0
- package/lib/types/elements/gtk-scale.d.ts +98 -0
- package/lib/types/elements/gtk-scrollbar.d.ts +124 -0
- package/lib/types/elements/gtk-scrolled-window.d.ts +121 -0
- package/lib/types/elements/gtk-search-bar.d.ts +39 -0
- package/lib/types/elements/gtk-search-entry.d.ts +27 -0
- package/lib/types/elements/gtk-separator.d.ts +10 -0
- package/lib/types/elements/gtk-spin-button.d.ts +94 -0
- package/lib/types/elements/gtk-spinner.d.ts +14 -0
- package/lib/types/elements/gtk-stack-sidebar.d.ts +43 -0
- package/lib/types/elements/gtk-stack-switcher.d.ts +58 -0
- package/lib/types/elements/gtk-stack.d.ts +154 -0
- package/lib/types/elements/gtk-switch.d.ts +4 -1
- package/lib/types/elements/gtk-text-view.d.ts +62 -0
- package/lib/types/elements/gtk-text.d.ts +45 -0
- package/lib/types/elements/gtk-toggle-button.d.ts +45 -0
- package/lib/types/elements/gtk-tree-expander.d.ts +38 -0
- package/lib/types/elements/gtk-video.d.ts +97 -0
- package/lib/types/elements/gtk-viewport.d.ts +84 -0
- package/lib/types/elements/gtk-window-controls.d.ts +80 -0
- package/lib/types/elements/gtk-window-handle.d.ts +39 -0
- package/lib/types/elements/gtk-window.d.ts +97 -0
- package/lib/types/elements/justification.d.ts +2 -0
- package/lib/types/elements/popover-menu.d.ts +18 -0
- package/lib/types/elements/roving-focus.d.ts +29 -1
- package/lib/types/emoji-data.d.ts +38 -0
- package/lib/types/font-description.d.ts +96 -0
- package/lib/types/gtk-about-dialog.spec.d.ts +1 -0
- package/lib/types/gtk-action-bar.spec.d.ts +1 -0
- package/lib/types/gtk-application-window.spec.d.ts +1 -0
- package/lib/types/gtk-aspect-frame.spec.d.ts +1 -0
- package/lib/types/gtk-calendar.spec.d.ts +1 -0
- package/lib/types/gtk-center-box.spec.d.ts +1 -0
- package/lib/types/gtk-color-dialog-button.spec.d.ts +1 -0
- package/lib/types/gtk-column-view.spec.d.ts +1 -0
- package/lib/types/gtk-drag-icon.spec.d.ts +1 -0
- package/lib/types/gtk-drawing-area.spec.d.ts +1 -0
- package/lib/types/gtk-editable-label.spec.d.ts +1 -0
- package/lib/types/gtk-emoji-chooser.spec.d.ts +1 -0
- package/lib/types/gtk-expander.spec.d.ts +1 -0
- package/lib/types/gtk-fixed.spec.d.ts +1 -0
- package/lib/types/gtk-flow-box.spec.d.ts +1 -0
- package/lib/types/gtk-font-dialog-button.spec.d.ts +1 -0
- package/lib/types/gtk-frame.spec.d.ts +1 -0
- package/lib/types/gtk-gl-area.spec.d.ts +1 -0
- package/lib/types/gtk-graphics-offload.spec.d.ts +1 -0
- package/lib/types/gtk-grid-view.spec.d.ts +1 -0
- package/lib/types/gtk-grid.spec.d.ts +1 -0
- package/lib/types/gtk-header-bar.spec.d.ts +1 -0
- package/lib/types/gtk-inscription.spec.d.ts +1 -0
- package/lib/types/gtk-level-bar.spec.d.ts +1 -0
- package/lib/types/gtk-link-button.spec.d.ts +1 -0
- package/lib/types/gtk-list-box.spec.d.ts +1 -0
- package/lib/types/gtk-list-view.spec.d.ts +1 -0
- package/lib/types/gtk-media-controls.spec.d.ts +1 -0
- package/lib/types/gtk-notebook.spec.d.ts +1 -0
- package/lib/types/gtk-overlay.spec.d.ts +1 -0
- package/lib/types/gtk-paned.spec.d.ts +1 -0
- package/lib/types/gtk-password-entry.spec.d.ts +1 -0
- package/lib/types/gtk-picture.spec.d.ts +1 -0
- package/lib/types/gtk-popover-bin.spec.d.ts +1 -0
- package/lib/types/gtk-popover-menu-bar.spec.d.ts +1 -0
- package/lib/types/gtk-popover-menu.spec.d.ts +1 -0
- package/lib/types/gtk-popover-role.spec.d.ts +1 -0
- package/lib/types/gtk-popover.spec.d.ts +1 -0
- package/lib/types/gtk-print-dialogs.spec.d.ts +1 -0
- package/lib/types/gtk-revealer.spec.d.ts +1 -0
- package/lib/types/gtk-scale-button.spec.d.ts +1 -0
- package/lib/types/gtk-scale.spec.d.ts +1 -0
- package/lib/types/gtk-scrollbar.spec.d.ts +1 -0
- package/lib/types/gtk-scrolled-window.spec.d.ts +1 -0
- package/lib/types/gtk-search-bar.spec.d.ts +1 -0
- package/lib/types/gtk-search-entry.spec.d.ts +1 -0
- package/lib/types/gtk-separator.spec.d.ts +1 -0
- package/lib/types/gtk-spin-button.spec.d.ts +1 -0
- package/lib/types/gtk-spinner.spec.d.ts +1 -0
- package/lib/types/gtk-stack-sidebar.spec.d.ts +1 -0
- package/lib/types/gtk-stack-switcher.spec.d.ts +1 -0
- package/lib/types/gtk-stack.spec.d.ts +1 -0
- package/lib/types/gtk-text-view.spec.d.ts +1 -0
- package/lib/types/gtk-text.spec.d.ts +1 -0
- package/lib/types/gtk-toggle-button.spec.d.ts +1 -0
- package/lib/types/gtk-tree-expander.spec.d.ts +1 -0
- package/lib/types/gtk-video.spec.d.ts +1 -0
- package/lib/types/gtk-viewport.spec.d.ts +1 -0
- package/lib/types/gtk-window-controls.spec.d.ts +1 -0
- package/lib/types/gtk-window-handle.spec.d.ts +1 -0
- package/lib/types/gtk-window.spec.d.ts +1 -0
- package/lib/types/index.d.ts +4 -1
- package/lib/types/list-view-dom.d.ts +44 -0
- package/lib/types/namespace/adw.d.ts +12 -0
- package/lib/types/namespace/gtk.d.ts +61 -0
- package/lib/types/page-setup.d.ts +100 -0
- package/lib/types/scroll-shading.d.ts +15 -1
- package/lib/types/shared-tree-builder.d.ts +30 -2
- package/lib/types/signals.d.ts +4 -0
- package/lib/types/styles.generated.d.ts +1 -1
- package/lib/types/tab-chip.d.ts +73 -0
- package/lib/types/template-classes.d.ts +11 -0
- package/package.json +12 -8
- package/scss/_action_row.scss +2 -2
- package/scss/_application_window.scss +26 -0
- package/scss/_aspect_frame.scss +25 -0
- package/scss/_bin.scss +26 -0
- package/scss/_button.scss +45 -0
- package/scss/_calendar.scss +176 -0
- package/scss/_center_box.scss +25 -0
- package/scss/_checks.scss +6 -1
- package/scss/_clamp_scrollable.scss +28 -0
- package/scss/_color_button.scss +67 -0
- package/scss/_column_view.scss +126 -0
- package/scss/_drag_icon.scss +55 -0
- package/scss/_drawing.scss +85 -0
- package/scss/_emoji_chooser.scss +213 -0
- package/scss/_entry.scss +13 -5
- package/scss/_entry_row.scss +1 -1
- package/scss/_expander.scss +113 -0
- package/scss/_fixed.scss +29 -0
- package/scss/_flow_box.scss +94 -0
- package/scss/_font_button.scss +63 -0
- package/scss/_frame.scss +41 -0
- package/scss/_grid.scss +19 -0
- package/scss/_grid_view.scss +46 -0
- package/scss/_gtk_about_dialog.scss +186 -0
- package/scss/_headerbar.scss +132 -0
- package/scss/_icons.generated.scss +186 -0
- package/scss/_inscription.scss +125 -0
- package/scss/_level_bar.scss +190 -0
- package/scss/_link.scss +82 -0
- package/scss/_list_box.scss +88 -0
- package/scss/_list_view.scss +96 -0
- package/scss/_media_controls.scss +139 -0
- package/scss/_overlay.scss +68 -0
- package/scss/_paned.scss +130 -0
- package/scss/_password_entry.scss +83 -0
- package/scss/_picture.scss +80 -0
- package/scss/_popover_bin.scss +53 -0
- package/scss/_popover_menu_bar.scss +104 -0
- package/scss/_preferences_row.scss +51 -0
- package/scss/_print_dialogs.scss +328 -0
- package/scss/_reset.scss +21 -19
- package/scss/_revealer.scss +37 -0
- package/scss/_row.scss +20 -5
- package/scss/_scale.scss +298 -0
- package/scss/_scale_button.scss +167 -0
- package/scss/_scrollbar.scss +230 -0
- package/scss/_scrolled_window.scss +131 -0
- package/scss/_search_bar.scss +118 -0
- package/scss/_search_entry.scss +86 -0
- package/scss/_separator.scss +44 -0
- package/scss/_shortcuts_dialog.scss +100 -0
- package/scss/_spin_button.scss +172 -0
- package/scss/_spin_row.scss +56 -8
- package/scss/_spinner.scss +85 -4
- package/scss/_stack.scss +729 -0
- package/scss/_switch.scss +13 -5
- package/scss/_switch_row.scss +10 -0
- package/scss/_tab_bar.scss +317 -0
- package/scss/_tab_button.scss +98 -0
- package/scss/_tab_overview.scss +483 -0
- package/scss/_text.scss +182 -0
- package/scss/_theme.scss +1 -1
- package/scss/_tree_expander.scss +62 -0
- package/scss/_variables.scss +43 -21
- package/scss/_video.scss +146 -0
- package/scss/_view_switcher_sidebar.scss +112 -0
- package/scss/_viewport.scss +50 -0
- package/scss/_window.scss +118 -1
- package/scss/_window_handle.scss +20 -0
- package/scss/adwaita-skin.scss +109 -0
- package/src/adw-action-rows.spec.ts +76 -0
- package/src/adw-application-window.spec.ts +118 -0
- package/src/adw-bin.spec.ts +75 -0
- package/src/adw-breakpoint-bin.spec.ts +324 -0
- package/src/adw-clamp-scrollable.spec.ts +189 -0
- package/src/adw-multi-layout-view.spec.ts +243 -0
- package/src/adw-preferences-row.spec.ts +164 -0
- package/src/adw-row-state.spec.ts +142 -0
- package/src/adw-shortcuts.spec.ts +155 -0
- package/src/adw-tab-bar.spec.ts +287 -0
- package/src/adw-tab-button.spec.ts +101 -0
- package/src/adw-tab-overview.spec.ts +443 -0
- package/src/adw-view-switcher-sidebar.spec.ts +281 -0
- package/src/adw-window.spec.ts +129 -0
- package/src/breakpoints.ts +25 -8
- package/src/capabilities.d.mts +3 -0
- package/src/capabilities.mjs +18 -0
- package/src/connect-lifecycle.spec.ts +12 -0
- package/src/construct-vectors.spec.ts +175 -0
- package/src/elements/adw-application-window.ts +154 -0
- package/src/elements/adw-bin.ts +101 -0
- package/src/elements/adw-breakpoint-bin.ts +287 -0
- package/src/elements/adw-clamp-scrollable.ts +207 -0
- package/src/elements/adw-dialog.ts +19 -0
- package/src/elements/adw-layout-slot.ts +95 -0
- package/src/elements/adw-multi-layout-view.ts +326 -0
- package/src/elements/adw-preferences-row.ts +150 -0
- package/src/elements/adw-shortcuts-dialog.ts +52 -0
- package/src/elements/adw-shortcuts-item.ts +171 -0
- package/src/elements/adw-shortcuts-section.ts +86 -0
- package/src/elements/adw-sidebar.ts +42 -3
- package/src/elements/adw-switch-row.ts +28 -1
- package/src/elements/adw-tab-bar.ts +529 -0
- package/src/elements/adw-tab-button.ts +194 -0
- package/src/elements/adw-tab-overview.ts +1011 -0
- package/src/elements/adw-tab-view.ts +66 -145
- package/src/elements/adw-toggle-group.ts +20 -5
- package/src/elements/adw-view-stack.ts +18 -0
- package/src/elements/adw-view-switcher-sidebar.ts +332 -0
- package/src/elements/adw-window.ts +185 -11
- package/src/elements/checks.ts +35 -8
- package/src/elements/gtk-about-dialog.ts +811 -0
- package/src/elements/gtk-application-window.ts +108 -0
- package/src/elements/gtk-aspect-frame.ts +160 -0
- package/src/elements/gtk-button.ts +12 -0
- package/src/elements/gtk-calendar.ts +757 -0
- package/src/elements/gtk-center-box.ts +184 -0
- package/src/elements/gtk-color-dialog-button.ts +278 -0
- package/src/elements/gtk-column-view.ts +320 -0
- package/src/elements/gtk-drag-icon.ts +257 -0
- package/src/elements/gtk-drawing-area.ts +303 -0
- package/src/elements/gtk-editable-label.ts +204 -0
- package/src/elements/gtk-emoji-chooser.ts +542 -0
- package/src/elements/gtk-entry.ts +39 -5
- package/src/elements/gtk-expander.ts +301 -0
- package/src/elements/gtk-fixed.ts +99 -0
- package/src/elements/gtk-flow-box-child.ts +68 -0
- package/src/elements/gtk-flow-box.ts +480 -0
- package/src/elements/gtk-font-dialog-button.ts +432 -0
- package/src/elements/gtk-frame.ts +174 -0
- package/src/elements/gtk-gl-area.ts +476 -0
- package/src/elements/gtk-graphics-offload.ts +130 -0
- package/src/elements/gtk-grid-view.ts +168 -0
- package/src/elements/gtk-grid.ts +127 -0
- package/src/elements/gtk-header-bar.ts +273 -0
- package/src/elements/gtk-inscription.ts +387 -0
- package/src/elements/gtk-label.ts +19 -11
- package/src/elements/gtk-level-bar.ts +323 -0
- package/src/elements/gtk-link-button.ts +138 -0
- package/src/elements/gtk-list-box-row.ts +195 -0
- package/src/elements/gtk-list-box.ts +413 -0
- package/src/elements/gtk-list-view.ts +370 -0
- package/src/elements/gtk-media-controls.ts +509 -0
- package/src/elements/gtk-notebook.ts +664 -0
- package/src/elements/gtk-overlay.ts +149 -0
- package/src/elements/gtk-page-setup-unix-dialog.ts +420 -0
- package/src/elements/gtk-paned.ts +597 -0
- package/src/elements/gtk-password-entry.ts +170 -0
- package/src/elements/gtk-picture.ts +254 -0
- package/src/elements/gtk-popover-bin.ts +332 -0
- package/src/elements/gtk-popover-menu-bar.ts +355 -0
- package/src/elements/gtk-popover-menu.ts +339 -0
- package/src/elements/gtk-popover.ts +92 -10
- package/src/elements/gtk-print-unix-dialog.ts +989 -0
- package/src/elements/gtk-progress-bar.ts +24 -11
- package/src/elements/gtk-revealer.ts +406 -0
- package/src/elements/gtk-scale-button.ts +358 -0
- package/src/elements/gtk-scale.ts +492 -0
- package/src/elements/gtk-scrollbar.ts +528 -0
- package/src/elements/gtk-scrolled-window.ts +642 -0
- package/src/elements/gtk-search-bar.ts +200 -0
- package/src/elements/gtk-search-entry.ts +172 -0
- package/src/elements/gtk-separator.ts +52 -0
- package/src/elements/gtk-spin-button.ts +475 -0
- package/src/elements/gtk-spinner.ts +126 -0
- package/src/elements/gtk-stack-sidebar.ts +212 -0
- package/src/elements/gtk-stack-switcher.ts +279 -0
- package/src/elements/gtk-stack.ts +748 -0
- package/src/elements/gtk-switch.ts +52 -19
- package/src/elements/gtk-text-view.ts +290 -0
- package/src/elements/gtk-text.ts +219 -0
- package/src/elements/gtk-toggle-button.ts +239 -0
- package/src/elements/gtk-tree-expander.ts +243 -0
- package/src/elements/gtk-video.ts +423 -0
- package/src/elements/gtk-viewport.ts +277 -0
- package/src/elements/gtk-window-controls.ts +341 -0
- package/src/elements/gtk-window-handle.ts +221 -0
- package/src/elements/gtk-window.ts +366 -0
- package/src/elements/justification.ts +24 -0
- package/src/elements/popover-menu.ts +24 -0
- package/src/elements/roving-focus.ts +53 -21
- package/src/emoji-data.ts +577 -0
- package/src/entry-rows.spec.ts +31 -0
- package/src/font-description.ts +238 -0
- package/src/gtk-about-dialog.spec.ts +250 -0
- package/src/gtk-action-bar.spec.ts +89 -0
- package/src/gtk-application-window.spec.ts +107 -0
- package/src/gtk-aspect-frame.spec.ts +114 -0
- package/src/gtk-calendar.spec.ts +589 -0
- package/src/gtk-center-box.spec.ts +125 -0
- package/src/gtk-color-dialog-button.spec.ts +141 -0
- package/src/gtk-column-view.spec.ts +154 -0
- package/src/gtk-drag-icon.spec.ts +190 -0
- package/src/gtk-drawing-area.spec.ts +211 -0
- package/src/gtk-editable-label.spec.ts +190 -0
- package/src/gtk-emoji-chooser.spec.ts +173 -0
- package/src/gtk-entry.spec.ts +23 -0
- package/src/gtk-expander.spec.ts +170 -0
- package/src/gtk-fixed.spec.ts +97 -0
- package/src/gtk-flow-box.spec.ts +289 -0
- package/src/gtk-font-dialog-button.spec.ts +166 -0
- package/src/gtk-frame.spec.ts +119 -0
- package/src/gtk-gl-area.spec.ts +361 -0
- package/src/gtk-graphics-offload.spec.ts +119 -0
- package/src/gtk-grid-view.spec.ts +106 -0
- package/src/gtk-grid.spec.ts +122 -0
- package/src/gtk-header-bar.spec.ts +202 -0
- package/src/gtk-inscription.spec.ts +235 -0
- package/src/gtk-level-bar.spec.ts +199 -0
- package/src/gtk-link-button.spec.ts +117 -0
- package/src/gtk-list-box.spec.ts +422 -0
- package/src/gtk-list-view.spec.ts +203 -0
- package/src/gtk-media-controls.spec.ts +295 -0
- package/src/gtk-notebook.spec.ts +546 -0
- package/src/gtk-overlay.spec.ts +141 -0
- package/src/gtk-paned.spec.ts +267 -0
- package/src/gtk-password-entry.spec.ts +150 -0
- package/src/gtk-picture.spec.ts +172 -0
- package/src/gtk-popover-bin.spec.ts +229 -0
- package/src/gtk-popover-menu-bar.spec.ts +296 -0
- package/src/gtk-popover-menu.spec.ts +261 -0
- package/src/gtk-popover-role.spec.ts +138 -0
- package/src/gtk-popover.spec.ts +264 -0
- package/src/gtk-print-dialogs.spec.ts +251 -0
- package/src/gtk-revealer.spec.ts +164 -0
- package/src/gtk-scale-button.spec.ts +218 -0
- package/src/gtk-scale.spec.ts +213 -0
- package/src/gtk-scrollbar.spec.ts +244 -0
- package/src/gtk-scrolled-window.spec.ts +262 -0
- package/src/gtk-search-bar.spec.ts +179 -0
- package/src/gtk-search-entry.spec.ts +142 -0
- package/src/gtk-separator.spec.ts +74 -0
- package/src/gtk-spin-button.spec.ts +186 -0
- package/src/gtk-spinner.spec.ts +130 -0
- package/src/gtk-stack-sidebar.spec.ts +217 -0
- package/src/gtk-stack-switcher.spec.ts +249 -0
- package/src/gtk-stack.spec.ts +432 -0
- package/src/gtk-text-view.spec.ts +189 -0
- package/src/gtk-text.spec.ts +163 -0
- package/src/gtk-toggle-button.spec.ts +186 -0
- package/src/gtk-tree-expander.spec.ts +201 -0
- package/src/gtk-video.spec.ts +240 -0
- package/src/gtk-viewport.spec.ts +140 -0
- package/src/gtk-window-controls.spec.ts +232 -0
- package/src/gtk-window-handle.spec.ts +158 -0
- package/src/gtk-window.spec.ts +190 -0
- package/src/index.ts +9 -1
- package/src/keyboard-operable.spec.ts +33 -1
- package/src/list-view-dom.ts +121 -0
- package/src/namespace/adw.ts +12 -0
- package/src/namespace/gtk.ts +61 -0
- package/src/page-setup.ts +222 -0
- package/src/scroll-shading.ts +18 -1
- package/src/shared-tree-builder.ts +263 -21
- package/src/signals.ts +15 -0
- package/src/source-view/theme.ts +11 -5
- package/src/style-classes.spec.ts +9 -8
- package/src/styles.generated.ts +1 -1
- package/src/tab-chip.ts +200 -0
- package/src/template-classes.ts +45 -0
- package/src/test.browser.mts +152 -0
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
// DOM-level tests for <gtk-calendar>: the 42 cells it paints, the four per-cell states, the six
|
|
2
|
+
// week numbers, the four arrows' sensitivity, the marks and the key table.
|
|
3
|
+
//
|
|
4
|
+
// The ARITHMETIC is `calendar.spec.ts` in @gjsify/adwaita-core, driven from the same
|
|
5
|
+
// conformance tables; what is asserted here is that the element WIRES it — that a month whose
|
|
6
|
+
// first day IS the locale's first day really paints a whole row of previous-month cells, that
|
|
7
|
+
// `markDay` shows on the cell and not on the table, and that `Ctrl`+Arrow walks the months
|
|
8
|
+
// while a bare Arrow walks the cells.
|
|
9
|
+
import { describe, expect, it } from '@gjsify/unit';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
CALENDAR_DAYS_VECTORS,
|
|
13
|
+
CALENDAR_MARK_VECTORS,
|
|
14
|
+
CALENDAR_NAVIGATION_VECTORS,
|
|
15
|
+
CALENDAR_SELECT_VECTORS,
|
|
16
|
+
CALENDAR_STEP_VECTORS,
|
|
17
|
+
CALENDAR_WEEK_VECTORS,
|
|
18
|
+
} from '@gjsify/adwaita-core/conformance';
|
|
19
|
+
|
|
20
|
+
import type { AdwCalendarStep } from '@gjsify/adwaita-core';
|
|
21
|
+
|
|
22
|
+
import { calendarWeekNumber } from '@gjsify/adwaita-core';
|
|
23
|
+
|
|
24
|
+
import type { GtkCalendar } from './elements/gtk-calendar.js';
|
|
25
|
+
|
|
26
|
+
function mount(attrs: Record<string, string> = {}): { el: GtkCalendar; host: HTMLElement } {
|
|
27
|
+
const host = document.createElement('div');
|
|
28
|
+
document.body.appendChild(host);
|
|
29
|
+
const el = document.createElement('gtk-calendar') as GtkCalendar;
|
|
30
|
+
for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
|
|
31
|
+
host.appendChild(el);
|
|
32
|
+
return { el, host };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const cells = (el: GtkCalendar): HTMLButtonElement[] => [
|
|
36
|
+
...el.querySelectorAll<HTMLButtonElement>('.adw-calendar-cell'),
|
|
37
|
+
];
|
|
38
|
+
const weekNumbers = (el: GtkCalendar): string[] =>
|
|
39
|
+
[...el.querySelectorAll<HTMLElement>('.adw-calendar-week-number')].map((el) => el.textContent ?? '');
|
|
40
|
+
const dayNames = (el: GtkCalendar): string[] =>
|
|
41
|
+
[...el.querySelectorAll<HTMLElement>('.adw-calendar-day-name')].map((el) => el.textContent ?? '');
|
|
42
|
+
const arrow = (el: GtkCalendar, name: string): HTMLButtonElement =>
|
|
43
|
+
el.querySelector<HTMLButtonElement>(`.adw-calendar-nav-button[aria-label*="${name}"]`)!;
|
|
44
|
+
const key = (target: Element, init: KeyboardEventInit) =>
|
|
45
|
+
target.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, ...init }));
|
|
46
|
+
|
|
47
|
+
/** Sunday-first, so every assertion below is pinned rather than locale-dependent. */
|
|
48
|
+
const SUNDAY_FIRST = '0';
|
|
49
|
+
|
|
50
|
+
/** `AdwCalendarDate` → the ISO string the `date` door reads, with the month 1-12 the core uses. */
|
|
51
|
+
/** What the element's own locale says, read the same way it reads it. */
|
|
52
|
+
const localeWeekStart = (): number => {
|
|
53
|
+
const language = globalThis.navigator?.language;
|
|
54
|
+
const Locale = (Intl as { Locale?: new (tag: string) => { getWeekInfo?: () => { firstDay: number } } }).Locale;
|
|
55
|
+
if (typeof language !== 'string' || Locale === undefined) return 0;
|
|
56
|
+
const weekInfo = new Locale(language).getWeekInfo?.();
|
|
57
|
+
if (weekInfo === undefined) return 0;
|
|
58
|
+
return ((weekInfo.firstDay % 7) + 7) % 7;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const isoDate = (date: { year: number; month: number; day: number }): string =>
|
|
62
|
+
`${String(date.year).padStart(4, '0')}-${String(date.month).padStart(2, '0')}-${String(date.day).padStart(2, '0')}`;
|
|
63
|
+
|
|
64
|
+
export const GtkCalendarTest = async () => {
|
|
65
|
+
await describe('<gtk-calendar> the grid it paints', async () => {
|
|
66
|
+
await it('always paints 42 cells, the 6x7 array the C allocates unconditionally', () => {
|
|
67
|
+
// gtkcalendar.c:802-815 — `day_number_labels[6][7]`, always, and row-homogeneous
|
|
68
|
+
// (`:786`), so a five-row month still paints six and the height does not jump.
|
|
69
|
+
for (const vector of CALENDAR_DAYS_VECTORS) {
|
|
70
|
+
const { el, host } = mount({ date: `${vector.year}-${String(vector.month).padStart(2, '0')}-01` });
|
|
71
|
+
expect(cells(el)).toHaveLength(42);
|
|
72
|
+
host.remove();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
await it('drives the vector table through the DOM', () => {
|
|
77
|
+
for (const vector of CALENDAR_DAYS_VECTORS) {
|
|
78
|
+
const { el, host } = mount({
|
|
79
|
+
date: `${vector.year}-${String(vector.month).padStart(2, '0')}-01`,
|
|
80
|
+
'week-start': String(vector.weekStart),
|
|
81
|
+
});
|
|
82
|
+
const painted = cells(el);
|
|
83
|
+
const leading = painted.findIndex((cell) => !cell.classList.contains('other-month'));
|
|
84
|
+
expect(leading).toBe(vector.leading);
|
|
85
|
+
let trailing = 0;
|
|
86
|
+
for (
|
|
87
|
+
let index = painted.length - 1;
|
|
88
|
+
index >= 0 && painted[index]!.classList.contains('other-month');
|
|
89
|
+
index--
|
|
90
|
+
) {
|
|
91
|
+
trailing++;
|
|
92
|
+
}
|
|
93
|
+
expect(trailing).toBe(vector.trailing);
|
|
94
|
+
const last = painted[painted.length - 1]!;
|
|
95
|
+
expect(`${last.textContent}`).toBe(String(Number(vector.last.slice(-2))));
|
|
96
|
+
host.remove();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
await it('marks the leading and trailing spill .other-month and nothing else', () => {
|
|
101
|
+
// 2027-02 under a Monday-first locale starts on row 2, so row 1 is all spill.
|
|
102
|
+
const { el, host } = mount({ date: '2027-02-15', 'week-start': '1' });
|
|
103
|
+
const painted = cells(el);
|
|
104
|
+
for (let index = 0; index < 7; index++) {
|
|
105
|
+
expect(painted[index]!.classList.contains('other-month')).toBe(true);
|
|
106
|
+
}
|
|
107
|
+
expect(painted[7]!.classList.contains('other-month')).toBe(false);
|
|
108
|
+
expect(painted[7]!.textContent).toBe('1');
|
|
109
|
+
host.remove();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
await it('follows the locale week start, and the week-start attribute pins it', () => {
|
|
113
|
+
// gtkcalendar.c:700-718 reads it out of the locale; `week-start` is the same
|
|
114
|
+
// override its `calendar:week_start:0` string is, and it is what makes a
|
|
115
|
+
// preview reproducible.
|
|
116
|
+
const { el, host } = mount({ date: '2027-02-15' });
|
|
117
|
+
expect(el.weekStart).toBe(localeWeekStart());
|
|
118
|
+
el.weekStart = 1;
|
|
119
|
+
expect(el.weekStart).toBe(1);
|
|
120
|
+
expect(cells(el)[7]!.classList.contains('other-month')).toBe(false);
|
|
121
|
+
el.weekStart = 0;
|
|
122
|
+
expect(cells(el)[0]!.classList.contains('other-month')).toBe(true);
|
|
123
|
+
el.setAttribute('week-start', '9');
|
|
124
|
+
expect(el.weekStart).toBe(localeWeekStart());
|
|
125
|
+
host.remove();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
await it('numbers the day names from the locale week start', () => {
|
|
129
|
+
// `day = (i + calendar->week_start) % 7` (gtkcalendar.c:773), and this element's
|
|
130
|
+
// week start is the C locale's Sunday-first.
|
|
131
|
+
const { el, host } = mount();
|
|
132
|
+
expect(dayNames(el)).toStrictEqual(['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
|
|
133
|
+
host.remove();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
await it('numbers each row with the ISO week of its LAST cell', () => {
|
|
137
|
+
// The C's own rule: `week = week_of_year (…, calendar->day[i][6])`
|
|
138
|
+
// (gtkcalendar.c:1160) — the row's Saturday.
|
|
139
|
+
const { el, host } = mount({ date: '2026-01-01' });
|
|
140
|
+
expect(weekNumbers(el)).toHaveLength(6);
|
|
141
|
+
expect(weekNumbers(el).every((week) => /^\d+$/.test(week))).toBe(true);
|
|
142
|
+
host.remove();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
await it('hides the week numbers until asked, and they are a real grid column', () => {
|
|
146
|
+
const { el, host } = mount();
|
|
147
|
+
const numbers = el.querySelectorAll('.adw-calendar-week-number');
|
|
148
|
+
expect(numbers.length).toBe(6);
|
|
149
|
+
// The COLUMN exists either way upstream (gtkcalendar.c:786-790), so the day names
|
|
150
|
+
// stay aligned when it appears.
|
|
151
|
+
expect(el.querySelector('.adw-calendar-week-spacer')).not.toBe(null);
|
|
152
|
+
el.showWeekNumbers = true;
|
|
153
|
+
expect(el.hasAttribute('show-week-numbers')).toBe(true);
|
|
154
|
+
host.remove();
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
await describe('<gtk-calendar> the date', async () => {
|
|
159
|
+
await it("reads an ISO YYYY-MM-DD date, GDateTime's own serialisation", () => {
|
|
160
|
+
const { el, host } = mount({ date: '2026-10-02' });
|
|
161
|
+
expect(el.date).toBe('2026-10-02');
|
|
162
|
+
expect(el.year).toBe(2026);
|
|
163
|
+
// The GIR `month` property is 0-11 (gtkcalendar.c:419-429), and it is the one place
|
|
164
|
+
// this element is not in GDateTime's own 1-12 numbering.
|
|
165
|
+
expect(el.month).toBe(9);
|
|
166
|
+
expect(el.day).toBe(2);
|
|
167
|
+
host.remove();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
await it('is TODAY with no attribute, as gtk_calendar_init seeds it', () => {
|
|
171
|
+
const { el, host } = mount();
|
|
172
|
+
const now = new Date();
|
|
173
|
+
expect(el.year).toBe(now.getFullYear());
|
|
174
|
+
expect(el.month).toBe(now.getMonth());
|
|
175
|
+
expect(el.day).toBe(now.getDate());
|
|
176
|
+
host.remove();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await it('ignores a malformed date rather than refusing the widget', () => {
|
|
180
|
+
const { el, host } = mount({ date: '2026-10-02' });
|
|
181
|
+
el.setAttribute('date', 'not-a-date');
|
|
182
|
+
expect(el.date).toBe('2026-10-02');
|
|
183
|
+
host.remove();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
await it('steps a year or a month through the DEPRECATED halves, keeping the rest', async () => {
|
|
187
|
+
// gtk_calendar_set_year (:860-880) builds a new date from the same day in the new
|
|
188
|
+
// year and hands it to the same select_day_internal.
|
|
189
|
+
const { el, host } = mount({ date: '2026-10-02' });
|
|
190
|
+
el.year = 2030;
|
|
191
|
+
expect(el.date).toBe('2030-10-02');
|
|
192
|
+
el.month = 0;
|
|
193
|
+
expect(el.date).toBe('2030-01-02');
|
|
194
|
+
el.day = 15;
|
|
195
|
+
expect(el.date).toBe('2030-01-15');
|
|
196
|
+
host.remove();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
await it('clamps an impossible day into the month the three halves name', () => {
|
|
200
|
+
const { el, host } = mount({ date: '2026-01-31' });
|
|
201
|
+
el.month = 1;
|
|
202
|
+
expect(el.date).toBe('2026-02-28');
|
|
203
|
+
host.remove();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
await it('clamps a leap day when the year steps away from it', () => {
|
|
207
|
+
const { el, host } = mount({ date: '2024-02-29' });
|
|
208
|
+
el.year = 2025;
|
|
209
|
+
expect(el.date).toBe('2025-02-28');
|
|
210
|
+
host.remove();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
await it('clamps 31 January plus a month to the 28th, never to 3 March', () => {
|
|
214
|
+
const { el, host } = mount({ date: '2026-01-31' });
|
|
215
|
+
arrow(el, 'Next Month').click();
|
|
216
|
+
expect(el.date).toBe('2026-02-28');
|
|
217
|
+
host.remove();
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
await describe('<gtk-calendar> the three show-* flags', async () => {
|
|
222
|
+
await it('defaults heading and day names ON and week numbers OFF', () => {
|
|
223
|
+
const { el, host } = mount();
|
|
224
|
+
expect(el.showHeading).toBe(true);
|
|
225
|
+
expect(el.showDayNames).toBe(true);
|
|
226
|
+
expect(el.showWeekNumbers).toBe(false);
|
|
227
|
+
host.remove();
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
await it('reads heading and day names as the OFF switch, being GIR defaults of TRUE', () => {
|
|
231
|
+
const { el, host } = mount({ 'show-heading': 'false', 'show-day-names': 'false' });
|
|
232
|
+
expect(el.showHeading).toBe(false);
|
|
233
|
+
expect(el.showDayNames).toBe(false);
|
|
234
|
+
host.remove();
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
await describe('<gtk-calendar> the four arrows', async () => {
|
|
239
|
+
await it("walks the months and the years, and emits each arrow's own signal", () => {
|
|
240
|
+
const { el, host } = mount({ date: '2026-10-15' });
|
|
241
|
+
const seen: string[] = [];
|
|
242
|
+
for (const name of ['prev-month', 'next-month', 'prev-year', 'next-year']) {
|
|
243
|
+
el.addEventListener(name, () => {
|
|
244
|
+
seen.push(name);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
arrow(el, 'Next Month').click();
|
|
248
|
+
expect(el.date).toBe('2026-11-15');
|
|
249
|
+
arrow(el, 'Previous Month').click();
|
|
250
|
+
expect(el.date).toBe('2026-10-15');
|
|
251
|
+
arrow(el, 'Next Year').click();
|
|
252
|
+
expect(el.date).toBe('2027-10-15');
|
|
253
|
+
arrow(el, 'Previous Year').click();
|
|
254
|
+
expect(el.date).toBe('2026-10-15');
|
|
255
|
+
expect(seen).toStrictEqual(['next-month', 'prev-month', 'next-year', 'prev-year']);
|
|
256
|
+
host.remove();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
await it('kills the backward pair at the first year and the forward pair at the last', () => {
|
|
260
|
+
// calendar_update_navigation_buttons (:1055-1084) disables the MONTH arrow and the
|
|
261
|
+
// YEAR arrow separately at each end.
|
|
262
|
+
const { el, host } = mount({ date: '0001-01-01' });
|
|
263
|
+
expect(arrow(el, 'Previous Month').disabled).toBe(true);
|
|
264
|
+
expect(arrow(el, 'Previous Year').disabled).toBe(true);
|
|
265
|
+
expect(arrow(el, 'Next Month').disabled).toBe(false);
|
|
266
|
+
el.date = '9999-12-31';
|
|
267
|
+
expect(arrow(el, 'Next Month').disabled).toBe(true);
|
|
268
|
+
expect(arrow(el, 'Next Year').disabled).toBe(true);
|
|
269
|
+
expect(arrow(el, 'Previous Month').disabled).toBe(false);
|
|
270
|
+
host.remove();
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
await it("paging a month does NOT fire day-selected, the C's emit_day_signal FALSE", () => {
|
|
274
|
+
// gtkcalendar.c:868-919 — the month and year arrows pass FALSE, and only the day
|
|
275
|
+
// notify/signal pair is inside `if (day_changed)` (:1169-1175).
|
|
276
|
+
const { el, host } = mount({ date: '2026-10-15' });
|
|
277
|
+
let selected = 0;
|
|
278
|
+
el.addEventListener('day-selected', () => {
|
|
279
|
+
selected++;
|
|
280
|
+
});
|
|
281
|
+
arrow(el, 'Next Month').click();
|
|
282
|
+
expect(selected).toBe(0);
|
|
283
|
+
cells(el)[15]!.click();
|
|
284
|
+
expect(selected).toBe(1);
|
|
285
|
+
host.remove();
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
await describe('<gtk-calendar> the per-cell states', async () => {
|
|
290
|
+
await it('marks the selected day and today separately', () => {
|
|
291
|
+
// March, so the assertion cannot pass or fail by accident on the day this runs.
|
|
292
|
+
const { el, host } = mount({ date: '2026-03-17' });
|
|
293
|
+
const selected = cells(el).filter((cell) => cell.classList.contains('selected'));
|
|
294
|
+
expect(selected).toHaveLength(1);
|
|
295
|
+
expect(selected[0]!.textContent).toBe('17');
|
|
296
|
+
expect(selected[0]!.classList.contains('today')).toBe(false);
|
|
297
|
+
host.remove();
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
await it('marks TODAY on the cell the month grid says is today', () => {
|
|
301
|
+
const now = new Date();
|
|
302
|
+
const { el, host } = mount({
|
|
303
|
+
date: `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-01`,
|
|
304
|
+
});
|
|
305
|
+
const marked = cells(el).filter((cell) => cell.classList.contains('today'));
|
|
306
|
+
expect(marked).toHaveLength(1);
|
|
307
|
+
expect(marked[0]!.textContent).toBe(String(now.getDate()));
|
|
308
|
+
host.remove();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
await it('shows a MARKED day as .marked, and only inside the current month', () => {
|
|
312
|
+
const { el, host } = mount({ date: '2026-10-01' });
|
|
313
|
+
el.markDay(14);
|
|
314
|
+
expect(el.markedDays).toStrictEqual([14]);
|
|
315
|
+
const marked = cells(el).filter((cell) => cell.classList.contains('marked'));
|
|
316
|
+
expect(marked).toHaveLength(1);
|
|
317
|
+
expect(marked[0]!.textContent).toBe('14');
|
|
318
|
+
expect(marked[0]!.classList.contains('other-month')).toBe(false);
|
|
319
|
+
host.remove();
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
await it('a mark on the 31st survives paging to a month that has no 31st', () => {
|
|
323
|
+
// The table is 31 slots and NOT per month, and `calendar_update_day_labels` only
|
|
324
|
+
// consults it for CURRENT-month cells (gtkcalendar.c:1041-1042) — so the mark does
|
|
325
|
+
// not show and comes back when the month does.
|
|
326
|
+
const { el, host } = mount({ date: '2026-01-01' });
|
|
327
|
+
el.markDay(31);
|
|
328
|
+
expect(cells(el).filter((cell) => cell.classList.contains('marked'))).toHaveLength(1);
|
|
329
|
+
arrow(el, 'Next Month').click();
|
|
330
|
+
expect(cells(el).filter((cell) => cell.classList.contains('marked'))).toHaveLength(0);
|
|
331
|
+
expect(el.markedDays).toStrictEqual([31]);
|
|
332
|
+
arrow(el, 'Next Month').click();
|
|
333
|
+
expect(cells(el).filter((cell) => cell.classList.contains('marked'))).toHaveLength(1);
|
|
334
|
+
host.remove();
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
await it('is idempotent, so marking twice is silent and the second does not add', () => {
|
|
338
|
+
const { el, host } = mount({ date: '2026-10-01' });
|
|
339
|
+
el.markDay(3);
|
|
340
|
+
el.markDay(3);
|
|
341
|
+
expect(el.markedDays).toStrictEqual([3]);
|
|
342
|
+
el.unmarkDay(3);
|
|
343
|
+
el.unmarkDay(3);
|
|
344
|
+
expect(el.dayIsMarked(3)).toBe(false);
|
|
345
|
+
host.remove();
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
await it('ignores an out-of-range day rather than clamping it', () => {
|
|
349
|
+
const { el, host } = mount({ date: '2026-10-01' });
|
|
350
|
+
el.markDay(0);
|
|
351
|
+
el.markDay(32);
|
|
352
|
+
expect(el.markedDays).toStrictEqual([]);
|
|
353
|
+
expect(el.dayIsMarked(32)).toBe(false);
|
|
354
|
+
host.remove();
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
await it('clears every mark at once', () => {
|
|
358
|
+
const { el, host } = mount({ date: '2026-10-01' });
|
|
359
|
+
el.markDay(1);
|
|
360
|
+
el.markDay(31);
|
|
361
|
+
el.clearMarks();
|
|
362
|
+
expect(el.markedDays).toStrictEqual([]);
|
|
363
|
+
host.remove();
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
await describe('<gtk-calendar> the ISO week and the navigation through the DOM', async () => {
|
|
368
|
+
for (const vector of CALENDAR_WEEK_VECTORS) {
|
|
369
|
+
await it(vector.rule, () => {
|
|
370
|
+
const { el, host } = mount({ date: isoDate(vector.date), 'week-start': SUNDAY_FIRST });
|
|
371
|
+
// A `week-number` label is the ISO week of its ROW'S LAST CELL — the C's own
|
|
372
|
+
// rule, `week_of_year (…, calendar->day[i][6])` (gtkcalendar.c:1160) — so the
|
|
373
|
+
// two things a DOM reader can check are that the row holding the vector's date
|
|
374
|
+
// shows ITS OWN week when the date ends the row, and that the vector's week is
|
|
375
|
+
// among the six labels the month painted.
|
|
376
|
+
const labels = weekNumbers(el);
|
|
377
|
+
const painted = cells(el);
|
|
378
|
+
const index = painted.findIndex(
|
|
379
|
+
(cell) => !cell.classList.contains('other-month') && cell.textContent === String(vector.date.day),
|
|
380
|
+
);
|
|
381
|
+
expect(index).toBeGreaterThanOrEqual(0);
|
|
382
|
+
expect(labels).toContain(String(vector.week));
|
|
383
|
+
// The row of the LAST cell, which is the one whose label the C computes.
|
|
384
|
+
const rowLast = index - (index % 7) + 6;
|
|
385
|
+
expect(labels[Math.trunc(rowLast / 7)]).toBe(String(calendarWeekNumber(el.cells[rowLast]!.date)));
|
|
386
|
+
host.remove();
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
for (const vector of CALENDAR_NAVIGATION_VECTORS) {
|
|
391
|
+
await it(vector.rule, () => {
|
|
392
|
+
const { el, host } = mount({ date: isoDate(vector.date) });
|
|
393
|
+
expect(arrow(el, 'Previous Month').disabled).toBe(!vector.expected.previousMonth);
|
|
394
|
+
expect(arrow(el, 'Next Month').disabled).toBe(!vector.expected.nextMonth);
|
|
395
|
+
expect(arrow(el, 'Previous Year').disabled).toBe(!vector.expected.previousYear);
|
|
396
|
+
expect(arrow(el, 'Next Year').disabled).toBe(!vector.expected.nextYear);
|
|
397
|
+
host.remove();
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
await describe('<gtk-calendar> the clamped steps, as the four arrows walk them', async () => {
|
|
403
|
+
for (const vector of CALENDAR_STEP_VECTORS) {
|
|
404
|
+
await it(vector.rule, () => {
|
|
405
|
+
const { el, host } = mount({ date: isoDate(vector.from) });
|
|
406
|
+
const label: Record<AdwCalendarStep, string> = {
|
|
407
|
+
'previous-month': 'Previous Month',
|
|
408
|
+
'next-month': 'Next Month',
|
|
409
|
+
'previous-year': 'Previous Year',
|
|
410
|
+
'next-year': 'Next Year',
|
|
411
|
+
};
|
|
412
|
+
const button = arrow(el, label[vector.step]);
|
|
413
|
+
// A dead arrow is the C's refusal at the ends of the range, and the vector
|
|
414
|
+
// expects the date to stay put when it is.
|
|
415
|
+
if (!button.disabled) button.click();
|
|
416
|
+
expect(el.date).toBe(isoDate(vector.expected));
|
|
417
|
+
host.remove();
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
await describe('<gtk-calendar> the select vectors, as attribute writes', async () => {
|
|
423
|
+
for (const vector of CALENDAR_SELECT_VECTORS) {
|
|
424
|
+
await it(vector.rule, () => {
|
|
425
|
+
const { el, host } = mount({ date: isoDate(vector.current) });
|
|
426
|
+
let selected = 0;
|
|
427
|
+
el.addEventListener('day-selected', () => {
|
|
428
|
+
selected++;
|
|
429
|
+
});
|
|
430
|
+
// A write through `date`, which is the door `emit_day_signal` TRUE belongs to;
|
|
431
|
+
// the navigation arrows below carry the FALSE half.
|
|
432
|
+
el.setAttribute('date', isoDate(vector.target));
|
|
433
|
+
expect(el.date).toBe(isoDate(vector.expected.date));
|
|
434
|
+
// The `emit` argument is the C's `emit_day_signal`; a PROPERTY WRITE passes
|
|
435
|
+
// TRUE, and the signal is then gated on `day_changed` (:1169-1175).
|
|
436
|
+
expect(selected).toBe(vector.emit && vector.expected.emitDaySignal ? 1 : 0);
|
|
437
|
+
host.remove();
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
await it('a write of the date already shown is silent in every component', () => {
|
|
442
|
+
const { el, host } = mount({ date: '2026-10-02' });
|
|
443
|
+
let selected = 0;
|
|
444
|
+
el.addEventListener('day-selected', () => {
|
|
445
|
+
selected++;
|
|
446
|
+
});
|
|
447
|
+
el.setAttribute('date', '2026-10-02');
|
|
448
|
+
expect(selected).toBe(0);
|
|
449
|
+
host.remove();
|
|
450
|
+
});
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
await describe('<gtk-calendar> the marks, through markDay', async () => {
|
|
454
|
+
for (const vector of CALENDAR_MARK_VECTORS) {
|
|
455
|
+
await it(vector.rule, () => {
|
|
456
|
+
const { el, host } = mount({ date: '2026-10-01' });
|
|
457
|
+
// The vector's table is 31 BOOLEANS, which is the C's own `marked_date`
|
|
458
|
+
// (gtkcalendar.c:826-827), and the element's door takes a day NUMBER.
|
|
459
|
+
vector.marked.forEach((mark, index) => {
|
|
460
|
+
if (mark) el.markDay(index + 1);
|
|
461
|
+
});
|
|
462
|
+
el[vector.mark ? 'markDay' : 'unmarkDay'](vector.day);
|
|
463
|
+
const painted = cells(el)
|
|
464
|
+
.filter((cell) => cell.classList.contains('marked'))
|
|
465
|
+
.map((cell) => Number(cell.textContent));
|
|
466
|
+
expect(painted).toStrictEqual(vector.expected.flatMap((mark, index) => (mark ? [index + 1] : [])));
|
|
467
|
+
host.remove();
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
await describe('<gtk-calendar> clicking a cell', async () => {
|
|
473
|
+
await it('selects the day it names and fires day-selected', () => {
|
|
474
|
+
const { el, host } = mount({ date: '2026-10-02' });
|
|
475
|
+
const painted = cells(el);
|
|
476
|
+
const ninth = painted.find((cell) => cell.textContent === '9' && !cell.classList.contains('other-month'))!;
|
|
477
|
+
let selected = 0;
|
|
478
|
+
el.addEventListener('day-selected', () => {
|
|
479
|
+
selected++;
|
|
480
|
+
});
|
|
481
|
+
ninth.click();
|
|
482
|
+
expect(el.date).toBe('2026-10-09');
|
|
483
|
+
expect(selected).toBe(1);
|
|
484
|
+
host.remove();
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
await it('PAGES first on a cell from another month, then selects that day', () => {
|
|
488
|
+
// The MONTH_PREV / MONTH_NEXT branch of the Space handler (:1521-1534); a click
|
|
489
|
+
// lands on the same cell either way.
|
|
490
|
+
const { el, host } = mount({ date: '2026-10-15' });
|
|
491
|
+
// October 2026 opens on a Thursday, so under a Sunday-first grid the leading spill
|
|
492
|
+
// is September's 27-30.
|
|
493
|
+
const spill = cells(el).find(
|
|
494
|
+
(cell) => cell.classList.contains('other-month') && cell.textContent === '28',
|
|
495
|
+
)!;
|
|
496
|
+
spill.click();
|
|
497
|
+
expect(el.date).toBe('2026-09-28');
|
|
498
|
+
host.remove();
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
await it('re-selecting the day already shown changes nothing and fires nothing', () => {
|
|
502
|
+
// The early return in calendar_select_day_internal (:1103-1104).
|
|
503
|
+
const { el, host } = mount({ date: '2026-10-02' });
|
|
504
|
+
let selected = 0;
|
|
505
|
+
el.addEventListener('day-selected', () => {
|
|
506
|
+
selected++;
|
|
507
|
+
});
|
|
508
|
+
const painted = cells(el);
|
|
509
|
+
painted.find((cell) => cell.textContent === '2' && !cell.classList.contains('other-month'))!.click();
|
|
510
|
+
expect(selected).toBe(0);
|
|
511
|
+
host.remove();
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
await describe('<gtk-calendar> the key table', async () => {
|
|
516
|
+
await it('moves the cursor with a bare arrow and leaves the date alone', () => {
|
|
517
|
+
const { el, host } = mount({ date: '2026-10-15' });
|
|
518
|
+
const painted = cells(el);
|
|
519
|
+
const fifteenth = painted.find(
|
|
520
|
+
(cell) => cell.textContent === '15' && !cell.classList.contains('other-month'),
|
|
521
|
+
)!;
|
|
522
|
+
fifteenth.focus();
|
|
523
|
+
key(fifteenth, { key: 'ArrowRight' });
|
|
524
|
+
expect(cells(el).filter((cell) => cell.classList.contains('focused'))).toHaveLength(1);
|
|
525
|
+
expect(el.date).toBe('2026-10-15');
|
|
526
|
+
host.remove();
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
await it('wraps the cursor off the grid, as move_focus does', () => {
|
|
530
|
+
// `focus_row`/`focus_col` start at -1 (gtkcalendar.c:817-818), which is the ONLY
|
|
531
|
+
// way those two `if (focus_row < 0) → 5` / `if (focus_col < 0) → 6` lines are
|
|
532
|
+
// reachable: the first ArrowUp with no cursor yet lands on row 5 column 6, the
|
|
533
|
+
// LAST cell. Once the cursor is somewhere, an ArrowUp at row 0 stays at row 0 —
|
|
534
|
+
// which is what the C does too, and a reader who expects a wrap there has the
|
|
535
|
+
// order of the two `if`s backwards.
|
|
536
|
+
const { el, host } = mount({ date: '2026-10-01' });
|
|
537
|
+
const painted = cells(el);
|
|
538
|
+
key(painted[0]!, { key: 'ArrowUp' });
|
|
539
|
+
expect(cells(el).find((cell) => cell.classList.contains('focused'))).toBe(painted[41]);
|
|
540
|
+
key(painted[0]!, { key: 'ArrowUp' });
|
|
541
|
+
expect(cells(el).find((cell) => cell.classList.contains('focused'))).toBe(painted[34]);
|
|
542
|
+
host.remove();
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
await it('Ctrl+Arrow walks the months and the years', () => {
|
|
546
|
+
const { el, host } = mount({ date: '2026-10-15' });
|
|
547
|
+
const painted = cells(el);
|
|
548
|
+
const fifteenth = painted.find(
|
|
549
|
+
(cell) => cell.textContent === '15' && !cell.classList.contains('other-month'),
|
|
550
|
+
)!;
|
|
551
|
+
fifteenth.focus();
|
|
552
|
+
key(fifteenth, { key: 'ArrowRight', ctrlKey: true });
|
|
553
|
+
expect(el.date).toBe('2026-11-15');
|
|
554
|
+
key(fifteenth, { key: 'ArrowLeft', ctrlKey: true });
|
|
555
|
+
expect(el.date).toBe('2026-10-15');
|
|
556
|
+
key(fifteenth, { key: 'ArrowDown', ctrlKey: true });
|
|
557
|
+
expect(el.date).toBe('2027-10-15');
|
|
558
|
+
host.remove();
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
await it('Ctrl+Arrow refuses where the ARROW would, at the ends of the range', () => {
|
|
562
|
+
// gtkcalendar.c:1492-1494 — "Not allowed with the mouse, not allowed with the
|
|
563
|
+
// keyboard", checked against the same four buttons.
|
|
564
|
+
const { el, host } = mount({ date: '0001-01-01' });
|
|
565
|
+
const painted = cells(el);
|
|
566
|
+
painted[7]!.focus();
|
|
567
|
+
key(painted[7]!, { key: 'ArrowLeft', ctrlKey: true });
|
|
568
|
+
expect(el.date).toBe('0001-01-01');
|
|
569
|
+
key(painted[7]!, { key: 'ArrowRight', ctrlKey: true });
|
|
570
|
+
expect(el.date).toBe('0001-02-01');
|
|
571
|
+
host.remove();
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
await it('Space selects the cell the CURSOR is on, and pages for a spill cell', () => {
|
|
575
|
+
// The cursor is ARROW-driven and only `move_focus` and a selection set it
|
|
576
|
+
// (`focus_row`/`focus_col` are internal state, gtkcalendar.c:817-818) — so focusing
|
|
577
|
+
// a cell with the mouse does not move it, and this test moves it the way the C does.
|
|
578
|
+
// Under a Sunday-first grid the last cell of October 2026 is 7 November, a
|
|
579
|
+
// MONTH_NEXT cell, so Space pages forward and then selects that day.
|
|
580
|
+
const { el, host } = mount({ date: '2026-10-15', 'week-start': SUNDAY_FIRST });
|
|
581
|
+
const painted = cells(el);
|
|
582
|
+
key(painted[0]!, { key: 'ArrowUp' });
|
|
583
|
+
expect(cells(el).find((cell) => cell.classList.contains('focused'))).toBe(painted[41]);
|
|
584
|
+
key(painted[0]!, { key: ' ' });
|
|
585
|
+
expect(el.date).toBe('2026-11-07');
|
|
586
|
+
host.remove();
|
|
587
|
+
});
|
|
588
|
+
});
|
|
589
|
+
};
|