@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,164 @@
|
|
|
1
|
+
// DOM-level tests for <gtk-revealer>. The animation is driven from a frame clock the C
|
|
2
|
+
// reads from GdkFrameClock, so every assertion here drives it the way a browser can be
|
|
3
|
+
// driven deterministically: `transition-duration="0"`, which is the C's own
|
|
4
|
+
// "no animation" branch, plus the geometry the position produces — the clip box sized to
|
|
5
|
+
// `ceil (natural × scale)` and the child's transform chain — which is the part of
|
|
6
|
+
// `gtk_revealer_size_allocate` a reader of the element can actually see.
|
|
7
|
+
import { describe, expect, it } from '@gjsify/unit';
|
|
8
|
+
|
|
9
|
+
import type { GtkRevealer } from './elements/gtk-revealer.js';
|
|
10
|
+
|
|
11
|
+
function mount(attrs: Record<string, string> = {}): { el: GtkRevealer; host: HTMLElement } {
|
|
12
|
+
const host = document.createElement('div');
|
|
13
|
+
document.body.appendChild(host);
|
|
14
|
+
const el = document.createElement('gtk-revealer') as GtkRevealer;
|
|
15
|
+
for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
|
|
16
|
+
const child = document.createElement('div');
|
|
17
|
+
child.id = 'body';
|
|
18
|
+
child.style.height = '80px';
|
|
19
|
+
child.style.width = '120px';
|
|
20
|
+
el.appendChild(child);
|
|
21
|
+
host.appendChild(el);
|
|
22
|
+
return { el, host };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Collect the `detail` of every `event` dispatched on `el`. */
|
|
26
|
+
function record(el: HTMLElement, event: string): unknown[] {
|
|
27
|
+
const details: unknown[] = [];
|
|
28
|
+
el.addEventListener(event, (e) => details.push((e as CustomEvent).detail));
|
|
29
|
+
return details;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const GtkRevealerTest = async () => {
|
|
33
|
+
await describe('<gtk-revealer> state', async () => {
|
|
34
|
+
await it('starts closed, unrevealed, and named for assistive technology', () => {
|
|
35
|
+
const { el, host } = mount();
|
|
36
|
+
expect(el.revealChild).toBe(false);
|
|
37
|
+
expect(el.childRevealed).toBe(false);
|
|
38
|
+
expect(el.getAttribute('role')).toBe('group');
|
|
39
|
+
expect(el.classList.contains('revealed')).toBe(false);
|
|
40
|
+
host.remove();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
await it('an unknown transition-type leaves the pspec default in place', () => {
|
|
44
|
+
const { el, host } = mount({ 'transition-type': 'slide-sideways' });
|
|
45
|
+
// `slide-down` is `GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN`, the pspec default
|
|
46
|
+
// (gtkrevealer.c:120-128) and the answer GtkBuilder gives an unknown nick.
|
|
47
|
+
expect(el.transitionType).toBe('slide-down');
|
|
48
|
+
host.remove();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
await it('duration 0 is a real duration, and a negative one is not one at all', () => {
|
|
52
|
+
const { el, host } = mount();
|
|
53
|
+
expect(el.transitionDuration).toBe(250);
|
|
54
|
+
el.transitionDuration = 0;
|
|
55
|
+
expect(el.transitionDuration).toBe(0);
|
|
56
|
+
// The pspec is a `guint`, so a negative value is not a duration — the default is
|
|
57
|
+
// what a property set of one leaves behind.
|
|
58
|
+
el.transitionDuration = -5;
|
|
59
|
+
expect(el.transitionDuration).toBe(250);
|
|
60
|
+
host.remove();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await it('a declarative reveal-child attribute lands before the first frame', async () => {
|
|
64
|
+
const { el, host } = mount({ 'reveal-child': '', 'transition-duration': '0' });
|
|
65
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
66
|
+
expect(el.revealChild).toBe(true);
|
|
67
|
+
expect(el.childRevealed).toBe(true);
|
|
68
|
+
expect(el.classList.contains('revealed')).toBe(true);
|
|
69
|
+
host.remove();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
await it('re-setting the same value notifies nothing', () => {
|
|
73
|
+
const { el, host } = mount({ 'transition-duration': '0' });
|
|
74
|
+
const revealed = record(el, 'notify::reveal-child');
|
|
75
|
+
el.revealChild = true;
|
|
76
|
+
el.revealChild = true;
|
|
77
|
+
expect(revealed.length).toBe(1);
|
|
78
|
+
host.remove();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
await it('notifies child-revealed when the position lands, and only then', () => {
|
|
82
|
+
const { el, host } = mount({ 'transition-duration': '0' });
|
|
83
|
+
const landed = record(el, 'notify::child-revealed');
|
|
84
|
+
el.revealChild = true;
|
|
85
|
+
expect(landed).toStrictEqual([{ childRevealed: true }]);
|
|
86
|
+
el.revealChild = false;
|
|
87
|
+
expect(landed).toStrictEqual([{ childRevealed: true }, { childRevealed: false }]);
|
|
88
|
+
host.remove();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
await describe('<gtk-revealer> geometry', async () => {
|
|
93
|
+
await it("a crossfade scales neither axis, so the box is the child's own", async () => {
|
|
94
|
+
const { el, host } = mount({ 'transition-duration': '0', 'transition-type': 'crossfade' });
|
|
95
|
+
el.revealChild = true;
|
|
96
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
97
|
+
const clip = el.querySelector('.adw-revealer-clip') as HTMLElement;
|
|
98
|
+
// `get_child_size_scale` returns 1.0 for CROSSFADE on both axes, so nothing is
|
|
99
|
+
// written and the box measures the child.
|
|
100
|
+
expect(clip.style.height).toBe('');
|
|
101
|
+
expect(clip.style.width).toBe('');
|
|
102
|
+
expect(clip.getBoundingClientRect().height).toBe(80);
|
|
103
|
+
host.remove();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
await it('a slide-down scales the height by the position and holds the child full size', async () => {
|
|
107
|
+
const { el, host } = mount({ 'transition-duration': '0' });
|
|
108
|
+
// Halfway through, which is the only position a duration-0 run passes through
|
|
109
|
+
// if the target is set before the first frame.
|
|
110
|
+
const clip = el.querySelector('.adw-revealer-clip') as HTMLElement;
|
|
111
|
+
const child = clip.firstElementChild as HTMLElement;
|
|
112
|
+
expect(clip.getBoundingClientRect().height).toBe(0);
|
|
113
|
+
expect(child.getBoundingClientRect().height).toBe(80);
|
|
114
|
+
// The child's transform is `translate (0, height - child_height)`, which at a
|
|
115
|
+
// closed revealer is the whole child — the C's `overflow: hidden` is what hides
|
|
116
|
+
// it, not a scaled paint.
|
|
117
|
+
expect(child.style.transform).toBe('translateY(-80px)');
|
|
118
|
+
el.revealChild = true;
|
|
119
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
120
|
+
expect(clip.getBoundingClientRect().height).toBe(80);
|
|
121
|
+
expect(child.style.transform).toBe('translateY(0px)');
|
|
122
|
+
host.remove();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
await it('slide-left pins the child at its own origin and scales the width', async () => {
|
|
126
|
+
const { el, host } = mount({ 'transition-duration': '0', 'transition-type': 'slide-left' });
|
|
127
|
+
el.revealChild = true;
|
|
128
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
129
|
+
const clip = el.querySelector('.adw-revealer-clip') as HTMLElement;
|
|
130
|
+
const child = clip.firstElementChild as HTMLElement;
|
|
131
|
+
// The C's switch has no case for SLIDE_LEFT, so the chain is empty — and its
|
|
132
|
+
// scale still takes the width.
|
|
133
|
+
expect(child.style.transform).toBe('');
|
|
134
|
+
expect(clip.getBoundingClientRect().width).toBe(120);
|
|
135
|
+
host.remove();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
await it('a fading type writes the position as the opacity', async () => {
|
|
139
|
+
const { el, host } = mount({ 'transition-duration': '0', 'transition-type': 'crossfade' });
|
|
140
|
+
const child = el.querySelector('.adw-revealer-clip')?.firstElementChild as HTMLElement;
|
|
141
|
+
expect(child.style.opacity).toBe('0');
|
|
142
|
+
el.revealChild = true;
|
|
143
|
+
expect(child.style.opacity).toBe('1');
|
|
144
|
+
// `none` is not a fading type at all, so the property is left unset rather than
|
|
145
|
+
// pinned to 1 — `gtk_revealer_snapshot` pushes no opacity for it.
|
|
146
|
+
el.transitionType = 'slide-down';
|
|
147
|
+
el.revealChild = false;
|
|
148
|
+
expect(child.style.opacity).toBe('');
|
|
149
|
+
host.remove();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
await it('clips, so the child stays in the accessibility tree while closed', () => {
|
|
153
|
+
const { el, host } = mount();
|
|
154
|
+
// gtkrevealer.c:61-63 — "always available in the accessibility tree, regardless of
|
|
155
|
+
// the state of the revealer widget", which rules out `display: none` and
|
|
156
|
+
// `visibility: hidden` on the child.
|
|
157
|
+
expect(getComputedStyle(el).overflow).toBe('hidden');
|
|
158
|
+
const child = el.querySelector('.adw-revealer-clip')?.firstElementChild as HTMLElement;
|
|
159
|
+
expect(child.style.display).toBe('');
|
|
160
|
+
expect(child.hasAttribute('hidden')).toBe(false);
|
|
161
|
+
host.remove();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
};
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// DOM-level tests for <gtk-scale-button>. Three things are ported from the C and none of
|
|
2
|
+
// them is obvious: the icon FOLLOWS THE VALUE (one name for every value, two split the
|
|
3
|
+
// range in half, three or more put the first at the bottom and the second at the top), the
|
|
4
|
+
// steppers move by the PAGE increment and go insensitive at the ends, and `active` is
|
|
5
|
+
// read-only — the dock follows it, not the other way round.
|
|
6
|
+
import { describe, expect, it } from '@gjsify/unit';
|
|
7
|
+
|
|
8
|
+
import type { GtkScaleButton } from './elements/gtk-scale-button.js';
|
|
9
|
+
|
|
10
|
+
function mount(attrs: Record<string, string> = {}): { el: GtkScaleButton; host: HTMLElement } {
|
|
11
|
+
const host = document.createElement('div');
|
|
12
|
+
document.body.appendChild(host);
|
|
13
|
+
const el = document.createElement('gtk-scale-button') as GtkScaleButton;
|
|
14
|
+
for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
|
|
15
|
+
host.appendChild(el);
|
|
16
|
+
return { el, host };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** The three children of the dock, in DOM order: the minus stepper, the range, the plus. */
|
|
20
|
+
function parts(el: GtkScaleButton): { minus: HTMLButtonElement; range: HTMLInputElement; plus: HTMLButtonElement } {
|
|
21
|
+
const box = el.querySelector('.scale-button-box') as HTMLElement;
|
|
22
|
+
const [minus, range, plus] = [...box.children] as [HTMLButtonElement, HTMLInputElement, HTMLButtonElement];
|
|
23
|
+
return { minus, range, plus };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** The icon the button currently shows — `image-missing` when the list is empty. */
|
|
27
|
+
function iconOf(el: GtkScaleButton): string | null {
|
|
28
|
+
return el.querySelector('.scale-button-glyph')?.getAttribute('icon-name') ?? null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const VOLUME_ICONS = '["audio-volume-muted-symbolic","audio-volume-low-symbolic","audio-volume-high-symbolic"]';
|
|
32
|
+
|
|
33
|
+
export const GtkScaleButtonTest = async () => {
|
|
34
|
+
await describe('<gtk-scale-button> defaults', async () => {
|
|
35
|
+
await it('opens at the bottom of GTK’s own 0…100 by 2 range, with a page of 20', () => {
|
|
36
|
+
const { el, host } = mount();
|
|
37
|
+
const { range } = parts(el);
|
|
38
|
+
expect(el.value).toBe(0);
|
|
39
|
+
expect(range.min).toBe('0');
|
|
40
|
+
expect(range.max).toBe('100');
|
|
41
|
+
expect(range.step).toBe('2');
|
|
42
|
+
host.remove();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
await it('is vertical by default, because Gtk.ScaleButton is', () => {
|
|
46
|
+
const { el, host } = mount();
|
|
47
|
+
expect(el.orientation).toBe('vertical');
|
|
48
|
+
expect(el.classList.contains('vertical')).toBe(true);
|
|
49
|
+
el.orientation = 'horizontal';
|
|
50
|
+
expect(el.getAttribute('orientation')).toBe('horizontal');
|
|
51
|
+
expect(el.classList.contains('horizontal')).toBe(true);
|
|
52
|
+
expect(el.classList.contains('vertical')).toBe(false);
|
|
53
|
+
host.remove();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await it('has no frame, so the icon button is flat', () => {
|
|
57
|
+
const { el, host } = mount();
|
|
58
|
+
const icon = el.querySelector('.scale-button-icon') as HTMLButtonElement;
|
|
59
|
+
expect(el.hasFrame).toBe(false);
|
|
60
|
+
expect(icon.classList.contains('flat')).toBe(true);
|
|
61
|
+
el.hasFrame = true;
|
|
62
|
+
expect(icon.classList.contains('flat')).toBe(false);
|
|
63
|
+
host.remove();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await it('shows image-missing with no icon list at all', () => {
|
|
67
|
+
const { el, host } = mount();
|
|
68
|
+
expect(iconOf(el)).toBe('image-missing');
|
|
69
|
+
host.remove();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
await describe('<gtk-scale-button> icon selection', async () => {
|
|
74
|
+
await it('one icon is used for every value', () => {
|
|
75
|
+
const { el, host } = mount({ icons: '["only-symbolic"]' });
|
|
76
|
+
el.value = 100;
|
|
77
|
+
expect(iconOf(el)).toBe('only-symbolic');
|
|
78
|
+
el.value = 0;
|
|
79
|
+
expect(iconOf(el)).toBe('only-symbolic');
|
|
80
|
+
host.remove();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
await it('two icons split the range in half', () => {
|
|
84
|
+
const { el, host } = mount({ icons: '["low-symbolic","high-symbolic"]' });
|
|
85
|
+
expect(iconOf(el)).toBe('low-symbolic');
|
|
86
|
+
el.value = 50;
|
|
87
|
+
expect(iconOf(el)).toBe('high-symbolic');
|
|
88
|
+
host.remove();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
await it('three icons put the first at the bottom and the SECOND at the top', () => {
|
|
92
|
+
const { el, host } = mount({ icons: VOLUME_ICONS, value: '50' });
|
|
93
|
+
// Two arithmetic facts of the C, both visible, neither a reading of the prose:
|
|
94
|
+
// with three names the step is the whole range, so the interior shares ONE icon
|
|
95
|
+
// (the third); and `value == upper` takes icon_list[1] — the SECOND name, which
|
|
96
|
+
// for this volume list is `audio-volume-low-symbolic`. The property doc calls it
|
|
97
|
+
// "the second item for the highest value" (:250-252), which is the same rule.
|
|
98
|
+
expect(iconOf(el)).toBe('audio-volume-high-symbolic');
|
|
99
|
+
el.value = 100;
|
|
100
|
+
expect(iconOf(el)).toBe('audio-volume-low-symbolic');
|
|
101
|
+
el.value = 0;
|
|
102
|
+
expect(iconOf(el)).toBe('audio-volume-muted-symbolic');
|
|
103
|
+
host.remove();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
await it('five icons spread the interior evenly over the three that are left', () => {
|
|
107
|
+
const { el, host } = mount({
|
|
108
|
+
icons: '["a-symbolic","b-symbolic","c-symbolic","d-symbolic","e-symbolic"]',
|
|
109
|
+
value: '90',
|
|
110
|
+
});
|
|
111
|
+
// step = 100 / 3, and the index is `2 + floor((value - lower) / step)`:
|
|
112
|
+
// 90 → 4 (the fifth), 40 → 3 (the fourth), 20 → 2 (the third).
|
|
113
|
+
expect(iconOf(el)).toBe('e-symbolic');
|
|
114
|
+
el.value = 40;
|
|
115
|
+
expect(iconOf(el)).toBe('d-symbolic');
|
|
116
|
+
el.value = 20;
|
|
117
|
+
expect(iconOf(el)).toBe('c-symbolic');
|
|
118
|
+
host.remove();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
await it('a malformed icons attribute is no list, and image-missing is that answer', () => {
|
|
122
|
+
const { el, host } = mount({ icons: 'audio-volume-high-symbolic' });
|
|
123
|
+
expect(el.icons).toStrictEqual([]);
|
|
124
|
+
expect(iconOf(el)).toBe('image-missing');
|
|
125
|
+
host.remove();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
await describe('<gtk-scale-button> value', async () => {
|
|
130
|
+
await it('clamps into the adjustment, and notifies once per real change', () => {
|
|
131
|
+
const { el, host } = mount();
|
|
132
|
+
const changed: unknown[] = [];
|
|
133
|
+
const notified: unknown[] = [];
|
|
134
|
+
el.addEventListener('value-changed', (e) => changed.push((e as CustomEvent).detail));
|
|
135
|
+
el.addEventListener('notify::value', (e) => notified.push((e as CustomEvent).detail));
|
|
136
|
+
el.value = 500;
|
|
137
|
+
expect(el.value).toBe(100);
|
|
138
|
+
expect(el.getAttribute('value')).toBe('100');
|
|
139
|
+
el.value = 100;
|
|
140
|
+
expect(changed).toStrictEqual([{ value: 100 }]);
|
|
141
|
+
expect(notified).toStrictEqual([{ value: 100 }]);
|
|
142
|
+
host.remove();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
await it('an authored adjustment replaces the range, and the value is clamped into it', () => {
|
|
146
|
+
const { el, host } = mount({
|
|
147
|
+
adjustment: '{"lower":10,"upper":30,"stepIncrement":5}',
|
|
148
|
+
value: '100',
|
|
149
|
+
});
|
|
150
|
+
const { range } = parts(el);
|
|
151
|
+
expect(range.min).toBe('10');
|
|
152
|
+
expect(range.max).toBe('30');
|
|
153
|
+
expect(range.step).toBe('5');
|
|
154
|
+
expect(el.value).toBe(30);
|
|
155
|
+
host.remove();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
await it('a stepper moves by the PAGE increment, not the step', () => {
|
|
159
|
+
const { el, host } = mount();
|
|
160
|
+
const { plus, minus } = parts(el);
|
|
161
|
+
plus.click();
|
|
162
|
+
expect(el.value).toBe(20);
|
|
163
|
+
minus.click();
|
|
164
|
+
expect(el.value).toBe(0);
|
|
165
|
+
host.remove();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
await it('each stepper goes insensitive at its end of the range', () => {
|
|
169
|
+
const { el, host } = mount();
|
|
170
|
+
const { plus, minus } = parts(el);
|
|
171
|
+
expect(plus.disabled).toBe(false);
|
|
172
|
+
expect(minus.disabled).toBe(true);
|
|
173
|
+
el.value = 100;
|
|
174
|
+
expect(plus.disabled).toBe(true);
|
|
175
|
+
expect(minus.disabled).toBe(false);
|
|
176
|
+
host.remove();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await it('carries the value as an ARIA range on the control that owns it', () => {
|
|
180
|
+
const { el, host } = mount({ value: '42' });
|
|
181
|
+
const { range } = parts(el);
|
|
182
|
+
expect(range.getAttribute('aria-valuenow')).toBe('42');
|
|
183
|
+
expect(range.getAttribute('aria-valuemin')).toBe('0');
|
|
184
|
+
expect(range.getAttribute('aria-valuemax')).toBe('100');
|
|
185
|
+
host.remove();
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
await describe('<gtk-scale-button> dock', async () => {
|
|
190
|
+
await it('pressing the icon button pops the scale up and marks the button pressed', () => {
|
|
191
|
+
const { el, host } = mount();
|
|
192
|
+
const icon = el.querySelector('.scale-button-icon') as HTMLButtonElement;
|
|
193
|
+
const dock = el.querySelector('gtk-popover') as HTMLElement;
|
|
194
|
+
const popped: string[] = [];
|
|
195
|
+
el.addEventListener('popup', () => popped.push('popup'));
|
|
196
|
+
el.addEventListener('popdown', () => popped.push('popdown'));
|
|
197
|
+
icon.click();
|
|
198
|
+
expect(el.active).toBe(true);
|
|
199
|
+
expect(icon.classList.contains('checked')).toBe(true);
|
|
200
|
+
expect(dock.hasAttribute('open')).toBe(true);
|
|
201
|
+
expect(popped).toStrictEqual(['popup']);
|
|
202
|
+
icon.click();
|
|
203
|
+
expect(el.active).toBe(false);
|
|
204
|
+
expect(dock.hasAttribute('open')).toBe(false);
|
|
205
|
+
expect(popped).toStrictEqual(['popup', 'popdown']);
|
|
206
|
+
host.remove();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
await it('a value written while the dock is up does not close it', () => {
|
|
210
|
+
const { el, host } = mount();
|
|
211
|
+
const icon = el.querySelector('.scale-button-icon') as HTMLButtonElement;
|
|
212
|
+
icon.click();
|
|
213
|
+
el.value = 30;
|
|
214
|
+
expect(el.active).toBe(true);
|
|
215
|
+
host.remove();
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
};
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// DOM-level tests for <gtk-scale>. `Gtk.Scale` extends the abstract `Gtk.Range`, so the
|
|
2
|
+
// surface under test is a range's plus four: the pointer mapping is `coord_to_value`, the
|
|
3
|
+
// keys are `GtkScale`'s own bindings, and the value text is `gtk_scale_format_value`.
|
|
4
|
+
import { describe, expect, it } from '@gjsify/unit';
|
|
5
|
+
|
|
6
|
+
import type { GtkScale } from './elements/gtk-scale.js';
|
|
7
|
+
|
|
8
|
+
function mount(attrs: Record<string, string> = {}): { el: GtkScale; host: HTMLElement } {
|
|
9
|
+
const host = document.createElement('div');
|
|
10
|
+
host.style.width = '300px';
|
|
11
|
+
document.body.appendChild(host);
|
|
12
|
+
const el = document.createElement('gtk-scale') as GtkScale;
|
|
13
|
+
for (const [name, value] of Object.entries(attrs)) el.setAttribute(name, value);
|
|
14
|
+
host.appendChild(el);
|
|
15
|
+
return { el, host };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function record(el: HTMLElement, event: string): unknown[] {
|
|
19
|
+
const details: unknown[] = [];
|
|
20
|
+
el.addEventListener(event, (e) => details.push((e as CustomEvent).detail));
|
|
21
|
+
return details;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** A real press on the trough, which is what `coord_to_value` is written against. */
|
|
25
|
+
function pressAt(el: GtkScale, fraction: number): void {
|
|
26
|
+
const trough = el.querySelector('.adw-scale-trough') as HTMLElement;
|
|
27
|
+
const rect = trough.getBoundingClientRect();
|
|
28
|
+
const event = new PointerEvent('pointerdown', {
|
|
29
|
+
bubbles: true,
|
|
30
|
+
cancelable: true,
|
|
31
|
+
pointerId: 1,
|
|
32
|
+
button: 0,
|
|
33
|
+
clientX: rect.left + rect.width * fraction,
|
|
34
|
+
});
|
|
35
|
+
trough.dispatchEvent(event);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const GtkScaleTest = async () => {
|
|
39
|
+
await describe('<gtk-scale> range', async () => {
|
|
40
|
+
await it('is a horizontal slider over 0…100 with a step of 1', () => {
|
|
41
|
+
const { el, host } = mount();
|
|
42
|
+
expect(el.orientation).toBe('horizontal');
|
|
43
|
+
expect(el.adjustment).toStrictEqual({
|
|
44
|
+
value: 0,
|
|
45
|
+
lower: 0,
|
|
46
|
+
upper: 100,
|
|
47
|
+
stepIncrement: 1,
|
|
48
|
+
pageIncrement: 1,
|
|
49
|
+
pageSize: 0,
|
|
50
|
+
});
|
|
51
|
+
expect(el.getAttribute('role')).toBe('slider');
|
|
52
|
+
expect(el.getAttribute('aria-orientation')).toBe('horizontal');
|
|
53
|
+
expect(el.getAttribute('aria-valuemin')).toBe('0');
|
|
54
|
+
expect(el.getAttribute('aria-valuemax')).toBe('100');
|
|
55
|
+
expect(el.getAttribute('aria-valuenow')).toBe('0');
|
|
56
|
+
host.remove();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await it('takes the adjustment as the portable value, and a bound move re-clamps', () => {
|
|
60
|
+
const { el, host } = mount({ adjustment: '{"lower":10,"upper":40,"stepIncrement":5}', value: '30' });
|
|
61
|
+
expect(el.adjustment.lower).toBe(10);
|
|
62
|
+
expect(el.adjustment.upper).toBe(40);
|
|
63
|
+
expect(el.value).toBe(30);
|
|
64
|
+
el.adjustment = { upper: 20 };
|
|
65
|
+
expect(el.value).toBe(20);
|
|
66
|
+
host.remove();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await it('a declarative value emits nothing until it changes', () => {
|
|
70
|
+
const host = document.createElement('div');
|
|
71
|
+
document.body.appendChild(host);
|
|
72
|
+
const el = document.createElement('gtk-scale') as GtkScale;
|
|
73
|
+
el.setAttribute('value', '60');
|
|
74
|
+
const changed = record(el, 'value-changed');
|
|
75
|
+
host.appendChild(el);
|
|
76
|
+
expect(el.value).toBe(60);
|
|
77
|
+
expect(changed.length).toBe(0);
|
|
78
|
+
el.value = 70;
|
|
79
|
+
expect(changed).toStrictEqual([{ value: 70 }]);
|
|
80
|
+
host.remove();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await describe('<gtk-scale> pointer and keys', async () => {
|
|
85
|
+
await it('a press on the trough moves the value to that fraction', () => {
|
|
86
|
+
const { el, host } = mount();
|
|
87
|
+
pressAt(el, 0.25);
|
|
88
|
+
expect(el.value).toBe(25);
|
|
89
|
+
pressAt(el, 0.5);
|
|
90
|
+
expect(el.value).toBe(50);
|
|
91
|
+
host.remove();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
await it('an inverted horizontal scale answers the press the other way round', () => {
|
|
95
|
+
const { el, host } = mount({ inverted: '' });
|
|
96
|
+
pressAt(el, 0.25);
|
|
97
|
+
expect(el.value).toBe(75);
|
|
98
|
+
host.remove();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await it('an arrow steps and Ctrl+arrow pages, in either orientation', () => {
|
|
102
|
+
const { el, host } = mount({ adjustment: '{"lower":0,"upper":100,"stepIncrement":2,"pageIncrement":20}' });
|
|
103
|
+
const press = (key: string, ctrlKey = false) =>
|
|
104
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key, ctrlKey, bubbles: true, cancelable: true }));
|
|
105
|
+
press('ArrowRight');
|
|
106
|
+
expect(el.value).toBe(2);
|
|
107
|
+
press('ArrowLeft');
|
|
108
|
+
expect(el.value).toBe(0);
|
|
109
|
+
press('ArrowRight', true);
|
|
110
|
+
expect(el.value).toBe(20);
|
|
111
|
+
press('Home');
|
|
112
|
+
expect(el.value).toBe(0);
|
|
113
|
+
press('End');
|
|
114
|
+
expect(el.value).toBe(100);
|
|
115
|
+
host.remove();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
await it('a disabled scale takes neither a press nor a key', () => {
|
|
119
|
+
const { el, host } = mount({ disabled: '' });
|
|
120
|
+
pressAt(el, 0.75);
|
|
121
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true, cancelable: true }));
|
|
122
|
+
expect(el.value).toBe(0);
|
|
123
|
+
expect(el.getAttribute('aria-disabled')).toBe('true');
|
|
124
|
+
host.remove();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
await describe('<gtk-scale> rendering', async () => {
|
|
129
|
+
await it('positions the knob by its centre and the highlight by the same fraction', () => {
|
|
130
|
+
const { el, host } = mount({ value: '40', 'draw-value': '' });
|
|
131
|
+
const knob = el.querySelector('.adw-scale-slider') as HTMLElement;
|
|
132
|
+
const highlight = el.querySelector('.adw-scale-highlight') as HTMLElement;
|
|
133
|
+
expect(knob.style.left).toBe('40%');
|
|
134
|
+
expect(highlight.style.width).toBe('40%');
|
|
135
|
+
expect((el.querySelector('.adw-scale-value') as HTMLElement).hidden).toBe(false);
|
|
136
|
+
expect(el.getAttribute('aria-valuetext')).toBe('40.0');
|
|
137
|
+
host.remove();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
await it('digits is the number of decimal places, default 1', () => {
|
|
141
|
+
const { el, host } = mount({ value: '0.5', 'draw-value': '' });
|
|
142
|
+
expect(el.digits).toBe(1);
|
|
143
|
+
expect((el.querySelector('.adw-scale-value') as HTMLElement).textContent).toBe('0.5');
|
|
144
|
+
el.setAttribute('digits', '2');
|
|
145
|
+
expect((el.querySelector('.adw-scale-value') as HTMLElement).textContent).toBe('0.50');
|
|
146
|
+
host.remove();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
await it('has-origin false withdraws the highlight, show-fill-level draws the second bar', () => {
|
|
150
|
+
const { el, host } = mount({ 'has-origin': 'false', 'show-fill-level': '', 'fill-level': '60' });
|
|
151
|
+
expect((el.querySelector('.adw-scale-highlight') as HTMLElement).hidden).toBe(true);
|
|
152
|
+
expect((el.querySelector('.adw-scale-fill') as HTMLElement).hidden).toBe(false);
|
|
153
|
+
expect((el.querySelector('.adw-scale-fill') as HTMLElement).style.width).toBe('60%');
|
|
154
|
+
host.remove();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await it('round-digits rounds a dragged value half up, and -1 leaves it alone', () => {
|
|
158
|
+
const { el, host } = mount({ 'round-digits': '0' });
|
|
159
|
+
el.value = 42.5;
|
|
160
|
+
expect(el.value).toBe(43);
|
|
161
|
+
el.setAttribute('round-digits', '-1');
|
|
162
|
+
el.value = 42.5;
|
|
163
|
+
expect(el.value).toBe(42.5);
|
|
164
|
+
host.remove();
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
await it('a vertical scale positions the knob from the bottom', () => {
|
|
168
|
+
const { el, host } = mount({ orientation: 'vertical', value: '30' });
|
|
169
|
+
expect((el.querySelector('.adw-scale-slider') as HTMLElement).style.bottom).toBe('30%');
|
|
170
|
+
expect(el.classList.contains('vertical')).toBe(true);
|
|
171
|
+
host.remove();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
await it('draw-value false hides the value text but keeps the a11y value', () => {
|
|
175
|
+
const { el, host } = mount({ value: '10' });
|
|
176
|
+
expect((el.querySelector('.adw-scale-value') as HTMLElement).hidden).toBe(true);
|
|
177
|
+
expect(el.getAttribute('aria-valuenow')).toBe('10');
|
|
178
|
+
host.remove();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// `gtk_scale_allocate` (gtkscale.c:373-421) puts the value at one EDGE of the widget,
|
|
182
|
+
// which is what the host's four `value-*` classes name — a class the element has to
|
|
183
|
+
// write, because upstream's own `update_value_position` (gtkscale.c:1042-1073) only
|
|
184
|
+
// ever puts the position on the value NODE.
|
|
185
|
+
await it('value-pos names the edge on the host and on the value node', () => {
|
|
186
|
+
const { el, host } = mount({ 'draw-value': '', 'value-pos': 'left' });
|
|
187
|
+
const value = el.querySelector('.adw-scale-value') as HTMLElement;
|
|
188
|
+
expect(el.classList.contains('value-left')).toBe(true);
|
|
189
|
+
expect(el.classList.contains('value-top')).toBe(false);
|
|
190
|
+
expect(value.classList.contains('left')).toBe(true);
|
|
191
|
+
expect(value.classList.contains('top')).toBe(false);
|
|
192
|
+
host.remove();
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
await it('value-pos defaults to top, follows a runtime change, and falls back to it', () => {
|
|
196
|
+
const { el, host } = mount({ 'draw-value': '' });
|
|
197
|
+
const value = el.querySelector('.adw-scale-value') as HTMLElement;
|
|
198
|
+
expect(el.valuePos).toBe('top');
|
|
199
|
+
expect(el.classList.contains('value-top')).toBe(true);
|
|
200
|
+
expect(value.classList.contains('top')).toBe(true);
|
|
201
|
+
el.setAttribute('value-pos', 'bottom');
|
|
202
|
+
expect(el.classList.contains('value-bottom')).toBe(true);
|
|
203
|
+
expect(el.classList.contains('value-top')).toBe(false);
|
|
204
|
+
expect(value.classList.contains('bottom')).toBe(true);
|
|
205
|
+
// Not one of the four nicks, so the pspec default stands.
|
|
206
|
+
el.setAttribute('value-pos', 'middle');
|
|
207
|
+
expect(el.valuePos).toBe('top');
|
|
208
|
+
expect(el.classList.contains('value-top')).toBe(true);
|
|
209
|
+
expect(el.classList.contains('value-bottom')).toBe(false);
|
|
210
|
+
host.remove();
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
};
|