UNPKG

@trustcaptcha/trustcaptcha-frontend

Version:

Frondend library for trustcaptcha

137 lines (136 loc) 7.77 kB
import { h } from "@stencil/core"; import { PrivacyText, SpeakerOffIcon, SpeakerOnIcon, TrustcaptchaText, XMarkIcon } from "./icons"; export class CaptchaSlider { constructor(config, onSuccess, onClose, onStateChange) { this.isSliderOpen = false; this.audio = false; this.progress = 0; this.status = 'init'; this.pressureStartTime = null; this.config = config; this.onSuccess = onSuccess; this.onClose = onClose; this.onStateChange = onStateChange; this.successAudio = new Audio('https://resources.trustcaptcha.com/1_8_x/success.mp3'); this.errorAudio = new Audio('https://resources.trustcaptcha.com/1_8_x/error.mp3'); } startSlider() { this.isSliderOpen = true; this.holdDuration = Math.random() * (5 - 1.5) + 1.5; this.progress = 0; this.remainingTime = this.holdDuration; this.status = 'running'; this.onStateChange(); } startButtonPress() { this.pressureStartTime = new Date(); const interval = 10; this.intervalId = window.setInterval(() => { this.fillButtonOneStep(); }, interval); } fillButtonOneStep() { const elapsedTime = this.getElapsedTime(); this.progress = Math.min((elapsedTime / this.holdDuration) * 100, 100); this.remainingTime = Math.max(this.holdDuration - elapsedTime, 0); if (+this.remainingTime.toFixed(2) === 0.5 && this.audio) { this.successAudio.play(); } if (this.progress >= 100) { this.progress = 100; this.status = 'release'; clearInterval(this.intervalId); this.intervalId = undefined; } this.onStateChange(); } handleButtonRelease() { if (this.progress <= 0 || this.status === 'success' || this.status === 'error') { return; } clearInterval(this.intervalId); this.intervalId = undefined; const timeDiff = Math.abs(this.getElapsedTime() - this.holdDuration); this.pressureStartTime = null; if (timeDiff <= 0.3) { this.status = 'success'; this.onStateChange(); setTimeout(() => { this.isSliderOpen = false; this.progress = 0; this.onStateChange(); this.onSuccess(); }, 1000); } else { this.status = 'error'; this.onStateChange(); if (this.audio) { this.errorAudio.play(); } setTimeout(() => { this.startSlider(); }, 1000); } } getElapsedTime() { if (!this.pressureStartTime) { return 0; } return (new Date().getTime() - this.pressureStartTime.getTime()) / 1000; } toggleAudio() { this.audio = !this.audio; this.onStateChange(); } closePopup() { if (this.status === 'error') { return; } this.onClose(); this.isSliderOpen = false; clearInterval(this.intervalId); this.intervalId = undefined; this.pressureStartTime = null; } setNewConfig(config) { this.config = config; } } export const SliderContent = ({ props }) => { var _a; return (h("div", { class: 'rounded-lg shadow-lg max-w-xs w-full border min-w-72 sm:min-w-96 bg-opacity-100 opacity-100', style: { backgroundColor: props.config.currentTheme === 'light' ? 'var(--s-bg-l)' : 'var(--s-bg-d)', color: props.config.currentTheme === 'light' ? 'var(--s-text-l)' : 'var(--s-text-d)', borderColor: props.config.currentTheme === 'light' ? 'var(--s-border-l)' : 'var(--s-border-d)', } }, h("div", { class: 'border-b p-3 flex justify-between', style: { borderColor: props.config.currentTheme === 'light' ? 'var(--s-border-l)' : 'var(--s-border-d)', } }, h("div", { class: "content-center" }, !(props.config.hideBranding && ((_a = props.config.licenseObject) === null || _a === void 0 ? void 0 : _a.customizabilityOption)) && h(TrustcaptchaText, { currentTheme: props.config.currentTheme, trustcaptchaUrl: props.config.trustcaptchaUrl, translation: props.config.translation })), h("div", { class: 'flex gap-3' }, h("button", { onClick: () => props.toggleAudio() }, !props.audio && h("div", null, h(SpeakerOnIcon, { size: 24 }), h("span", { class: "sr-only" }, "Switch on sounds for accessibility")), props.audio && h("div", null, h(SpeakerOffIcon, { size: 24 }), h("span", { class: "sr-only" }, "Switch off sounds"))), h("button", { class: 'disabled:text-gray-500 disabled:cursor-default', disabled: props.status === 'error', onClick: () => props.closePopup() }, h(XMarkIcon, { size: 24 }), h("span", { class: "sr-only" }, "Close slider popup")))), h("div", { class: "p-3 text-center" }, h("p", { class: 'text-md mb-4', style: { borderColor: props.config.currentTheme === 'light' ? 'var(--s-text-l)' : 'var(--s-text-d)', } }, props.status === 'running' && props.config.translation.sliderRunning, props.status === 'release' && props.config.translation.sliderRelease, props.status === 'success' && props.config.translation.sliderSuccess, props.status === 'error' && props.config.translation.sliderError), h("button", { class: 'relative w-full h-12 rounded-lg overflow-hidden', style: { backgroundColor: props.config.currentTheme === 'light' ? 'var(--s-slider-bg-l)' : 'var(--s-slider-bg-d)', }, onMouseDown: () => props.startButtonPress(), onMouseUp: () => props.handleButtonRelease(), onMouseLeave: () => props.handleButtonRelease(), onTouchStart: (e) => { e.preventDefault(); // Prevents default touch behavior props.startButtonPress(); }, onTouchEnd: (e) => { e.preventDefault(); props.handleButtonRelease(); }, onTouchCancel: (e) => { e.preventDefault(); props.handleButtonRelease(); }, disabled: props.status === 'error' || props.status === 'success' }, h("div", { class: 'absolute top-0 left-0 h-full transition-all duration-500 linear', style: { width: `${props.progress}%`, transition: 'width 10ms linear', backgroundColor: props.status !== 'error' ? props.config.currentTheme === 'light' ? 'var(--s-slider-filling-bg-l)' : 'var(--s-slider-filling-bg-d)' : props.config.currentTheme === 'light' ? 'var(--s-slider-error-bg-l)' : 'var(--s-slider-error-bg-d)', } }), h("span", { class: 'absolute inset-0 flex items-center justify-center font-bold', style: { color: props.config.currentTheme === 'light' ? 'var(--s-text-l)' : 'var(--s-text-d)', } }, props.progress < 100 ? `${props.config.translation.sliderHold} (${props.remainingTime.toFixed(1)}s)` : props.config.translation.sliderRelease), h("span", { class: "sr-only" }, "Hold this button until the tone sounds")), h("div", { class: "text-right" }, h(PrivacyText, { privacyUrl: props.config.privacyUrl, translation: props.config.translation }))))); }; export const Slider = ({ props }) => (h("div", { role: "dialog", "aria-modal": "true" }, props.isSliderOpen && h("div", { class: "relative w-full" }, props.config.slider === 'popup' && (h("div", { class: "fixed inset-0 flex items-center justify-center z-50 bg-gray-800 bg-opacity-50" }, h(SliderContent, { props: props }))), props.config.slider === 'inline' && (h("div", { class: "absolute top-1/2 left-0 transform -translate-y-1/2 translate-x-8 z-50" }, h(SliderContent, { props: props })))))); //# sourceMappingURL=captcha-slider.js.map