UNPKG

ngx-slider-recaptcha

Version:
507 lines (495 loc) 37.5 kB
import * as i0 from '@angular/core'; import { Injectable, InjectionToken, EventEmitter, TemplateRef, Component, Inject, ViewChild, Input, Output, HostListener, NgModule } from '@angular/core'; import { of } from 'rxjs'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; const DEFAULT_SLIDER_RECAPTCHA_CONFIG = { width: 300, height: 200, puzzleSize: 45, puzzleRadius: 10, toleranceOffset: 5, maxRetryAttempts: 3, allowRefresh: false, allowResponsiveWidth: false, disabled: false, primaryColor: '#0083c1', errorColor: '#c4161c', successColor: '#52ccba', textColor: '#4b4b4b', sliderContainerBackgroundColor: '#f7f9fa', sliderContainerBorderColor: '#e6e8eb', borderRadius: 4, loadingText: 'Loading...', instructionText: 'Slide to complete the puzzle', }; class DefaultNgxSliderRecaptchaImageService { getSliderImage() { return of(`assets/images/ngx-slider-recaptcha-${Math.floor(Math.random() * 5)}.jpg`); } } DefaultNgxSliderRecaptchaImageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DefaultNgxSliderRecaptchaImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); DefaultNgxSliderRecaptchaImageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DefaultNgxSliderRecaptchaImageService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DefaultNgxSliderRecaptchaImageService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class DefaultNgxSliderRecaptchaVerificationService { verify(verificationRequest) { var _a; if (!((_a = verificationRequest === null || verificationRequest === void 0 ? void 0 : verificationRequest.sliderMovements) === null || _a === void 0 ? void 0 : _a.length)) { return of({ success: false, message: 'No slider movement detected. Please try again.' }); } const { sliderMovements, puzzleBlockPosition, puzzlePosition, toleranceOffset: offset } = verificationRequest; const averageMovement = sliderMovements.reduce((sum, value) => sum + value, 0) / sliderMovements.length; const movementDeviation = Math.sqrt(sliderMovements.reduce((sum, value) => sum + Math.pow(value - averageMovement, 2), 0) / sliderMovements.length); const isVerified = movementDeviation !== 0; const isSpliced = Math.abs(puzzleBlockPosition - puzzlePosition) < (offset !== null && offset !== void 0 ? offset : 0); const response = { success: isSpliced && isVerified, message: isSpliced && isVerified ? 'Verification successful' : 'Verification failed', }; return of(response); } } DefaultNgxSliderRecaptchaVerificationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DefaultNgxSliderRecaptchaVerificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); DefaultNgxSliderRecaptchaVerificationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DefaultNgxSliderRecaptchaVerificationService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DefaultNgxSliderRecaptchaVerificationService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); const NGX_SLIDER_RECAPTCHA_IMAGE_SERVICE_TOKEN = new InjectionToken('NgxSliderRecaptchaImageService'); const NGX_SLIDER_RECAPTCHA_CONFIG_TOKEN = new InjectionToken('NgxSliderRecaptchaConfig'); const NGX_SLIDER_RECAPTCHA_VERIFICATION_SERVICE_TOKEN = new InjectionToken('NgxSliderRecaptchaVerificationService'); class NgxSliderRecaptchaComponent { constructor(renderer, cdr, globalSliderConfig, verifier, imageRetriever) { this.renderer = renderer; this.cdr = cdr; this.globalSliderConfig = globalSliderConfig; this.verifier = verifier; this.imageRetriever = imageRetriever; this.disabled = false; this.onVerified = new EventEmitter(); this.onRefresh = new EventEmitter(); this.onError = new EventEmitter(); this._sliderText = ''; this._sliderOffsetX = 0; this._blockOffsetX = 0; this._maskWidth = 0; this._isSliderDragging = false; this._isVerifying = false; this._verificationStatus = 'none'; this.dragStartX = 0; this.dragStartY = 0; this.puzzleX = 0; this.puzzleY = 0; this.loadCount = 0; this.sliderMovements = []; this.isUsingIE = window.navigator.userAgent.includes('Trident'); this.SLIDER_CONTAINER_MARGIN = 7; } ngOnInit() { this._sliderConfig = Object.assign(Object.assign(Object.assign({}, this._sliderConfig), this.globalSliderConfig), DEFAULT_SLIDER_RECAPTCHA_CONFIG); } ngAfterViewInit() { if (!this.ctx || !this.blockCtx) { this.initializeCaptcha(); } } ngOnChanges(changes) { var _a; if ((_a = changes['config']) === null || _a === void 0 ? void 0 : _a.currentValue) { this._sliderConfig = Object.assign(Object.assign(Object.assign({}, this._sliderConfig), this.globalSliderConfig), this.config); this._sliderText = this.sliderConfig.instructionText; this.initializeStyles(); this.cdr.detectChanges(); } } reset() { setTimeout(() => { this._maskWidth = 0; this._sliderOffsetX = 0; this._blockOffsetX = 0; this.sliderMovements = []; this._verificationStatus = 'none'; this._sliderText = this.sliderConfig.loadingText; this.initializeCaptcha(); this.cdr.detectChanges(); }, 500); } refresh() { this.reset(); this.onRefresh.emit(); } isTemplate(input) { return input instanceof TemplateRef; } get isSliderDragging() { return this._isSliderDragging; } get isVerifying() { return this._isVerifying; } get sliderText() { return this._sliderText; } get verificationStatus() { return this._verificationStatus; } get maskWidth() { return this._maskWidth; } get sliderOffsetX() { return this._sliderOffsetX; } get blockOffsetX() { return this._blockOffsetX; } get sliderConfig() { return this._sliderConfig; } get isDisabled() { var _a, _b; return (_b = (_a = this.disabled) !== null && _a !== void 0 ? _a : this.sliderConfig.disabled) !== null && _b !== void 0 ? _b : false; } onDragStart(event) { const target = event.target; if (this.isVerifying || !this.slider.nativeElement.contains(target)) { return; } this._isSliderDragging = true; this.initializeDragStartCoordinates(event); } onDragMove(event) { if (this.isVerifying || !this._isSliderDragging) return; const { x, y } = this.extractEventCoordinates(event); const { width, puzzleSize } = this.sliderConfig; let deltaX = x - this.dragStartX; let deltaY = y - this.dragStartY; if (deltaX < 0 || deltaX + puzzleSize > width) return; this._sliderOffsetX = (deltaX - 1); this._maskWidth = (deltaX + 4); this._blockOffsetX = (width - this.sliderConfig.puzzleSize - 20) / (width - puzzleSize) * deltaX; this.sliderMovements.push(Math.round(deltaY)); } onDragEnd(event) { if (this.isVerifying || !this._isSliderDragging) return; this._isSliderDragging = false; const { x } = this.extractEventCoordinates(event); if (x === this.dragStartX) return; const verificationRequest = { sliderMovements: this.sliderMovements, puzzleBlockPosition: this.blockOffsetX, puzzlePosition: this.puzzleX, toleranceOffset: this.sliderConfig.toleranceOffset }; this._isVerifying = true; this.verifier.verify(verificationRequest).subscribe({ next: (response) => { this._isVerifying = false; if (response.success) { this._verificationStatus = 'success'; this.onVerified.emit(response); } else { this._verificationStatus = 'fail'; this.onError.emit("Verification failed"); setTimeout(() => this.reset(), 1000); } }, error: (error) => { this._isVerifying = false; this.onError.emit(error); setTimeout(() => this.reset(), 1000); } }); } initializeCanvasDimensions() { const { width, height, puzzleSize } = this.sliderConfig; const sliderContainerHeight = (puzzleSize !== null && puzzleSize !== void 0 ? puzzleSize : 0) + this.SLIDER_CONTAINER_MARGIN; const adjustedHeight = (height !== null && height !== void 0 ? height : 0) - sliderContainerHeight; [this.canvas.nativeElement, this.block.nativeElement].forEach(element => { this.renderer.setAttribute(element, 'width', width.toString()); this.renderer.setAttribute(element, 'height', adjustedHeight.toString()); }); } initializeCanvasContexts() { this.initializeCanvasDimensions(); this.ctx = this.canvas.nativeElement.getContext('2d', { willReadFrequently: true }); this.blockCtx = this.block.nativeElement.getContext('2d', { willReadFrequently: true }); if (!this.ctx || !this.blockCtx) { throw new Error("Failed to initialize canvas contexts"); } } initializeCaptcha() { this.resetCanvas(); this.initializeStyles(); this.initializeCanvasContexts(); this.renderPuzzle(); } renderPuzzle() { let img = new Image(); img.crossOrigin = 'Anonymous'; img.onload = () => this.configurePuzzleImage(img); img.onerror = () => this.retryImageLoad(img); this.fetchImageSource(img); this._sliderText = this.sliderConfig.loadingText; this.cdr.detectChanges(); } configurePuzzleImage(img) { const { width, puzzleSize, puzzleRadius, instructionText } = this.sliderConfig; let puzzleBlockWidth = puzzleSize + puzzleRadius * 2 + 3; const { width: canvasWidth, height: canvasHeight } = this.canvas.nativeElement; this.puzzleX = this.generateRandomNumber(puzzleBlockWidth + 10, canvasWidth - (puzzleBlockWidth + 10)); this.puzzleY = this.generateRandomNumber(10 + puzzleRadius * 2, canvasHeight - (puzzleBlockWidth + 10)); this.drawPuzzlePieceShape(this.ctx, 'fill'); this.drawPuzzlePieceShape(this.blockCtx, 'clip'); this.ctx.drawImage(img, 0, 0, width, canvasHeight); this.blockCtx.drawImage(img, 0, 0, width, canvasHeight); const yOffset = this.puzzleY - puzzleRadius * 2 - 1; const imageData = this.blockCtx.getImageData(this.puzzleX - 3, yOffset, puzzleBlockWidth, puzzleBlockWidth); this.renderer.setAttribute(this.block.nativeElement, 'width', puzzleBlockWidth.toString()); this.renderer.setAttribute(this.block.nativeElement, 'height', canvasHeight.toString()); this.blockCtx.putImageData(imageData, 0, yOffset + 1); this._sliderText = instructionText; this.cdr.detectChanges(); } retryImageLoad(img) { this.loadCount++; if (this.loadCount <= this.sliderConfig.maxRetryAttempts) { this.renderPuzzle(); } else { img.src = this.loadFallbackImage(); } } fetchImageSource(img) { this.imageRetriever.getSliderImage().subscribe({ next: (image) => img.src = image, error: (error) => this.onError.emit(error) }); } loadFallbackImage() { return `assets/images/ngx-slider-recaptcha-${Math.floor(Math.random() * 4)}.jpg`; } drawPuzzlePieceShape(ctx, operation) { const { puzzleSize: size, puzzleRadius: radius } = this.sliderConfig; const { PI } = Math; const { puzzleX, puzzleY } = this; ctx.beginPath(); ctx.moveTo(puzzleX, puzzleY); ctx.arc(puzzleX + size / 2, puzzleY - radius + 2, radius, 0.72 * PI, 2.26 * PI); ctx.lineTo(puzzleX + size, puzzleY); ctx.arc(puzzleX + size + radius - 2, puzzleY + size / 2, radius, 1.21 * PI, 2.78 * PI); ctx.lineTo(puzzleX + size, puzzleY + size); ctx.lineTo(puzzleX, puzzleY + size); ctx.arc(puzzleX + radius - 2, puzzleY + size / 2, radius + 0.4, 2.76 * PI, 1.24 * PI, true); ctx.lineTo(puzzleX, puzzleY); ctx.lineWidth = 2; ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'; ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'; ctx.stroke(); ctx[operation](); ctx.globalCompositeOperation = this.isUsingIE ? 'xor' : 'destination-over'; } generateRandomNumber(start, end) { return Math.round(Math.random() * (end - start) + start); } ; resetCanvas() { var _a, _b; const { width, height } = this.canvas.nativeElement; (_a = this.ctx) === null || _a === void 0 ? void 0 : _a.clearRect(0, 0, width, height); (_b = this.blockCtx) === null || _b === void 0 ? void 0 : _b.clearRect(0, 0, width, height); } extractEventCoordinates(event) { if (event instanceof MouseEvent) { return { x: event.clientX, y: event.clientY }; } else { return { x: event.changedTouches[0].clientX, y: event.changedTouches[0].clientY }; } } initializeDragStartCoordinates(event) { const { x, y } = this.extractEventCoordinates(event); this.dragStartX = x; this.dragStartY = y; } initializeStyles() { if (this.sliderConfig.allowResponsiveWidth) { this._sliderConfig = Object.assign(Object.assign({}, this._sliderConfig), { width: this.captchaContainer.nativeElement.offsetWidth }); } const { width, height, primaryColor, successColor, errorColor, textColor, sliderContainerBackgroundColor: containerBackgroundColor, sliderContainerBorderColor: containerBorderColor, borderRadius: commonBorderRadius, puzzleSize } = this.sliderConfig; this.setStyle('--recaptcha-container-width', `${width}px`); this.setStyle('--recaptcha-container-height', `${height}px`); this.setStyle('--recaptcha-canvas-width', `${width}px`); this.setStyle('--recaptcha-canvas-height', `${(height - (puzzleSize + this.SLIDER_CONTAINER_MARGIN))}px`); this.setStyle('--recaptcha-primary-color', primaryColor); this.setStyle('--recaptcha-error-color', errorColor); this.setStyle('--recaptcha-success-color', successColor); this.setStyle('--recaptcha-text-color', textColor); this.setStyle('--recaptcha-container-background-color', containerBackgroundColor); this.setStyle('--recaptcha-container-border-color', containerBorderColor); this.setStyle('--recaptcha-common-border-radius', `${commonBorderRadius}px`); this.setStyle('--recaptcha-slider-container-height', `${puzzleSize}px`); this.setStyle('--recaptcha-slider-mask-primary-color', this.hexToRgba(primaryColor, 0.3)); this.setStyle('--recaptcha-slider-mask-success-color', this.hexToRgba(successColor, 0.3)); this.setStyle('--recaptcha-slider-mask-error-color', this.hexToRgba(errorColor, 0.3)); } setStyle(property, value) { document.documentElement.style.setProperty(property, value); } hexToRgba(hex, opacity) { const sanitizedHex = hex === null || hex === void 0 ? void 0 : hex.replace(/^#/, ''); const [radius, g, b] = [0, 2, 4].map((start) => parseInt(sanitizedHex.slice(start, start + 2), 16)); return `rgba(${radius}, ${g}, ${b}, ${opacity})`; } } NgxSliderRecaptchaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgxSliderRecaptchaComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: NGX_SLIDER_RECAPTCHA_CONFIG_TOKEN }, { token: NGX_SLIDER_RECAPTCHA_VERIFICATION_SERVICE_TOKEN }, { token: NGX_SLIDER_RECAPTCHA_IMAGE_SERVICE_TOKEN }], target: i0.ɵɵFactoryTarget.Component }); NgxSliderRecaptchaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: NgxSliderRecaptchaComponent, isStandalone: true, selector: "ngx-slider-recaptcha", inputs: { config: "config", disabled: "disabled", sliderContent: "sliderContent", successContent: "successContent", failContent: "failContent" }, outputs: { onVerified: "onVerified", onRefresh: "onRefresh", onError: "onError" }, host: { listeners: { "document:mousedown": "onDragStart($event)", "document:touchstart": "onDragStart($event)", "document:mousemove": "onDragMove($event)", "document:touchmove": "onDragMove($event)", "document:mouseup": "onDragEnd($event)", "document:touchend": "onDragEnd($event)" } }, viewQueries: [{ propertyName: "canvas", first: true, predicate: ["canvas"], descendants: true, static: true }, { propertyName: "block", first: true, predicate: ["block"], descendants: true, static: true }, { propertyName: "captchaContainer", first: true, predicate: ["captchaContainer"], descendants: true, static: true }, { propertyName: "slider", first: true, predicate: ["slider"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #captchaContainer class=\"captcha-container\">\r\n <canvas #canvas class=\"canvas\"></canvas>\r\n <canvas #block class=\"block\" [style.left.px]=\"blockOffsetX\"></canvas>\r\n <div class=\"slider-container\" [class.active]=\"isSliderDragging\" [class.success]=\"verificationStatus === 'success'\"\r\n [class.fail]=\"verificationStatus === 'fail'\">\r\n <div class=\"slider-mask\" [style.width.px]=\"maskWidth\">\r\n <div #slider class=\"slider\" [style.left.px]=\"sliderOffsetX\">\r\n <ng-container *ngIf=\"verificationStatus === 'none'\">\r\n <ng-container *ngIf=\"sliderContent; else defaultTemplate\">\r\n <ng-container *ngIf=\"isTemplate(sliderContent); else sliderContentStringTemplate\">\r\n <ng-container *ngTemplateOutlet=\"sliderContent\"></ng-container>\r\n </ng-container>\r\n <ng-template #sliderContentStringTemplate>\r\n {{ sliderContent }}\r\n </ng-template>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"verificationStatus === 'success'\">\r\n <ng-container *ngIf=\"successContent; else defaultTemplate\">\r\n <ng-container *ngIf=\"isTemplate(successContent); else successContentStringTemplate\">\r\n <ng-container *ngTemplateOutlet=\"successContent\"></ng-container>\r\n </ng-container>\r\n <ng-template #successContentStringTemplate>\r\n {{ successContent }}\r\n </ng-template>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"verificationStatus === 'fail'\">\r\n <ng-container *ngIf=\"failContent; else defaultTemplate\">\r\n <ng-container *ngIf=\"isTemplate(failContent); else failContentStringTemplate\">\r\n <ng-container *ngTemplateOutlet=\"failContent\"></ng-container>\r\n </ng-container>\r\n <ng-template #failContentStringTemplate>\r\n {{ sliderContent }}\r\n </ng-template>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #defaultTemplate>\r\n <span class=\"slider-icon\"></span>\r\n </ng-template>\r\n </div>\r\n </div>\r\n <span class=\"slider-text\" *ngIf=\"!isVerifying\">{{ sliderText }}</span>\r\n </div>\r\n <i *ngIf=\"sliderConfig.allowRefresh\" class=\"refresh-icon\" (click)=\"refresh()\"></i>\r\n <div class=\"disable-wrapper\" *ngIf=\"isDisabled || isVerifying\"></div>\r\n</div>", styles: ["@charset \"UTF-8\";.captcha-container{display:flex;flex-direction:column;position:relative}.canvas{width:var(--recaptcha-canvas-width);height:var(--recaptcha-canvas-height);border:1px solid #ccc;border-radius:3px}.block{position:absolute;left:0;top:0}.slider-container{position:relative;display:flex;justify-content:center;align-items:center;margin-top:5px;height:var(--recaptcha-slider-container-height);width:var(--recaptcha-canvas-width);border:1px solid var(--recaptcha-container-border-color);background:var(--recaptcha-container-background-color);border-radius:var(--recaptcha-common-border-radius);box-shadow:inset 0 0 5px #00000026}.slider-container .slider-text{position:relative;color:var(--recaptcha-text-color);white-space:nowrap;text-overflow:ellipsis;overflow:hidden;padding-left:calc(var(--recaptcha-slider-container-height) + 10px);padding-right:10px}.slider-container .slider-mask{position:absolute;left:0;top:0;height:var(--recaptcha-slider-container-height);width:var(--recaptcha-slider-container-height);border:1px solid transparent;border-right:0;transform:translate(-1px,-1px);border-radius:calc(var(--recaptcha-common-border-radius) - 1px)}.slider-container .slider-icon:before{content:\"\\2794\"}.slider-container.active .slider-text,.slider-container.success .slider-text,.slider-container.fail .slider-text{display:none}.slider{position:absolute;top:0;left:0;width:var(--recaptcha-slider-container-height);height:var(--recaptcha-slider-container-height);max-width:var(--recaptcha-slider-container-height);max-height:var(--recaptcha-slider-container-height);background:#fff;box-shadow:0 0 3px #0000004d;cursor:pointer;border-radius:calc(var(--recaptcha-common-border-radius) - 1px);display:flex;align-items:center;justify-content:center;border:1px solid #fff;transform:translateY(-1px)}.slider:hover{background:var(--recaptcha-primary-color);color:#fff;border:1px solid var(--recaptcha-primary-color)}.slider:hover .slider-icon{background-position:0 -13px;color:#fff}.active .slider{top:-1px;border:1px solid var(--recaptcha-primary-color);background-color:var(--recaptcha-primary-color);color:#fff;transform:translateY(0)}.active .slider-mask{border-color:var(--recaptcha-primary-color);background:var(--recaptcha-slider-mask-primary-color)}.success .slider{top:-1px;border:1px solid var(--recaptcha-success-color);background-color:var(--recaptcha-success-color);color:#fff;transform:translateY(0)}.success .slider-mask{border-color:var(--recaptcha-success-color);background-color:#d2f4ef}.success .slider-icon:before{content:\"\\2713\"}.fail .slider{top:-1px;border:1px solid var(--recaptcha-error-color);background-color:var(--recaptcha-error-color);color:#fff;transform:translateY(0)}.fail .slider-mask{border-color:var(--recaptcha-error-color);background-color:var(--recaptcha-slider-mask-error-color)}.fail .slider-icon:before{content:\"\\2715\"}.refresh-icon{position:absolute;right:6px;top:6px;cursor:pointer;color:#ffffff4d;font-size:1rem;z-index:5;transition:color .3s linear}.refresh-icon:before{content:\"\\27f3\"}.refresh-icon:hover{color:#fff}.disable-wrapper{position:absolute;cursor:not-allowed;z-index:9999;width:var(--recaptcha-container-width);height:var(--recaptcha-container-height);background-color:#e1e1e14d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgxSliderRecaptchaComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'ngx-slider-recaptcha', imports: [CommonModule], template: "<div #captchaContainer class=\"captcha-container\">\r\n <canvas #canvas class=\"canvas\"></canvas>\r\n <canvas #block class=\"block\" [style.left.px]=\"blockOffsetX\"></canvas>\r\n <div class=\"slider-container\" [class.active]=\"isSliderDragging\" [class.success]=\"verificationStatus === 'success'\"\r\n [class.fail]=\"verificationStatus === 'fail'\">\r\n <div class=\"slider-mask\" [style.width.px]=\"maskWidth\">\r\n <div #slider class=\"slider\" [style.left.px]=\"sliderOffsetX\">\r\n <ng-container *ngIf=\"verificationStatus === 'none'\">\r\n <ng-container *ngIf=\"sliderContent; else defaultTemplate\">\r\n <ng-container *ngIf=\"isTemplate(sliderContent); else sliderContentStringTemplate\">\r\n <ng-container *ngTemplateOutlet=\"sliderContent\"></ng-container>\r\n </ng-container>\r\n <ng-template #sliderContentStringTemplate>\r\n {{ sliderContent }}\r\n </ng-template>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"verificationStatus === 'success'\">\r\n <ng-container *ngIf=\"successContent; else defaultTemplate\">\r\n <ng-container *ngIf=\"isTemplate(successContent); else successContentStringTemplate\">\r\n <ng-container *ngTemplateOutlet=\"successContent\"></ng-container>\r\n </ng-container>\r\n <ng-template #successContentStringTemplate>\r\n {{ successContent }}\r\n </ng-template>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"verificationStatus === 'fail'\">\r\n <ng-container *ngIf=\"failContent; else defaultTemplate\">\r\n <ng-container *ngIf=\"isTemplate(failContent); else failContentStringTemplate\">\r\n <ng-container *ngTemplateOutlet=\"failContent\"></ng-container>\r\n </ng-container>\r\n <ng-template #failContentStringTemplate>\r\n {{ sliderContent }}\r\n </ng-template>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-template #defaultTemplate>\r\n <span class=\"slider-icon\"></span>\r\n </ng-template>\r\n </div>\r\n </div>\r\n <span class=\"slider-text\" *ngIf=\"!isVerifying\">{{ sliderText }}</span>\r\n </div>\r\n <i *ngIf=\"sliderConfig.allowRefresh\" class=\"refresh-icon\" (click)=\"refresh()\"></i>\r\n <div class=\"disable-wrapper\" *ngIf=\"isDisabled || isVerifying\"></div>\r\n</div>", styles: ["@charset \"UTF-8\";.captcha-container{display:flex;flex-direction:column;position:relative}.canvas{width:var(--recaptcha-canvas-width);height:var(--recaptcha-canvas-height);border:1px solid #ccc;border-radius:3px}.block{position:absolute;left:0;top:0}.slider-container{position:relative;display:flex;justify-content:center;align-items:center;margin-top:5px;height:var(--recaptcha-slider-container-height);width:var(--recaptcha-canvas-width);border:1px solid var(--recaptcha-container-border-color);background:var(--recaptcha-container-background-color);border-radius:var(--recaptcha-common-border-radius);box-shadow:inset 0 0 5px #00000026}.slider-container .slider-text{position:relative;color:var(--recaptcha-text-color);white-space:nowrap;text-overflow:ellipsis;overflow:hidden;padding-left:calc(var(--recaptcha-slider-container-height) + 10px);padding-right:10px}.slider-container .slider-mask{position:absolute;left:0;top:0;height:var(--recaptcha-slider-container-height);width:var(--recaptcha-slider-container-height);border:1px solid transparent;border-right:0;transform:translate(-1px,-1px);border-radius:calc(var(--recaptcha-common-border-radius) - 1px)}.slider-container .slider-icon:before{content:\"\\2794\"}.slider-container.active .slider-text,.slider-container.success .slider-text,.slider-container.fail .slider-text{display:none}.slider{position:absolute;top:0;left:0;width:var(--recaptcha-slider-container-height);height:var(--recaptcha-slider-container-height);max-width:var(--recaptcha-slider-container-height);max-height:var(--recaptcha-slider-container-height);background:#fff;box-shadow:0 0 3px #0000004d;cursor:pointer;border-radius:calc(var(--recaptcha-common-border-radius) - 1px);display:flex;align-items:center;justify-content:center;border:1px solid #fff;transform:translateY(-1px)}.slider:hover{background:var(--recaptcha-primary-color);color:#fff;border:1px solid var(--recaptcha-primary-color)}.slider:hover .slider-icon{background-position:0 -13px;color:#fff}.active .slider{top:-1px;border:1px solid var(--recaptcha-primary-color);background-color:var(--recaptcha-primary-color);color:#fff;transform:translateY(0)}.active .slider-mask{border-color:var(--recaptcha-primary-color);background:var(--recaptcha-slider-mask-primary-color)}.success .slider{top:-1px;border:1px solid var(--recaptcha-success-color);background-color:var(--recaptcha-success-color);color:#fff;transform:translateY(0)}.success .slider-mask{border-color:var(--recaptcha-success-color);background-color:#d2f4ef}.success .slider-icon:before{content:\"\\2713\"}.fail .slider{top:-1px;border:1px solid var(--recaptcha-error-color);background-color:var(--recaptcha-error-color);color:#fff;transform:translateY(0)}.fail .slider-mask{border-color:var(--recaptcha-error-color);background-color:var(--recaptcha-slider-mask-error-color)}.fail .slider-icon:before{content:\"\\2715\"}.refresh-icon{position:absolute;right:6px;top:6px;cursor:pointer;color:#ffffff4d;font-size:1rem;z-index:5;transition:color .3s linear}.refresh-icon:before{content:\"\\27f3\"}.refresh-icon:hover{color:#fff}.disable-wrapper{position:absolute;cursor:not-allowed;z-index:9999;width:var(--recaptcha-container-width);height:var(--recaptcha-container-height);background-color:#e1e1e14d}\n"] }] }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{ type: Inject, args: [NGX_SLIDER_RECAPTCHA_CONFIG_TOKEN] }] }, { type: undefined, decorators: [{ type: Inject, args: [NGX_SLIDER_RECAPTCHA_VERIFICATION_SERVICE_TOKEN] }] }, { type: undefined, decorators: [{ type: Inject, args: [NGX_SLIDER_RECAPTCHA_IMAGE_SERVICE_TOKEN] }] }]; }, propDecorators: { canvas: [{ type: ViewChild, args: ['canvas', { static: true }] }], block: [{ type: ViewChild, args: ['block', { static: true }] }], captchaContainer: [{ type: ViewChild, args: ['captchaContainer', { static: true }] }], slider: [{ type: ViewChild, args: ['slider', { static: true }] }], config: [{ type: Input }], disabled: [{ type: Input }], sliderContent: [{ type: Input }], successContent: [{ type: Input }], failContent: [{ type: Input }], onVerified: [{ type: Output }], onRefresh: [{ type: Output }], onError: [{ type: Output }], onDragStart: [{ type: HostListener, args: ['document:mousedown', ['$event']] }, { type: HostListener, args: ['document:touchstart', ['$event']] }], onDragMove: [{ type: HostListener, args: ['document:mousemove', ['$event']] }, { type: HostListener, args: ['document:touchmove', ['$event']] }], onDragEnd: [{ type: HostListener, args: ['document:mouseup', ['$event']] }, { type: HostListener, args: ['document:touchend', ['$event']] }] } }); class NgxSliderRecaptchaModule { static forRoot(options = {}) { const { sliderConfig = DEFAULT_SLIDER_RECAPTCHA_CONFIG, verificationService = DefaultNgxSliderRecaptchaVerificationService, imageRetrievalService = DefaultNgxSliderRecaptchaImageService } = options; return { ngModule: NgxSliderRecaptchaModule, providers: [ { provide: NGX_SLIDER_RECAPTCHA_CONFIG_TOKEN, useValue: sliderConfig }, { provide: NGX_SLIDER_RECAPTCHA_VERIFICATION_SERVICE_TOKEN, useClass: verificationService }, { provide: NGX_SLIDER_RECAPTCHA_IMAGE_SERVICE_TOKEN, useClass: imageRetrievalService } ] }; } } NgxSliderRecaptchaModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgxSliderRecaptchaModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); NgxSliderRecaptchaModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: NgxSliderRecaptchaModule, imports: [CommonModule, NgxSliderRecaptchaComponent], exports: [NgxSliderRecaptchaComponent] }); NgxSliderRecaptchaModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgxSliderRecaptchaModule, providers: [ { provide: NGX_SLIDER_RECAPTCHA_CONFIG_TOKEN, useValue: DEFAULT_SLIDER_RECAPTCHA_CONFIG }, { provide: NGX_SLIDER_RECAPTCHA_VERIFICATION_SERVICE_TOKEN, useClass: DefaultNgxSliderRecaptchaVerificationService }, { provide: NGX_SLIDER_RECAPTCHA_IMAGE_SERVICE_TOKEN, useClass: DefaultNgxSliderRecaptchaImageService } ], imports: [CommonModule, NgxSliderRecaptchaComponent] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgxSliderRecaptchaModule, decorators: [{ type: NgModule, args: [{ imports: [ CommonModule, NgxSliderRecaptchaComponent ], exports: [ NgxSliderRecaptchaComponent ], providers: [ { provide: NGX_SLIDER_RECAPTCHA_CONFIG_TOKEN, useValue: DEFAULT_SLIDER_RECAPTCHA_CONFIG }, { provide: NGX_SLIDER_RECAPTCHA_VERIFICATION_SERVICE_TOKEN, useClass: DefaultNgxSliderRecaptchaVerificationService }, { provide: NGX_SLIDER_RECAPTCHA_IMAGE_SERVICE_TOKEN, useClass: DefaultNgxSliderRecaptchaImageService } ] }] }] }); /* * Public API Surface of ngx-slider-recaptcha */ /** * Generated bundle index. Do not edit. */ export { DEFAULT_SLIDER_RECAPTCHA_CONFIG, DefaultNgxSliderRecaptchaImageService, DefaultNgxSliderRecaptchaVerificationService, NGX_SLIDER_RECAPTCHA_CONFIG_TOKEN, NGX_SLIDER_RECAPTCHA_IMAGE_SERVICE_TOKEN, NGX_SLIDER_RECAPTCHA_VERIFICATION_SERVICE_TOKEN, NgxSliderRecaptchaComponent, NgxSliderRecaptchaModule }; //# sourceMappingURL=ngx-slider-recaptcha.mjs.map