UNPKG

react-native-qrcode-svg

Version:

A QR Code generator for React Native based on react-native-svg and javascript-qrcode.

188 lines (179 loc) 4.48 kB
import React, { useMemo, useId } from "react"; import Svg, { Defs, G, Path, Rect, Image, ClipPath, LinearGradient, Stop, } from "react-native-svg"; import genMatrix from "./genMatrix"; import transformMatrixIntoPath from "./transformMatrixIntoPath"; import LogoSVG from "./LogoSVG"; const renderLogo = ({ size, backgroundColor, logo, logoSVG, logoSize, logoBackgroundColor, logoColor, logoMargin, logoBorderRadius, clipPathId }) => { const logoPosition = (size - logoSize - logoMargin * 2) / 2; const logoBackgroundSize = logoSize + logoMargin * 2; const logoBackgroundBorderRadius = logoBorderRadius + (logoMargin / logoSize) * logoBorderRadius; const clipLogoBackgroundId = `clip-logo-background-${clipPathId}`; const clipLogoId = `clip-logo-${clipPathId}`; return ( <G x={logoPosition} y={logoPosition}> <Defs> <ClipPath id={clipLogoBackgroundId}> <Rect width={logoBackgroundSize} height={logoBackgroundSize} rx={logoBackgroundBorderRadius} ry={logoBackgroundBorderRadius} /> </ClipPath> <ClipPath id={clipLogoId}> <Rect width={logoSize} height={logoSize} rx={logoBorderRadius} ry={logoBorderRadius} /> </ClipPath> </Defs> <G> <Rect width={logoBackgroundSize} height={logoBackgroundSize} fill={backgroundColor} clipPath={`url(#${clipLogoBackgroundId})`} /> </G> <G x={logoMargin} y={logoMargin} clipPath={`url(#${clipLogoId})`}> <Rect width={logoBackgroundSize - logoMargin} height={logoBackgroundSize - logoMargin} fill={logoBackgroundColor} /> {logoSVG ? ( <LogoSVG svg={logoSVG} logoSize={logoSize} logoColor={logoColor} /> ) : ( <Image width={logoSize} height={logoSize} preserveAspectRatio="xMidYMid slice" href={logo} clipPath={`url(#${clipLogoId})`} /> )} </G> </G> ); }; const QRCode = ({ value = "this is a QR code", size = 100, color = "black", backgroundColor = "white", logo, logoSVG, logoSize = size * 0.2, logoBackgroundColor = "transparent", logoColor, logoMargin = 2, logoBorderRadius = 0, quietZone = 0, enableLinearGradient = false, gradientDirection = ["0%", "0%", "100%", "100%"], linearGradient = ["rgb(255,0,0)", "rgb(0,255,255)"], ecl = "M", getRef, onError, testID, }) => { const clipPathId = useId(); const result = useMemo(() => { try { return transformMatrixIntoPath(genMatrix(value, ecl), size); } catch (error) { if (onError && typeof onError === "function") { onError(error); } else { // Pass the error when no handler presented throw error; } } }, [value, size, ecl]); if (!result) { return null; } const { path, cellSize } = result; const displayLogo = logo || logoSVG; return ( <Svg testID={testID} ref={getRef} viewBox={[ -quietZone, -quietZone, size + quietZone * 2, size + quietZone * 2, ].join(" ")} width={size} height={size} > <Defs> <LinearGradient id="grad" x1={gradientDirection[0]} y1={gradientDirection[1]} x2={gradientDirection[2]} y2={gradientDirection[3]} > <Stop offset="0" stopColor={linearGradient[0]} stopOpacity="1" /> <Stop offset="1" stopColor={linearGradient[1]} stopOpacity="1" /> </LinearGradient> </Defs> <G> <Rect x={-quietZone} y={-quietZone} width={size + quietZone * 2} height={size + quietZone * 2} fill={backgroundColor} /> </G> <G> <Path d={path} strokeLinecap="butt" stroke={enableLinearGradient ? "url(#grad)" : color} strokeWidth={cellSize} /> </G> {displayLogo && renderLogo({ size, backgroundColor, logo, logoSVG, logoSize, logoBackgroundColor, logoColor, logoMargin, logoBorderRadius, clipPathId, })} </Svg> ); }; export default QRCode;