@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,323 @@
|
|
|
1
|
+
// <gtk-level-bar> — a filled portion of a bounded range: a password strength meter, a
|
|
2
|
+
// battery. It is NOT a progress bar: the value may go DOWN, and it is drawn in
|
|
3
|
+
// PROPORTION to an interval (`min-value`…`max-value`), not to a 0…1 fraction.
|
|
4
|
+
//
|
|
5
|
+
// CSS NODES, PORTED VERBATIM (gtklevelbar.c:99-116):
|
|
6
|
+
// levelbar[.discrete] ─╮
|
|
7
|
+
// ├── trough │
|
|
8
|
+
// │ ├── block.filled.level-name
|
|
9
|
+
// │ └── block.empty
|
|
10
|
+
// The `level-name` class on a filled block IS the public API for colouring a bar —
|
|
11
|
+
// libadwaita paints `.low` warning, `.high`/`:not(.empty)` accent and `.full` success
|
|
12
|
+
// off it (refs/libadwaita/src/stylesheet/widgets/_level-bar.scss:71-93), and an
|
|
13
|
+
// application adds its own offset to add its own class (gtklevelbar.c:59-76).
|
|
14
|
+
//
|
|
15
|
+
// WHICH CLASS, FROM THE OFFSETS. `update_level_style_classes` walks the offsets in
|
|
16
|
+
// ASCENDING order and stops at the first one that can name the current value
|
|
17
|
+
// (gtklevelbar.c:604-625): the lowest offset at or above the value wins, and the lowest
|
|
18
|
+
// one of all wins even when the value sits below it. Three offsets exist before any
|
|
19
|
+
// code runs — `low` 0.25, `high` 0.75, `full` 1.0 (gtklevelbar.c:1058-1060) — so
|
|
20
|
+
// `value = 0` already reads `low`, exactly as it does in GTK.
|
|
21
|
+
//
|
|
22
|
+
// HOW MANY BLOCKS. Continuous is ONE drawn level with two nodes under the trough (the
|
|
23
|
+
// empty one and the filled one painted on top, gtklevelbar.c:344-362); discrete is
|
|
24
|
+
// `MAX(1, round(max) − round(min))` drawn blocks (gtklevelbar.c:285-294) of which
|
|
25
|
+
// `MIN(blocks, round(value) − round(min))` are filled (gtklevelbar.c:630-633). `inverted`
|
|
26
|
+
// counts from the other end — it reverses which block index is filled, it does not
|
|
27
|
+
// reverse the DOM (gtklevelbar.c:637, 648).
|
|
28
|
+
//
|
|
29
|
+
// SETTING AN END MOVES THE VALUE. `set_min_value` pushes `value` up to the new minimum
|
|
30
|
+
// and `set_max_value` pushes it down to the new maximum (gtklevelbar.c:1191-1192,
|
|
31
|
+
// :1229-1230), and the maximum additionally CLAMPS every offset into the new interval
|
|
32
|
+
// (:1234, :667-682) — the minimum deliberately does not. Both are GObject property
|
|
33
|
+
// setters, so each fires `notify::` for the value it moved as well as its own.
|
|
34
|
+
//
|
|
35
|
+
// A11Y: `role="meter"`, which is GtkLevelBar's own accessible role
|
|
36
|
+
// (gtklevelbar.c:1033), with `aria-valuemin` / `aria-valuemax` / `aria-valuenow` over
|
|
37
|
+
// the REAL interval rather than 0…1 (gtklevelbar.c:1070-1074, :1199-1202, :1238-1241,
|
|
38
|
+
// :1266-1268).
|
|
39
|
+
//
|
|
40
|
+
// Events: `notify::<prop>` (CustomEvent, bubbles, detail `{ <prop>: value }`) on every
|
|
41
|
+
// real change, and `offset-changed` (CustomEvent, bubbles, detail `{ name }`), GtkLevelBar's
|
|
42
|
+
// own DETAILED signal (gtklevelbar.c:936-958, :1410) — the browser has no per-name signal
|
|
43
|
+
// channel, so the name rides in the detail.
|
|
44
|
+
//
|
|
45
|
+
// Reference: refs/gtk/gtk/gtklevelbar.c
|
|
46
|
+
// Copyright (c) The GTK Team. LGPLv2.1+.
|
|
47
|
+
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
48
|
+
|
|
49
|
+
import { normalizeBoxOrientation, type BoxOrientation } from '@gjsify/adwaita-core';
|
|
50
|
+
|
|
51
|
+
/** `GtkLevelBarMode`, spelled as the GIR's enum nicks (:1004-1008). */
|
|
52
|
+
type LevelBarMode = 'continuous' | 'discrete';
|
|
53
|
+
|
|
54
|
+
/** The offsets GTK installs before any application code runs (gtklevelbar.c:1058-1060). */
|
|
55
|
+
const DEFAULT_OFFSETS: readonly (readonly [string, number])[] = [
|
|
56
|
+
['low', 0.25],
|
|
57
|
+
['high', 0.75],
|
|
58
|
+
['full', 1.0],
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The offset that names `value`, transcribed from `update_level_style_classes`
|
|
63
|
+
* (gtklevelbar.c:604-625): ascending, first offset at or above the value wins, and an
|
|
64
|
+
* offset whose PREDECESSOR is not below the value names nothing — the walk continues.
|
|
65
|
+
* Keeping the `previous < value` test rather than simplifying it away is the point:
|
|
66
|
+
* two offsets sharing a value make the two spellings disagree, and only one is C.
|
|
67
|
+
*/
|
|
68
|
+
function levelClassFor(offsets: readonly (readonly [string, number])[], value: number): string | null {
|
|
69
|
+
for (let i = 0; i < offsets.length; i++) {
|
|
70
|
+
const [name, threshold] = offsets[i];
|
|
71
|
+
if (value > threshold) continue;
|
|
72
|
+
const previous = i === 0 ? null : offsets[i - 1][1];
|
|
73
|
+
if (previous === null || previous < value) return name;
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** A missing or unparseable attribute is `fallback`, which is also the GIR default. */
|
|
79
|
+
function numberAttribute(element: HTMLElement, name: string, fallback: number): number {
|
|
80
|
+
const raw = Number.parseFloat(element.getAttribute(name) ?? '');
|
|
81
|
+
return Number.isFinite(raw) ? raw : fallback;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export class GtkLevelBar extends HTMLElement {
|
|
85
|
+
private _trough!: HTMLSpanElement;
|
|
86
|
+
private _initialized = false;
|
|
87
|
+
/** Offset name → value, kept sorted ascending exactly as the C's `GList` is. */
|
|
88
|
+
private _offsets: (readonly [string, number])[] = DEFAULT_OFFSETS.map((entry) => [...entry] as const);
|
|
89
|
+
|
|
90
|
+
static get observedAttributes() {
|
|
91
|
+
return ['value', 'min-value', 'max-value', 'mode', 'inverted', 'orientation', 'disabled'];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** `Gtk.LevelBar:value` — the filled level. */
|
|
95
|
+
get value(): number {
|
|
96
|
+
return numberAttribute(this, 'value', 0);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
set value(v: number) {
|
|
100
|
+
this._write('value', String(v));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** `Gtk.LevelBar:min-value` — the low end of the interval. Defaults to 0. */
|
|
104
|
+
get minValue(): number {
|
|
105
|
+
return numberAttribute(this, 'min-value', 0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
set minValue(v: number) {
|
|
109
|
+
this._write('min-value', String(v));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** `Gtk.LevelBar:max-value` — the high end of the interval. Defaults to 1. */
|
|
113
|
+
get maxValue(): number {
|
|
114
|
+
return numberAttribute(this, 'max-value', 1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
set maxValue(v: number) {
|
|
118
|
+
this._write('max-value', String(v));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** `Gtk.LevelBar:mode` — one filled block, or one per unit of the interval. */
|
|
122
|
+
get mode(): LevelBarMode {
|
|
123
|
+
return this.getAttribute('mode') === 'discrete' ? 'discrete' : 'continuous';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
set mode(v: LevelBarMode) {
|
|
127
|
+
this._write('mode', v);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** `Gtk.LevelBar:inverted` — grow from the far end. */
|
|
131
|
+
get inverted(): boolean {
|
|
132
|
+
return this.hasAttribute('inverted');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
set inverted(v: boolean) {
|
|
136
|
+
this.toggleAttribute('inverted', !!v);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** `GtkOrientable:orientation` (gtklevelbar.c:825-835). Horizontal fills rightwards. */
|
|
140
|
+
get orientation(): BoxOrientation {
|
|
141
|
+
return normalizeBoxOrientation(this.getAttribute('orientation'));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
set orientation(v: BoxOrientation) {
|
|
145
|
+
this._write('orientation', v);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* `setAttribute` runs the custom-element reaction for a write that changes nothing,
|
|
150
|
+
* while every GObject setter here returns early when the value is already right
|
|
151
|
+
* (gtklevelbar.c:1186-1187, :1224-1225, :1300-1301, :1260-1261). This is the guard
|
|
152
|
+
* that makes "notify only on a real change" true for the numeric and enum half.
|
|
153
|
+
*/
|
|
154
|
+
private _write(name: string, value: string): void {
|
|
155
|
+
if (this.getAttribute(name) !== value) this.setAttribute(name, value);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
get disabled(): boolean {
|
|
159
|
+
return this.hasAttribute('disabled');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
set disabled(v: boolean) {
|
|
163
|
+
this.toggleAttribute('disabled', !!v);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* `gtk_level_bar_add_offset_value` (gtklevelbar.c:1395-1411): replaces the value of
|
|
168
|
+
* an offset of the same name, keeps the list sorted, refuses a value outside the
|
|
169
|
+
* interval (`g_return_if_fail (gtk_level_bar_value_in_interval (…))`, :1403), and
|
|
170
|
+
* emits `offset-changed` — but only when the value actually moved (:259-260).
|
|
171
|
+
*/
|
|
172
|
+
addOffsetValue(name: string, value: number): void {
|
|
173
|
+
if (value < this.minValue || value > this.maxValue) return;
|
|
174
|
+
const existing = this._offsets.findIndex(([key]) => key === name);
|
|
175
|
+
if (existing !== -1 && this._offsets[existing][1] === value) return;
|
|
176
|
+
if (existing !== -1) this._offsets.splice(existing, 1);
|
|
177
|
+
this._offsets.push([name, value]);
|
|
178
|
+
this._offsets.sort((a, b) => a[1] - b[1]);
|
|
179
|
+
this._render();
|
|
180
|
+
this.dispatchEvent(new CustomEvent('offset-changed', { bubbles: true, detail: { name } }));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** `gtk_level_bar_remove_offset_value` (gtklevelbar.c:1362-1377). */
|
|
184
|
+
removeOffsetValue(name: string): void {
|
|
185
|
+
const existing = this._offsets.findIndex(([key]) => key === name);
|
|
186
|
+
if (existing === -1) return;
|
|
187
|
+
this._offsets.splice(existing, 1);
|
|
188
|
+
this._render();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** `gtk_level_bar_get_offset_value` (gtklevelbar.c:1423-1443) — `null` when absent. */
|
|
192
|
+
offsetValue(name: string): number | null {
|
|
193
|
+
return this._offsets.find(([key]) => key === name)?.[1] ?? null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
connectedCallback() {
|
|
197
|
+
if (this._initialized) {
|
|
198
|
+
this._render();
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
this._initialized = true;
|
|
202
|
+
|
|
203
|
+
this._trough = document.createElement('span');
|
|
204
|
+
this._trough.className = 'adw-level-bar-trough';
|
|
205
|
+
this.replaceChildren(this._trough);
|
|
206
|
+
|
|
207
|
+
this.setAttribute('role', 'meter');
|
|
208
|
+
this._render();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
attributeChangedCallback(name: string) {
|
|
212
|
+
if (!this._initialized || name === 'disabled') return;
|
|
213
|
+
// A NEW interval endpoint drags the value with it (gtklevelbar.c:1191-1192,
|
|
214
|
+
// :1229-1230); writing the clamped value back re-enters here as a `value` change,
|
|
215
|
+
// so the value notifies first and the endpoint second — the C's order, where
|
|
216
|
+
// `set_value_internal` runs before the endpoint's own `g_object_notify_by_pspec`
|
|
217
|
+
// (:1164 before :1204, :1243). `set_max_value` clamps the OFFSETS as well, and on
|
|
218
|
+
// both paths.
|
|
219
|
+
if (name === 'min-value' && this.value < this.minValue) {
|
|
220
|
+
this._write('value', String(this.minValue));
|
|
221
|
+
this._notify(name);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (name === 'max-value') {
|
|
225
|
+
this._clampOffsets();
|
|
226
|
+
if (this.value > this.maxValue) {
|
|
227
|
+
this._write('value', String(this.maxValue));
|
|
228
|
+
this._notify(name);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
this._render();
|
|
233
|
+
this._notify(name);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private _notify(name: string): void {
|
|
237
|
+
this.dispatchEvent(
|
|
238
|
+
new CustomEvent(`notify::${name}`, { bubbles: true, detail: { [name]: this._property(name) } }),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** One interval endpoint CLAMPS every offset into the new range — the other does not. */
|
|
243
|
+
private _clampOffsets(): void {
|
|
244
|
+
for (let i = 0; i < this._offsets.length; i++) {
|
|
245
|
+
const [name, value] = this._offsets[i];
|
|
246
|
+
if (value < this.minValue) this._offsets[i] = [name, this.minValue];
|
|
247
|
+
else if (value > this.maxValue) this._offsets[i] = [name, this.maxValue];
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** The `notify::` detail for `name`: the PROPERTY, parsed, not the raw attribute. */
|
|
252
|
+
private _property(name: string): string | number | boolean {
|
|
253
|
+
switch (name) {
|
|
254
|
+
case 'value':
|
|
255
|
+
return this.value;
|
|
256
|
+
case 'min-value':
|
|
257
|
+
return this.minValue;
|
|
258
|
+
case 'max-value':
|
|
259
|
+
return this.maxValue;
|
|
260
|
+
case 'mode':
|
|
261
|
+
return this.mode;
|
|
262
|
+
case 'inverted':
|
|
263
|
+
return this.inverted;
|
|
264
|
+
default:
|
|
265
|
+
return this.orientation;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private _render(): void {
|
|
270
|
+
if (!this._trough) return;
|
|
271
|
+
const discrete = this.mode === 'discrete';
|
|
272
|
+
const vertical = this.orientation === 'vertical';
|
|
273
|
+
// `update_mode_style_classes` puts exactly one of the two on the node
|
|
274
|
+
// (gtklevelbar.c:574-590), and libadwaita's `levelbar.horizontal` /
|
|
275
|
+
// `levelbar.vertical` selectors are what read them.
|
|
276
|
+
this.classList.toggle('continuous', !discrete);
|
|
277
|
+
this.classList.toggle('discrete', discrete);
|
|
278
|
+
this.classList.toggle('vertical', vertical);
|
|
279
|
+
this.classList.toggle('horizontal', !vertical);
|
|
280
|
+
|
|
281
|
+
const min = this.minValue;
|
|
282
|
+
const max = this.maxValue;
|
|
283
|
+
const value = this.value;
|
|
284
|
+
// `gtk_level_bar_get_num_blocks` (gtklevelbar.c:285-294) — the node count is one
|
|
285
|
+
// MORE than the block count in continuous mode: the empty level is its own node.
|
|
286
|
+
const blocks = discrete ? Math.max(1, Math.round(max) - Math.round(min)) : 1;
|
|
287
|
+
const level = levelClassFor(this._offsets, value);
|
|
288
|
+
|
|
289
|
+
this._trough.replaceChildren();
|
|
290
|
+
if (!discrete) {
|
|
291
|
+
// The empty level is allocated full size and the filled one painted over it
|
|
292
|
+
// (gtklevelbar.c:344-362); at value 0 the filled node is never allocated at
|
|
293
|
+
// all (:429-430), which is what `hidden` stands for here.
|
|
294
|
+
const empty = this._block('empty', null);
|
|
295
|
+
const filled = this._block('filled', level);
|
|
296
|
+
filled.style.setProperty('--level-fraction', String(max > min ? (value - min) / (max - min) : 0));
|
|
297
|
+
filled.hidden = value === 0;
|
|
298
|
+
this._trough.append(empty, filled);
|
|
299
|
+
} else {
|
|
300
|
+
const count = Math.min(blocks, Math.max(0, Math.round(value) - Math.round(min)));
|
|
301
|
+
for (let i = 0; i < blocks; i++) {
|
|
302
|
+
// `inverted` fills from the far end by reversing the INDEX, so the first
|
|
303
|
+
// DOM block is filled last (gtklevelbar.c:637, 648).
|
|
304
|
+
const isFilled = this.inverted ? i >= blocks - count : i < count;
|
|
305
|
+
this._trough.append(this._block(isFilled ? 'filled' : 'empty', isFilled ? level : null));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
this.setAttribute('aria-valuemin', String(min));
|
|
310
|
+
this.setAttribute('aria-valuemax', String(max));
|
|
311
|
+
this.setAttribute('aria-valuenow', String(value));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** One `block` node, `filled` or `empty`, wearing the offset's class (:635-652). */
|
|
315
|
+
private _block(state: 'filled' | 'empty', level: string | null): HTMLSpanElement {
|
|
316
|
+
const block = document.createElement('span');
|
|
317
|
+
block.className = `adw-level-bar-block ${state}`;
|
|
318
|
+
if (state === 'filled' && level) block.classList.add(level);
|
|
319
|
+
return block;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
customElements.define('gtk-level-bar', GtkLevelBar);
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// <gtk-link-button> — a button that follows a URI. `Gtk.LinkButton` IS a `Gtk.Button`
|
|
2
|
+
// with two properties of its own, so this element extends `<gtk-button>` and inherits
|
|
3
|
+
// its label, icon, child and style-class attributes unchanged; `uri` and `visited` are
|
|
4
|
+
// the whole of the addition.
|
|
5
|
+
//
|
|
6
|
+
// `visited` is the state a browser already knows: once a link has been followed it is
|
|
7
|
+
// drawn in the visited colour and announces as visited. GTK reaches that through two
|
|
8
|
+
// state flags — `GTK_STATE_FLAG_LINK` when unvisited, `GTK_STATE_FLAG_VISITED` when
|
|
9
|
+
// visited (gtklinkbutton.c:359, 742-749) — and here it is one `.visited` class on the
|
|
10
|
+
// inner button, because the stylesheet has to be able to select on it.
|
|
11
|
+
//
|
|
12
|
+
// THE ORDER OF TWO OPERATIONS IS GTK'S, not ours. `gtk_link_button_set_uri()` ends with
|
|
13
|
+
// `gtk_link_button_set_visited (link_button, FALSE)` (gtklinkbutton.c:695): pointing the
|
|
14
|
+
// button somewhere else un-visits it, because the new target has not been seen. And
|
|
15
|
+
// `gtk_link_button_activate_link()` — the DEFAULT handler of `::activate-link` — sets it
|
|
16
|
+
// visited AFTER handing the URI to the launcher (:550). The state follows the click.
|
|
17
|
+
//
|
|
18
|
+
// `::activate-link` is a BOOLEAN-ACCUMULATOR signal: a handler returning TRUE stops the
|
|
19
|
+
// default handler from running (gtklinkbutton.c:216-238). The DOM spelling of "return
|
|
20
|
+
// TRUE" is `preventDefault()` on a cancelable event, so `activate-link` is dispatched
|
|
21
|
+
// cancelable and the launch happens only when nothing cancelled it.
|
|
22
|
+
//
|
|
23
|
+
// WHAT THE LAUNCH IS HERE. GTK hands the URI to the desktop's handler
|
|
24
|
+
// (`GtkUriLauncher`, gtklinkbutton.c:528-548), which opens it in ANOTHER application and
|
|
25
|
+
// leaves the button's window standing. The browser's equivalent of "another
|
|
26
|
+
// application" is another tab, so the URI goes to `window.open(uri, '_blank',
|
|
27
|
+
// 'noopener')` — deliberately not `location.assign`, which would tear the page down the
|
|
28
|
+
// way a desktop does not.
|
|
29
|
+
//
|
|
30
|
+
// NOT PORTED, and it is not a property: the CONTEXT MENU. `GtkLinkButton` installs
|
|
31
|
+
// `clipboard.copy` and `menu.popup` actions and binds Shift+F10 / Menu to them
|
|
32
|
+
// (gtklinkbutton.c:247-264), opening a `GtkPopoverMenu` with one entry. A browser
|
|
33
|
+
// already owns the context menu on a button, and taking it over would remove the
|
|
34
|
+
// platform's menu from every link on the page — so `::activate-link` is the whole of
|
|
35
|
+
// the activation surface here.
|
|
36
|
+
//
|
|
37
|
+
// A11Y: GTK's role is LINK (gtklinkbutton.c:244). A native `<button>` keeps the button
|
|
38
|
+
// role — a `<button role="link">` would stop being announced as pressable — and the URI
|
|
39
|
+
// rides along in the tooltip exactly as `gtk_link_button_query_tooltip_cb` puts it there
|
|
40
|
+
// when the button has no tooltip of its own and its label is not already the URI
|
|
41
|
+
// (:646-672).
|
|
42
|
+
//
|
|
43
|
+
// Reference: refs/gtk/gtk/gtklinkbutton.c (uri, visited, activate-link, the tooltip)
|
|
44
|
+
// Reference: refs/libadwaita/src/stylesheet/widgets/_links.scss (`button.link`)
|
|
45
|
+
// Copyright (c) GNOME contributors (libadwaita). LGPLv2.1+.
|
|
46
|
+
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
47
|
+
|
|
48
|
+
import { GtkButton } from './gtk-button.js';
|
|
49
|
+
|
|
50
|
+
export class GtkLinkButton extends GtkButton {
|
|
51
|
+
private _wired = false;
|
|
52
|
+
|
|
53
|
+
static get observedAttributes() {
|
|
54
|
+
return [...GtkButton.observedAttributes, 'uri', 'visited'];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** `Gtk.LinkButton:uri` — the address this button points at. */
|
|
58
|
+
get uri(): string {
|
|
59
|
+
return this.getAttribute('uri') ?? '';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
set uri(value: string) {
|
|
63
|
+
this.setAttribute('uri', value);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `Gtk.LinkButton:visited` — whether the link has been followed. The state flag
|
|
68
|
+
* GTK swaps here is what the stylesheet paints as `:visited`, and the `VISITED`
|
|
69
|
+
* accessibility state beside it; see the header.
|
|
70
|
+
*/
|
|
71
|
+
get visited(): boolean {
|
|
72
|
+
return this.hasAttribute('visited');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
set visited(value: boolean) {
|
|
76
|
+
this.toggleAttribute('visited', !!value);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
connectedCallback() {
|
|
80
|
+
super.connectedCallback();
|
|
81
|
+
if (this._wired) return;
|
|
82
|
+
this._wired = true;
|
|
83
|
+
this.button.addEventListener('click', () => this._activateLink());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Optional because `GtkButton`'s own callback declares no parameter, and an override
|
|
87
|
+
// may not demand one the base signature does not pass.
|
|
88
|
+
attributeChangedCallback(name?: string) {
|
|
89
|
+
// A new destination has not been seen: `gtk_link_button_set_uri()` unsets
|
|
90
|
+
// `visited` itself (gtklinkbutton.c:695), and only for `uri` — writing `visited`
|
|
91
|
+
// directly is the author's own state change and has to survive.
|
|
92
|
+
if (name === 'uri' && this.isConnected) this.visited = false;
|
|
93
|
+
super.attributeChangedCallback();
|
|
94
|
+
if (name === 'visited' && this.isConnected) {
|
|
95
|
+
this.dispatchEvent(
|
|
96
|
+
new CustomEvent('notify::visited', { bubbles: true, detail: { visited: this.visited } }),
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* `::activate-link` — cancelable, because the signal is a boolean accumulator
|
|
103
|
+
* (gtklinkbutton.c:216-238) and `preventDefault()` is the DOM spelling of a handler
|
|
104
|
+
* returning TRUE. Nothing cancelled ⇒ the default handler runs.
|
|
105
|
+
*/
|
|
106
|
+
private _activateLink(): void {
|
|
107
|
+
const event = new CustomEvent('activate-link', { bubbles: true, cancelable: true });
|
|
108
|
+
this.dispatchEvent(event);
|
|
109
|
+
if (event.defaultPrevented) return;
|
|
110
|
+
const { uri } = this;
|
|
111
|
+
// `gtk_link_button_new()` requires a URI (`g_return_val_if_fail (uri != NULL)`),
|
|
112
|
+
// so a button without one is half-written and there is nothing to launch.
|
|
113
|
+
if (uri === '') return;
|
|
114
|
+
this.launch(uri);
|
|
115
|
+
this.visited = true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The launcher call, on its own method so a caller (or a spec) can stand in for the
|
|
120
|
+
* window the desktop would have opened.
|
|
121
|
+
*/
|
|
122
|
+
protected launch(uri: string): void {
|
|
123
|
+
window.open(uri, '_blank', 'noopener');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
protected override decorate(button: HTMLButtonElement): void {
|
|
127
|
+
button.classList.add('link');
|
|
128
|
+
button.classList.toggle('visited', this.visited);
|
|
129
|
+
const label = (this.getAttribute('label') ?? '').trim();
|
|
130
|
+
const tooltip = this.getAttribute('tooltip') ?? this.getAttribute('tooltip-text');
|
|
131
|
+
// `query_tooltip_cb` shows the URI only when the label would not repeat it.
|
|
132
|
+
if (tooltip === null && label !== '' && this.uri !== '' && this.uri !== label) {
|
|
133
|
+
button.title = this.uri;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
customElements.define('gtk-link-button', GtkLinkButton);
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// <gtk-list-box-row> — one row of a `Gtk.ListBox`: the `activatable` / `selectable` pair and
|
|
2
|
+
// the child that fills it, the web counterpart of `Gtk.ListBoxRow`.
|
|
3
|
+
//
|
|
4
|
+
// BOTH PROPERTIES DEFAULT TRUE (gtklistbox.c:3961-3962), so on this element they are INVERTED
|
|
5
|
+
// flags and the attribute is read as `activatable="false"` — the same convention
|
|
6
|
+
// `<gtk-tree-expander>` uses for `indent-for-depth`, and for the same reason: a bare
|
|
7
|
+
// `activatable` on an element whose GIR default is TRUE would mean the opposite of what it
|
|
8
|
+
// reads like. The alternative — a present-means-true attribute — cannot express "true", which
|
|
9
|
+
// is the DEFAULT case and therefore the common one.
|
|
10
|
+
//
|
|
11
|
+
// THE `.activatable` CLASS IS NOT `activatable`. `gtk_list_box_update_row`
|
|
12
|
+
// (gtklistbox.c:3600-3624) sets it when the row is activatable OR when it is selectable and
|
|
13
|
+
// the BOX is not in `GTK_SELECTION_NONE`, and removes it otherwise. So a row in a
|
|
14
|
+
// `selection-mode="none"` box with `activatable="false"` carries no class, and the same row
|
|
15
|
+
// in a `selection-mode="single"` box does. The row therefore asks its parent, and the parent
|
|
16
|
+
// owns that answer for every row at once — which is what `<gtk-list-box>`'s `_syncRows`
|
|
17
|
+
// calls down into here for.
|
|
18
|
+
//
|
|
19
|
+
// `aria-selected` IS THE PARENT'S TOO, for the same C line: the accessible state is only
|
|
20
|
+
// published when `selectable && can_select`, so a row in a `none` box must NOT announce
|
|
21
|
+
// itself as unselected, and this element sets nothing of its own — `<gtk-list-box>` writes
|
|
22
|
+
// the attribute.
|
|
23
|
+
//
|
|
24
|
+
// ENTER AND SPACE ARE THE ROW'S, and the C says so twice: `attachRowActivation` is the
|
|
25
|
+
// module that makes a `GtkListBoxRow` a tab stop, and `gtk_list_box_row_class_init` installs
|
|
26
|
+
// the `activate` signal this row dispatches (gtklistbox.c:3905-3910).
|
|
27
|
+
//
|
|
28
|
+
// WHAT IS NOT HERE, and why: `action-name` / `action-target` are `g_param_spec_override`s of
|
|
29
|
+
// `GtkActionable` (gtklistbox.c:3946-3950), a `GAction` name and a `GVariant` target over a
|
|
30
|
+
// `GActionMap` — there is no map here to look a name up in, and a target is a value rather
|
|
31
|
+
// than a string. `get_index()` and `is_selected()` are METHODS over the box's children
|
|
32
|
+
// sequence and are answered from the DOM (`index`, `selected`), so a row moved by
|
|
33
|
+
// `insert_child_before` keeps reporting where it IS. The GIR puts `action-name` and
|
|
34
|
+
// `action-target` in the `GtkActionableProps` chain rather than in the row's own body, so
|
|
35
|
+
// `check-adwaita-element-properties` reads the row's OWN surface — which is exactly the two
|
|
36
|
+
// booleans this element observes, and neither has a gap entry.
|
|
37
|
+
//
|
|
38
|
+
// Reference: refs/gtk/gtk/gtklistbox.c:3307-3331 (child), :3594-3722 (activatable, selectable,
|
|
39
|
+
// the `.activatable` class and the accessible state), :3877-3966 (class init, the signal, the
|
|
40
|
+
// defaults and the css name)
|
|
41
|
+
// Reference: refs/libadwaita/src/stylesheet/widgets/_lists.scss:16-19, :47-95 (row)
|
|
42
|
+
// Copyright (c) GNOME contributors (GTK/libadwaita). LGPLv2.1+.
|
|
43
|
+
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
44
|
+
|
|
45
|
+
import { bindSlottedChildren } from '../slotted-children.js';
|
|
46
|
+
import { type AdwRowActivation, attachRowActivation } from './row-activation.js';
|
|
47
|
+
|
|
48
|
+
export class GtkListBoxRow extends HTMLElement {
|
|
49
|
+
private _contentsEl!: HTMLDivElement;
|
|
50
|
+
private _activation?: AdwRowActivation;
|
|
51
|
+
private _initialized = false;
|
|
52
|
+
|
|
53
|
+
static get observedAttributes() {
|
|
54
|
+
return ['activatable', 'selectable'];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* `GtkListBoxRow:activatable` — TRUE by default (gtklistbox.c:3961), so this is the OFF
|
|
59
|
+
* switch and the attribute is read as `activatable="false"`.
|
|
60
|
+
*/
|
|
61
|
+
get activatable(): boolean {
|
|
62
|
+
return this.getAttribute('activatable') !== 'false';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
set activatable(value: boolean) {
|
|
66
|
+
this.setAttribute('activatable', String(!!value));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* `GtkListBoxRow:selectable` — TRUE by default (gtklistbox.c:3962), read the same way as
|
|
71
|
+
* `activatable`.
|
|
72
|
+
*/
|
|
73
|
+
get selectable(): boolean {
|
|
74
|
+
return this.getAttribute('selectable') !== 'false';
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
set selectable(value: boolean) {
|
|
78
|
+
this.setAttribute('selectable', String(!!value));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Where this row sits in its box, or -1 while it has no box. */
|
|
82
|
+
get index(): number {
|
|
83
|
+
return this.parentElement ? [...this.parentElement.children].indexOf(this) : -1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Whether this row is selected — `gtk_list_box_row_is_selected`, answered by the parent so
|
|
88
|
+
* a row moved between boxes never carries a stale answer.
|
|
89
|
+
*/
|
|
90
|
+
get selected(): boolean {
|
|
91
|
+
return this.classList.contains('selected');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** `GtkListBoxRow:child`, as the light-DOM child it already is. */
|
|
95
|
+
get child(): Element | null {
|
|
96
|
+
return this._contentsEl.firstElementChild;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
connectedCallback() {
|
|
100
|
+
if (this._initialized) {
|
|
101
|
+
// Re-entering a document: nothing here is torn down, so only the parent's derived
|
|
102
|
+
// state needs re-asking, and it re-asks on its own child list change.
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this._initialized = true;
|
|
106
|
+
|
|
107
|
+
this._contentsEl = document.createElement('div');
|
|
108
|
+
this._contentsEl.className = 'adw-list-box-row-contents';
|
|
109
|
+
|
|
110
|
+
// `child` is a WIDGET property, so it is a slot here (gtklistbox.c:3307-3331): the
|
|
111
|
+
// authored child lands in the same node `gtk_list_box_row_set_child` would put it in,
|
|
112
|
+
// and a child appended after connect lands there too.
|
|
113
|
+
bindSlottedChildren(this, [{ into: this._contentsEl }]).install(this._contentsEl);
|
|
114
|
+
|
|
115
|
+
// GTK declares the accessible role unconditionally (gtklistbox.c:3955), so there is
|
|
116
|
+
// no `selection-mode` to condition it on here.
|
|
117
|
+
this.setAttribute('role', 'listitem');
|
|
118
|
+
// `gtk_list_box_row_init` adds `.activatable` and makes the row focusable BEFORE any
|
|
119
|
+
// box exists (gtklistbox.c:3959-3966), because both properties default TRUE — so the
|
|
120
|
+
// class is already right for a row nobody has adopted yet, and it is the tab stop. The
|
|
121
|
+
// box NARROWS it in `syncClasses`, which is where `can_select` enters — and it also
|
|
122
|
+
// takes the tab stop over, see {@link claim}.
|
|
123
|
+
//
|
|
124
|
+
// A custom element's connect reactions are enqueued PARENT FIRST, so a row inside a
|
|
125
|
+
// box reaches this line AFTER `<gtk-list-box>` has already answered for it, with
|
|
126
|
+
// `can_select` already answered from `selection-mode`. Deriving the pre-adoption
|
|
127
|
+
// answer here would put back what the box just removed: `.activatable` on every row
|
|
128
|
+
// of a `selection-mode="none"` box, and — because `syncClasses` also re-derives the
|
|
129
|
+
// tab stop — every row back in the Tab order under `tab-behavior`, which is the
|
|
130
|
+
// measured defect `gtk-list-box.spec.ts`'s tab-behavior block exists to catch.
|
|
131
|
+
if (this._claimed) this._syncActivation();
|
|
132
|
+
else this.syncClasses(true);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Hand this row's `.activatable` class and tab stop to its box.
|
|
137
|
+
*
|
|
138
|
+
* Both are the box's to derive and neither is derivable here: `can_select` is the BOX's
|
|
139
|
+
* `selection-mode` (gtklistbox.c:3606-3609) and the tab stop is `GtkListBox:tab-behavior`,
|
|
140
|
+
* where `all` gives every activatable row its own stop and `item`/`cell` hand out a
|
|
141
|
+
* roving one — the split `gtk_list_box_focus` draws by walking rows between Tab presses
|
|
142
|
+
* only under `GTK_LIST_TAB_ALL` (gtklistbox.c:2037, :2067). The keys stay the row's:
|
|
143
|
+
* Enter and Space are `GtkListBoxRow`'s own (see `row-activation.ts`).
|
|
144
|
+
*/
|
|
145
|
+
claim(): void {
|
|
146
|
+
this._claimed = true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Give the row back to itself, for a box that no longer manages it. */
|
|
150
|
+
release(): void {
|
|
151
|
+
this._claimed = false;
|
|
152
|
+
// `gtk_list_box_update_row (NULL, row)` answers `can_select = FALSE` (gtklistbox.c:3606-3609),
|
|
153
|
+
// so what is left is the row's own `activatable` flag.
|
|
154
|
+
this.syncClasses(false);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** What the box last said about itself; TRUE until a box narrows it. */
|
|
158
|
+
private _canSelect = true;
|
|
159
|
+
|
|
160
|
+
/** Set by {@link claim}. While it is set the row derives neither class nor tab stop. */
|
|
161
|
+
private _claimed = false;
|
|
162
|
+
|
|
163
|
+
attributeChangedCallback() {
|
|
164
|
+
if (!this._initialized) return;
|
|
165
|
+
// Both flags feed the class, so a write to either re-derives it against the box's LAST
|
|
166
|
+
// answer — not against a fresh default, which would resurrect the class on a row whose
|
|
167
|
+
// box has `selection-mode="none"`.
|
|
168
|
+
this.syncClasses(this._canSelect);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Re-derive the tab stop and the `.activatable` class.
|
|
173
|
+
*
|
|
174
|
+
* Public because the box owns the second half of the class rule — it knows
|
|
175
|
+
* `selection-mode`, this row does not — and calls this for every row when that changes.
|
|
176
|
+
*/
|
|
177
|
+
syncClasses(canSelect: boolean): void {
|
|
178
|
+
this._canSelect = canSelect;
|
|
179
|
+
// `gtk_list_box_update_row` :3611-3615.
|
|
180
|
+
this.classList.toggle('activatable', this.activatable || (this.selectable && canSelect));
|
|
181
|
+
this._syncActivation();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private _syncActivation(): void {
|
|
185
|
+
this._activation ??= attachRowActivation({
|
|
186
|
+
row: this,
|
|
187
|
+
activatable: () => this.classList.contains('activatable'),
|
|
188
|
+
activate: () => this.dispatchEvent(new CustomEvent('activate', { bubbles: true })),
|
|
189
|
+
});
|
|
190
|
+
// The KEYS are installed either way; only the tab stop belongs to a claimed row.
|
|
191
|
+
if (!this._claimed) this._activation.sync();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
customElements.define('gtk-list-box-row', GtkListBoxRow);
|