kwikid-components-react
Version:
KwikID's Component Library in React
530 lines (482 loc) • 18.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getCaptchaLetterSpacing = exports.generateCaptchaText = exports.drawStandardCaptcha = exports.drawSimplifiedCaptcha = exports.drawNoisyCaptcha = exports.drawDistortedCaptcha = exports.drawCaptchaOnCanvas = void 0;
var _Captcha = require("./Captcha.definition");
const generateRandomChar = (min, max) => String.fromCharCode(Math.floor(Math.random() * (max - min + 1) + min));
const generateCaptchaText = characterSize => {
let captcha = "";
for (let i = 0; i < characterSize; i++) {
const charGenerators = [() => generateRandomChar(65, 90),
// Uppercase letters
() => generateRandomChar(97, 122),
// Lowercase letters
() => generateRandomChar(48, 57) // Numbers
];
const randomIndex = Math.floor(Math.random() * charGenerators.length);
captcha += charGenerators[randomIndex]();
}
return captcha.split("").sort(() => Math.random() - 0.5).join("");
};
/**
* Draw simplified captcha - basic text rendering
*/
exports.generateCaptchaText = generateCaptchaText;
const drawSimplifiedCaptcha = (ctx, captcha, size) => {
let xInitialSpacing;
let characterYSpacing;
let canvasWidth;
let canvasHeight;
switch (size) {
case _Captcha.IKwikUICaptchaSize.S:
canvasWidth = 120;
canvasHeight = 30;
xInitialSpacing = 10;
characterYSpacing = canvasHeight - 5;
break;
case _Captcha.IKwikUICaptchaSize.L:
canvasWidth = 300;
canvasHeight = 75;
xInitialSpacing = 20;
characterYSpacing = canvasHeight - 20;
break;
default:
canvasWidth = 200;
canvasHeight = 50;
xInitialSpacing = 15;
characterYSpacing = canvasHeight - 10;
break;
}
// Set canvas dimensions
ctx.canvas.width = canvasWidth;
ctx.canvas.height = canvasHeight;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
const fontSize = Math.min(canvasWidth / (captcha.length + 1), canvasHeight * 0.6);
const textColors = ["rgb(0, 0, 0)", "rgb(80, 80, 80)", "rgb(160, 160, 160)"];
ctx.font = "".concat(fontSize, "px Manrope Mono");
for (let i = 0; i < captcha.length; i++) {
ctx.fillStyle = textColors[Math.floor(Math.random() * textColors.length)];
ctx.fillText(captcha[i], xInitialSpacing + i * fontSize, characterYSpacing, fontSize);
}
};
/**
* Draw standard captcha - with light background and slight character rotation
*/
exports.drawSimplifiedCaptcha = drawSimplifiedCaptcha;
const drawStandardCaptcha = (ctx, captcha, size) => {
let xInitialSpacing;
let characterYSpacing;
let canvasWidth;
let canvasHeight;
switch (size) {
case _Captcha.IKwikUICaptchaSize.S:
canvasWidth = 120;
canvasHeight = 30;
xInitialSpacing = 10;
characterYSpacing = canvasHeight - 5;
break;
case _Captcha.IKwikUICaptchaSize.L:
canvasWidth = 300;
canvasHeight = 75;
xInitialSpacing = 20;
characterYSpacing = canvasHeight - 20;
break;
default:
canvasWidth = 200;
canvasHeight = 50;
xInitialSpacing = 15;
characterYSpacing = canvasHeight - 10;
break;
}
// Set canvas dimensions
ctx.canvas.width = canvasWidth;
ctx.canvas.height = canvasHeight;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// Fill background with complex gradient
const gradient = ctx.createRadialGradient(canvasWidth / 2, canvasHeight / 2, 5, canvasWidth / 2, canvasHeight / 2, canvasWidth / 1.5);
gradient.addColorStop(0, 'rgb(245, 245, 245)');
gradient.addColorStop(0.5, 'rgb(235, 235, 235)');
gradient.addColorStop(1, 'rgb(225, 225, 225)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// Add varied pattern background
for (let i = 0; i < canvasWidth; i += 3) {
for (let j = 0; j < canvasHeight; j += 3) {
if (Math.random() > 0.75) {
const grayValue = Math.floor(Math.random() * 30) + 200;
const opacity = 0.1 + Math.random() * 0.4;
ctx.fillStyle = "rgba(".concat(grayValue, ", ").concat(grayValue, ", ").concat(grayValue, ", ").concat(opacity, ")");
ctx.fillRect(i, j, Math.random() * 2 + 1, Math.random() * 2 + 1);
}
}
}
// Add noise pattern overlays
for (let i = 0; i < 300; i++) {
const x = Math.random() * canvasWidth;
const y = Math.random() * canvasHeight;
const size = Math.random() * 1.5;
const opacity = 0.05 + Math.random() * 0.15;
const grayValue = Math.floor(Math.random() * 100) + 100;
ctx.beginPath();
ctx.fillStyle = "rgba(".concat(grayValue, ", ").concat(grayValue, ", ").concat(grayValue, ", ").concat(opacity, ")");
if (Math.random() > 0.5) {
ctx.arc(x, y, size, 0, Math.PI * 2);
} else {
ctx.rect(x, y, size, size);
}
ctx.fill();
}
// Add curved intersecting lines
for (let i = 0; i < 10; i++) {
ctx.beginPath();
const startX = Math.random() * canvasWidth;
const startY = Math.random() * canvasHeight;
const cp1x = Math.random() * canvasWidth;
const cp1y = Math.random() * canvasHeight;
const cp2x = Math.random() * canvasWidth;
const cp2y = Math.random() * canvasHeight;
const endX = Math.random() * canvasWidth;
const endY = Math.random() * canvasHeight;
ctx.moveTo(startX, startY);
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, endX, endY);
const grayValue = Math.floor(Math.random() * 70) + 170;
const opacity = 0.1 + Math.random() * 0.2;
ctx.strokeStyle = "rgba(".concat(grayValue, ", ").concat(grayValue, ", ").concat(grayValue, ", ").concat(opacity, ")");
ctx.lineWidth = 0.5 + Math.random() * 0.5;
ctx.stroke();
}
// Add background grid patterns
for (let i = 0; i < canvasWidth; i += 10) {
ctx.beginPath();
ctx.moveTo(i, 0);
ctx.lineTo(i, canvasHeight);
const opacity = 0.02 + Math.random() * 0.05;
ctx.strokeStyle = "rgba(100, 100, 100, ".concat(opacity, ")");
ctx.lineWidth = 0.5;
ctx.stroke();
}
for (let i = 0; i < canvasHeight; i += 10) {
ctx.beginPath();
ctx.moveTo(0, i);
ctx.lineTo(canvasWidth, i);
const opacity = 0.02 + Math.random() * 0.05;
ctx.strokeStyle = "rgba(100, 100, 100, ".concat(opacity, ")");
ctx.lineWidth = 0.5;
ctx.stroke();
}
const fontSize = Math.min(canvasWidth / (captcha.length + 1), canvasHeight * 0.6);
// Grayscale text colors with varying intensities and opacity
const textColors = ["rgba(20, 20, 20, 0.9)",
// Near black, slight transparency
"rgba(40, 40, 40, 0.85)",
// Very dark gray with transparency
"rgba(60, 60, 60, 0.95)",
// Dark gray, more opaque
"rgba(0, 0, 0, 0.8)" // Black with transparency
];
// Font variations
const fontVariations = ["".concat(fontSize, "px Manrope Mono"), "bold ".concat(fontSize, "px Manrope Mono"), "italic ".concat(fontSize, "px Manrope Mono"), "".concat(fontSize - 1, "px Manrope Mono")];
// Calculate total width of text to center it
const totalTextWidth = fontSize * captcha.length;
const startX = (canvasWidth - totalTextWidth) / 2;
// Draw slight shadow versions of the text first
for (let i = 0; i < captcha.length; i++) {
ctx.save();
const charX = startX + i * fontSize;
ctx.translate(charX, characterYSpacing);
const shadowOpacity = 0.1 + Math.random() * 0.2;
ctx.fillStyle = "rgba(150, 150, 150, ".concat(shadowOpacity, ")");
ctx.font = fontVariations[Math.floor(Math.random() * fontVariations.length)];
// Offset shadow
const shadowOffsetX = (Math.random() - 0.5) * 3;
const shadowOffsetY = (Math.random() - 0.5) * 3;
ctx.fillText(captcha[i], shadowOffsetX, shadowOffsetY, fontSize);
ctx.restore();
}
// Draw main text characters with variations
for (let i = 0; i < captcha.length; i++) {
ctx.save();
const charX = startX + i * fontSize;
ctx.translate(charX, characterYSpacing);
// More pronounced rotation
const rotation = (Math.random() - 0.5) * 0.25;
ctx.rotate(rotation);
// Add shadow for depth
ctx.shadowColor = 'rgba(0, 0, 0, 0.2)';
ctx.shadowBlur = 1 + Math.random() * 2;
ctx.shadowOffsetX = 0.5 + Math.random() * 1;
ctx.shadowOffsetY = 0.5 + Math.random() * 1;
ctx.fillStyle = textColors[Math.floor(Math.random() * textColors.length)];
// Random font for each character
ctx.font = fontVariations[Math.floor(Math.random() * fontVariations.length)];
// Varied character distortion
const scaleX = 0.85 + Math.random() * 0.3;
const scaleY = 0.85 + Math.random() * 0.3;
ctx.scale(scaleX, scaleY);
// Apply skew for more distortion
const skewX = (Math.random() - 0.5) * 0.4;
const skewY = (Math.random() - 0.5) * 0.2;
ctx.transform(1, skewY, skewX, 1, 0, 0);
// Draw the character
ctx.fillText(captcha[i], 0, 0, fontSize);
// Sometimes draw a second time with slight offset for bold effect
if (Math.random() > 0.6) {
ctx.fillText(captcha[i], 0.5, 0.5, fontSize);
}
ctx.restore();
}
// Add a few overlapping elements on top
for (let i = 0; i < 5; i++) {
ctx.beginPath();
const startX = Math.random() * canvasWidth;
const startY = Math.random() * canvasHeight;
const endX = startX + (Math.random() - 0.5) * 80;
const endY = startY + (Math.random() - 0.5) * 30;
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
const opacity = 0.05 + Math.random() * 0.15;
ctx.strokeStyle = "rgba(50, 50, 50, ".concat(opacity, ")");
ctx.lineWidth = 0.5 + Math.random() * 1;
ctx.stroke();
}
};
/**
* Draw noisy captcha - with background noise and lines
*/
exports.drawStandardCaptcha = drawStandardCaptcha;
const drawNoisyCaptcha = (ctx, captcha, size) => {
let xInitialSpacing;
let characterYSpacing;
let canvasWidth;
let canvasHeight;
switch (size) {
case _Captcha.IKwikUICaptchaSize.S:
canvasWidth = 120;
canvasHeight = 30;
xInitialSpacing = 10;
characterYSpacing = canvasHeight - 5;
break;
case _Captcha.IKwikUICaptchaSize.L:
canvasWidth = 300;
canvasHeight = 75;
xInitialSpacing = 20;
characterYSpacing = canvasHeight - 20;
break;
default:
canvasWidth = 200;
canvasHeight = 50;
xInitialSpacing = 15;
characterYSpacing = canvasHeight - 10;
break;
}
// Set canvas dimensions
ctx.canvas.width = canvasWidth;
ctx.canvas.height = canvasHeight;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// Fill background with light gray
ctx.fillStyle = 'rgb(240, 240, 240)';
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// Add grayscale noise patterns (lighter gray)
for (let i = 0; i < 600; i++) {
const grayValue = Math.floor(Math.random() * 100) + 150; // Light to medium gray
ctx.fillStyle = "rgb(".concat(grayValue, ", ").concat(grayValue, ", ").concat(grayValue, ")");
ctx.fillRect(Math.random() * canvasWidth, Math.random() * canvasHeight, Math.random() * 2, Math.random() * 2);
}
// Add many black/dark dots to confuse OCR
for (let i = 0; i < 1000; i++) {
const size = Math.random() * 1.5;
const x = Math.random() * canvasWidth;
const y = Math.random() * canvasHeight;
// Vary the darkness of dots to create more noise
const darkness = Math.floor(Math.random() * 50);
ctx.fillStyle = "rgb(".concat(darkness, ", ").concat(darkness, ", ").concat(darkness, ")");
// Use different shapes for dots to increase complexity
if (Math.random() > 0.7) {
// Circular dots
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fill();
} else {
// Square dots
ctx.fillRect(x, y, size, size);
}
}
const fontSize = Math.min(canvasWidth / (captcha.length + 1), canvasHeight * 0.6);
const textColors = ["rgb(0, 0, 0)",
// Black
"rgb(20, 20, 20)",
// Near black
"rgb(40, 40, 40)",
// Very dark gray
"rgb(60, 60, 60)" // Dark gray
];
ctx.font = "bold ".concat(fontSize, "px Manrope Mono");
// Calculate total width to center text
const totalTextWidth = fontSize * captcha.length;
const startX = (canvasWidth - totalTextWidth) / 2;
// Draw text with bold effect to stand out from noise
for (let i = 0; i < captcha.length; i++) {
ctx.save();
const charX = startX + i * fontSize;
ctx.translate(charX, characterYSpacing);
// Medium rotation for each character
const rotation = (Math.random() - 0.5) * 0.2;
ctx.rotate(rotation);
// Add slight shadow for better visibility against noise
ctx.shadowColor = 'rgba(255, 255, 255, 0.5)';
ctx.shadowBlur = 2;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.fillStyle = textColors[Math.floor(Math.random() * textColors.length)];
// Draw character with offset for bold effect
ctx.fillText(captcha[i], 0, 0, fontSize);
ctx.fillText(captcha[i], 0.5, 0.5, fontSize);
ctx.restore();
}
// Add random crossing lines
for (let i = 0; i < 8; i++) {
ctx.beginPath();
const startX = Math.random() * canvasWidth;
const startY = Math.random() * canvasHeight;
const endX = startX + (Math.random() - 0.5) * 80;
const endY = startY + (Math.random() - 0.5) * 80;
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
const grayValue = Math.floor(Math.random() * 80) + 20; // Dark to very dark gray
ctx.strokeStyle = "rgb(".concat(grayValue, ", ").concat(grayValue, ", ").concat(grayValue, ")");
ctx.lineWidth = Math.random() * 1 + 0.5;
ctx.stroke();
}
};
/**
* Draw distorted captcha - with wave effects and transform distortions
*/
exports.drawNoisyCaptcha = drawNoisyCaptcha;
const drawDistortedCaptcha = (ctx, captcha, size) => {
let xInitialSpacing;
let characterYSpacing;
let canvasWidth;
let canvasHeight;
switch (size) {
case _Captcha.IKwikUICaptchaSize.S:
canvasWidth = 120;
canvasHeight = 30;
xInitialSpacing = 10;
characterYSpacing = canvasHeight - 5;
break;
case _Captcha.IKwikUICaptchaSize.L:
canvasWidth = 300;
canvasHeight = 75;
xInitialSpacing = 20;
characterYSpacing = canvasHeight - 20;
break;
default:
canvasWidth = 200;
canvasHeight = 50;
xInitialSpacing = 15;
characterYSpacing = canvasHeight - 10;
break;
}
// Set canvas dimensions
ctx.canvas.width = canvasWidth;
ctx.canvas.height = canvasHeight;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// Fill background with light gray
ctx.fillStyle = 'rgb(240, 240, 240)';
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// Add grayscale noise patterns
for (let i = 0; i < 100; i++) {
const grayValue = Math.floor(Math.random() * 100) + 150;
ctx.fillStyle = "rgb(".concat(grayValue, ", ").concat(grayValue, ", ").concat(grayValue, ")");
ctx.fillRect(Math.random() * canvasWidth, Math.random() * canvasHeight, Math.random() * 2, Math.random() * 2);
}
const fontSize = Math.min(canvasWidth / (captcha.length + 1), canvasHeight * 0.6);
const textColors = ["rgb(0, 0, 0)",
// Black
"rgb(40, 40, 40)",
// Very dark gray
"rgb(80, 80, 80)",
// Dark gray
"rgb(120, 120, 120)",
// Medium gray
"rgb(160, 160, 160)" // Light gray
];
ctx.font = "".concat(fontSize, "px Manrope Mono");
// Calculate total width to center text
const totalTextWidth = fontSize * captcha.length;
const startX = (canvasWidth - totalTextWidth) / 2;
for (let i = 0; i < captcha.length; i++) {
ctx.save();
const charX = startX + i * fontSize;
ctx.translate(charX, characterYSpacing);
// Strong rotation for each character
const rotation = (Math.random() - 0.5) * 0.3;
ctx.rotate(rotation);
// Add shadow for depth
ctx.shadowColor = 'rgba(0, 0, 0, 0.2)';
ctx.shadowBlur = 1;
ctx.shadowOffsetX = 1;
ctx.shadowOffsetY = 1;
ctx.fillStyle = textColors[Math.floor(Math.random() * textColors.length)];
// Add distortion
const distortion = (Math.random() - 0.5) * 2;
ctx.transform(1, distortion, 0, 1, 0, 0);
// Draw character with slight offset for bold effect
ctx.fillText(captcha[i], 0, 0, fontSize);
ctx.fillText(captcha[i], 1, 1, fontSize);
ctx.restore();
}
// Add wave distortion
for (let i = 0; i < canvasHeight; i += 2) {
const wave = Math.sin(i / 10) * 2;
ctx.beginPath();
ctx.moveTo(0, i);
ctx.lineTo(canvasWidth, i);
ctx.strokeStyle = "rgba(0, 0, 0, ".concat(Math.random() * 0.1, ")");
ctx.lineWidth = 1;
ctx.stroke();
}
// Add crossing lines
for (let i = 0; i < 5; i++) {
ctx.beginPath();
const startX = Math.random() * canvasWidth;
const startY = Math.random() * canvasHeight;
const endX = startX + (Math.random() - 0.5) * 70;
const endY = startY + (Math.random() - 0.5) * 70;
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
const grayValue = Math.floor(Math.random() * 100) + 100;
ctx.strokeStyle = "rgb(".concat(grayValue, ", ").concat(grayValue, ", ").concat(grayValue, ")");
ctx.lineWidth = Math.random() * 1.5;
ctx.stroke();
}
};
/**
* Draw captcha on canvas based on variant
*/
exports.drawDistortedCaptcha = drawDistortedCaptcha;
const drawCaptchaOnCanvas = function (ctx, captcha, size) {
let variant = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _Captcha.IKwikUICaptchaVariant.SIMPLIFIED;
if (!ctx) return;
switch (variant) {
case _Captcha.IKwikUICaptchaVariant.SIMPLIFIED:
drawSimplifiedCaptcha(ctx, captcha, size);
break;
case _Captcha.IKwikUICaptchaVariant.STANDARD:
drawStandardCaptcha(ctx, captcha, size);
break;
case _Captcha.IKwikUICaptchaVariant.NOISY:
drawNoisyCaptcha(ctx, captcha, size);
break;
case _Captcha.IKwikUICaptchaVariant.DISTORTED:
drawDistortedCaptcha(ctx, captcha, size);
break;
default:
drawSimplifiedCaptcha(ctx, captcha, size);
break;
}
};
exports.drawCaptchaOnCanvas = drawCaptchaOnCanvas;
const getCaptchaLetterSpacing = value => getComputedStyle(document.documentElement).getPropertyValue(value);
exports.getCaptchaLetterSpacing = getCaptchaLetterSpacing;