@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,163 @@
|
|
|
1
|
+
// DOM-level tests for `<gtk-text>`: the four properties that reach a real mechanism
|
|
2
|
+
// (`max-length` in code points, `placeholder-text`, `visibility` as the mask switch,
|
|
3
|
+
// `propagate-text-width` as the input's own `size`) and the `.read-only` node class the C
|
|
4
|
+
// toggles with `editable`.
|
|
5
|
+
//
|
|
6
|
+
// `Gtk.Text` has two BOOLEAN pspecs that default TRUE (`editable`, `visibility`), which is
|
|
7
|
+
// why they are read from a value and not from presence: a bare `visibility` attribute would
|
|
8
|
+
// say the same as leaving it off. Those are the rows below that would fail for an element
|
|
9
|
+
// that used `hasAttribute`.
|
|
10
|
+
|
|
11
|
+
import { describe, expect, it } from '@gjsify/unit';
|
|
12
|
+
|
|
13
|
+
import type { GtkText } from './elements/gtk-text.js';
|
|
14
|
+
|
|
15
|
+
function mount(attrs: Record<string, string> = {}): GtkText {
|
|
16
|
+
const el = document.createElement('gtk-text') as GtkText;
|
|
17
|
+
for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
|
|
18
|
+
document.body.appendChild(el);
|
|
19
|
+
return el;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function unmountAll(): void {
|
|
23
|
+
for (const el of Array.from(document.querySelectorAll('gtk-text'))) el.remove();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** What a keydown reaches the inner input with — the browser does not dispatch one for a test. */
|
|
27
|
+
function pressEnter(input: HTMLInputElement): void {
|
|
28
|
+
input.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true }));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const GtkTextTest = async () => {
|
|
32
|
+
await describe('<gtk-text> text', async () => {
|
|
33
|
+
await it('seeds the field from `text` and reports the live value back', () => {
|
|
34
|
+
const el = mount({ text: 'Ada Lovelace' });
|
|
35
|
+
expect(el.text).toBe('Ada Lovelace');
|
|
36
|
+
expect(el.input.value).toBe('Ada Lovelace');
|
|
37
|
+
unmountAll();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
await it('counts its length in CODE POINTS, as the buffer does', () => {
|
|
41
|
+
const el = mount({ text: '🔒é' });
|
|
42
|
+
expect(el.textLength).toBe(2);
|
|
43
|
+
unmountAll();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
await it('fires `activate` on Enter, the signal GTK binds Return to', () => {
|
|
47
|
+
const el = mount({ text: 'notes' });
|
|
48
|
+
const seen: unknown[] = [];
|
|
49
|
+
el.addEventListener('activate', (event) => seen.push((event as CustomEvent).detail));
|
|
50
|
+
pressEnter(el.input);
|
|
51
|
+
expect(seen).toStrictEqual([{ text: 'notes' }]);
|
|
52
|
+
unmountAll();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await describe('<gtk-text> max length', async () => {
|
|
57
|
+
await it('clamps the seeded text on code points, where `maxlength` would not', () => {
|
|
58
|
+
const el = mount({ text: '🔒éééé', 'max-length': '3' });
|
|
59
|
+
expect(el.text).toBe('🔒éé');
|
|
60
|
+
expect(el.textLength).toBe(3);
|
|
61
|
+
unmountAll();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
await it('clamps what is typed, not only what is assigned', () => {
|
|
65
|
+
const el = mount({ 'max-length': '4' });
|
|
66
|
+
el.input.value = 'abcdefgh';
|
|
67
|
+
el.input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
68
|
+
expect(el.input.value).toBe('abcd');
|
|
69
|
+
unmountAll();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
await it('0 means unlimited', () => {
|
|
73
|
+
const el = mount({ text: 'a long value' });
|
|
74
|
+
el.maxLength = 0;
|
|
75
|
+
expect(el.maxLength).toBe(0);
|
|
76
|
+
el.text = 'another long value';
|
|
77
|
+
expect(el.text).toBe('another long value');
|
|
78
|
+
unmountAll();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await describe('<gtk-text> visibility', async () => {
|
|
83
|
+
await it('defaults TRUE, and the pspec default is what an absent attribute means', () => {
|
|
84
|
+
const el = mount();
|
|
85
|
+
expect(el.visibility).toBe(true);
|
|
86
|
+
expect(el.input.type).toBe('text');
|
|
87
|
+
unmountAll();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
await it('`visibility="false"` masks the field; a bare attribute does not', () => {
|
|
91
|
+
const masked = mount({ visibility: 'false' });
|
|
92
|
+
expect(masked.visibility).toBe(false);
|
|
93
|
+
expect(masked.input.type).toBe('password');
|
|
94
|
+
const bare = mount({ visibility: '' });
|
|
95
|
+
expect(bare.visibility).toBe(true);
|
|
96
|
+
expect(bare.input.type).toBe('text');
|
|
97
|
+
unmountAll();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
await it('follows the property and leaves the default unwritten', () => {
|
|
101
|
+
const el = mount();
|
|
102
|
+
el.visibility = false;
|
|
103
|
+
expect(el.getAttribute('visibility')).toBe('false');
|
|
104
|
+
expect(el.input.type).toBe('password');
|
|
105
|
+
el.visibility = true;
|
|
106
|
+
expect(el.hasAttribute('visibility')).toBe(false);
|
|
107
|
+
expect(el.input.type).toBe('text');
|
|
108
|
+
unmountAll();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
await describe('<gtk-text> editable', async () => {
|
|
113
|
+
await it("wears libadwaita's `.read-only` node class when it cannot be changed", () => {
|
|
114
|
+
const el = mount();
|
|
115
|
+
expect(el.editable).toBe(true);
|
|
116
|
+
expect(el.classList.contains('read-only')).toBe(false);
|
|
117
|
+
el.editable = false;
|
|
118
|
+
expect(el.classList.contains('read-only')).toBe(true);
|
|
119
|
+
expect(el.input.readOnly).toBe(true);
|
|
120
|
+
unmountAll();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
await it('takes `editable="false"` as the value the default-TRUE pspec needs', () => {
|
|
124
|
+
const el = mount({ editable: 'false' });
|
|
125
|
+
expect(el.editable).toBe(false);
|
|
126
|
+
expect(el.input.readOnly).toBe(true);
|
|
127
|
+
unmountAll();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
await describe('<gtk-text> propagate text width', async () => {
|
|
132
|
+
await it('sizes the field to its text while set, and stops on request', () => {
|
|
133
|
+
const el = mount({ text: 'abc' });
|
|
134
|
+
el.propagateTextWidth = true;
|
|
135
|
+
expect(el.classList.contains('propagate-text-width')).toBe(true);
|
|
136
|
+
expect(el.input.size).toBe(3);
|
|
137
|
+
el.text = 'abcdefgh';
|
|
138
|
+
expect(el.input.size).toBe(8);
|
|
139
|
+
el.propagateTextWidth = false;
|
|
140
|
+
expect(el.classList.contains('propagate-text-width')).toBe(false);
|
|
141
|
+
unmountAll();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
await it('stays inside its container', () => {
|
|
145
|
+
const el = mount({ text: 'abc', 'propagate-text-width': '' });
|
|
146
|
+
expect(el.getBoundingClientRect().width).toBeLessThanOrEqual(document.body.clientWidth);
|
|
147
|
+
unmountAll();
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
await describe('<gtk-text> look', async () => {
|
|
152
|
+
await it('paints the view colours libadwaita gives a `text` node', () => {
|
|
153
|
+
const el = mount();
|
|
154
|
+
const style = getComputedStyle(el.input);
|
|
155
|
+
// `caret-color: currentColor` (_entries.scss:11) resolves against the element's
|
|
156
|
+
// own colour, and the tokens move with the OS theme — so the row compares two
|
|
157
|
+
// computed values instead of naming either of them.
|
|
158
|
+
expect(style.caretColor).toBe(getComputedStyle(el).color);
|
|
159
|
+
expect(style.backgroundColor).not.toBe('rgba(0, 0, 0, 0)');
|
|
160
|
+
unmountAll();
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// DOM-level tests for <gtk-toggle-button>. It IS a <gtk-button>, so what matters here is
|
|
2
|
+
// the one thing it adds: `active`. The state is the attribute; the inner button wears
|
|
3
|
+
// libadwaita's `:checked` as `.checked` and `aria-pressed`; `toggled` and `notify::active`
|
|
4
|
+
// fire on every real change and on none that did not happen.
|
|
5
|
+
import { describe, expect, it } from '@gjsify/unit';
|
|
6
|
+
|
|
7
|
+
import type { GtkToggleButton } from './elements/gtk-toggle-button.js';
|
|
8
|
+
|
|
9
|
+
function mount(attrs: Record<string, string> = {}): { el: GtkToggleButton; host: HTMLElement } {
|
|
10
|
+
const host = document.createElement('div');
|
|
11
|
+
document.body.appendChild(host);
|
|
12
|
+
const el = document.createElement('gtk-toggle-button') as GtkToggleButton;
|
|
13
|
+
for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
|
|
14
|
+
host.appendChild(el);
|
|
15
|
+
return { el, host };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Collect the `detail` of every `event` dispatched on (or bubbling to) `el`. */
|
|
19
|
+
function record(el: HTMLElement, event: string): unknown[] {
|
|
20
|
+
const details: unknown[] = [];
|
|
21
|
+
el.addEventListener(event, (e) => details.push((e as CustomEvent).detail));
|
|
22
|
+
return details;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const GtkToggleButtonTest = async () => {
|
|
26
|
+
await describe('<gtk-toggle-button> state', async () => {
|
|
27
|
+
await it('starts released, and renders as a gtk-button would', () => {
|
|
28
|
+
const { el, host } = mount({ label: 'Mute' });
|
|
29
|
+
expect(el.active).toBe(false);
|
|
30
|
+
expect(el.button.classList.contains('adw-button')).toBe(true);
|
|
31
|
+
expect(el.button.classList.contains('checked')).toBe(false);
|
|
32
|
+
expect(el.button.getAttribute('aria-pressed')).toBe('false');
|
|
33
|
+
expect(el.button.textContent).toBe('Mute');
|
|
34
|
+
host.remove();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await it('adopts a declarative active attribute without emitting', () => {
|
|
38
|
+
const host = document.createElement('div');
|
|
39
|
+
document.body.appendChild(host);
|
|
40
|
+
const el = document.createElement('gtk-toggle-button') as GtkToggleButton;
|
|
41
|
+
el.setAttribute('active', '');
|
|
42
|
+
const events = record(el, 'toggled');
|
|
43
|
+
host.appendChild(el);
|
|
44
|
+
expect(el.active).toBe(true);
|
|
45
|
+
expect(el.button.classList.contains('checked')).toBe(true);
|
|
46
|
+
expect(el.button.getAttribute('aria-pressed')).toBe('true');
|
|
47
|
+
expect(events.length).toBe(0);
|
|
48
|
+
host.remove();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
await it('a click flips it, and notifies once per change', () => {
|
|
52
|
+
const { el, host } = mount({ label: 'Mute' });
|
|
53
|
+
const toggled = record(el, 'toggled');
|
|
54
|
+
const notified = record(el, 'notify::active');
|
|
55
|
+
el.button.click();
|
|
56
|
+
expect(el.active).toBe(true);
|
|
57
|
+
expect(el.button.classList.contains('checked')).toBe(true);
|
|
58
|
+
el.button.click();
|
|
59
|
+
expect(el.active).toBe(false);
|
|
60
|
+
expect(toggled.length).toBe(2);
|
|
61
|
+
expect(notified).toStrictEqual([{ active: true }, { active: false }]);
|
|
62
|
+
host.remove();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
await it('a programmatic set notifies, and re-setting the same value does not', () => {
|
|
66
|
+
const { el, host } = mount();
|
|
67
|
+
const notified = record(el, 'notify::active');
|
|
68
|
+
el.active = true;
|
|
69
|
+
el.active = true;
|
|
70
|
+
expect(notified).toStrictEqual([{ active: true }]);
|
|
71
|
+
host.remove();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await it('a disabled button does not toggle on a click, but the property still applies', () => {
|
|
75
|
+
const { el, host } = mount({ disabled: '' });
|
|
76
|
+
el.button.click();
|
|
77
|
+
expect(el.active).toBe(false);
|
|
78
|
+
el.active = true;
|
|
79
|
+
expect(el.button.classList.contains('checked')).toBe(true);
|
|
80
|
+
host.remove();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
await it('keeps the checked class through a re-render of the label and the styles', () => {
|
|
84
|
+
const { el, host } = mount({ label: 'Mute', active: '' });
|
|
85
|
+
el.setAttribute('label', 'Unmute');
|
|
86
|
+
el.setAttribute('flat', '');
|
|
87
|
+
expect(el.button.textContent).toBe('Unmute');
|
|
88
|
+
expect(el.button.classList.contains('flat')).toBe(true);
|
|
89
|
+
expect(el.button.classList.contains('checked')).toBe(true);
|
|
90
|
+
host.remove();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
await it('an ungrouped button still toggles off when clicked', () => {
|
|
94
|
+
const { el, host } = mount({ label: 'Mute' });
|
|
95
|
+
el.button.click();
|
|
96
|
+
expect(el.active).toBe(true);
|
|
97
|
+
el.button.click();
|
|
98
|
+
expect(el.active).toBe(false);
|
|
99
|
+
host.remove();
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
await describe('<gtk-toggle-button> look', async () => {
|
|
104
|
+
await it('a checked button paints darker than a released one', () => {
|
|
105
|
+
const { el, host } = mount({ label: 'Mute' });
|
|
106
|
+
const released = getComputedStyle(el.button).backgroundColor;
|
|
107
|
+
el.active = true;
|
|
108
|
+
const checked = getComputedStyle(el.button).backgroundColor;
|
|
109
|
+
expect(checked === released).toBe(false);
|
|
110
|
+
host.remove();
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
await describe('<gtk-toggle-button> group', async () => {
|
|
115
|
+
await it('joining a group links the two ways, and leaves the attribute naming it', () => {
|
|
116
|
+
const a = mount({ id: 'group-a', label: 'A' });
|
|
117
|
+
const b = mount({ id: 'group-b', label: 'B' });
|
|
118
|
+
b.el.group = a.el;
|
|
119
|
+
expect(b.el.getAttribute('group')).toBe('group-a');
|
|
120
|
+
// `gtk_toggle_button_set_group` inserts SELF before the target, so B is the one
|
|
121
|
+
// that gains `group_next` — which is also the one a click can no longer release.
|
|
122
|
+
b.el.button.click();
|
|
123
|
+
expect(b.el.active).toBe(true);
|
|
124
|
+
b.el.button.click();
|
|
125
|
+
expect(b.el.active).toBe(true);
|
|
126
|
+
a.host.remove();
|
|
127
|
+
b.host.remove();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
await it('activating a member releases the others, whichever order they were linked in', () => {
|
|
131
|
+
const a = mount({ id: 'chain-a', label: 'A' });
|
|
132
|
+
const b = mount({ id: 'chain-b', label: 'B' });
|
|
133
|
+
const c = mount({ id: 'chain-c', label: 'C' });
|
|
134
|
+
b.el.group = a.el;
|
|
135
|
+
c.el.group = a.el;
|
|
136
|
+
const toggled = record(c.el, 'toggled');
|
|
137
|
+
c.el.active = true;
|
|
138
|
+
expect(a.el.active).toBe(false);
|
|
139
|
+
expect(b.el.active).toBe(false);
|
|
140
|
+
expect(c.el.active).toBe(true);
|
|
141
|
+
a.el.active = true;
|
|
142
|
+
expect(c.el.active).toBe(false);
|
|
143
|
+
expect(b.el.active).toBe(false);
|
|
144
|
+
expect(a.el.active).toBe(true);
|
|
145
|
+
expect(toggled.length).toBe(2);
|
|
146
|
+
a.host.remove();
|
|
147
|
+
b.host.remove();
|
|
148
|
+
c.host.remove();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
await it('the attribute door names the partner by id, and an unknown name changes nothing', () => {
|
|
152
|
+
const a = mount({ id: 'attr-a', label: 'A' });
|
|
153
|
+
const b = mount({ id: 'attr-b', label: 'B' });
|
|
154
|
+
b.el.setAttribute('group', 'attr-a');
|
|
155
|
+
a.el.active = true;
|
|
156
|
+
b.el.active = true;
|
|
157
|
+
expect(a.el.active).toBe(false);
|
|
158
|
+
expect(b.el.active).toBe(true);
|
|
159
|
+
b.el.setAttribute('group', 'nowhere');
|
|
160
|
+
expect(b.el.getAttribute('group')).toBe('nowhere');
|
|
161
|
+
a.el.active = true;
|
|
162
|
+
expect(b.el.active).toBe(true);
|
|
163
|
+
a.host.remove();
|
|
164
|
+
b.host.remove();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
await it('leaving the group releases the links, and the same group twice notifies once', () => {
|
|
168
|
+
const a = mount({ id: 'once-a', label: 'A' });
|
|
169
|
+
const b = mount({ id: 'once-b', label: 'B' });
|
|
170
|
+
const notified = record(b.el, 'notify::group');
|
|
171
|
+
b.el.group = a.el;
|
|
172
|
+
b.el.group = a.el;
|
|
173
|
+
expect(notified.length).toBe(1);
|
|
174
|
+
b.el.group = null;
|
|
175
|
+
expect(notified.length).toBe(2);
|
|
176
|
+
expect(b.el.hasAttribute('group')).toBe(false);
|
|
177
|
+
// Unlinked, B is clickable off again — the guard is the link, not the element.
|
|
178
|
+
b.el.button.click();
|
|
179
|
+
expect(b.el.active).toBe(true);
|
|
180
|
+
b.el.button.click();
|
|
181
|
+
expect(b.el.active).toBe(false);
|
|
182
|
+
a.host.remove();
|
|
183
|
+
b.host.remove();
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// DOM-level tests for <gtk-tree-expander>: the nodes it puts in front of its child, the
|
|
2
|
+
// arrow that toggles, the shortcuts, and the ARIA a tree row owes a screen reader. The
|
|
3
|
+
// arithmetic itself is `tree-expander.spec.ts` in @gjsify/adwaita-core; what is asserted
|
|
4
|
+
// here is that the element draws what the arithmetic says.
|
|
5
|
+
import { describe, expect, it } from '@gjsify/unit';
|
|
6
|
+
|
|
7
|
+
import { TREE_EXPANDER_LAYOUT_VECTORS, TREE_EXPANDER_SHORTCUT_VECTORS } from '@gjsify/adwaita-core/conformance';
|
|
8
|
+
|
|
9
|
+
import type { GtkTreeExpander } from './elements/gtk-tree-expander.js';
|
|
10
|
+
|
|
11
|
+
function mount(attrs: Record<string, string> = {}): { el: GtkTreeExpander; host: HTMLElement } {
|
|
12
|
+
const host = document.createElement('div');
|
|
13
|
+
document.body.appendChild(host);
|
|
14
|
+
const el = document.createElement('gtk-tree-expander') as GtkTreeExpander;
|
|
15
|
+
for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
|
|
16
|
+
const child = document.createElement('gtk-label');
|
|
17
|
+
child.setAttribute('label', 'Row');
|
|
18
|
+
el.appendChild(child);
|
|
19
|
+
host.appendChild(el);
|
|
20
|
+
return { el, host };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const indents = (el: GtkTreeExpander): number => el.querySelectorAll('.adw-tree-expander-indent').length;
|
|
24
|
+
const icon = (el: GtkTreeExpander): HTMLElement | null => el.querySelector('.adw-tree-expander-icon');
|
|
25
|
+
|
|
26
|
+
export const GtkTreeExpanderTest = async () => {
|
|
27
|
+
await describe('<gtk-tree-expander> drives the layout vectors as real nodes', async () => {
|
|
28
|
+
// The ONE row with no counterpart here is `row: null`: upstream an expander exists
|
|
29
|
+
// before a `Gtk.TreeListRow` is assigned to it, and on this port the row IS the
|
|
30
|
+
// three attributes, so an expander with none of them is a root leaf rather than a
|
|
31
|
+
// rowless widget. The element header records the same divergence.
|
|
32
|
+
for (const vector of TREE_EXPANDER_LAYOUT_VECTORS.filter((candidate) => candidate.row !== null)) {
|
|
33
|
+
await it(vector.rule, () => {
|
|
34
|
+
const row = vector.row!;
|
|
35
|
+
const attrs: Record<string, string> = { depth: String(row.depth) };
|
|
36
|
+
if (row.expandable) attrs.expandable = '';
|
|
37
|
+
if (row.expanded) attrs.expanded = '';
|
|
38
|
+
if (vector.options.hideExpander === true) attrs['hide-expander'] = '';
|
|
39
|
+
if (vector.options.indentForDepth === false) attrs['indent-for-depth'] = 'false';
|
|
40
|
+
if (vector.options.indentForIcon === false) attrs['indent-for-icon'] = 'false';
|
|
41
|
+
const { el, host } = mount(attrs);
|
|
42
|
+
|
|
43
|
+
expect(indents(el)).toBe(vector.indents);
|
|
44
|
+
expect(
|
|
45
|
+
icon(el) === null ? 'none' : el.getAttribute('aria-expanded') === 'true' ? 'expanded' : 'collapsed',
|
|
46
|
+
).toBe(vector.expander);
|
|
47
|
+
expect(el.getAttribute('aria-level')).toBe(String(vector.level));
|
|
48
|
+
host.remove();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await describe('<gtk-tree-expander> drives the shortcut vectors as real key presses', async () => {
|
|
54
|
+
for (const vector of TREE_EXPANDER_SHORTCUT_VECTORS) {
|
|
55
|
+
await it(vector.rule, () => {
|
|
56
|
+
// Every row is driven from BOTH starting states, so "the key did nothing"
|
|
57
|
+
// and "the key asked for the state it was already in" cannot be confused.
|
|
58
|
+
for (const before of [false, true]) {
|
|
59
|
+
const attrs: Record<string, string> = { expandable: '' };
|
|
60
|
+
if (before) attrs.expanded = '';
|
|
61
|
+
// The locale half of the arrow rule is the COMPUTED direction, which
|
|
62
|
+
// is what the element reads and what `dir` is the markup for.
|
|
63
|
+
if (vector.state.rtl === true) attrs.dir = 'rtl';
|
|
64
|
+
const { el, host } = mount(attrs);
|
|
65
|
+
el.dispatchEvent(
|
|
66
|
+
new KeyboardEvent('keydown', {
|
|
67
|
+
key: vector.key,
|
|
68
|
+
ctrlKey: vector.state.ctrlKey === true,
|
|
69
|
+
shiftKey: vector.state.shiftKey === true,
|
|
70
|
+
bubbles: true,
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
73
|
+
const expected =
|
|
74
|
+
vector.action === 'expand'
|
|
75
|
+
? true
|
|
76
|
+
: vector.action === 'collapse'
|
|
77
|
+
? false
|
|
78
|
+
: vector.action === 'toggle'
|
|
79
|
+
? !before
|
|
80
|
+
: before;
|
|
81
|
+
expect(el.expanded).toBe(expected);
|
|
82
|
+
host.remove();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
await describe('<gtk-tree-expander> nodes', async () => {
|
|
89
|
+
await it('draws one indent per level and an arrow for an expandable row', () => {
|
|
90
|
+
const { el, host } = mount({ depth: '2', expandable: '' });
|
|
91
|
+
expect(indents(el)).toBe(2);
|
|
92
|
+
expect(icon(el)).not.toBe(null);
|
|
93
|
+
expect(el.getAttribute('aria-expanded')).toBe('false');
|
|
94
|
+
expect(el.getAttribute('aria-level')).toBe('3');
|
|
95
|
+
host.remove();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
await it('gives a LEAF one more indent instead of the arrow', () => {
|
|
99
|
+
const { el, host } = mount({ depth: '1' });
|
|
100
|
+
expect(indents(el)).toBe(2);
|
|
101
|
+
expect(icon(el)).toBe(null);
|
|
102
|
+
expect(el.hasAttribute('aria-expanded')).toBe(false);
|
|
103
|
+
host.remove();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
await it('keeps the ornaments IN FRONT of the child, as insert_before does', () => {
|
|
107
|
+
const { el, host } = mount({ depth: '1', expandable: '' });
|
|
108
|
+
const names = [...el.children].map((child) => child.tagName.toLowerCase());
|
|
109
|
+
expect(names).toStrictEqual(['span', 'gtk-image', 'gtk-label']);
|
|
110
|
+
host.remove();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
await it('hides the expander on request and indents like a leaf instead', () => {
|
|
114
|
+
const { el, host } = mount({ depth: '1', expandable: '', 'hide-expander': '' });
|
|
115
|
+
expect(icon(el)).toBe(null);
|
|
116
|
+
expect(indents(el)).toBe(2);
|
|
117
|
+
host.remove();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
await it('stops indenting with indent-for-depth="false" but keeps the arrow', () => {
|
|
121
|
+
const { el, host } = mount({ depth: '3', expandable: '', 'indent-for-depth': 'false' });
|
|
122
|
+
expect(indents(el)).toBe(0);
|
|
123
|
+
expect(icon(el)).not.toBe(null);
|
|
124
|
+
host.remove();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await it('rebuilds when the row changes under it', () => {
|
|
128
|
+
const { el, host } = mount({ depth: '0', expandable: '' });
|
|
129
|
+
expect(indents(el)).toBe(0);
|
|
130
|
+
el.depth = 2;
|
|
131
|
+
expect(indents(el)).toBe(2);
|
|
132
|
+
el.expandable = false;
|
|
133
|
+
expect(icon(el)).toBe(null);
|
|
134
|
+
expect(indents(el)).toBe(3);
|
|
135
|
+
host.remove();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
await describe('<gtk-tree-expander> expansion', async () => {
|
|
140
|
+
await it('toggles on the ARROW and notifies on every change', () => {
|
|
141
|
+
const { el, host } = mount({ expandable: '' });
|
|
142
|
+
const seen: boolean[] = [];
|
|
143
|
+
el.addEventListener('notify::expanded', (event) => {
|
|
144
|
+
seen.push((event as CustomEvent).detail.expanded as boolean);
|
|
145
|
+
});
|
|
146
|
+
icon(el)!.click();
|
|
147
|
+
expect(el.expanded).toBe(true);
|
|
148
|
+
expect(icon(el)!.classList.contains('expanded')).toBe(true);
|
|
149
|
+
el.expanded = false;
|
|
150
|
+
expect(seen).toStrictEqual([true, false]);
|
|
151
|
+
host.remove();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await it('does not let the arrow click reach the row around it', () => {
|
|
155
|
+
// Upstream the gesture sits on the expander icon, so the list view's own row
|
|
156
|
+
// click never sees it.
|
|
157
|
+
const { el, host } = mount({ expandable: '' });
|
|
158
|
+
let reachedHost = false;
|
|
159
|
+
host.addEventListener('click', () => (reachedHost = true));
|
|
160
|
+
icon(el)!.click();
|
|
161
|
+
expect(reachedHost).toBe(false);
|
|
162
|
+
host.remove();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
await it('expands on + and collapses on -', () => {
|
|
166
|
+
const { el, host } = mount({ expandable: '' });
|
|
167
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: '+', bubbles: true }));
|
|
168
|
+
expect(el.expanded).toBe(true);
|
|
169
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: '-', bubbles: true }));
|
|
170
|
+
expect(el.expanded).toBe(false);
|
|
171
|
+
host.remove();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
await it('toggles on Ctrl+Space and ignores a bare Space', () => {
|
|
175
|
+
const { el, host } = mount({ expandable: '' });
|
|
176
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: ' ', bubbles: true }));
|
|
177
|
+
expect(el.expanded).toBe(false);
|
|
178
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: ' ', ctrlKey: true, bubbles: true }));
|
|
179
|
+
expect(el.expanded).toBe(true);
|
|
180
|
+
host.remove();
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
await it('needs Shift for the arrow keys', () => {
|
|
184
|
+
const { el, host } = mount({ expandable: '' });
|
|
185
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
186
|
+
expect(el.expanded).toBe(false);
|
|
187
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', shiftKey: true, bubbles: true }));
|
|
188
|
+
expect(el.expanded).toBe(true);
|
|
189
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', shiftKey: true, bubbles: true }));
|
|
190
|
+
expect(el.expanded).toBe(false);
|
|
191
|
+
host.remove();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
await it('is a focusable button, which is what carries the shortcuts', () => {
|
|
195
|
+
const { el, host } = mount({ expandable: '' });
|
|
196
|
+
expect(el.getAttribute('role')).toBe('button');
|
|
197
|
+
expect(el.tabIndex).toBe(0);
|
|
198
|
+
host.remove();
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
};
|