UNPKG

@reown/appkit-ui

Version:

The full stack toolkit to build onchain app UX.

129 lines 5.49 kB
import QRCodeUtil from 'qrcode'; import { svg } from 'lit'; const CONNECTING_ERROR_MARGIN = 0.1; const CIRCLE_SIZE_MODIFIER = 2.5; const QRCODE_MATRIX_MARGIN = 7; function isAdjecentDots(cy, otherCy, cellSize) { if (cy === otherCy) { return false; } const diff = cy - otherCy < 0 ? otherCy - cy : cy - otherCy; return diff <= cellSize + CONNECTING_ERROR_MARGIN; } function getMatrix(value, errorCorrectionLevel) { const arr = Array.prototype.slice.call(QRCodeUtil.create(value, { errorCorrectionLevel }).modules.data, 0); const sqrt = Math.sqrt(arr.length); return arr.reduce((rows, key, index) => (index % sqrt === 0 ? rows.push([key]) : rows[rows.length - 1].push(key)) && rows, []); } export const QrCodeUtil = { generate({ uri, size, logoSize, padding = 8, dotColor = 'var(--apkt-colors-black)' }) { const strokeWidth = 10; const dots = []; const matrix = getMatrix(uri, 'Q'); const cellSize = (size - 2 * padding) / matrix.length; const qrList = [ { x: 0, y: 0 }, { x: 1, y: 0 }, { x: 0, y: 1 } ]; qrList.forEach(({ x, y }) => { const x1 = (matrix.length - QRCODE_MATRIX_MARGIN) * cellSize * x + padding; const y1 = (matrix.length - QRCODE_MATRIX_MARGIN) * cellSize * y + padding; const borderRadius = 0.45; for (let i = 0; i < qrList.length; i += 1) { const dotSize = cellSize * (QRCODE_MATRIX_MARGIN - i * 2); dots.push(svg ` <rect fill=${i === 2 ? 'var(--apkt-colors-black)' : 'var(--apkt-colors-white)'} width=${i === 0 ? dotSize - strokeWidth : dotSize} rx= ${i === 0 ? (dotSize - strokeWidth) * borderRadius : dotSize * borderRadius} ry= ${i === 0 ? (dotSize - strokeWidth) * borderRadius : dotSize * borderRadius} stroke=${dotColor} stroke-width=${i === 0 ? strokeWidth : 0} height=${i === 0 ? dotSize - strokeWidth : dotSize} x= ${i === 0 ? y1 + cellSize * i + strokeWidth / 2 : y1 + cellSize * i} y= ${i === 0 ? x1 + cellSize * i + strokeWidth / 2 : x1 + cellSize * i} /> `); } }); const clearArenaSize = Math.floor((logoSize + 25) / cellSize); const matrixMiddleStart = matrix.length / 2 - clearArenaSize / 2; const matrixMiddleEnd = matrix.length / 2 + clearArenaSize / 2 - 1; const circles = []; matrix.forEach((row, i) => { row.forEach((_, j) => { if (matrix[i][j]) { if (!((i < QRCODE_MATRIX_MARGIN && j < QRCODE_MATRIX_MARGIN) || (i > matrix.length - (QRCODE_MATRIX_MARGIN + 1) && j < QRCODE_MATRIX_MARGIN) || (i < QRCODE_MATRIX_MARGIN && j > matrix.length - (QRCODE_MATRIX_MARGIN + 1)))) { if (!(i > matrixMiddleStart && i < matrixMiddleEnd && j > matrixMiddleStart && j < matrixMiddleEnd)) { const cx = i * cellSize + cellSize / 2 + padding; const cy = j * cellSize + cellSize / 2 + padding; circles.push([cx, cy]); } } } }); }); const circlesToConnect = {}; circles.forEach(([cx, cy]) => { if (circlesToConnect[cx]) { circlesToConnect[cx]?.push(cy); } else { circlesToConnect[cx] = [cy]; } }); Object.entries(circlesToConnect) .map(([cx, cys]) => { const newCys = cys.filter(cy => cys.every(otherCy => !isAdjecentDots(cy, otherCy, cellSize))); return [Number(cx), newCys]; }) .forEach(([cx, cys]) => { cys.forEach(cy => { dots.push(svg `<circle cx=${cx} cy=${cy} fill=${dotColor} r=${cellSize / CIRCLE_SIZE_MODIFIER} />`); }); }); Object.entries(circlesToConnect) .filter(([_, cys]) => cys.length > 1) .map(([cx, cys]) => { const newCys = cys.filter(cy => cys.some(otherCy => isAdjecentDots(cy, otherCy, cellSize))); return [Number(cx), newCys]; }) .map(([cx, cys]) => { cys.sort((a, b) => (a < b ? -1 : 1)); const groups = []; for (const cy of cys) { const group = groups.find(item => item.some(otherCy => isAdjecentDots(cy, otherCy, cellSize))); if (group) { group.push(cy); } else { groups.push([cy]); } } return [cx, groups.map(item => [item[0], item[item.length - 1]])]; }) .forEach(([cx, groups]) => { groups.forEach(([y1, y2]) => { dots.push(svg ` <line x1=${cx} x2=${cx} y1=${y1} y2=${y2} stroke=${dotColor} stroke-width=${cellSize / (CIRCLE_SIZE_MODIFIER / 2)} stroke-linecap="round" /> `); }); }); return dots; } }; //# sourceMappingURL=QrCode.js.map