@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,423 @@
|
|
|
1
|
+
// <gtk-video> — a playing surface with a play affordance and a controls bar, and NOTHING
|
|
2
|
+
// else. It owns no decoding, no pipeline and no transport of its own: `GtkVideo` is a
|
|
3
|
+
// `GtkWidget` with a `GtkMediaStream` on it and a three-node template over it
|
|
4
|
+
// (refs/gtk/gtk/ui/gtkvideo.ui), and every question of "what is playing" is answered by
|
|
5
|
+
// the stream.
|
|
6
|
+
//
|
|
7
|
+
// THE REPLICA IS A REAL `<video>`, AND SAYING SO IS THE POINT. GTK's `GtkMediaStream` is
|
|
8
|
+
// an abstract playback backend; the browser already ships one, and `<video>` is it. So the
|
|
9
|
+
// element takes a `<video>` as its light-DOM child, applies `autoplay` and `loop` to it as
|
|
10
|
+
// the two PROPERTIES are declared (gtkpicture's sibling `gtkvideo.c:407-414`, :432-439),
|
|
11
|
+
// and reflects its events back out. What it does NOT do is reimplement a transport: there
|
|
12
|
+
// is no buffering state model, no seek-pending flag, no `GstPipeline`, because the C has
|
|
13
|
+
// none either — those live in the backend behind `GtkMediaStream`, not in the widget.
|
|
14
|
+
//
|
|
15
|
+
// `autoplay` WAITS FOR PREPARED, WHICH IS A REAL DIFFERENCE FROM THE ATTRIBUTE. The C does
|
|
16
|
+
// not play on `set_autoplay`; it plays when the stream reports `prepared` AND the widget is
|
|
17
|
+
// mapped, and it re-checks that on every `prepared` notification
|
|
18
|
+
// (gtkvideo.c:684-690, `gtk_video_notify_cb`). Setting `autoplay` on a `<video>` element
|
|
19
|
+
// before its `src` is known therefore plays nothing, and setting it after `src` plays —
|
|
20
|
+
// the same order-dependence the C has, arrived at honestly, so the attribute is applied as
|
|
21
|
+
// the C applies it: the property is stored, and `play()` is called on the media's own
|
|
22
|
+
// readiness, never on the write.
|
|
23
|
+
//
|
|
24
|
+
// THE OVERLAY ICON IS A FOUR-WAY CHOICE AND THE ORDER IS THE POINT.
|
|
25
|
+
// `gtk_video_update_overlay_icon` (gtkvideo.c:626-646) picks in this order: no stream at
|
|
26
|
+
// all → `media-eject-symbolic`; a stream with an ERROR → `dialog-error-symbolic`; a stream
|
|
27
|
+
// that ENDED → `media-playlist-repeat-symbolic`; otherwise → `media-playback-start-symbolic`.
|
|
28
|
+
// No media stream is the FIRST arm and not the last, so an element that has not been given
|
|
29
|
+
// a `<video>` draws the eject glyph — the shape of "there is nothing here to play" — rather
|
|
30
|
+
// than a play glyph over nothing. `error` before `ended` matters too: a stream that both
|
|
31
|
+
// ended and failed shows the error.
|
|
32
|
+
//
|
|
33
|
+
// THE OVERLAY IS HIDDEN WHILE PLAYING, NOT SWAPPED. `gtk_video_update_playing` sets the
|
|
34
|
+
// overlay's VISIBILITY to `!playing` (gtkvideo.c:665) and restores the cursor at the same
|
|
35
|
+
// time. There is no pause icon in the overlay: a video that is playing shows the frames and
|
|
36
|
+
// nothing on top of them, and the controls bar is what carries the pause button. That is
|
|
37
|
+
// why this element has one overlay node and no per-state icon table of its own.
|
|
38
|
+
//
|
|
39
|
+
// THE CONTROLS REVEAL AND HIDE ON A TIMER. `gtk_video_reveal_controls` reveals the
|
|
40
|
+
// revealer and arms a 3-second timeout that hides it again (gtkvideo.c:125-133), and the
|
|
41
|
+
// motion controller calls it (gtkvideo.c:177-178). So the controls are shown on pointer
|
|
42
|
+
// movement and withdrawn three seconds after the last movement, and the SAME
|
|
43
|
+
// `revealControls()` is what a click on the video calls. `CONTROLS_HIDE_MS` is that 3000.
|
|
44
|
+
//
|
|
45
|
+
// `graphics-offload` IS A RENDERING HINT AND IS HONOURED AS ONE. `GtkGraphicsOffload` moves
|
|
46
|
+
// the child into a shared GL texture so a widget and its neighbours composite on the GPU;
|
|
47
|
+
// its `enabled` property is what `GtkVideo:graphics-offload` reads and writes
|
|
48
|
+
// (gtkvideo.c:988-992, :1010-1023). CSS has no equivalent — there is no compositor to move a
|
|
49
|
+
// subtree into — so the property is stored, readable and writable, and surfaced as a class,
|
|
50
|
+
// and NOTHING ELSE HAPPENS. That is declared rather than hidden: see `_video.scss`'s header.
|
|
51
|
+
//
|
|
52
|
+
// THE TEMPLATE'S THREE OVERLAY NODES ARE ALL PRESENT. `ui/gtkvideo.ui` puts an overlay
|
|
53
|
+
// icon, a `controls_revealer` and (implicitly, as the main child) the picture, inside a
|
|
54
|
+
// `GtkOverlay`. The overlay icon wears `.osd` AND `.circular`, and libadwaita gives
|
|
55
|
+
// `video image.osd` a 64px box with a 32px radius
|
|
56
|
+
// (refs/libadwaita/src/stylesheet/widgets/_misc.scss:75-81) — which is exactly what a
|
|
57
|
+
// `.circular` button already is at 34px, so the 64/32 pair is the video's own larger
|
|
58
|
+
// version of it and is stated in the stylesheet rather than invented here.
|
|
59
|
+
//
|
|
60
|
+
// Reference: refs/gtk/gtk/gtkvideo.c (the overlay-icon four-way choice :626-646,
|
|
61
|
+
// `update_playing` hiding it :658-666, the autoplay-on-prepared check :679-690,
|
|
62
|
+
// `gtk_video_reveal_controls` :125-133, the property table :400-445,
|
|
63
|
+
// `graphics-offload` :976-1023)
|
|
64
|
+
// Reference: refs/gtk/gtk/ui/gtkvideo.ui (the three-node overlay template)
|
|
65
|
+
// Reference: refs/libadwaita/src/stylesheet/widgets/_misc.scss:74-81 (the 64/32 osd icon)
|
|
66
|
+
// Copyright (c) The GTK Team. LGPLv2.1+.
|
|
67
|
+
// Modifications: Implemented as a Web Component for @gjsify/adwaita-web.
|
|
68
|
+
|
|
69
|
+
/** The four overlay glyphs, in the order `update_overlay_icon` tests them (gtkvideo.c:626-646). */
|
|
70
|
+
export type VideoOverlayIcon =
|
|
71
|
+
| 'media-eject-symbolic'
|
|
72
|
+
| 'dialog-error-symbolic'
|
|
73
|
+
| 'media-playlist-repeat-symbolic'
|
|
74
|
+
| 'media-playback-start-symbolic';
|
|
75
|
+
|
|
76
|
+
// FOUR CONSTANTS, NOT ONE TABLE, and not with a type annotation on the declaration. Both
|
|
77
|
+
// are load-bearing: `check-adwaita-icon-masks.mjs` finds an emitted icon name with a regex
|
|
78
|
+
// for a SCREAMING_SNAKE identifier ending in `ICON` or `ICON_NAME` whose `=` is followed by
|
|
79
|
+
// a plain string literal. A `const X: Type = '…'` puts a `: Type` between the name and the
|
|
80
|
+
// `=` and is invisible to it; so is one member of an array of literals. Either way the
|
|
81
|
+
// check's second arm reports ICONS entries nothing emits, while all four are emitted.
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The glyph a video with NO stream draws — the FIRST arm of the four-way choice
|
|
85
|
+
* (gtkvideo.c:629), because "there is nothing here to play" is the state every GtkVideo
|
|
86
|
+
* starts in.
|
|
87
|
+
*/
|
|
88
|
+
export const NO_STREAM_ICON = 'media-eject-symbolic';
|
|
89
|
+
|
|
90
|
+
/** The glyph a stream that FAILED draws (gtkvideo.c:633) — tested before `ended`. */
|
|
91
|
+
export const ERROR_ICON = 'dialog-error-symbolic';
|
|
92
|
+
|
|
93
|
+
/** The glyph a stream that has ENDED draws (gtkvideo.c:638-639). */
|
|
94
|
+
export const ENDED_ICON = 'media-playlist-repeat-symbolic';
|
|
95
|
+
|
|
96
|
+
/** The glyph a READY stream draws (gtkvideo.c:645) — the arm everything else falls through to. */
|
|
97
|
+
export const READY_ICON = 'media-playback-start-symbolic';
|
|
98
|
+
|
|
99
|
+
/** `gtk_video_reveal_controls`' timeout: 3 s (gtkvideo.c:130). */
|
|
100
|
+
export const CONTROLS_HIDE_MS = 3000;
|
|
101
|
+
|
|
102
|
+
export class GtkVideo extends HTMLElement {
|
|
103
|
+
private _initialized = false;
|
|
104
|
+
private _overlayIcon!: HTMLButtonElement;
|
|
105
|
+
private _controlsRevealer!: HTMLDivElement;
|
|
106
|
+
private _media: HTMLVideoElement | null = null;
|
|
107
|
+
/** The listeners currently bound on `_media`, so `_detachMedia` removes the SAME ones. */
|
|
108
|
+
private mediaListeners: [string, EventListener][] = [];
|
|
109
|
+
private _hideTimer: number | null = null;
|
|
110
|
+
/** What the media element last told us, in the four fields the overlay choice reads. */
|
|
111
|
+
private _hasStream = false;
|
|
112
|
+
private _error: string | null = null;
|
|
113
|
+
private _ended = false;
|
|
114
|
+
private _playing = false;
|
|
115
|
+
|
|
116
|
+
static get observedAttributes() {
|
|
117
|
+
return ['autoplay', 'graphics-offload', 'loop'];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* `GtkVideo:autoplay` (gtkvideo.c:407-414). Defaults to FALSE. The C plays on the
|
|
122
|
+
* stream's `prepared` notification and not on this write — see the header — so this
|
|
123
|
+
* setter records the flag and lets the media's own readiness decide.
|
|
124
|
+
*/
|
|
125
|
+
get autoplay(): boolean {
|
|
126
|
+
return this.hasAttribute('autoplay');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
set autoplay(value: boolean) {
|
|
130
|
+
this._write('autoplay', !!value);
|
|
131
|
+
this._syncMedia();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** `GtkVideo:loop` (gtkvideo.c:432-439). Defaults to FALSE. A plain `<video loop>`. */
|
|
135
|
+
get loop(): boolean {
|
|
136
|
+
return this.hasAttribute('loop');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
set loop(value: boolean) {
|
|
140
|
+
this._write('loop', !!value);
|
|
141
|
+
this._syncMedia();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* `GtkVideo:graphics-offload` (gtkvideo.c:400-406, :1010-1023). Defaults to FALSE — the
|
|
146
|
+
* template ships `<property name="enabled">disabled</property>` (ui/gtkvideo.ui), so the
|
|
147
|
+
* C starts with the offload OFF and an application has to ask for it.
|
|
148
|
+
*
|
|
149
|
+
* Stored, readable and class-flagged, and NOTHING ELSE HAPPENS: CSS has no way to move a
|
|
150
|
+
* subtree into a shared GPU texture, which is what `GtkGraphicsOffload` is. The class is
|
|
151
|
+
* `graphics-offload` so a page can still target it, and `KNOWN_GAPS` in
|
|
152
|
+
* `check-adwaita-element-properties.mjs` does not list it because the PROPERTY is
|
|
153
|
+
* observed — what it does not buy is a faster composite.
|
|
154
|
+
*/
|
|
155
|
+
get graphicsOffload(): boolean {
|
|
156
|
+
return this.hasAttribute('graphics-offload');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
set graphicsOffload(value: boolean) {
|
|
160
|
+
this._write('graphics-offload', !!value);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** The `<video>` this element drives — the browser's answer to a `GtkMediaStream`. */
|
|
164
|
+
get media(): HTMLVideoElement | null {
|
|
165
|
+
return this._media;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Whether the media reports itself playing — `GtkVideo:playing` (`gtk_video_get_playing`). */
|
|
169
|
+
get playing(): boolean {
|
|
170
|
+
return this._playing;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** The current position in SECONDS — the C's `timestamp`, in microseconds × 1000. */
|
|
174
|
+
get timestamp(): number {
|
|
175
|
+
return this._media?.currentTime ?? 0;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** The media's duration in SECONDS — the C's `duration`; 0 while it is unknown. */
|
|
179
|
+
get duration(): number {
|
|
180
|
+
const value = this._media?.duration ?? 0;
|
|
181
|
+
return Number.isFinite(value) ? value : 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Whether the overlay controls bar is currently revealed. */
|
|
185
|
+
get controlsRevealed(): boolean {
|
|
186
|
+
return this._controlsRevealer?.classList.contains('revealed') ?? false;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private _write(name: string, value: boolean): void {
|
|
190
|
+
this.toggleAttribute(name, value);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
connectedCallback() {
|
|
194
|
+
if (this._initialized) {
|
|
195
|
+
this._adoptMedia();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
this._initialized = true;
|
|
199
|
+
|
|
200
|
+
// `ui/gtkvideo.ui`'s overlay icon is a GtkImage wearing `.osd` and `.circular` with
|
|
201
|
+
// an accessible role of BUTTON (the gesture is what makes it a button). A `<button>`
|
|
202
|
+
// IS that role natively, which is the honest way to build it rather than a div with
|
|
203
|
+
// a click handler and an ARIA keyword.
|
|
204
|
+
this._overlayIcon = document.createElement('button');
|
|
205
|
+
this._overlayIcon.className = 'adw-video-overlay-icon osd circular';
|
|
206
|
+
this._overlayIcon.type = 'button';
|
|
207
|
+
this._overlayIcon.setAttribute('aria-label', 'Play');
|
|
208
|
+
this._overlayIcon.title = 'Play';
|
|
209
|
+
this._overlayIcon.addEventListener('click', () => this._overlayClicked());
|
|
210
|
+
|
|
211
|
+
this._controlsRevealer = document.createElement('div');
|
|
212
|
+
this._controlsRevealer.className = 'adw-video-controls-revealer';
|
|
213
|
+
|
|
214
|
+
this._wrap();
|
|
215
|
+
this._adoptMedia();
|
|
216
|
+
// `gtk_video_motion` (ui/gtkvideo.ui) — the motion controller's only job. Bound on
|
|
217
|
+
// the element rather than on the surface so a pointer anywhere over the video (the
|
|
218
|
+
// surface, the controls bar, the overlay icon) counts, which is what GTK's
|
|
219
|
+
// `GtkEventControllerMotion` on the template's root does.
|
|
220
|
+
this.addEventListener('pointermove', this._onPointerMove);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* `ui/gtkvideo.ui` keeps the author's `<video>` as the MAIN child of the overlay and adds
|
|
225
|
+
* the two overlay children around it. Wrapping in place rather than re-creating is what
|
|
226
|
+
* lets the light DOM stay the API: a page writes `<gtk-video><video src=…></video></gtk-video>`
|
|
227
|
+
* and the element never has to be told where the media is.
|
|
228
|
+
*/
|
|
229
|
+
private _wrap(): void {
|
|
230
|
+
const media = this.querySelector<HTMLVideoElement>(':scope > video');
|
|
231
|
+
// EVERY other light child is the CONTROLS, and the template says where they go:
|
|
232
|
+
// `ui/gtkvideo.ui`'s `controls_revealer` holds a `GtkMediaControls` as its child, and
|
|
233
|
+
// `revealed` is what reveals it. `replaceChildren` therefore cannot simply discard
|
|
234
|
+
// them — a bar dropped on the floor is a bar outside the document, which loses its
|
|
235
|
+
// stylesheet, its popover's own `connectedCallback`, and the `closest('gtk-video')` a
|
|
236
|
+
// `<gtk-media-controls>` reads its stream from. So they are moved, not dropped.
|
|
237
|
+
const controls = [...this.children].filter((child) => child !== media);
|
|
238
|
+
const surface = document.createElement('div');
|
|
239
|
+
surface.className = 'adw-video-surface';
|
|
240
|
+
this.replaceChildren(surface);
|
|
241
|
+
if (media) surface.appendChild(media);
|
|
242
|
+
surface.append(this._overlayIcon);
|
|
243
|
+
this._controlsRevealer.append(...controls);
|
|
244
|
+
surface.append(this._controlsRevealer);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private _adoptMedia(): void {
|
|
248
|
+
// Narrowed at the selector: `querySelector` answers `Element`, and the whole point of the
|
|
249
|
+
// media is that it has `play`, `paused` and `error`. `?? null` for the reason
|
|
250
|
+
// `<gtk-media-controls>`'s own `_adoptMedia` states: the no-stream arm of the four-way
|
|
251
|
+
// choice is compared against a field initialised to `null`, and an `undefined` there
|
|
252
|
+
// would read as a stream.
|
|
253
|
+
const media = this.querySelector<HTMLVideoElement>(':scope > .adw-video-surface > video') ?? null;
|
|
254
|
+
if (media === this._media) {
|
|
255
|
+
this._syncMedia();
|
|
256
|
+
// `gtk_video_set_media_stream` calls `gtk_video_update_all` (gtkvideo.c:761-763)
|
|
257
|
+
// on EVERY assignment, and a video with NO `<video>` child is the assignment of
|
|
258
|
+
// nothing — the same function, the same four arms, no stream. Returning early
|
|
259
|
+
// without this left the no-stream arm undrawn on the FIRST call, which is the only
|
|
260
|
+
// call a streamless `<gtk-video>` ever makes: the eject glyph is the state every
|
|
261
|
+
// GtkVideo starts in, and it has to be the state it STARTS in.
|
|
262
|
+
this._updateOverlayIcon();
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (this._media) this._detachMedia(this._media);
|
|
266
|
+
this._media = media;
|
|
267
|
+
// No stream is the FIRST arm of the four-way overlay choice (gtkvideo.c:629), so an
|
|
268
|
+
// element with no `<video>` child draws the eject glyph from the start rather than
|
|
269
|
+
// flashing a play glyph over nothing.
|
|
270
|
+
this._hasStream = media !== null;
|
|
271
|
+
if (media) {
|
|
272
|
+
const onPlay = () => this._updatePlaying(true);
|
|
273
|
+
const onPause = () => this._updatePlaying(false);
|
|
274
|
+
const onEnded = () => {
|
|
275
|
+
this._ended = true;
|
|
276
|
+
this._updateOverlayIcon();
|
|
277
|
+
};
|
|
278
|
+
const onError = () => {
|
|
279
|
+
this._error = media.error?.message ?? 'Playback failed';
|
|
280
|
+
this._updateOverlayIcon();
|
|
281
|
+
};
|
|
282
|
+
const onMetadata = () => {
|
|
283
|
+
// A stream that reports a NEW duration is no longer ended, exactly as
|
|
284
|
+
// `gtk_video_update_ended` re-reads the stream on every notification.
|
|
285
|
+
this._ended = false;
|
|
286
|
+
this._error = null;
|
|
287
|
+
this._updateOverlayIcon();
|
|
288
|
+
};
|
|
289
|
+
// `gtk_video_notify_cb`'s `prepared` arm (gtkvideo.c:679-690): autoplay plays
|
|
290
|
+
// here and NOT on the property write, so the flag and the readiness are two
|
|
291
|
+
// independent conditions and the C checks both.
|
|
292
|
+
const onPrepared = () => {
|
|
293
|
+
if (this.autoplay) void media.play().catch(() => {});
|
|
294
|
+
};
|
|
295
|
+
this.mediaListeners = [
|
|
296
|
+
['play', onPlay],
|
|
297
|
+
['pause', onPause],
|
|
298
|
+
['ended', onEnded],
|
|
299
|
+
['error', onError],
|
|
300
|
+
['loadedmetadata', onMetadata],
|
|
301
|
+
['loadeddata', onPrepared],
|
|
302
|
+
];
|
|
303
|
+
for (const [type, handler] of this.mediaListeners) media.addEventListener(type, handler);
|
|
304
|
+
}
|
|
305
|
+
this._syncMedia();
|
|
306
|
+
this._updateOverlayIcon();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private _detachMedia(media: HTMLVideoElement): void {
|
|
310
|
+
// The listeners are held rather than re-created per event: `_adoptMedia` runs on
|
|
311
|
+
// every reconnect and a `() => …` handler removed here would not be the same
|
|
312
|
+
// function the one added there bound, so a re-parented `<video>` would end up with
|
|
313
|
+
// two handlers per event and two `notify::playing` per play.
|
|
314
|
+
for (const [type, handler] of this.mediaListeners) media.removeEventListener(type, handler);
|
|
315
|
+
this.mediaListeners = [];
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/** `autoplay` and `loop` are declared PROPERTIES of the widget, so they are applied to
|
|
319
|
+
* the media rather than left to the author's markup — `ui/gtkvideo.ui` does the same by
|
|
320
|
+
* binding them on the template. */
|
|
321
|
+
private _syncMedia(): void {
|
|
322
|
+
if (!this._media) return;
|
|
323
|
+
this._media.loop = this.loop;
|
|
324
|
+
// The C's `autoplay` is NOT the element's autoplay attribute, so the media is
|
|
325
|
+
// never given one: a `preload`/autoplay element the author did not ask for is
|
|
326
|
+
// exactly the "plays when the stream becomes prepared" behaviour the C has, and the
|
|
327
|
+
// readiness gate is already on `loadeddata` above.
|
|
328
|
+
this._media.autoplay = false;
|
|
329
|
+
this.classList.toggle('graphics-offload', this.graphicsOffload);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
private _overlayClicked(): void {
|
|
333
|
+
// `overlay_clicked_cb` (ui/gtkvideo.ui) toggles: it plays when stopped and pauses
|
|
334
|
+
// when playing, which is the overlay's whole contract — it is only VISIBLE when
|
|
335
|
+
// stopped, so the pause branch is reachable only from the controls bar's own button.
|
|
336
|
+
const media = this._media ?? null;
|
|
337
|
+
if (media === null) return;
|
|
338
|
+
if (media.paused) void media.play().catch(() => {});
|
|
339
|
+
else media.pause();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* `gtk_video_reveal_controls` (gtkvideo.c:125-133): reveal, then arm a 3 s timeout that
|
|
344
|
+
* hides it again. Re-arming on every call is what makes it a "three seconds after the
|
|
345
|
+
* LAST movement" rather than a "three seconds after the first".
|
|
346
|
+
*/
|
|
347
|
+
revealControls(): void {
|
|
348
|
+
if (!this._controlsRevealer) return;
|
|
349
|
+
this._controlsRevealer.classList.add('revealed');
|
|
350
|
+
if (this._hideTimer !== null) clearTimeout(this._hideTimer);
|
|
351
|
+
this._hideTimer = setTimeout(() => this._hideControls(), CONTROLS_HIDE_MS) as unknown as number;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private _hideControls(): void {
|
|
355
|
+
this._hideTimer = null;
|
|
356
|
+
this._controlsRevealer?.classList.remove('revealed');
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/** `gtk_video_motion` (ui/gtkvideo.ui) — the motion controller's only job. */
|
|
360
|
+
private _onPointerMove = (): void => {
|
|
361
|
+
this.revealControls();
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
attributeChangedCallback(name: string) {
|
|
365
|
+
if (!this._initialized) return;
|
|
366
|
+
if (name === 'graphics-offload') this._syncMedia();
|
|
367
|
+
this.dispatchEvent(
|
|
368
|
+
new CustomEvent(`notify::${name}`, { bubbles: true, detail: { [name]: this._property(name) } }),
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** The `notify::` detail for `name`: the PROPERTY, parsed, not the raw attribute. */
|
|
373
|
+
private _property(name: string): boolean {
|
|
374
|
+
switch (name) {
|
|
375
|
+
case 'autoplay':
|
|
376
|
+
return this.autoplay;
|
|
377
|
+
case 'loop':
|
|
378
|
+
return this.loop;
|
|
379
|
+
default:
|
|
380
|
+
return this.graphicsOffload;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/** `gtk_video_update_playing` (gtkvideo.c:658-666) — VISIBILITY, not an icon swap. */
|
|
385
|
+
private _updatePlaying(playing: boolean): void {
|
|
386
|
+
this._playing = playing;
|
|
387
|
+
if (this._overlayIcon) this._overlayIcon.hidden = playing;
|
|
388
|
+
this.classList.toggle('playing', playing);
|
|
389
|
+
this.dispatchEvent(new CustomEvent('notify::playing', { bubbles: true, detail: { playing } }));
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/** `gtk_video_update_overlay_icon` (gtkvideo.c:626-646), arm by arm. */
|
|
393
|
+
private _updateOverlayIcon(): void {
|
|
394
|
+
if (!this._overlayIcon) return;
|
|
395
|
+
let icon: VideoOverlayIcon;
|
|
396
|
+
let tooltip: string | null = null;
|
|
397
|
+
if (!this._hasStream) icon = NO_STREAM_ICON;
|
|
398
|
+
else if (this._error !== null) {
|
|
399
|
+
icon = ERROR_ICON;
|
|
400
|
+
tooltip = this._error;
|
|
401
|
+
} else if (this._ended) icon = ENDED_ICON;
|
|
402
|
+
else icon = READY_ICON;
|
|
403
|
+
|
|
404
|
+
const image = document.createElement('gtk-image');
|
|
405
|
+
// The four names carry their `-symbolic` suffix already — `normalizeIconName` accepts
|
|
406
|
+
// either spelling and the mask classes are keyed on the bare name, see `gtk-image.ts`.
|
|
407
|
+
image.setAttribute('icon-name', icon);
|
|
408
|
+
// `icon-size` 2 in the template (ui/gtkvideo.ui) is GTK's ICON_SIZE dialog-scale,
|
|
409
|
+
// which libadwaita renders at 64px through the `video image.osd` rule; the web's own
|
|
410
|
+
// size is the stylesheet's, so nothing is set here and the rule wins as it should.
|
|
411
|
+
this._overlayIcon.replaceChildren(image);
|
|
412
|
+
if (tooltip) this._overlayIcon.title = tooltip;
|
|
413
|
+
else this._overlayIcon.title = '';
|
|
414
|
+
this._overlayIcon.classList.toggle('error', this._error !== null);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
disconnectedCallback() {
|
|
418
|
+
if (this._hideTimer !== null) clearTimeout(this._hideTimer);
|
|
419
|
+
this._hideTimer = null;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
customElements.define('gtk-video', GtkVideo);
|