Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/silver-traces-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@lglab/react-qr-code': minor
---

Add circuit-board data module style and microchip finder pattern inner style.
2 changes: 1 addition & 1 deletion apps/docs/public/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The main component exported by the library.
| `randomSize` | `boolean` | `false` | If true, modules will have slightly varied sizes. |

**Available Styles (`DataModulesStyle`):**
`'square'`, `'square-sm'`, `'pinched-square'`, `'rounded'`, `'leaf'`, `'vertical-line'`, `'horizontal-line'`, `'circle'`, `'diamond'`, `'star'`, `'heart'`, `'hashtag'`
`'square'`, `'square-sm'`, `'pinched-square'`, `'rounded'`, `'leaf'`, `'vertical-line'`, `'horizontal-line'`, `'circuit-board'`, `'circle'`, `'diamond'`, `'star'`, `'heart'`, `'hashtag'`

### FinderPatternOuterSettings

Expand Down
19 changes: 10 additions & 9 deletions apps/docs/src/app/data-modules-settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@ const props: Prop[] = [
description: 'The style of the modules',
defaultValue: 'square',
possibleValues: [
'square',
'square-sm',
'pinched-square',
'rounded',
'leaf',
'vertical-line',
'horizontal-line',
'circle',
'circuit-board',
'diamond',
'star',
'heart',
'hashtag',
'heart',
'horizontal-line',
'leaf',
'pinched-square',
'rounded',
'square',
'square-sm',
'star',
'vertical-line',
],
},
{
Expand Down
27 changes: 14 additions & 13 deletions apps/docs/src/app/finder-pattern-inner-settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@ const props: Prop[] = [
description: 'The style of the finder patterns inner part',
defaultValue: 'square',
possibleValues: [
'square',
'pinched-square',
'rounded-sm',
'rounded',
'rounded-lg',
'circle',
'inpoint-sm',
'diamond',
'hashtag',
'heart',
'inpoint',
'inpoint-lg',
'outpoint-sm',
'outpoint',
'outpoint-lg',
'leaf-sm',
'inpoint-sm',
'leaf',
'leaf-lg',
'diamond',
'leaf-sm',
'microchip',
'outpoint',
'outpoint-lg',
'outpoint-sm',
'pinched-square',
'rounded',
'rounded-lg',
'rounded-sm',
'square',
'star',
'heart',
'hashtag',
],
},
]
Expand Down
20 changes: 10 additions & 10 deletions apps/docs/src/app/finder-pattern-outer-settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,21 @@ const props: Prop[] = [
description: 'The style of the finder patterns outer part',
defaultValue: 'square',
possibleValues: [
'square',
'pinched-square',
'rounded-sm',
'rounded',
'rounded-lg',
'circle',
'inpoint-sm',
'inpoint',
'inpoint-lg',
'outpoint-sm',
'outpoint',
'outpoint-lg',
'leaf-sm',
'inpoint-sm',
'leaf',
'leaf-lg',
'leaf-sm',
'outpoint',
'outpoint-lg',
'outpoint-sm',
'pinched-square',
'rounded',
'rounded-lg',
'rounded-sm',
'square',
],
},
]
Expand Down
19 changes: 10 additions & 9 deletions apps/docs/src/components/demo/data-modules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@ interface DataModulesProps {
}

const styles: DataModulesStyle[] = [
'square',
'square-sm',
'pinched-square',
'rounded',
'leaf',
'vertical-line',
'horizontal-line',
'circle',
'circuit-board',
'diamond',
'star',
'heart',
'hashtag',
'heart',
'horizontal-line',
'leaf',
'pinched-square',
'rounded',
'square',
'square-sm',
'star',
'vertical-line',
]

