@particle-academy/react-fancy 5.35.1 → 5.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -11,6 +11,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [5.36.0] - 2026-10-11
15
+
16
+ ### Added
17
+
18
+ - **`<QrCode>` — a QR code as an SVG, with no dependencies.** ISO/IEC 18004,
19
+ versions 1–40, error correction L/M/Q/H, and numeric / alphanumeric / byte
20
+ modes selected automatically. **Nothing to do** — it is a new component and
21
+ nothing else changed.
22
+
23
+ ```tsx
24
+ <QrCode value="https://host/pair#482913" size={192} label="Pair this device" />
25
+ ```
26
+
27
+ `label` is required. A QR code is unusable to anyone who cannot point a second
28
+ device at the screen, so it needs an accessible name describing the
29
+ *destination* — and the value should also appear as text or a link nearby,
30
+ which an `aria-label` cannot substitute for.
31
+
32
+ Also exported on the `./qr-code` subpath, and **the encoder is exported
33
+ separately** (`encodeQr`, `selectMode`) for a consumer that needs the modules
34
+ rather than an SVG — a canvas, a PDF, a thermal printer, a terminal. Without
35
+ that, getting at them would mean adding a dependency for something already in
36
+ the package.
37
+
38
+ Three notes that decide whether a code actually scans, none of which are
39
+ visible in a screenshot:
40
+
41
+ - **The quiet zone is not padding.** It is how a scanner finds the symbol's
42
+ edge, so it defaults to the standard's minimum of 4 modules. `quietZone={0}`
43
+ is allowed and is not a space saving.
44
+ - **`background` defaults to `"transparent"`**, which inherits whatever is
45
+ behind it — so on a dark surface the symbol renders dark-on-dark and most
46
+ scanners refuse it. Set `foreground` and `background` together there.
47
+ - **`"H"` is not a free upgrade over `"M"`.** It survives more damage and
48
+ holds a third less, so at the same pixel width the modules are smaller; on a
49
+ phone screen it can read *worse*. Raise it for print or a covered symbol.
50
+
51
+ Rendered as a single `<path>` on a module-unit `viewBox` rather than a `<rect>`
52
+ per module: a version 10 symbol has over three thousand modules, and the
53
+ module-unit viewBox is what lets `size` scale with no resampling — a raster
54
+ code at a non-integer multiple of its module size has blurred module edges,
55
+ and a scanner reading a blurred edge guesses.
56
+
57
+ `encodeQr` throws a `RangeError` rather than truncating a value that will not
58
+ fit, because a truncated symbol scans cleanly and yields the wrong string.
59
+ Kanji mode and structured append are not supported; an untested branch in an
60
+ encoder fails as a code a phone quietly refuses to read.
61
+
62
+ Built for `claude · tynn`'s device-pairing panel (Genie 2 §6.8), which
63
+ previously had only a typed URL.
64
+
14
65
  ## [5.35.1] - 2026-10-10
15
66
 
16
67
  ### Fixed
