Skip to content

Commit 4a528f0

Browse files
committed
feat: Add 'pinched-square' style for modules and finder patterns
1 parent 4d3d36d commit 4a528f0

11 files changed

Lines changed: 100 additions & 10 deletions

File tree

.changeset/modern-trees-beg.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@lglab/react-qr-code': minor
3+
---
4+
5+
Add 'pinched-square' style for modules and finder patterns

apps/playground/src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import {
1818

1919
function App() {
2020
const [finderPatternOuterStyle, setFinderPatternOuterStyle] =
21-
useState<FinderPatternOuterStyle>('square')
21+
useState<FinderPatternOuterStyle>('pinched-square')
2222
const [finderPatternInnerStyle, setFinderPatternInnerStyle] =
23-
useState<FinderPatternInnerStyle>('square')
23+
useState<FinderPatternInnerStyle>('pinched-square')
2424
const [dataModulesStyle, setDataModulesStyle] = useState<DataModulesStyle>('square')
2525
const [dataModulesRandomSize, setDataModulesRandomSize] = useState<boolean>(false)
2626

apps/playground/src/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66

77
export const FINDER_PATTERN_OUTER_STYLES: FinderPatternOuterStyle[] = [
88
'square',
9+
'pinched-square',
910
'rounded-sm',
1011
'rounded',
1112
'rounded-lg',
@@ -23,6 +24,7 @@ export const FINDER_PATTERN_OUTER_STYLES: FinderPatternOuterStyle[] = [
2324

2425
export const FINDER_PATTERN_INNER_STYLES: FinderPatternInnerStyle[] = [
2526
'square',
27+
'pinched-square',
2628
'rounded-sm',
2729
'rounded',
2830
'rounded-lg',
@@ -45,6 +47,7 @@ export const FINDER_PATTERN_INNER_STYLES: FinderPatternInnerStyle[] = [
4547
export const DATA_MODULES_STYLES: DataModulesStyle[] = [
4648
'square',
4749
'square-sm',
50+
'pinched-square',
4851
'rounded',
4952
'leaf',
5053
'vertical-line',

packages/react-qr-code/src/components/data-modules.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ describe('DataModules', () => {
3535
heart: 'heart',
3636
star: 'star',
3737
hashtag: 'hashtag',
38+
'pinched-square': 'pinchedSquare',
3839
}
3940

4041
Object.entries(stylesToMethods).forEach(([style, method]) => {
41-
const utils = ['heart', 'star', 'hashtag'].includes(style)
42+
const utils = ['heart', 'star', 'hashtag', 'pinched-square'].includes(style)
4243
? svgUtils
4344
: dataModulesUtils
4445
const spy = vi.spyOn(utils, method as keyof typeof utils)

packages/react-qr-code/src/components/data-modules.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
import { isFinderPatternInnerModule } from '../utils/finder-patterns-inner'
2525
import { isFinderPatternOuterModule } from '../utils/finder-patterns-outer'
2626
import { sanitizeDataModulesSettings } from '../utils/settings'
27-
import { hashtag, heart, star } from '../utils/svg'
27+
import { hashtag, heart, pinchedSquare, star } from '../utils/svg'
2828

2929
export const DataModules = ({
3030
modules,
@@ -65,6 +65,8 @@ export const DataModules = ({
6565
if (cell) {
6666
if (style === 'square' || style === 'square-sm') {
6767
ops.push(square(xPos, yPos, size))
68+
} else if (style === 'pinched-square') {
69+
ops.push(pinchedSquare(xPos, yPos, size, 0.25))
6870
} else if (style === 'circle') {
6971
ops.push(circle(xPos, yPos, size))
7072
} else if (style === 'diamond') {

packages/react-qr-code/src/components/finder-patter-inner.test.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,20 @@ describe('DataModules', () => {
146146
expect(path.getAttribute('fill')).toBe('#ff0000')
147147
})
148148
})
149+
150+
it('renders correctly with style pinched-square', () => {
151+
const spy = vi.spyOn(svgUtils, 'pinchedSquare')
152+
render(
153+
<FinderPatternsInner
154+
{...defaultProps}
155+
settings={{ style: 'pinched-square', color: '#ff0000' }}
156+
/>,
157+
)
158+
const paths = screen.getAllByTestId('finder-patterns-inner')
159+
expect(paths).toHaveLength(3)
160+
paths.forEach((path) => {
161+
expect(spy).toHaveBeenCalled()
162+
expect(path.getAttribute('fill')).toBe('#ff0000')
163+
})
164+
})
149165
})

packages/react-qr-code/src/components/finder-patter-outer.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,21 @@ describe('DataModules', () => {
6767
)
6868
})
6969

70+
it('renders correctly with style pinched-square', () => {
71+
render(
72+
<FinderPatternsOuter
73+
{...defaultProps}
74+
settings={{ style: 'pinched-square', color: '#ff0000' }}
75+
/>,
76+
)
77+
const paths = screen.getAllByTestId('finder-patterns-outer')
78+
expect(paths).toHaveLength(1)
79+
expect(paths[0].getAttribute('fill')).toBe('#ff0000')
80+
expect(paths[0].getAttribute('d')).toBe(
81+
'M 2 2Q 2.5 5.5, 2 9Q 5.5 8.5, 9 9Q 8.5 5.5, 9 2Q 5.5 2.5, 2 2zM 3 3Q 5.5 3.25, 8 3Q 7.75 5.5, 8 8Q 5.5 7.75, 3 8Q 3.25 5.5, 3 3zM -2 2Q -1.5 5.5, -2 9Q 1.5 8.5, 5 9Q 4.5 5.5, 5 2Q 1.5 2.5, -2 2zM -1 3Q 1.5 3.25, 4 3Q 3.75 5.5, 4 8Q 1.5 7.75, -1 8Q -0.75 5.5, -1 3zM 2 -2Q 2.5 1.5, 2 5Q 5.5 4.5, 9 5Q 8.5 1.5, 9 -2Q 5.5 -1.5, 2 -2zM 3 -1Q 5.5 -0.75, 8 -1Q 7.75 1.5, 8 4Q 5.5 3.75, 3 4Q 3.25 1.5, 3 -1z',
82+
)
83+
})
84+
7085
it('calls the correct shape function based on style prop', () => {
7186
const stylesToMethods = {
7287
'inpoint-sm': 'finderPatternsOuterInOutPoint',

packages/react-qr-code/src/components/finder-patterns-inner.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
finderPatternsInnerLeaf,
1515
} from '../utils/finder-patterns-inner'
1616
import { sanitizeFinderPatternInnerSettings } from '../utils/settings'
17-
import { hashtag, heart, star } from '../utils/svg'
17+
import { hashtag, heart, pinchedSquare, star } from '../utils/svg'
1818

1919
const testProps = {
2020
'data-testid': 'finder-patterns-inner',
@@ -67,6 +67,14 @@ export const FinderPatternsInner = ({
6767
})
6868
}
6969

70+
if (style === 'pinched-square') {
71+
return coordinates.map((coordinate) => {
72+
const { x, y } = coordinate
73+
const path = pinchedSquare(x, y, FINDER_PATTERN_INNER_SIZE, 0.25)
74+
return <path key={key(x, y)} fill={fill} d={path} {...testProps} />
75+
})
76+
}
77+
7078
if (style === 'diamond') {
7179
return coordinates.map((coordinate) => {
7280
const { x, y } = coordinate

packages/react-qr-code/src/components/finder-patterns-outer.tsx

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,16 @@ export const FinderPatternsOuter = ({
4141
[margin, modules.length],
4242
)
4343

44-
if (['rounded-sm', 'rounded', 'rounded-lg', 'circle', 'square'].includes(style)) {
44+
if (
45+
[
46+
'rounded-sm',
47+
'rounded',
48+
'rounded-lg',
49+
'circle',
50+
'square',
51+
'pinched-square',
52+
].includes(style)
53+
) {
4554
for (const coordinate of coordinates) {
4655
const { x, y } = coordinate
4756
if (style === 'rounded-sm' || style === 'rounded' || style === 'rounded-lg') {
@@ -63,6 +72,21 @@ export const FinderPatternsOuter = ({
6372
} 0 1 1 -0.01 0` +
6473
'Z',
6574
)
75+
} else if (style === 'pinched-square') {
76+
ops.push(
77+
`M ${x} ${y}` +
78+
`Q ${x + 0.5} ${y + FINDER_PATTERN_SIZE / 2}, ${x} ${y + FINDER_PATTERN_SIZE}` +
79+
`Q ${x + FINDER_PATTERN_SIZE / 2} ${y + FINDER_PATTERN_SIZE - 0.5}, ${x + FINDER_PATTERN_SIZE} ${y + FINDER_PATTERN_SIZE}` +
80+
`Q ${x + FINDER_PATTERN_SIZE - 0.5} ${y + FINDER_PATTERN_SIZE / 2}, ${x + FINDER_PATTERN_SIZE} ${y}` +
81+
`Q ${x + FINDER_PATTERN_SIZE / 2} ${y + 0.5}, ${x} ${y}` +
82+
'z' +
83+
`M ${x + 1} ${y + 1}` +
84+
`Q ${x + FINDER_PATTERN_SIZE / 2} ${y + 1.25}, ${x + FINDER_PATTERN_SIZE - 1} ${y + 1}` +
85+
`Q ${x + FINDER_PATTERN_SIZE - 1.25} ${y + FINDER_PATTERN_SIZE / 2}, ${x + FINDER_PATTERN_SIZE - 1} ${y + FINDER_PATTERN_SIZE - 1}` +
86+
`Q ${x + FINDER_PATTERN_SIZE / 2} ${y + FINDER_PATTERN_SIZE - 1.25}, ${x + 1} ${y + FINDER_PATTERN_SIZE - 1}` +
87+
`Q ${x + 1.25} ${y + FINDER_PATTERN_SIZE / 2}, ${x + 1} ${y + 1}` +
88+
'z',
89+
)
6690
} else {
6791
ops.push(
6892
`M ${x} ${y}` +
@@ -71,9 +95,9 @@ export const FinderPatternsOuter = ({
7195
`v ${-FINDER_PATTERN_SIZE}` +
7296
'z' +
7397
`M ${x + 1} ${y + 1}` +
74-
`h ${FINDER_PATTERN_SIZE - 2 * 1}` +
75-
`v ${FINDER_PATTERN_SIZE - 2 * 1}` +
76-
`h ${-FINDER_PATTERN_SIZE + 2 * 1}` +
98+
`h ${FINDER_PATTERN_SIZE - 2}` +
99+
`v ${FINDER_PATTERN_SIZE - 2}` +
100+
`h ${-FINDER_PATTERN_SIZE + 2}` +
77101
'z',
78102
)
79103
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface GradientSettings {
3131
export type DataModulesStyle =
3232
| 'square'
3333
| 'square-sm'
34+
| 'pinched-square'
3435
| 'rounded'
3536
| 'leaf'
3637
| 'vertical-line'
@@ -49,6 +50,7 @@ export interface DataModulesSettings {
4950

5051
export type FinderPatternOuterStyle =
5152
| 'square'
53+
| 'pinched-square'
5254
| 'rounded-sm'
5355
| 'rounded'
5456
| 'rounded-lg'
@@ -70,6 +72,7 @@ export interface FinderPatternOuterSettings {
7072

7173
export type FinderPatternInnerStyle =
7274
| 'square'
75+
| 'pinched-square'
7376
| 'rounded-sm'
7477
| 'rounded'
7578
| 'rounded-lg'

0 commit comments

Comments
 (0)