export const DataModules = ({ qrProps, setQrProps }: DataModulesProps) => {
Expand Down
27 changes: 14 additions & 13 deletions apps/docs/src/components/demo/finder-pattern-inner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,26 @@ interface FinderPatternInnerProps {
}

const styles: FinderPatternInnerStyle[] = [
'square',
'pinched-square',
'rounded-sm',
'rounded',
'rounded-lg',
'circle',
'inpoint-sm',
'diamond',
'hashtag',
'heart',
'inpoint',
'inpoint-lg',
'outpoint-sm',
'outpoint',
'outpoint-lg',
'leaf-sm',
'inpoint-sm',
'leaf',
'leaf-lg',
'diamond',
'leaf-sm',
'microchip',
'outpoint',
'outpoint-lg',
'outpoint-sm',
'pinched-square',
'rounded',
'rounded-lg',
'rounded-sm',
'square',
'star',
'heart',
'hashtag',
]

export const FinderPatternInner = ({ qrProps, setQrProps }: FinderPatternInnerProps) => {
Expand Down
20 changes: 10 additions & 10 deletions apps/docs/src/components/demo/finder-pattern-outer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ interface DataModulesProps {
}

const styles: FinderPatternOuterStyle[] = [
'square',
'pinched-square',
'rounded-sm',
'rounded',
'rounded-lg',
'circle',
'inpoint-sm',
'inpoint',
'inpoint-lg',
'outpoint-sm',
'outpoint',
'outpoint-lg',
'leaf-sm',
'inpoint-sm',
'leaf',
'leaf-lg',
'leaf-sm',
'outpoint',
'outpoint-lg',
'outpoint-sm',
'pinched-square',
'rounded',
'rounded-lg',
'rounded-sm',
'square',
]

export const FinderPatternOuter = ({ qrProps, setQrProps }: DataModulesProps) => {
Expand Down
3 changes: 2 additions & 1 deletion apps/docs/src/components/demo/main-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ const errorCorrectionLevels: ErrorCorrectionLevel[] = ['L', 'M', 'Q', 'H']

export const MainSettings = ({ qrProps, setQrProps }: MainSettingsProps) => {
const onInputChange = (e: React.ChangeEvent<HTMLInputElement>, key: string) => {
const { value, type } = e.target
setQrProps((prevProps) => ({
...prevProps,
[key]: e.target.value,
[key]: type === 'number' && value !== '' ? Number(value) : value,
Comment thread
LGLabGreg marked this conversation as resolved.
}))
}
const onValueChange = (value: string, key: string) => {
Expand Down
120 changes: 119 additions & 1 deletion packages/react-qr-code/src/components/data-modules.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { render } from '@testing-library/react'
import { render, screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'

import { CIRCUIT_BOARD_LINE_WIDTH, CIRCUIT_BOARD_PAD_RADIUS } from '../constants'
import {
dataModulesHorizontalLineNeighbours,
dataModulesLeafNeighbours,
Expand Down Expand Up @@ -53,6 +54,123 @@ describe('DataModules', () => {
})
})

it('renders circuit-board as traces with pads', () => {
const modules = Array.from({ length: 10 }, () => Array(10).fill(false))
modules[8][8] = true
modules[8][9] = true
modules[9][8] = true

render(
<DataModules
modules={modules}
margin={2}
gradientId='mock-gradient-id'
settings={{ style: 'circuit-board', color: '#ffdd99' }}
/>,
)

const path = screen.getByTestId('data-modules')

expect(path.tagName.toLowerCase()).toBe('path')
expect(path).toHaveAttribute('fill', '#ffdd99')
expect(path).not.toHaveAttribute('stroke')
const d = path.getAttribute('d') ?? ''
const traceHalf = CIRCUIT_BOARD_LINE_WIDTH / 2
const traceLength = 1 + CIRCUIT_BOARD_LINE_WIDTH
expect(d).toContain(
dataModulesUtils.rect(
10.5 - traceHalf,
10.5 - traceHalf,
traceLength,
CIRCUIT_BOARD_LINE_WIDTH,
),
)
expect(d).toContain(
dataModulesUtils.rect(
10.5 - traceHalf,
10.5 - traceHalf,
CIRCUIT_BOARD_LINE_WIDTH,
traceLength,
),
)
expect(d).toContain(
dataModulesUtils.circuitBoardPad(11.5, 10.5, CIRCUIT_BOARD_PAD_RADIUS),
)
expect(d).toContain(
dataModulesUtils.circuitBoardPad(10.5, 11.5, CIRCUIT_BOARD_PAD_RADIUS),
)
expect(d).not.toContain(
dataModulesUtils.circuitBoardPad(10.5, 10.5, CIRCUIT_BOARD_PAD_RADIUS),
)
})

it('renders standalone circuit-board modules as squares', () => {
const modules = Array.from({ length: 10 }, () => Array(10).fill(false))
modules[8][8] = true

render(
<DataModules
modules={modules}
margin={2}
gradientId='mock-gradient-id'
settings={{ style: 'circuit-board', color: '#ffdd99' }}
/>,
)

const path = screen.getByTestId('data-modules')

expect(path.tagName.toLowerCase()).toBe('path')
expect(path).toHaveAttribute('d', 'M10.125,10.125h0.75v0.75h-0.75Z')
})

it('fully covers the cell centre at circuit-board junctions', () => {
// Junction cell at (8,8) with neighbours at (7,8), (9,8), (8,7), (8,9):
// it has top+left+right+bottom = count 4 but draws no traces itself
// (only right/bottom). The incoming traces from each neighbour must
// collectively fill the cell centre or a white notch appears.
const modules = Array.from({ length: 12 }, () => Array(12).fill(false))
modules[7][8] = true
modules[8][7] = true
modules[8][8] = true
modules[8][9] = true
modules[9][8] = true

render(
<DataModules
modules={modules}
margin={2}
gradientId='mock-gradient-id'
settings={{ style: 'circuit-board', color: '#000000' }}
/>,
)

const d = screen.getByTestId('data-modules').getAttribute('d') ?? ''
const traceHalf = CIRCUIT_BOARD_LINE_WIDTH / 2
const traceLength = 1 + CIRCUIT_BOARD_LINE_WIDTH

// Incoming horizontal trace from cell (8,7), centre (9.5, 10.5):
// must extend past its own end (10.5) by traceHalf so the junction
// cell's centre is covered from the left.
expect(d).toContain(
dataModulesUtils.rect(
9.5 - traceHalf,
10.5 - traceHalf,
traceLength,
CIRCUIT_BOARD_LINE_WIDTH,
),
)
// Incoming vertical trace from cell (7,8), centre (10.5, 9.5):
// covers the junction from above.
expect(d).toContain(
dataModulesUtils.rect(
10.5 - traceHalf,
9.5 - traceHalf,
CIRCUIT_BOARD_LINE_WIDTH,
traceLength,
),
)
})

it.each(dataModulesRoundedNeighbours)(
`with neighbours %j calls the correct shape function %s for style rounded`,
(neighbours, method) => {
Expand Down
Loading