@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,546 @@
|
|
|
1
|
+
// DOM-level tests for <gtk-notebook>. The widget is four separable things and each gets
|
|
2
|
+
// its own describe: WHICH PAGE is current (the guards in `set_current_page` and
|
|
3
|
+
// `real_switch_page`), the PAGE DESCRIPTOR (a GtkNotebookPage is a GObject, so its
|
|
4
|
+
// properties are attributes on the child), THE TAB STRIP (which the notebook builds
|
|
5
|
+
// itself, and what `tab-pos` does to it) and the NOTIFICATION contract.
|
|
6
|
+
import { describe, expect, it } from '@gjsify/unit';
|
|
7
|
+
|
|
8
|
+
import type { GtkNotebook } from './elements/gtk-notebook.js';
|
|
9
|
+
import { buildSharedTree } from './shared-tree-builder.js';
|
|
10
|
+
|
|
11
|
+
interface Page {
|
|
12
|
+
label?: string;
|
|
13
|
+
menu?: string;
|
|
14
|
+
fill?: boolean;
|
|
15
|
+
expand?: boolean;
|
|
16
|
+
reorderable?: boolean;
|
|
17
|
+
detachable?: boolean;
|
|
18
|
+
hidden?: boolean;
|
|
19
|
+
body?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** A notebook with its pages, `<gtk-notebook>` already upgraded and rendered. */
|
|
23
|
+
function mount(pages: Page[] = [], attrs: Record<string, string> = {}): { el: GtkNotebook; host: HTMLElement } {
|
|
24
|
+
const host = document.createElement('div');
|
|
25
|
+
document.body.appendChild(host);
|
|
26
|
+
const el = document.createElement('gtk-notebook') as GtkNotebook;
|
|
27
|
+
for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
|
|
28
|
+
for (const page of pages) {
|
|
29
|
+
const child = document.createElement('div');
|
|
30
|
+
if (page.label !== undefined) child.setAttribute('tab-label', page.label);
|
|
31
|
+
if (page.menu !== undefined) child.setAttribute('menu-label', page.menu);
|
|
32
|
+
if (page.fill === false) child.setAttribute('tab-fill', 'false');
|
|
33
|
+
if (page.expand) child.setAttribute('tab-expand', '');
|
|
34
|
+
if (page.reorderable) child.setAttribute('reorderable', '');
|
|
35
|
+
if (page.detachable) child.setAttribute('detachable', '');
|
|
36
|
+
if (page.hidden) child.setAttribute('hidden', '');
|
|
37
|
+
child.textContent = page.body ?? page.label ?? 'page';
|
|
38
|
+
el.appendChild(child);
|
|
39
|
+
}
|
|
40
|
+
host.appendChild(el);
|
|
41
|
+
return { el, host };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The tab buttons the render pass produced, as the strip holds them. */
|
|
45
|
+
function tabs(el: GtkNotebook): HTMLButtonElement[] {
|
|
46
|
+
return Array.from(el.querySelectorAll('.adw-notebook-tab')) as HTMLButtonElement[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The children in DOM order, with `visible-page` marked, as the render pass sees them. */
|
|
50
|
+
function marks(el: GtkNotebook): string[] {
|
|
51
|
+
return (Array.from(el.children) as HTMLElement[])
|
|
52
|
+
.filter((child) => child !== el.querySelector('.adw-notebook-header'))
|
|
53
|
+
.map(
|
|
54
|
+
(child) =>
|
|
55
|
+
`${child.getAttribute('tab-label') ?? '?'}${child.classList.contains('visible-page') ? ':visible' : ''}`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const GtkNotebookTest = async () => {
|
|
60
|
+
await describe('<gtk-notebook> defaults', async () => {
|
|
61
|
+
await it('shows the first page and marks only that one visible', () => {
|
|
62
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
63
|
+
expect(el.nPages).toBe(2);
|
|
64
|
+
expect(el.page).toBe(0);
|
|
65
|
+
expect(marks(el)).toStrictEqual(['One:visible', 'Two']);
|
|
66
|
+
host.remove();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await it('labels a page with no tab-label "Page N", counting from one', () => {
|
|
70
|
+
// gtk_notebook_update_labels (gtknotebook.c:4353-4373): `g_snprintf (string,
|
|
71
|
+
// …, _("Page %u"), page_num++)` and `text = page->tab_text ?: string`, so the
|
|
72
|
+
// number is the FALLBACK rather than a reason to have no tab.
|
|
73
|
+
const { el, host } = mount([{ label: 'One' }, {}, {}]);
|
|
74
|
+
expect(tabs(el).map((tab) => tab.textContent)).toStrictEqual(['One', 'Page 2', 'Page 3']);
|
|
75
|
+
host.remove();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await it('counts the numbering over the VISIBLE pages only', () => {
|
|
79
|
+
// `gtk_notebook_search_page (…, STEP_NEXT, FALSE)` walks the visible pages, so
|
|
80
|
+
// a hidden one takes no number and does not shift the ones after it
|
|
81
|
+
// (gtknotebook.c:4361-4364).
|
|
82
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two', hidden: true }, {}]);
|
|
83
|
+
expect(tabs(el).map((tab) => tab.textContent)).toStrictEqual(['One', 'Two', 'Page 2']);
|
|
84
|
+
expect(tabs(el)[1].hidden).toBe(true);
|
|
85
|
+
host.remove();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
await it('a hidden page does not make the observer spin', async () => {
|
|
89
|
+
// The regression that HANGS the whole browser suite rather than failing one
|
|
90
|
+
// test: `setAttribute` queues a mutation record even when the value is
|
|
91
|
+
// unchanged, and the render pass writes `hidden` on the tabs, so an observer
|
|
92
|
+
// that watched the whole subtree fed its own writes straight back in. The
|
|
93
|
+
// await is the assertion — a spin starves the macrotask queue and the run
|
|
94
|
+
// never finishes, which is how the bug presented.
|
|
95
|
+
const { el, host } = mount([{ label: 'One', hidden: true }, { label: 'Two' }]);
|
|
96
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
97
|
+
expect(tabs(el).map((tab) => tab.hidden)).toStrictEqual([true, false]);
|
|
98
|
+
expect(el.page).toBe(1);
|
|
99
|
+
host.remove();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await it('gives the current tab the checked state and aria-selected', () => {
|
|
103
|
+
// `gtk_widget_set_state_flags (page->tab_widget, GTK_STATE_FLAG_CHECKED)` and
|
|
104
|
+
// the accessible SELECTED that follows it (gtknotebook.c:5466, :5472-5474).
|
|
105
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
106
|
+
expect(tabs(el).map((tab) => tab.classList.contains('active'))).toStrictEqual([true, false]);
|
|
107
|
+
expect(tabs(el).map((tab) => tab.getAttribute('aria-selected'))).toStrictEqual(['true', 'false']);
|
|
108
|
+
host.remove();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
await it('reports the tab position as top, and reflects it', () => {
|
|
112
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
113
|
+
expect(el.tabPos).toBe('top');
|
|
114
|
+
expect(el.getAttribute('data-tab-pos')).toBe('top');
|
|
115
|
+
host.remove();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
await it('swaps left and right under RTL, which is what data-tab-pos is for', () => {
|
|
119
|
+
// get_effective_tab_pos (gtknotebook.c:1741-1757) swaps only the two horizontal
|
|
120
|
+
// edges; `top` and `bottom` are unaffected.
|
|
121
|
+
const rtl = mount([{ label: 'One' }], { 'tab-pos': 'left' });
|
|
122
|
+
rtl.el.setAttribute('dir', 'rtl');
|
|
123
|
+
rtl.el.refresh();
|
|
124
|
+
expect(rtl.el.getAttribute('data-tab-pos')).toBe('right');
|
|
125
|
+
rtl.host.remove();
|
|
126
|
+
|
|
127
|
+
const ltr = mount([{ label: 'One' }], { 'tab-pos': 'bottom' });
|
|
128
|
+
ltr.el.setAttribute('dir', 'rtl');
|
|
129
|
+
ltr.el.refresh();
|
|
130
|
+
expect(ltr.el.getAttribute('data-tab-pos')).toBe('bottom');
|
|
131
|
+
ltr.host.remove();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
await describe('<gtk-notebook> switching', async () => {
|
|
136
|
+
await it('a negative page means the LAST page, not "none"', () => {
|
|
137
|
+
// `if (page_num < 0) page_num = g_list_length (notebook->children) - 1`
|
|
138
|
+
// (gtknotebook.c:6054).
|
|
139
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }, { label: 'Three' }]);
|
|
140
|
+
expect(el.setCurrentPage(-1)).toBe(true);
|
|
141
|
+
expect(el.page).toBe(2);
|
|
142
|
+
host.remove();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
await it('an out-of-range page does nothing at all', () => {
|
|
146
|
+
// `list = g_list_nth (…); if (list) gtk_notebook_switch_page (…)`
|
|
147
|
+
// (gtknotebook.c:6056-6058) — the guard, not a clamp and not a throw.
|
|
148
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
149
|
+
expect(el.setCurrentPage(7)).toBe(false);
|
|
150
|
+
expect(el.page).toBe(0);
|
|
151
|
+
host.remove();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await it('refuses a page whose child is hidden', () => {
|
|
155
|
+
// `notebook->cur_page == page || !gtk_widget_get_visible (GTK_WIDGET (child))`
|
|
156
|
+
// is ONE condition (gtknotebook.c:5444), so a hidden page is not switchable
|
|
157
|
+
// however it is asked for.
|
|
158
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two', hidden: true }]);
|
|
159
|
+
expect(el.setCurrentPage(1)).toBe(false);
|
|
160
|
+
expect(el.page).toBe(0);
|
|
161
|
+
host.remove();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
await it('switching to the current page is not a change', () => {
|
|
165
|
+
// The other half of :5444 — the guard returns before anything is notified.
|
|
166
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
167
|
+
let switches = 0;
|
|
168
|
+
el.addEventListener('switch-page', () => (switches += 1));
|
|
169
|
+
expect(el.setCurrentPage(0)).toBe(false);
|
|
170
|
+
expect(switches).toBe(0);
|
|
171
|
+
host.remove();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
await it('next and prev step OVER a hidden page', () => {
|
|
175
|
+
// `gtk_notebook_search_page (…, STEP_NEXT, TRUE)` — the TRUE is `find_visible`
|
|
176
|
+
// (gtknotebook.c:6078), which is why a hidden page does not end the walk.
|
|
177
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two', hidden: true }, { label: 'Three' }]);
|
|
178
|
+
expect(el.nextPage()).toBe(true);
|
|
179
|
+
expect(el.page).toBe(2);
|
|
180
|
+
expect(el.prevPage()).toBe(true);
|
|
181
|
+
expect(el.page).toBe(0);
|
|
182
|
+
host.remove();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
await it('off either end next and prev do nothing', () => {
|
|
186
|
+
// `if (!list) return` after the search (gtknotebook.c:6079-6080).
|
|
187
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
188
|
+
expect(el.prevPage()).toBe(false);
|
|
189
|
+
expect(el.nextPage()).toBe(false);
|
|
190
|
+
expect(el.page).toBe(0);
|
|
191
|
+
host.remove();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
await it('a click on a tab switches to that page', () => {
|
|
195
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
196
|
+
tabs(el)[1].click();
|
|
197
|
+
expect(el.page).toBe(1);
|
|
198
|
+
expect(el.currentPage?.getAttribute('tab-label')).toBe('Two');
|
|
199
|
+
host.remove();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
await it('reads page LIVE, and leaves the attribute as the input it was', () => {
|
|
203
|
+
// `get_property` returns `gtk_notebook_get_current_page (notebook)`
|
|
204
|
+
// (gtknotebook.c:1977-1979) rather than the value last written, so a switch
|
|
205
|
+
// that reached the notebook by clicking a tab is visible through the property
|
|
206
|
+
// even though nothing wrote the attribute.
|
|
207
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
208
|
+
el.setAttribute('page', '1');
|
|
209
|
+
expect(el.page).toBe(1);
|
|
210
|
+
tabs(el)[0].click();
|
|
211
|
+
expect(el.page).toBe(0);
|
|
212
|
+
expect(el.getAttribute('page')).toBe('1');
|
|
213
|
+
host.remove();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
await it('switch-page is emitted BEFORE the switch, with the page switched TO', () => {
|
|
217
|
+
// `gtk_notebook_switch_page` emits and the class handler `real_switch_page`
|
|
218
|
+
// performs (gtknotebook.c:5518-5523), so a handler that vetoes by not drawing
|
|
219
|
+
// is the documented use — the page still reads the OLD one at that moment.
|
|
220
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
221
|
+
const seen: number[] = [];
|
|
222
|
+
el.addEventListener('switch-page', (e) => seen.push((e as CustomEvent).detail.page, el.page));
|
|
223
|
+
el.setCurrentPage(1);
|
|
224
|
+
expect(seen).toStrictEqual([1, 0]);
|
|
225
|
+
expect(el.page).toBe(1);
|
|
226
|
+
host.remove();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
await it('a handler that vetoes by not drawing leaves the page alone', async () => {
|
|
230
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
231
|
+
el.addEventListener('switch-page', (e) => e.preventDefault());
|
|
232
|
+
el.setCurrentPage(1);
|
|
233
|
+
expect(el.page).toBe(0);
|
|
234
|
+
host.remove();
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
await describe('<gtk-notebook> the page descriptor', async () => {
|
|
239
|
+
await it('carries the five scalar page properties as attributes', () => {
|
|
240
|
+
// A GtkNotebookPage is a GObject (gtknotebook.c:423), so its properties are the
|
|
241
|
+
// attributes on the child and `getPage()` hands back the descriptor.
|
|
242
|
+
const { el, host } = mount([{ label: 'One', menu: 'First', reorderable: true, detachable: true }]);
|
|
243
|
+
const info = el.getPage(el.children[1] as HTMLElement);
|
|
244
|
+
expect(info?.tabLabel).toBe('One');
|
|
245
|
+
expect(info?.menuLabel).toBe('First');
|
|
246
|
+
expect(info?.reorderable).toBe(true);
|
|
247
|
+
expect(info?.detachable).toBe(true);
|
|
248
|
+
host.remove();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
await it('tab-fill defaults TRUE and tab-expand FALSE', () => {
|
|
252
|
+
// `g_param_spec_boolean ("tab-expand", …, FALSE, …)` and `("tab-fill", …,
|
|
253
|
+
// TRUE, …)` (gtknotebook.c:667-681), and `page->fill = TRUE` in the page's
|
|
254
|
+
// `init` (gtknotebook.c:430).
|
|
255
|
+
const { el, host } = mount([
|
|
256
|
+
{ label: 'One' },
|
|
257
|
+
{ label: 'Two', fill: false },
|
|
258
|
+
{ label: 'Three', expand: true },
|
|
259
|
+
]);
|
|
260
|
+
expect(el.getPage(el.children[1] as HTMLElement)?.tabFill).toBe(true);
|
|
261
|
+
expect(el.getPage(el.children[2] as HTMLElement)?.tabFill).toBe(false);
|
|
262
|
+
expect(el.getPage(el.children[3] as HTMLElement)?.tabExpand).toBe(true);
|
|
263
|
+
expect(tabs(el).map((tab) => tab.classList.contains('fill'))).toStrictEqual([true, false, true]);
|
|
264
|
+
expect(tabs(el).map((tab) => tab.classList.contains('expand'))).toStrictEqual([false, false, true]);
|
|
265
|
+
host.remove();
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
await it('maps the child index to a page number, both ways', () => {
|
|
269
|
+
// `gtk_notebook_page_num` (gtknotebook.c:6006) and
|
|
270
|
+
// `gtk_notebook_get_nth_page` (gtknotebook.c:5956), the latter counting from
|
|
271
|
+
// the END for a negative index.
|
|
272
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }, { label: 'Three' }]);
|
|
273
|
+
const pages = Array.from(el.children).filter((child) => child !== el.querySelector('.adw-notebook-header'));
|
|
274
|
+
expect(el.pageNum(pages[2] as HTMLElement)).toBe(2);
|
|
275
|
+
expect(el.getNthPage(-1)).toBe(pages[2]);
|
|
276
|
+
expect(el.getNthPage(9)).toBeNull();
|
|
277
|
+
host.remove();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
await it('appends a page, which becomes the current one only if there was none', () => {
|
|
281
|
+
// `if (!gtk_notebook_has_current_page (notebook)) gtk_notebook_switch_page (…)`
|
|
282
|
+
// (gtknotebook.c:4131-4134).
|
|
283
|
+
const empty = mount([]);
|
|
284
|
+
const added = document.createElement('div');
|
|
285
|
+
added.setAttribute('tab-label', 'One');
|
|
286
|
+
empty.el.appendPage(added);
|
|
287
|
+
expect(empty.el.page).toBe(0);
|
|
288
|
+
empty.host.remove();
|
|
289
|
+
|
|
290
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
291
|
+
const second = document.createElement('div');
|
|
292
|
+
second.setAttribute('tab-label', 'Two');
|
|
293
|
+
el.appendPage(second);
|
|
294
|
+
expect(el.page).toBe(0);
|
|
295
|
+
expect(el.nPages).toBe(2);
|
|
296
|
+
host.remove();
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
await it('removing the current page hands over to the NEXT one, not the first', () => {
|
|
300
|
+
// C takes `search_page (…, STEP_NEXT)` and falls back to `STEP_PREV` at the end
|
|
301
|
+
// (gtknotebook.c:4281-4290) — so from the middle it is the page that follows.
|
|
302
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }, { label: 'Three' }]);
|
|
303
|
+
const pages = Array.from(el.children).filter((child) => child !== el.querySelector('.adw-notebook-header'));
|
|
304
|
+
el.setCurrentPage(1);
|
|
305
|
+
expect(el.removePage(pages[1] as HTMLElement)).toBe(true);
|
|
306
|
+
expect(el.page).toBe(1);
|
|
307
|
+
expect(el.getNthPage(1)?.getAttribute('tab-label')).toBe('Three');
|
|
308
|
+
host.remove();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
await it('removing the LAST current page falls back backwards', () => {
|
|
312
|
+
// The `STEP_PREV` half of gtknotebook.c:4280-4282.
|
|
313
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
314
|
+
const pages = Array.from(el.children).filter((child) => child !== el.querySelector('.adw-notebook-header'));
|
|
315
|
+
el.setCurrentPage(1);
|
|
316
|
+
el.removePage(pages[1] as HTMLElement);
|
|
317
|
+
expect(el.page).toBe(0);
|
|
318
|
+
expect(el.nPages).toBe(1);
|
|
319
|
+
host.remove();
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
await describe('<gtk-notebook> the tab strip', async () => {
|
|
324
|
+
await it("builds the strip as header > tabs > tab, libadwaita's own tree", () => {
|
|
325
|
+
// refs/libadwaita/src/stylesheet/widgets/_notebook.scss:4-10.
|
|
326
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
327
|
+
const header = el.querySelector('.adw-notebook-header') as HTMLElement;
|
|
328
|
+
const strip = el.querySelector('.adw-notebook-tabs') as HTMLElement;
|
|
329
|
+
expect(header.parentElement).toBe(el);
|
|
330
|
+
expect(strip.parentElement).toBe(header);
|
|
331
|
+
expect(tabs(el)[0].parentElement).toBe(strip);
|
|
332
|
+
expect(strip.getAttribute('role')).toBe('tablist');
|
|
333
|
+
expect(tabs(el)[0].getAttribute('role')).toBe('tab');
|
|
334
|
+
host.remove();
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
await it('takes its tabs away with show-tabs, and puts them back', () => {
|
|
338
|
+
// `gtk_widget_set_visible (header_widget, show_tabs)` (gtknotebook.c:5467).
|
|
339
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
340
|
+
const header = el.querySelector('.adw-notebook-header') as HTMLElement;
|
|
341
|
+
expect(header.hidden).toBe(false);
|
|
342
|
+
el.showTabs = false;
|
|
343
|
+
expect(header.hidden).toBe(true);
|
|
344
|
+
expect(el.nPages).toBe(1);
|
|
345
|
+
el.showTabs = true;
|
|
346
|
+
expect(header.hidden).toBe(false);
|
|
347
|
+
host.remove();
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
await it('show-border is the .frame class, because in C it is a CSS class', () => {
|
|
351
|
+
// `gtk_notebook_set_show_border` adds `.frame` and clearing the property removes
|
|
352
|
+
// it (gtknotebook.c:6134-6146); it defaults TRUE (gtknotebook.c:1505). The
|
|
353
|
+
// property is still an attribute — the CLASS is what the border hangs off, which
|
|
354
|
+
// is the distinction a boolean attribute would have lost.
|
|
355
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
356
|
+
expect(el.showBorder).toBe(true);
|
|
357
|
+
expect(el.classList.contains('frame')).toBe(true);
|
|
358
|
+
el.showBorder = false;
|
|
359
|
+
expect(el.classList.contains('frame')).toBe(false);
|
|
360
|
+
expect(el.showBorder).toBe(false);
|
|
361
|
+
expect(el.getAttribute('show-border')).toBe('false');
|
|
362
|
+
host.remove();
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
await it('marks the page area, which is a GtkStack inside the C', () => {
|
|
366
|
+
// `gtk_stack_set_visible_child (…, cur_page->child)` (gtknotebook.c:5476) — one
|
|
367
|
+
// visible child, and libadwaita's `> stack:not(:only-child)` page background
|
|
368
|
+
// (_notebook.scss:213-215) is what `.adw-notebook-page` is styled as.
|
|
369
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
370
|
+
const area = Array.from(el.children).filter((child) => child !== el.querySelector('.adw-notebook-header'));
|
|
371
|
+
expect(area.every((child) => child.classList.contains('adw-notebook-page'))).toBe(true);
|
|
372
|
+
expect(area.map((child) => child.classList.contains('visible-page'))).toStrictEqual([true, false]);
|
|
373
|
+
host.remove();
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
await describe('<gtk-notebook> the popup menu', async () => {
|
|
378
|
+
await it('opens a listbox of the pages on contextmenu, when enable-popup is set', async () => {
|
|
379
|
+
// `gtk_notebook_popup_enable` builds a GtkPopoverMenu of the pages
|
|
380
|
+
// (gtknotebook.c:6420-6462) and a right-click pops it up (gtknotebook.c:2684).
|
|
381
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two', menu: 'The second' }]);
|
|
382
|
+
el.enablePopup = true;
|
|
383
|
+
el.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, cancelable: true }));
|
|
384
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
385
|
+
const menu = el.querySelector('.adw-notebook-menu') as HTMLElement;
|
|
386
|
+
const items = Array.from(menu.querySelectorAll('.adw-notebook-menu-item')) as HTMLElement[];
|
|
387
|
+
expect(menu.getAttribute('role')).toBe('listbox');
|
|
388
|
+
expect(items.map((item) => item.textContent)).toStrictEqual(['One', 'The second']);
|
|
389
|
+
expect(items[0].getAttribute('aria-selected')).toBe('true');
|
|
390
|
+
host.remove();
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
await it("falls back to the tab label, and hides a hidden page's item", async () => {
|
|
394
|
+
// `gtk_notebook_menu_item_create` builds the label from `menu_label`, falls
|
|
395
|
+
// back to the tab label when it is a GtkLabel, and hides the item for a page
|
|
396
|
+
// whose child is hidden (gtknotebook.c:5624-5649).
|
|
397
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two', hidden: true }, {}]);
|
|
398
|
+
el.enablePopup = true;
|
|
399
|
+
el.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, cancelable: true }));
|
|
400
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
401
|
+
const items = Array.from(el.querySelectorAll('.adw-notebook-menu-item')) as HTMLElement[];
|
|
402
|
+
expect(items.map((item) => item.textContent)).toStrictEqual(['One', 'Two', 'Page 2']);
|
|
403
|
+
expect(items[1].hidden).toBe(true);
|
|
404
|
+
host.remove();
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
await it('does nothing at all while enable-popup is off', () => {
|
|
408
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
409
|
+
expect(el.enablePopup).toBe(false);
|
|
410
|
+
const event = new MouseEvent('contextmenu', { bubbles: true, cancelable: true });
|
|
411
|
+
el.dispatchEvent(event);
|
|
412
|
+
expect(el.querySelector('.adw-notebook-menu')).toBeNull();
|
|
413
|
+
expect(event.defaultPrevented).toBe(false);
|
|
414
|
+
host.remove();
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
await it('closes on disconnect, which is where the menu goes', () => {
|
|
418
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
419
|
+
el.enablePopup = true;
|
|
420
|
+
el.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, cancelable: true }));
|
|
421
|
+
expect(el.querySelector('.adw-notebook-menu')).not.toBeNull();
|
|
422
|
+
host.remove();
|
|
423
|
+
expect(el.querySelector('.adw-notebook-menu')).toBeNull();
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
await describe('<gtk-notebook> re-parent', async () => {
|
|
428
|
+
await it('keeps ONE header across a move, and never grows a second one', async () => {
|
|
429
|
+
// The header is built once and stays a child of the notebook even while the
|
|
430
|
+
// notebook itself is detached, because a GTK widget keeps its children across
|
|
431
|
+
// a re-parent. Rebuilding it on the way back in would leave the old one behind,
|
|
432
|
+
// and `_pages()` — which filters the header out BY IDENTITY — would read that
|
|
433
|
+
// leftover as a page.
|
|
434
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
435
|
+
const elsewhere = document.createElement('div');
|
|
436
|
+
document.body.appendChild(elsewhere);
|
|
437
|
+
elsewhere.appendChild(el);
|
|
438
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
439
|
+
expect(el.querySelectorAll('.adw-notebook-header')).toHaveLength(1);
|
|
440
|
+
expect(el.nPages).toBe(2);
|
|
441
|
+
expect(marks(el)).toStrictEqual(['One:visible', 'Two']);
|
|
442
|
+
host.remove();
|
|
443
|
+
elsewhere.remove();
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
await it('keeps the current page across a move', async () => {
|
|
447
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
448
|
+
tabs(el)[1].click();
|
|
449
|
+
const elsewhere = document.createElement('div');
|
|
450
|
+
document.body.appendChild(elsewhere);
|
|
451
|
+
elsewhere.appendChild(el);
|
|
452
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
453
|
+
expect(el.page).toBe(1);
|
|
454
|
+
host.remove();
|
|
455
|
+
elsewhere.remove();
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
await describe('<gtk-notebook> notification', async () => {
|
|
460
|
+
await it('notifies page once per real switch', () => {
|
|
461
|
+
// `g_object_notify_by_pspec (G_OBJECT (notebook), properties[PROP_PAGE])`
|
|
462
|
+
// (gtknotebook.c:5497) is at the END of `real_switch_page`, so it fires once and
|
|
463
|
+
// only after the switch took.
|
|
464
|
+
const { el, host } = mount([{ label: 'One' }, { label: 'Two' }]);
|
|
465
|
+
let notifies = 0;
|
|
466
|
+
el.addEventListener('notify::page', () => (notifies += 1));
|
|
467
|
+
el.setCurrentPage(1);
|
|
468
|
+
expect(notifies).toBe(1);
|
|
469
|
+
el.setCurrentPage(0);
|
|
470
|
+
expect(notifies).toBe(2);
|
|
471
|
+
host.remove();
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
await it('reports the parsed property, not the raw attribute', () => {
|
|
475
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
476
|
+
const details: unknown[] = [];
|
|
477
|
+
el.addEventListener('notify::tab-pos', (e) => details.push((e as CustomEvent).detail));
|
|
478
|
+
el.tabPos = 'bottom';
|
|
479
|
+
expect(details).toStrictEqual([{ 'tab-pos': 'bottom' }]);
|
|
480
|
+
host.remove();
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
await it('reports an inserted page as page-added and a removed one as page-removed', () => {
|
|
484
|
+
// The two page-list signals the C raises around an insert and a remove
|
|
485
|
+
// (gtknotebook.c:1380-1391 emitted at :4129, :1358-1369 emitted at :3551).
|
|
486
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
487
|
+
const events: string[] = [];
|
|
488
|
+
el.addEventListener('page-added', () => events.push('added'));
|
|
489
|
+
el.addEventListener('page-removed', () => events.push('removed'));
|
|
490
|
+
const second = document.createElement('div');
|
|
491
|
+
second.setAttribute('tab-label', 'Two');
|
|
492
|
+
el.appendPage(second);
|
|
493
|
+
el.removePage(second);
|
|
494
|
+
expect(events).toStrictEqual(['added', 'removed']);
|
|
495
|
+
host.remove();
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
await it('carries the position and the new page count with each of them', () => {
|
|
499
|
+
const { el, host } = mount([{ label: 'One' }]);
|
|
500
|
+
const details: unknown[] = [];
|
|
501
|
+
el.addEventListener('page-added', (e) => details.push((e as CustomEvent).detail));
|
|
502
|
+
const second = document.createElement('div');
|
|
503
|
+
el.appendPage(second, 'Two');
|
|
504
|
+
expect(details).toStrictEqual([{ position: 1, nPages: 2 }]);
|
|
505
|
+
host.remove();
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
await describe('geometry measured on a native Gtk.Notebook', async () => {
|
|
510
|
+
await it('has 37 px tabs under a 37 px header, 8 px in, and does not stretch them', () => {
|
|
511
|
+
const { el, host } = mount([{ label: 'A' }, { label: 'Longer label' }]);
|
|
512
|
+
const header = el.querySelector('.adw-notebook-header') as HTMLElement;
|
|
513
|
+
const tabs = [...el.querySelectorAll('.adw-notebook-tab')] as HTMLElement[];
|
|
514
|
+
const box = el.getBoundingClientRect();
|
|
515
|
+
expect(header.getBoundingClientRect().height).toBe(37);
|
|
516
|
+
expect(tabs.map((tab) => tab.getBoundingClientRect().height)).toStrictEqual([37, 37]);
|
|
517
|
+
// The 1 px frame, then the 8 px of header padding, strip margin, strip padding and tab margin.
|
|
518
|
+
expect(tabs[0].getBoundingClientRect().left - box.left).toBe(9);
|
|
519
|
+
expect(tabs[0].getBoundingClientRect().width).toBeLessThan(tabs[1].getBoundingClientRect().width);
|
|
520
|
+
expect(tabs[1].getBoundingClientRect().right).toBeLessThan(box.right - 100);
|
|
521
|
+
host.remove();
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
await describe('a shared-tree page', async () => {
|
|
526
|
+
await it('is written as the tab-label the notebook reads, and a stack reads name and title', () => {
|
|
527
|
+
const notebook = buildSharedTree({
|
|
528
|
+
tag: 'GtkNotebook',
|
|
529
|
+
children: [{ tag: 'GtkLabel', page: { label: 'One' }, props: { label: 'first' } }],
|
|
530
|
+
});
|
|
531
|
+
expect(notebook.children[0].getAttribute('tab-label')).toBe('One');
|
|
532
|
+
const stack = buildSharedTree({
|
|
533
|
+
tag: 'GtkStack',
|
|
534
|
+
children: [{ tag: 'GtkLabel', page: { name: 'a', label: 'A' } }],
|
|
535
|
+
});
|
|
536
|
+
expect(stack.children[0].getAttribute('name')).toBe('a');
|
|
537
|
+
expect(stack.children[0].getAttribute('title')).toBe('A');
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
await it('is refused BY NAME on a parent with no pages', () => {
|
|
541
|
+
expect(() =>
|
|
542
|
+
buildSharedTree({ tag: 'GtkBox', children: [{ tag: 'GtkLabel', page: { label: 'X' } }] }),
|
|
543
|
+
).toThrow('has no pages');
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
};
|