@trustcaptcha/trustcaptcha-frontend
Version:
Frondend library for trustcaptcha
137 lines (136 loc) • 7.77 kB
JavaScript
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