UNPKG

sa-totop

Version:

A lightweight Angular standalone component for smooth scroll-to-top functionality.

195 lines (191 loc) 9.97 kB
import * as i1 from '@angular/common'; import { isPlatformBrowser, CommonModule } from '@angular/common'; import * as i0 from '@angular/core'; import { EventEmitter, PLATFORM_ID, Component, Inject, Input, Output } from '@angular/core'; class TotopComponent { constructor(platformId) { this.platformId = platformId; this.width = 40; this.bottom = 20; this.end = 20; this.color = '#0891b2'; this.scrollBehavior = 'smooth'; this.background = 'transparent'; this.duration = 0.3; this.visibilityHeight = 450; this.alwaysVisible = false; this.customeBtn = false; this.scrollComplete = new EventEmitter(); this.toTopClicked = new EventEmitter(); this.documentHieght = 0; this.scrollHeight = 0; this.divisionConst = 0; this.dashOffset = 310; this.screenHieght = 0; } toTop() { if (isPlatformBrowser(this.platformId)) { this.toTopClicked.emit(); window.scroll({ top: 0, left: 0, behavior: this.scrollBehavior, }); } } ngOnInit() { if (isPlatformBrowser(this.platformId)) { this.screenHieght = window.innerHeight; window.onscroll = () => { this.documentHieght = document.documentElement.scrollHeight; this.divisionConst = this.documentHieght / 310; this.scrollHeight = document.documentElement.scrollTop; let position = this.documentHieght - this.screenHieght - this.scrollHeight; this.dashOffset = position / this.divisionConst; if (this.documentHieght - 1000 < this.scrollHeight) { this.scrollComplete.emit(); } }; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: TotopComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: TotopComponent, isStandalone: true, selector: "sa-totop", inputs: { width: "width", bottom: "bottom", end: "end", color: "color", scrollBehavior: "scrollBehavior", background: "background", duration: "duration", visibilityHeight: "visibilityHeight", alwaysVisible: "alwaysVisible", customeBtn: "customeBtn" }, outputs: { scrollComplete: "scrollComplete", toTopClicked: "toTopClicked" }, ngImport: i0, template: ` <div (click)="toTop()" [style]=" '--width:' + width + 'px;' + '--animation-time:' + duration + 's;' + '--color:' + color + ';--background:' + background + ';--bottom:' + bottom + 'px' + ';--end:' + end + 'px' " [ngClass]="{ hide: scrollHeight < visibilityHeight && !alwaysVisible, active: documentHieght - 1000 < scrollHeight }" > <ng-container *ngIf="!customeBtn"> <button> <svg width="100%" height="100%" viewBox="-1 -1 102 102" [style]="'--progress:' + dashOffset" > <path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"></path> </svg> <svg id="arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" > <path fill="currentColor" d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z" ></path> </svg> </button> <div></div> </ng-container> <ng-content></ng-content> </div> `, isInline: true, styles: [":host{position:relative}div{position:fixed;bottom:var(--bottom);inset-inline-end:var(--end);z-index:90;transition:.5s}div button{width:var(--width);height:var(--width);border-radius:100%;overflow:hidden;aspect-ratio:1/1;position:relative;display:flex;align-items:center;justify-content:center;color:var(--color);background-color:var(--background);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:var(--animation-time)}div button:after{content:\"\";position:absolute;top:50%;left:0;transform:translate(100%,-50%) rotate(-45deg);width:calc(var(--width) * 2.2);height:calc(var(--width) / 3);transition:var(--animation-time);background:linear-gradient(288deg,white,transparent)}div button svg{position:absolute;stroke:var(--color);z-index:10;fill:none;overflow:visible;transition:var(--animation-time);stroke-width:6px;stroke-dasharray:310;stroke-dashoffset:var(--progress);stroke-linecap:round}div button #arrow{width:16px}div>div{position:absolute;width:100%;height:100%;background-color:#a1a1aa;opacity:0;transition:var(--animation-time);bottom:-25px;transform:scaleY(.1);filter:blur(10px);inset-inline-end:0px}div:hover button,div.active button{transform:translateY(-4px);background-color:var(--color);color:#fff}div:hover button:after,div.active button:after{transform:translate(100%)}div:hover button svg,div.active button svg{stroke:#fff;transform:scale(.85)}div:hover div,div.active div{opacity:.5}div.hide{transform:translateY(4rem);opacity:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: TotopComponent, decorators: [{ type: Component, args: [{ selector: 'sa-totop', standalone: true, imports: [CommonModule], template: ` <div (click)="toTop()" [style]=" '--width:' + width + 'px;' + '--animation-time:' + duration + 's;' + '--color:' + color + ';--background:' + background + ';--bottom:' + bottom + 'px' + ';--end:' + end + 'px' " [ngClass]="{ hide: scrollHeight < visibilityHeight && !alwaysVisible, active: documentHieght - 1000 < scrollHeight }" > <ng-container *ngIf="!customeBtn"> <button> <svg width="100%" height="100%" viewBox="-1 -1 102 102" [style]="'--progress:' + dashOffset" > <path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98"></path> </svg> <svg id="arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" > <path fill="currentColor" d="M214.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-160 160c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 141.2V448c0 17.7 14.3 32 32 32s32-14.3 32-32V141.2L329.4 246.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3l-160-160z" ></path> </svg> </button> <div></div> </ng-container> <ng-content></ng-content> </div> `, styles: [":host{position:relative}div{position:fixed;bottom:var(--bottom);inset-inline-end:var(--end);z-index:90;transition:.5s}div button{width:var(--width);height:var(--width);border-radius:100%;overflow:hidden;aspect-ratio:1/1;position:relative;display:flex;align-items:center;justify-content:center;color:var(--color);background-color:var(--background);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:var(--animation-time)}div button:after{content:\"\";position:absolute;top:50%;left:0;transform:translate(100%,-50%) rotate(-45deg);width:calc(var(--width) * 2.2);height:calc(var(--width) / 3);transition:var(--animation-time);background:linear-gradient(288deg,white,transparent)}div button svg{position:absolute;stroke:var(--color);z-index:10;fill:none;overflow:visible;transition:var(--animation-time);stroke-width:6px;stroke-dasharray:310;stroke-dashoffset:var(--progress);stroke-linecap:round}div button #arrow{width:16px}div>div{position:absolute;width:100%;height:100%;background-color:#a1a1aa;opacity:0;transition:var(--animation-time);bottom:-25px;transform:scaleY(.1);filter:blur(10px);inset-inline-end:0px}div:hover button,div.active button{transform:translateY(-4px);background-color:var(--color);color:#fff}div:hover button:after,div.active button:after{transform:translate(100%)}div:hover button svg,div.active button svg{stroke:#fff;transform:scale(.85)}div:hover div,div.active div{opacity:.5}div.hide{transform:translateY(4rem);opacity:0}\n"] }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID] }] }], propDecorators: { width: [{ type: Input }], bottom: [{ type: Input }], end: [{ type: Input }], color: [{ type: Input }], scrollBehavior: [{ type: Input }], background: [{ type: Input }], duration: [{ type: Input }], visibilityHeight: [{ type: Input }], alwaysVisible: [{ type: Input }], customeBtn: [{ type: Input }], scrollComplete: [{ type: Output }], toTopClicked: [{ type: Output }] } }); /** * Generated bundle index. Do not edit. */ export { TotopComponent }; //# sourceMappingURL=sa-totop.mjs.map