@@ -0,0 +1,630 @@
1
+ 'use strict';
2
+
3
+ var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
4
+ var react = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ // src/components/QrCode/qr-tables.ts
8
+ var EC_LEVELS = ["L", "M", "Q", "H"];
9
+ var BLOCK_TABLE = [
10
+ // v1
11
+ [[19, 7, 1, 19, 0, 0], [16, 10, 1, 16, 0, 0], [13, 13, 1, 13, 0, 0], [9, 17, 1, 9, 0, 0]],
12
+ [[34, 10, 1, 34, 0, 0], [28, 16, 1, 28, 0, 0], [22, 22, 1, 22, 0, 0], [16, 28, 1, 16, 0, 0]],
13
+ [[55, 15, 1, 55, 0, 0], [44, 26, 1, 44, 0, 0], [34, 18, 2, 17, 0, 0], [26, 22, 2, 13, 0, 0]],
14
+ [[80, 20, 1, 80, 0, 0], [64, 18, 2, 32, 0, 0], [48, 26, 2, 24, 0, 0], [36, 16, 4, 9, 0, 0]],
15
+ [[108, 26, 1, 108, 0, 0], [86, 24, 2, 43, 0, 0], [62, 18, 2, 15, 2, 16], [46, 22, 2, 11, 2, 12]],
16
+ [[136, 18, 2, 68, 0, 0], [108, 16, 4, 27, 0, 0], [76, 24, 4, 19, 0, 0], [60, 28, 4, 15, 0, 0]],
17
+ [[156, 20, 2, 78, 0, 0], [124, 18, 4, 31, 0, 0], [88, 18, 2, 14, 4, 15], [66, 26, 4, 13, 1, 14]],
18
+ [[194, 24, 2, 97, 0, 0], [154, 22, 2, 38, 2, 39], [110, 22, 4, 18, 2, 19], [86, 26, 4, 14, 2, 15]],
19
+ [[232, 30, 2, 116, 0, 0], [182, 22, 3, 36, 2, 37], [132, 20, 4, 16, 4, 17], [100, 24, 4, 12, 4, 13]],
20
+ // v10
21
+ [[274, 18, 2, 68, 2, 69], [216, 26, 4, 43, 1, 44], [154, 24, 6, 19, 2, 20], [122, 28, 6, 15, 2, 16]],
22
+ [[324, 20, 4, 81, 0, 0], [254, 30, 1, 50, 4, 51], [180, 28, 4, 22, 4, 23], [140, 24, 3, 12, 8, 13]],
23
+ [[370, 24, 2, 92, 2, 93], [290, 22, 6, 36, 2, 37], [206, 26, 4, 20, 6, 21], [158, 28, 7, 14, 4, 15]],
24
+ [[428, 26, 4, 107, 0, 0], [334, 22, 8, 37, 1, 38], [244, 24, 8, 20, 4, 21], [180, 22, 12, 11, 4, 12]],
25
+ [[461, 30, 3, 115, 1, 116], [365, 24, 4, 40, 5, 41], [261, 20, 11, 16, 5, 17], [197, 24, 11, 12, 5, 13]],
26
+ [[523, 22, 5, 87, 1, 88], [415, 24, 5, 41, 5, 42], [295, 30, 5, 24, 7, 25], [223, 24, 11, 12, 7, 13]],
27
+ [[589, 24, 5, 98, 1, 99], [453, 28, 7, 45, 3, 46], [325, 24, 15, 19, 2, 20], [253, 30, 3, 15, 13, 16]],
28
+ [[647, 28, 1, 107, 5, 108], [507, 28, 10, 46, 1, 47], [367, 28, 1, 22, 15, 23], [283, 28, 2, 14, 17, 15]],
29
+ [[721, 30, 5, 120, 1, 121], [563, 26, 9, 43, 4, 44], [397, 28, 17, 22, 1, 23], [313, 28, 2, 14, 19, 15]],
30
+ [[795, 28, 3, 113, 4, 114], [627, 26, 3, 44, 11, 45], [445, 26, 17, 21, 4, 22], [341, 26, 9, 13, 16, 14]],
31
+ // v20
32
+ [[861, 28, 3, 107, 5, 108], [669, 26, 3, 41, 13, 42], [485, 30, 15, 24, 5, 25], [385, 28, 15, 15, 10, 16]],
33
+ [[932, 28, 4, 116, 4, 117], [714, 26, 17, 42, 0, 0], [512, 28, 17, 22, 6, 23], [406, 30, 19, 16, 6, 17]],
34
+ [[1006, 28, 2, 111, 7, 112], [782, 28, 17, 46, 0, 0], [568, 30, 7, 24, 16, 25], [442, 24, 34, 13, 0, 0]],
35
+ [[1094, 30, 4, 121, 5, 122], [860, 28, 4, 47, 14, 48], [614, 30, 11, 24, 14, 25], [464, 30, 16, 15, 14, 16]],
36
+ [[1174, 30, 6, 117, 4, 118], [914, 28, 6, 45, 14, 46], [664, 30, 11, 24, 16, 25], [514, 30, 30, 16, 2, 17]],
37
+ [[1276, 26, 8, 106, 4, 107], [1e3, 28, 8, 47, 13, 48], [718, 30, 7, 24, 22, 25], [538, 30, 22, 15, 13, 16]],
38
+ [[1370, 28, 10, 114, 2, 115], [1062, 28, 19, 46, 4, 47], [754, 28, 28, 22, 6, 23], [596, 30, 33, 16, 4, 17]],
39
+ [[1468, 30, 8, 122, 4, 123], [1128, 28, 22, 45, 3, 46], [808, 30, 8, 23, 26, 24], [628, 30, 12, 15, 28, 16]],
40
+ [[1531, 30, 3, 117, 10, 118], [1193, 28, 3, 45, 23, 46], [871, 30, 4, 24, 31, 25], [661, 30, 11, 15, 31, 16]],
41
+ [[1631, 30, 7, 116, 7, 117], [1267, 28, 21, 45, 7, 46], [911, 30, 1, 23, 37, 24], [701, 30, 19, 15, 26, 16]],
42
+ // v30
43
+ [[1735, 30, 5, 115, 10, 116], [1373, 28, 19, 47, 10, 48], [985, 30, 15, 24, 25, 25], [745, 30, 23, 15, 25, 16]],
44
+ [[1843, 30, 13, 115, 3, 116], [1455, 28, 2, 46, 29, 47], [1033, 30, 42, 24, 1, 25], [793, 30, 23, 15, 28, 16]],
45
+ [[1955, 30, 17, 115, 0, 0], [1541, 28, 10, 46, 23, 47], [1115, 30, 10, 24, 35, 25], [845, 30, 19, 15, 35, 16]],
46
+ [[2071, 30, 17, 115, 1, 116], [1631, 28, 14, 46, 21, 47], [1171, 30, 29, 24, 19, 25], [901, 30, 11, 15, 46, 16]],
47
+ [[2191, 30, 13, 115, 6, 116], [1725, 28, 14, 46, 23, 47], [1231, 30, 44, 24, 7, 25], [961, 30, 59, 16, 1, 17]],
48
+ [[2306, 30, 12, 121, 7, 122], [1812, 28, 12, 47, 26, 48], [1286, 30, 39, 24, 14, 25], [986, 30, 22, 15, 41, 16]],
49
+ [[2434, 30, 6, 121, 14, 122], [1914, 28, 6, 47, 34, 48], [1354, 30, 46, 24, 10, 25], [1054, 30, 2, 15, 64, 16]],
50
+ [[2566, 30, 17, 122, 4, 123], [1992, 28, 29, 46, 14, 47], [1426, 30, 49, 24, 10, 25], [1096, 30, 24, 15, 46, 16]],
51
+ [[2702, 30, 4, 122, 18, 123], [2102, 28, 13, 46, 32, 47], [1502, 30, 48, 24, 14, 25], [1142, 30, 42, 15, 32, 16]],
52
+ [[2812, 30, 20, 117, 4, 118], [2216, 28, 40, 47, 7, 48], [1582, 30, 43, 24, 22, 25], [1222, 30, 10, 15, 67, 16]],
53
+ // v40
54
+ [[2956, 30, 19, 118, 6, 119], [2334, 28, 18, 47, 31, 48], [1666, 30, 34, 24, 34, 25], [1276, 30, 20, 15, 61, 16]]
55
+ ];
56
+ var MIN_VERSION = 1;
57
+ var MAX_VERSION = 40;
58
+ function blockLayout(version, ec) {
59
+ const row = BLOCK_TABLE[version - 1]?.[EC_LEVELS.indexOf(ec)];
60
+ if (!row) {
61
+ throw new RangeError(`No block layout for version ${version} level ${ec}`);
62
+ }
63
+ const [dataCodewords2, ecPerBlock, g1Blocks, g1Size, g2Blocks, g2Size] = row;
64
+ return { dataCodewords: dataCodewords2, ecPerBlock, g1Blocks, g1Size, g2Blocks, g2Size };
65
+ }
66
+ var FORMAT_BITS = {
67
+ L: [
68
+ 30660,
69
+ 29427,
70
+ 32170,
71
+ 30877,
72
+ 26159,
73
+ 25368,
74
+ 27713,
75
+ 26998
76
+ ],
77
+ M: [
78
+ 21522,
79
+ 20773,
80
+ 24188,
81
+ 23371,
82
+ 17913,
83
+ 16590,
84
+ 20375,
85
+ 19104
86
+ ],
87
+ Q: [
88
+ 13663,
89
+ 12392,
90
+ 16177,
91
+ 14854,
92
+ 9396,
93
+ 8579,
94
+ 11994,
95
+ 11245
96
+ ],
97
+ H: [
98
+ 5769,
99
+ 5054,
100
+ 7399,
101
+ 6608,
102
+ 1890,
103
+ 597,
104
+ 3340,
105
+ 2107
106
+ ]
107
+ };
108
+ function versionBits(version) {
109
+ let remainder = version;
110
+ for (let i = 0; i < 12; i += 1) {
111
+ remainder = remainder << 1 ^ (remainder >>> 11) * 7973;
112
+ }
113
+ return (version << 12 | remainder) >>> 0;
114
+ }
115
+ function alignmentPositions(version) {
116
+ if (version === 1) {
117
+ return [];
118
+ }
119
+ const count = Math.floor(version / 7) + 2;
120
+ const size = version * 4 + 17;
121
+ const step = version === 32 ? 26 : Math.ceil((size - 13) / (count * 2 - 2)) * 2;
122
+ const positions = [6];
123
+ for (let pos = size - 7; positions.length < count; pos -= step) {
124
+ positions.unshift(pos);
125
+ }
126
+ return positions.sort((a, b) => a - b);
127
+ }
128
+
129
+ // src/components/QrCode/qr-encode.ts
130
+ var MODE_INDICATOR = { numeric: 1, alphanumeric: 2, byte: 4 };
131
+ var ALPHANUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
132
+ var EXP = new Uint8Array(256);
133
+ var LOG = new Uint8Array(256);
134
+ {
135
+ let x = 1;
136
+ for (let i = 0; i < 255; i += 1) {
137
+ EXP[i] = x;
138
+ LOG[x] = i;
139
+ x <<= 1;
140
+ if (x & 256) {
141
+ x ^= 285;
142
+ }
143
+ }
144
+ EXP[255] = EXP[0];
145
+ }
146
+ function gfMul(a, b) {
147
+ if (a === 0 || b === 0) {
148
+ return 0;
149
+ }
150
+ return EXP[(LOG[a] + LOG[b]) % 255];
151
+ }
152
+ function generatorPoly(degree) {
153
+ let poly = [1];
154
+ for (let i = 0; i < degree; i += 1) {
155
+ const next = new Array(poly.length + 1).fill(0);
156
+ for (let j = 0; j < poly.length; j += 1) {
157
+ next[j] = next[j] ^ poly[j];
158
+ next[j + 1] = next[j + 1] ^ gfMul(poly[j], EXP[i]);
159
+ }
160
+ poly = next;
161
+ }
162
+ return poly;
163
+ }
164
+ function reedSolomon(data, degree) {
165
+ const generator = generatorPoly(degree);
166
+ const remainder = new Array(degree).fill(0);
167
+ for (const byte of data) {
168
+ const factor = byte ^ remainder.shift();
169
+ remainder.push(0);
170
+ for (let i = 0; i < degree; i += 1) {
171
+ remainder[i] = remainder[i] ^ gfMul(generator[i + 1], factor);
172
+ }
173
+ }
174
+ return remainder;
175
+ }
176
+ function selectMode(value) {
177
+ if (/^[0-9]*$/.test(value)) {
178
+ return "numeric";
179
+ }
180
+ if ([...value].every((char) => ALPHANUMERIC.includes(char))) {
181
+ return "alphanumeric";
182
+ }
183
+ return "byte";
184
+ }
185
+ function countBits(mode, version) {
186
+ const tier = version <= 9 ? 0 : version <= 26 ? 1 : 2;
187
+ if (mode === "numeric") {
188
+ return [10, 12, 14][tier];
189
+ }
190
+ if (mode === "alphanumeric") {
191
+ return [9, 11, 13][tier];
192
+ }
193
+ return [8, 16, 16][tier];
194
+ }
195
+ var BitBuffer = class {
196
+ constructor() {
197
+ this.bits = [];
198
+ }
199
+ push(value, length) {
200
+ for (let i = length - 1; i >= 0; i -= 1) {
201
+ this.bits.push(value >>> i & 1);
202
+ }
203
+ }
204
+ };
205
+ function utf8Bytes(value) {
206
+ const out = [];
207
+ for (const char of value) {
208
+ const code = char.codePointAt(0);
209
+ if (code < 128) {
210
+ out.push(code);
211
+ } else if (code < 2048) {
212
+ out.push(192 | code >> 6, 128 | code & 63);
213
+ } else if (code < 65536) {
214
+ out.push(224 | code >> 12, 128 | code >> 6 & 63, 128 | code & 63);
215
+ } else {
216
+ out.push(
217
+ 240 | code >> 18,
218
+ 128 | code >> 12 & 63,
219
+ 128 | code >> 6 & 63,
220
+ 128 | code & 63
221
+ );
222
+ }
223
+ }
224
+ return out;
225
+ }
226
+ function encodePayload(value, mode, version) {
227
+ const buffer = new BitBuffer();
228
+ buffer.push(MODE_INDICATOR[mode], 4);
229
+ if (mode === "numeric") {
230
+ buffer.push(value.length, countBits(mode, version));
231
+ for (let i = 0; i < value.length; i += 3) {
232
+ const group = value.slice(i, i + 3);
233
+ buffer.push(Number.parseInt(group, 10), group.length * 3 + 1);
234
+ }
235
+ return buffer;
236
+ }
237
+ if (mode === "alphanumeric") {
238
+ buffer.push(value.length, countBits(mode, version));
239
+ for (let i = 0; i < value.length; i += 2) {
240
+ const first = ALPHANUMERIC.indexOf(value[i]);
241
+ if (i + 1 < value.length) {
242
+ buffer.push(first * 45 + ALPHANUMERIC.indexOf(value[i + 1]), 11);
243
+ } else {
244
+ buffer.push(first, 6);
245
+ }
246
+ }
247
+ return buffer;
248
+ }
249
+ const bytes = utf8Bytes(value);
250
+ buffer.push(bytes.length, countBits(mode, version));
251
+ for (const byte of bytes) {
252
+ buffer.push(byte, 8);
253
+ }
254
+ return buffer;
255
+ }
256
+ function payloadBits(value, mode, version) {
257
+ return encodePayload(value, mode, version).bits.length;
258
+ }
259
+ function selectVersion(value, mode, ec, minVersion) {
260
+ for (let version = Math.max(minVersion, MIN_VERSION); version <= MAX_VERSION; version += 1) {
261
+ if (payloadBits(value, mode, version) <= blockLayout(version, ec).dataCodewords * 8) {
262
+ return version;
263
+ }
264
+ }
265
+ return null;
266
+ }
267
+ function dataCodewords(value, mode, version, ec) {
268
+ const capacity = blockLayout(version, ec).dataCodewords * 8;
269
+ const buffer = encodePayload(value, mode, version);
270
+ buffer.push(0, Math.min(4, capacity - buffer.bits.length));
271
+ buffer.push(0, (8 - buffer.bits.length % 8) % 8);
272
+ const codewords = [];
273
+ for (let i = 0; i < buffer.bits.length; i += 8) {
274
+ let byte = 0;
275
+ for (let bit = 0; bit < 8; bit += 1) {
276
+ byte = byte << 1 | buffer.bits[i + bit];
277
+ }
278
+ codewords.push(byte);
279
+ }
280
+ const target = capacity / 8;
281
+ for (let i = 0; codewords.length < target; i += 1) {
282
+ codewords.push(i % 2 === 0 ? 236 : 17);
283
+ }
284
+ return codewords;
285
+ }
286
+ function interleave(codewords, version, ec) {
287
+ const { ecPerBlock, g1Blocks, g1Size, g2Blocks, g2Size } = blockLayout(version, ec);
288
+ const dataBlocks = [];
289
+ let offset = 0;
290
+ for (let i = 0; i < g1Blocks; i += 1) {
291
+ dataBlocks.push(codewords.slice(offset, offset + g1Size));
292
+ offset += g1Size;
293
+ }
294
+ for (let i = 0; i < g2Blocks; i += 1) {
295
+ dataBlocks.push(codewords.slice(offset, offset + g2Size));
296
+ offset += g2Size;
297
+ }
298
+ const ecBlocks = dataBlocks.map((block) => reedSolomon(block, ecPerBlock));
299
+ const result = [];
300
+ const widest = Math.max(g1Size, g2Blocks > 0 ? g2Size : 0);
301
+ for (let i = 0; i < widest; i += 1) {
302
+ for (const block of dataBlocks) {
303
+ if (i < block.length) {
304
+ result.push(block[i]);
305
+ }
306
+ }
307
+ }
308
+ for (let i = 0; i < ecPerBlock; i += 1) {
309
+ for (const block of ecBlocks) {
310
+ result.push(block[i]);
311
+ }
312
+ }
313
+ return result;
314
+ }
315
+ function reservedModules(version) {
316
+ const size = version * 4 + 17;
317
+ const grid = Array.from({ length: size }, () => new Array(size).fill(null));
318
+ const set = (row, col, dark) => {
319
+ grid[row][col] = dark;
320
+ };
321
+ for (const [baseRow, baseCol] of [
322
+ [0, 0],
323
+ [0, size - 7],
324
+ [size - 7, 0]
325
+ ]) {
326
+ for (let row = -1; row <= 7; row += 1) {
327
+ for (let col = -1; col <= 7; col += 1) {
328
+ const r = baseRow + row;
329
+ const c = baseCol + col;
330
+ if (r < 0 || r >= size || c < 0 || c >= size) {
331
+ continue;
332
+ }
333
+ const ring = Math.max(Math.abs(row - 3), Math.abs(col - 3));
334
+ set(r, c, ring !== 2 && ring <= 3);
335
+ }
336
+ }
337
+ }
338
+ for (let i = 0; i < size; i += 1) {
339
+ if (grid[6][i] === null) {
340
+ set(6, i, i % 2 === 0);
341
+ }
342
+ if (grid[i][6] === null) {
343
+ set(i, 6, i % 2 === 0);
344
+ }
345
+ }
346
+ const positions = alignmentPositions(version);
347
+ for (const row of positions) {
348
+ for (const col of positions) {
349
+ const nearFinder = row <= 8 && col <= 8 || row <= 8 && col >= size - 9 || row >= size - 9 && col <= 8;
350
+ if (nearFinder) {
351
+ continue;
352
+ }
353
+ for (let dr = -2; dr <= 2; dr += 1) {
354
+ for (let dc = -2; dc <= 2; dc += 1) {
355
+ const ring = Math.max(Math.abs(dr), Math.abs(dc));
356
+ set(row + dr, col + dc, ring !== 1);
357
+ }
358
+ }
359
+ }
360
+ }
361
+ for (let i = 0; i < 9; i += 1) {
362
+ if (grid[8][i] === null) {
363
+ set(8, i, false);
364
+ }
365
+ if (grid[i][8] === null) {
366
+ set(i, 8, false);
367
+ }
368
+ }
369
+ for (let i = 0; i < 8; i += 1) {
370
+ set(8, size - 1 - i, false);
371
+ set(size - 1 - i, 8, false);
372
+ }
373
+ set(size - 8, 8, true);
374
+ if (version >= 7) {
375
+ const bits = versionBits(version);
376
+ for (let i = 0; i < 18; i += 1) {
377
+ const bit = (bits >>> i & 1) === 1;
378
+ set(Math.floor(i / 3), size - 11 + i % 3, bit);
379
+ set(size - 11 + i % 3, Math.floor(i / 3), bit);
380
+ }
381
+ }
382
+ return grid;
383
+ }
384
+ function placeData(grid, codewords) {
385
+ const size = grid.length;
386
+ let bitIndex = 0;
387
+ const nextBit = () => {
388
+ const byte = codewords[bitIndex >>> 3];
389
+ const bit = byte === void 0 ? 0 : byte >>> 7 - (bitIndex & 7) & 1;
390
+ bitIndex += 1;
391
+ return bit === 1;
392
+ };
393
+ let upward = true;
394
+ for (let right = size - 1; right >= 1; right -= 2) {
395
+ const pair = right === 6 ? [5, 4] : [right, right - 1];
396
+ for (let step = 0; step < size; step += 1) {
397
+ const row = upward ? size - 1 - step : step;
398
+ for (const col of pair) {
399
+ if (grid[row][col] === null) {
400
+ grid[row][col] = nextBit();
401
+ }
402
+ }
403
+ }
404
+ if (right === 6) {
405
+ right -= 1;
406
+ }
407
+ upward = !upward;
408
+ }
409
+ }
410
+ function maskCondition(mask, row, col) {
411
+ switch (mask) {
412
+ case 0:
413
+ return (row + col) % 2 === 0;
414
+ case 1:
415
+ return row % 2 === 0;
416
+ case 2:
417
+ return col % 3 === 0;
418
+ case 3:
419
+ return (row + col) % 3 === 0;
420
+ case 4:
421
+ return (Math.floor(row / 2) + Math.floor(col / 3)) % 2 === 0;
422
+ case 5:
423
+ return row * col % 2 + row * col % 3 === 0;
424
+ case 6:
425
+ return (row * col % 2 + row * col % 3) % 2 === 0;
426
+ default:
427
+ return ((row + col) % 2 + row * col % 3) % 2 === 0;
428
+ }
429
+ }
430
+ function penalty(modules) {
431
+ const size = modules.length;
432
+ let score = 0;
433
+ const scoreLine = (run) => run >= 5 ? run - 2 : 0;
434
+ for (let i = 0; i < size; i += 1) {
435
+ for (const horizontal of [true, false]) {
436
+ let run = 1;
437
+ for (let j = 1; j < size; j += 1) {
438
+ const prev = horizontal ? modules[i][j - 1] : modules[j - 1][i];
439
+ const cur = horizontal ? modules[i][j] : modules[j][i];
440
+ if (cur === prev) {
441
+ run += 1;
442
+ } else {
443
+ score += scoreLine(run);
444
+ run = 1;
445
+ }
446
+ }
447
+ score += scoreLine(run);
448
+ }
449
+ }
450
+ for (let row = 0; row < size - 1; row += 1) {
451
+ for (let col = 0; col < size - 1; col += 1) {
452
+ const a = modules[row][col];
453
+ if (a === modules[row][col + 1] && a === modules[row + 1][col] && a === modules[row + 1][col + 1]) {
454
+ score += 3;
455
+ }
456
+ }
457
+ }
458
+ const finderish = [true, false, true, true, true, false, true];
459
+ const light4 = [false, false, false, false];
460
+ const matches = (line, at, pattern) => pattern.every((want, i) => line[at + i] === want);
461
+ for (let i = 0; i < size; i += 1) {
462
+ const row = modules[i];
463
+ const col = modules.map((r) => r[i]);
464
+ for (const line of [row, col]) {
465
+ for (let j = 0; j + 7 <= size; j += 1) {
466
+ if (!matches(line, j, finderish)) {
467
+ continue;
468
+ }
469
+ if (j >= 4 && matches(line, j - 4, light4)) {
470
+ score += 40;
471
+ }
472
+ if (j + 11 <= size && matches(line, j + 7, light4)) {
473
+ score += 40;
474
+ }
475
+ }
476
+ }
477
+ }
478
+ let dark = 0;
479
+ for (const row of modules) {
480
+ for (const cell of row) {
481
+ if (cell) {
482
+ dark += 1;
483
+ }
484
+ }
485
+ }
486
+ const percent = dark * 100 / (size * size);
487
+ score += Math.floor(Math.abs(percent - 50) / 5) * 10;
488
+ return score;
489
+ }
490
+ function applyFormat(modules, ec, mask) {
491
+ const size = modules.length;
492
+ const bits = FORMAT_BITS[ec][mask] >>> 0;
493
+ const bit = (i) => (bits >>> i & 1) === 1;
494
+ for (let i = 0; i <= 5; i += 1) {
495
+ modules[8][i] = bit(14 - i);
496
+ }
497
+ modules[8][7] = bit(8);
498
+ modules[8][8] = bit(7);
499
+ modules[7][8] = bit(6);
500
+ for (let i = 9; i <= 14; i += 1) {
501
+ modules[14 - i][8] = bit(14 - i);
502
+ }
503
+ for (let i = 0; i <= 6; i += 1) {
504
+ modules[size - 1 - i][8] = bit(i);
505
+ }
506
+ for (let i = 7; i <= 14; i += 1) {
507
+ modules[8][size - 15 + i] = bit(i);
508
+ }
509
+ modules[size - 8][8] = true;
510
+ }
511
+ function encodeQr(value, options = {}) {
512
+ const ec = options.errorCorrection ?? "M";
513
+ const mode = options.mode ?? selectMode(value);
514
+ if (mode === "numeric" && !/^[0-9]*$/.test(value)) {
515
+ throw new RangeError("Numeric mode accepts digits only");
516
+ }
517
+ if (mode === "alphanumeric" && ![...value].every((char) => ALPHANUMERIC.includes(char))) {
518
+ throw new RangeError("Alphanumeric mode accepts 0-9 A-Z space and $%*+-./: only");
519
+ }
520
+ let version;
521
+ if (options.version !== void 0) {
522
+ if (options.version < MIN_VERSION || options.version > MAX_VERSION) {
523
+ throw new RangeError(`Version must be ${MIN_VERSION}-${MAX_VERSION}`);
524
+ }
525
+ version = options.version;
526
+ if (payloadBits(value, mode, version) > blockLayout(version, ec).dataCodewords * 8) {
527
+ throw new RangeError(`Value does not fit in version ${version} at level ${ec}`);
528
+ }
529
+ } else {
530
+ const chosen = selectVersion(value, mode, ec, MIN_VERSION);
531
+ if (chosen === null) {
532
+ throw new RangeError(
533
+ `Value is too long for a QR code at level ${ec} (${value.length} characters)`
534
+ );
535
+ }
536
+ version = chosen;
537
+ }
538
+ const codewords = interleave(dataCodewords(value, mode, version, ec), version, ec);
539
+ const template = reservedModules(version);
540
+ const candidates = [];
541
+ const masksToTry = options.mask === void 0 ? [0, 1, 2, 3, 4, 5, 6, 7] : [options.mask];
542
+ for (const mask of masksToTry) {
543
+ const grid = template.map((row) => [...row]);
544
+ placeData(grid, codewords);
545
+ const modules = grid.map(
546
+ (row, rowIndex) => row.map((cell, colIndex) => {
547
+ const value_ = cell;
548
+ const isData = template[rowIndex][colIndex] === null;
549
+ return isData && maskCondition(mask, rowIndex, colIndex) ? !value_ : value_;
550
+ })
551
+ );
552
+ applyFormat(modules, ec, mask);
553
+ candidates.push({ mask, modules });
554
+ }
555
+ const best = candidates.reduce((a, b) => penalty(a.modules) <= penalty(b.modules) ? a : b);
556
+ return {
557
+ modules: best.modules,
558
+ size: version * 4 + 17,
559
+ version,
560
+ errorCorrection: ec,
561
+ mode,
562
+ mask: best.mask
563
+ };
564
+ }
565
+ var QrCode = react.forwardRef(
566
+ ({
567
+ value,
568
+ size = 192,
569
+ errorCorrection = "M",
570
+ label,
571
+ quietZone = 4,
572
+ foreground = "currentColor",
573
+ background = "transparent",
574
+ mode,
575
+ version,
576
+ className,
577
+ ...props
578
+ }, ref) => {
579
+ const symbol = react.useMemo(
580
+ () => encodeQr(value, { errorCorrection, mode, version }),
581
+ [value, errorCorrection, mode, version]
582
+ );
583
+ const extent = symbol.size + quietZone * 2;
584
+ const path = react.useMemo(() => {
585
+ const parts = [];
586
+ for (let row = 0; row < symbol.size; row += 1) {
587
+ const line = symbol.modules[row];
588
+ let col = 0;
589
+ while (col < symbol.size) {
590
+ if (!line[col]) {
591
+ col += 1;
592
+ continue;
593
+ }
594
+ let run = 1;
595
+ while (col + run < symbol.size && line[col + run]) {
596
+ run += 1;
597
+ }
598
+ parts.push(`M${col + quietZone} ${row + quietZone}h${run}v1h-${run}z`);
599
+ col += run;
600
+ }
601
+ }
602
+ return parts.join("");
603
+ }, [symbol, quietZone]);
604
+ return /* @__PURE__ */ jsxRuntime.jsxs(
605
+ "svg",
606
+ {
607
+ ref,
608
+ width: size,
609
+ height: size,
610
+ viewBox: `0 0 ${extent} ${extent}`,
611
+ role: "img",
612
+ "aria-label": label,
613
+ shapeRendering: "crispEdges",
614
+ className: chunkZU5Q77OT_cjs.cn("fa-qr-code", className),
615
+ ...props,
616
+ children: [
617
+ background !== "transparent" && /* @__PURE__ */ jsxRuntime.jsx("rect", { width: extent, height: extent, fill: background }),
618
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: path, fill: foreground })
619
+ ]
620
+ }
621
+ );
622
+ }
623
+ );
624
+ QrCode.displayName = "QrCode";
625
+
626
+ exports.QrCode = QrCode;
627
+ exports.encodeQr = encodeQr;
628
+ exports.selectMode = selectMode;
629
+ //# sourceMappingURL=chunk-6KFCJLJN.cjs.map
630
+ //# sourceMappingURL=chunk-6KFCJLJN.cjs.map