Skip to content

Commit 9a71d8d

Browse files
committed
feat: background gradient
1 parent 31d170c commit 9a71d8d

5 files changed

Lines changed: 64 additions & 12 deletions

File tree

apps/playground/src/App.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ function App() {
3131
value: 'https://github.com/LGLabGreg/react-qr-code.git',
3232
size: 500,
3333
marginSize: 3,
34-
bgColor: '#f1f1f1',
34+
background: '#f9f9f9',
3535
gradient: {
3636
type: 'linear',
3737
rotation: 0,
3838
stops: [
39-
{ offset: '0%', color: '#ff0000' },
40-
{ offset: '100%', color: '#0000ff' },
39+
{ offset: '0%', color: '#4568DC' },
40+
{ offset: '100%', color: '#B06AB3' },
4141
],
4242
},
4343
dataModulesSettings: {
@@ -64,7 +64,7 @@ function App() {
6464
}
6565

6666
const download = ({ format = 'svg', size = 400 }: DownloadOptions) => {
67-
ref.current?.download({ format, size, name: 'demo-qr-code' })
67+
ref.current?.download({ format, size })
6868
}
6969

7070
return (
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { BG_GRADIENT_ID, DEFAULT_BGCOLOR } from '../constants'
2+
import type { BackgroundSettings } from '../types/lib'
3+
import { calculateGradientVectors } from '../utils/svg'
4+
5+
interface BackgroundProps {
6+
background?: BackgroundSettings
7+
numCells: number
8+
}
9+
10+
export const Background = ({ background, numCells }: BackgroundProps) => {
11+
if (!background) {
12+
return <path fill={DEFAULT_BGCOLOR} d={`M0,0 h${numCells}v${numCells}H0z`} />
13+
}
14+
15+
if (typeof background === 'string') {
16+
return <path fill={background} d={`M0,0 h${numCells}v${numCells}H0z`} />
17+
}
18+
19+
const vectors = calculateGradientVectors(background?.rotation || 0)
20+
21+
return (
22+
<>
23+
<defs>
24+
{background.type === 'linear' ? (
25+
<linearGradient id={BG_GRADIENT_ID} gradientUnits='userSpaceOnUse' {...vectors}>
26+
{background.stops?.map((stop, index) => (
27+
<stop key={index} offset={stop.offset} stopColor={stop.color} />
28+
))}
29+
</linearGradient>
30+
) : (
31+
<radialGradient
32+
id={BG_GRADIENT_ID}
33+
gradientUnits='userSpaceOnUse'
34+
cx='50%'
35+
cy='50%'
36+
r='50%'
37+
>
38+
{background.stops?.map((stop, index) => (
39+
<stop key={index} offset={stop.offset} stopColor={stop.color} />
40+
))}
41+
</radialGradient>
42+
)}
43+
</defs>
44+
<path fill={`url(#${BG_GRADIENT_ID})`} d={`M0,0 h${numCells}v${numCells}H0z`} />
45+
</>
46+
)
47+
}

packages/react-qr-code/src/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ export const DEFAULT_FINDER_PATTERN_OUTER_STYLE: FinderPatternOuterStyle = 'squa
3333
export const DEFAULT_FINDER_PATTERN_INNER_STYLE: FinderPatternInnerStyle = 'square'
3434
export const DEFAULT_DATA_MODULES_STYLE: DataModulesStyle = 'square'
3535

36+
export const DEFAULT_FILENAME = 'react-qr-code'
37+
3638
export const GRADIENT_ID = 'react-qr-code-gradient'
39+
export const BG_GRADIENT_ID = 'react-qr-code-bg-gradient'
3740

3841
// This is *very* rough estimate of max amount of QRCode allowed to be covered.
3942
// It is "wrong" in a lot of ways (area is a terrible way to estimate, it

packages/react-qr-code/src/react-qr-code.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { useImperativeHandle, useRef } from 'react'
22

3+
import { Background } from './components/background'
34
import { DataModules } from './components/data-modules'
45
import { FinderPatternsInner } from './components/finder-patterns-inner'
56
import { FinderPatternsOuter } from './components/finder-patterns-outer'
67
import { Gradient } from './components/gradient'
78
import {
8-
DEFAULT_BGCOLOR,
9+
DEFAULT_FILENAME,
910
DEFAULT_LEVEL,
1011
DEFAULT_MINVERSION,
1112
DEFAULT_SIZE,
@@ -21,7 +22,7 @@ const ReactQRCode = (props: ReactQRCodeProps) => {
2122
value,
2223
size = DEFAULT_SIZE,
2324
level = DEFAULT_LEVEL,
24-
bgColor = DEFAULT_BGCOLOR,
25+
background,
2526
gradient,
2627
minVersion = DEFAULT_MINVERSION,
2728
boostLevel,
@@ -48,7 +49,7 @@ const ReactQRCode = (props: ReactQRCodeProps) => {
4849
useImperativeHandle(ref, () => ({
4950
svg: svgRef.current,
5051
download: ({
51-
name: fileName = 'qr-code',
52+
name: fileName = DEFAULT_FILENAME,
5253
format: fileFormat = 'svg',
5354
size: fileSize = 500,
5455
}: DownloadOptions) => {
@@ -111,7 +112,7 @@ const ReactQRCode = (props: ReactQRCodeProps) => {
111112
{...svgProps}
112113
>
113114
<Gradient gradient={gradient} />
114-
<path fill={bgColor} d={`M0,0 h${numCells}v${numCells}H0z`} />
115+
<Background background={background} numCells={numCells} />
115116
<FinderPatternsOuter settings={finderPatternOuterSettings} {...svgElementsProps} />
116117
<FinderPatternsInner settings={finderPatternInnerSettings} {...svgElementsProps} />
117118
<DataModules settings={dataModulesSettings} {...svgElementsProps} />

packages/react-qr-code/src/types/lib.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export type ERROR_LEVEL_MAPPED_TYPE = {
1515
/**
1616
* ReactQRCode props.
1717
*/
18+
export type BackgroundSettings = string | GradientSettings
19+
1820
export type GradientSettingsType = 'linear' | 'radial'
1921
export interface GradientSettingsStop {
2022
offset: string
@@ -143,13 +145,12 @@ export interface ReactQRCodeProps {
143145
*/
144146
boostLevel?: boolean
145147
/**
146-
* The background color used to render the QR Code.
147-
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
148+
* The QR code background either a hex color or GradientSettings.
148149
* @defaultValue #FFFFFF
149150
*/
150-
bgColor?: string
151+
background?: BackgroundSettings
151152
/**
152-
* The gradient settings applied to the whole qr code.
153+
* The gradient settings applied to the qr code data modules and finder patterns.
153154
*/
154155
gradient?: GradientSettings
155156
/**

0 commit comments

Comments
 (0)