From be07cd90d243af26a8244a597dac11a1ac882a85 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 23 Feb 2022 13:06:24 +0100 Subject: [PATCH] Compensate scrollbars. --- .../angular/compensate-scrollbar.directive.ts | 61 +++++++++++++++++++ .../angular/list-view.component.html | 2 +- frontend/src/app/framework/declarations.ts | 1 + frontend/src/app/framework/module.ts | 4 +- 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 frontend/src/app/framework/angular/compensate-scrollbar.directive.ts diff --git a/frontend/src/app/framework/angular/compensate-scrollbar.directive.ts b/frontend/src/app/framework/angular/compensate-scrollbar.directive.ts new file mode 100644 index 000000000..862aa5bcc --- /dev/null +++ b/frontend/src/app/framework/angular/compensate-scrollbar.directive.ts @@ -0,0 +1,61 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { Directive, ElementRef, HostListener, Input, Renderer2 } from '@angular/core'; +import { ResizeListener, ResizeService, ResourceOwner } from '@app/framework/internal'; + +@Directive({ + selector: '[sqxCompensateScrollbar]', +}) +export class CompensateScrollbarDirective extends ResourceOwner implements ResizeListener { + private previousScrollbarWidth = -1; + + @Input('sqxCompensateScrollbar') + public enabled?: string | boolean | null = true; + + constructor( + private readonly renderer: Renderer2, + private readonly element: ElementRef, + private readonly resizeService: ResizeService, + ) { + super(); + + this.own(this.resizeService.listen(this.element.nativeElement, this)); + } + + public ngAfterViewInit() { + this.resize(); + } + + public onResize() { + this.resize(); + } + + @HostListener('scroll') + public onScroll() { + this.resize(); + } + + private resize() { + if (this.enabled === false) { + return; + } + + const element = this.element.nativeElement; + + const scrollWidth = element.clientWidth; + const scollbarWidth = element.offsetWidth - scrollWidth; + + if (this.previousScrollbarWidth == scollbarWidth) { + return; + } + + this.renderer.setStyle(element, 'padding-left', `${scollbarWidth}px`); + + this.previousScrollbarWidth = scollbarWidth; + } +} diff --git a/frontend/src/app/framework/angular/list-view.component.html b/frontend/src/app/framework/angular/list-view.component.html index 7ec47f1eb..1ade4be00 100644 --- a/frontend/src/app/framework/angular/list-view.component.html +++ b/frontend/src/app/framework/angular/list-view.component.html @@ -9,7 +9,7 @@ -
+
diff --git a/frontend/src/app/framework/declarations.ts b/frontend/src/app/framework/declarations.ts index 3c208da70..9a12ab68b 100644 --- a/frontend/src/app/framework/declarations.ts +++ b/frontend/src/app/framework/declarations.ts @@ -7,6 +7,7 @@ export * from './angular/avatar.component'; export * from './angular/code.component'; +export * from './angular/compensate-scrollbar.directive'; export * from './angular/dropdown-menu.component'; export * from './angular/external-link.directive'; export * from './angular/forms/confirm-click.directive'; diff --git a/frontend/src/app/framework/module.ts b/frontend/src/app/framework/module.ts index 73c0570ba..d7679e4ed 100644 --- a/frontend/src/app/framework/module.ts +++ b/frontend/src/app/framework/module.ts @@ -11,7 +11,7 @@ import { ModuleWithProviders, NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { RouterModule } from '@angular/router'; import { ColorPickerModule } from 'ngx-color-picker'; -import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterceptor, CanDeactivateGuard, CheckboxGroupComponent, ClipboardService, CodeComponent, CodeEditorComponent, ColorPickerComponent, ConfirmClickDirective, ControlErrorsComponent, ControlErrorsMessagesComponent, CopyDirective, DarkenPipe, DatePipe, DateTimeEditorComponent, DayOfWeekPipe, DayPipe, DialogRendererComponent, DialogService, DisplayNamePipe, DropdownComponent, DropdownMenuComponent, DurationPipe, EditableTitleComponent, ExternalLinkDirective, FileDropDirective, FileSizePipe, FocusOnInitDirective, FormAlertComponent, FormErrorComponent, FormHintComponent, FromNowPipe, FullDateTimePipe, HighlightPipe, HoverBackgroundDirective, ImageSourceDirective, ImageUrlDirective, IndeterminateValueDirective, ISODatePipe, KeysPipe, KNumberPipe, LanguageSelectorComponent, LayoutComponent, LayoutContainerDirective, LightenPipe, ListViewComponent, LoadingInterceptor, LoadingService, LocalizedInputComponent, LocalStoreService, MarkdownDirective, MarkdownInlinePipe, MarkdownPipe, MessageBus, ModalDialogComponent, ModalDirective, ModalPlacementDirective, MonthPipe, OnboardingService, OnboardingTooltipComponent, PagerComponent, ParentLinkDirective, ProgressBarComponent, ResizedDirective, ResizeService, ResourceLoaderService, RootViewComponent, SafeHtmlPipe, SafeResourceUrlPipe, SafeUrlPipe, ScrollActiveDirective, ShortcutComponent, ShortcutDirective, ShortcutService, ShortDatePipe, ShortTimePipe, StarsComponent, StatusIconComponent, StopClickDirective, StopDragDirective, SyncScollingDirective, SyncWidthDirective, TabRouterlinkDirective, TagEditorComponent, TemplateWrapperDirective, TempService, TitleComponent, TitleService, ToggleComponent, ToolbarComponent, TooltipDirective, TransformInputDirective, TranslatePipe, VideoPlayerComponent } from './declarations'; +import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterceptor, CanDeactivateGuard, CheckboxGroupComponent, ClipboardService, CodeComponent, CodeEditorComponent, ColorPickerComponent, CompensateScrollbarDirective, ConfirmClickDirective, ControlErrorsComponent, ControlErrorsMessagesComponent, CopyDirective, DarkenPipe, DatePipe, DateTimeEditorComponent, DayOfWeekPipe, DayPipe, DialogRendererComponent, DialogService, DisplayNamePipe, DropdownComponent, DropdownMenuComponent, DurationPipe, EditableTitleComponent, ExternalLinkDirective, FileDropDirective, FileSizePipe, FocusOnInitDirective, FormAlertComponent, FormErrorComponent, FormHintComponent, FromNowPipe, FullDateTimePipe, HighlightPipe, HoverBackgroundDirective, ImageSourceDirective, ImageUrlDirective, IndeterminateValueDirective, ISODatePipe, KeysPipe, KNumberPipe, LanguageSelectorComponent, LayoutComponent, LayoutContainerDirective, LightenPipe, ListViewComponent, LoadingInterceptor, LoadingService, LocalizedInputComponent, LocalStoreService, MarkdownDirective, MarkdownInlinePipe, MarkdownPipe, MessageBus, ModalDialogComponent, ModalDirective, ModalPlacementDirective, MonthPipe, OnboardingService, OnboardingTooltipComponent, PagerComponent, ParentLinkDirective, ProgressBarComponent, ResizedDirective, ResizeService, ResourceLoaderService, RootViewComponent, SafeHtmlPipe, SafeResourceUrlPipe, SafeUrlPipe, ScrollActiveDirective, ShortcutComponent, ShortcutDirective, ShortcutService, ShortDatePipe, ShortTimePipe, StarsComponent, StatusIconComponent, StopClickDirective, StopDragDirective, SyncScollingDirective, SyncWidthDirective, TabRouterlinkDirective, TagEditorComponent, TemplateWrapperDirective, TempService, TitleComponent, TitleService, ToggleComponent, ToolbarComponent, TooltipDirective, TransformInputDirective, TranslatePipe, VideoPlayerComponent } from './declarations'; @NgModule({ imports: [ @@ -28,6 +28,7 @@ import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterc CodeComponent, CodeEditorComponent, ColorPickerComponent, + CompensateScrollbarDirective, ConfirmClickDirective, ControlErrorsComponent, ControlErrorsMessagesComponent, @@ -112,6 +113,7 @@ import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterc CodeEditorComponent, ColorPickerComponent, CommonModule, + CompensateScrollbarDirective, ConfirmClickDirective, ControlErrorsComponent, CopyDirective,