@mantine-vue/qr-code 3.4.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/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # @mantine-vue/qr-code
2
+
3
+ A Mantine Vue QR code component with custom data and finder shapes, image overlays, a complete Styles API, and SVG, PNG, JPEG, and WebP downloads.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ yarn add @mantine-vue/qr-code @mantine-vue/core @mantine-vue/hooks qrcode
9
+ ```
10
+
11
+ Import styles after core styles:
12
+
13
+ ```ts
14
+ import '@mantine-vue/core/styles.css'
15
+ import '@mantine-vue/qr-code/styles.css'
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ```vue
21
+ <script setup lang="ts">
22
+ import { QRCode } from '@mantine-vue/qr-code'
23
+ </script>
24
+
25
+ <template>
26
+ <QRCode value="https://mantine-vue.dev" />
27
+ </template>
28
+ ```
29
+
30
+ See the Mantine Vue documentation for all customization and download examples.
package/cjs/index.cjs ADDED
@@ -0,0 +1,413 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let _mantine_vue_core = require("@mantine-vue/core");
25
+ let vue = require("vue");
26
+ let _mantine_vue_hooks = require("@mantine-vue/hooks");
27
+ let qrcode = require("qrcode");
28
+ qrcode = __toESM(qrcode);
29
+ //#region src/utils/dot-shapes.ts
30
+ /** Generates SVG path data for one data module. */
31
+ function dotPath(x, y, cellSize, style) {
32
+ if (style === "dots") {
33
+ const radius = cellSize / 2;
34
+ return `M${x + radius},${y + radius - radius}a${radius},${radius} 0 1,1 0,${radius * 2}a${radius},${radius} 0 1,1 0,${-radius * 2}z`;
35
+ }
36
+ if (style === "rounded") {
37
+ const radius = cellSize * .3;
38
+ return `M${x + radius},${y}h${cellSize - 2 * radius}a${radius},${radius} 0 0,1 ${radius},${radius}v${cellSize - 2 * radius}a${radius},${radius} 0 0,1 ${-radius},${radius}h${-(cellSize - 2 * radius)}a${radius},${radius} 0 0,1 ${-radius},${-radius}v${-(cellSize - 2 * radius)}a${radius},${radius} 0 0,1 ${radius},${-radius}z`;
39
+ }
40
+ return `M${x},${y}h${cellSize}v${cellSize}h${-cellSize}z`;
41
+ }
42
+ //#endregion
43
+ //#region src/utils/finder-shapes.ts
44
+ function roundedRect(x, y, width, height, radius) {
45
+ return `M${x + radius},${y}h${width - 2 * radius}a${radius},${radius} 0 0,1 ${radius},${radius}v${height - 2 * radius}a${radius},${radius} 0 0,1 ${-radius},${radius}h${-(width - 2 * radius)}a${radius},${radius} 0 0,1 ${-radius},${-radius}v${-(height - 2 * radius)}a${radius},${radius} 0 0,1 ${radius},${-radius}z`;
46
+ }
47
+ function roundedRectReverse(x, y, width, height, radius) {
48
+ return `M${x + radius},${y}a${radius},${radius} 0 0,0 ${-radius},${radius}v${height - 2 * radius}a${radius},${radius} 0 0,0 ${radius},${radius}h${width - 2 * radius}a${radius},${radius} 0 0,0 ${radius},${-radius}v${-(height - 2 * radius)}a${radius},${radius} 0 0,0 ${-radius},${-radius}z`;
49
+ }
50
+ /** Generates separate outer-ring and inner paths for a 7x7 finder pattern. */
51
+ function finderPatternPaths(x, y, cellSize, style) {
52
+ if (style === "square") return {
53
+ outer: `M${x},${y}h${cellSize * 7}v${cellSize * 7}h${-cellSize * 7}zM${x + cellSize},${y + cellSize}v${cellSize * 5}h${cellSize * 5}v${-cellSize * 5}z`,
54
+ inner: `M${x + cellSize * 2},${y + cellSize * 2}h${cellSize * 3}v${cellSize * 3}h${-cellSize * 3}z`
55
+ };
56
+ const outerRadius = style === "dots" ? cellSize * 3.5 : cellSize * 1.2;
57
+ const holeRadius = style === "dots" ? cellSize * 2.5 : cellSize * .8;
58
+ const innerRadius = style === "dots" ? cellSize * 1.5 : cellSize * .6;
59
+ return {
60
+ outer: roundedRect(x, y, cellSize * 7, cellSize * 7, outerRadius) + roundedRectReverse(x + cellSize, y + cellSize, cellSize * 5, cellSize * 5, holeRadius),
61
+ inner: roundedRect(x + cellSize * 2, y + cellSize * 2, cellSize * 3, cellSize * 3, innerRadius)
62
+ };
63
+ }
64
+ //#endregion
65
+ //#region src/utils/qr-encoder.ts
66
+ function generateQRMatrix(value, errorCorrectionLevel = "M") {
67
+ const qr = qrcode.default.create(value, { errorCorrectionLevel });
68
+ const size = qr.modules.size;
69
+ const matrix = [];
70
+ for (let row = 0; row < size; row += 1) {
71
+ const rowData = [];
72
+ for (let column = 0; column < size; column += 1) rowData.push(qr.modules.data[row * size + column] === 1);
73
+ matrix.push(rowData);
74
+ }
75
+ return {
76
+ modules: matrix,
77
+ size
78
+ };
79
+ }
80
+ function isFinderPattern(row, column, matrixSize) {
81
+ return row < 7 && column < 7 || row < 7 && column >= matrixSize - 7 || row >= matrixSize - 7 && column < 7;
82
+ }
83
+ //#endregion
84
+ //#region src/utils/utils.ts
85
+ /** Builds a mask identifying modules hidden by the center image and its padding. */
86
+ function getExcavationMask(matrixSize, imageModuleSize, imagePadding) {
87
+ const mask = Array.from({ length: matrixSize }, () => Array(matrixSize).fill(false));
88
+ const totalImageModules = imageModuleSize + imagePadding * 2;
89
+ const startModule = Math.floor((matrixSize - totalImageModules) / 2);
90
+ const endModule = startModule + totalImageModules;
91
+ for (let row = 0; row < matrixSize; row += 1) for (let column = 0; column < matrixSize; column += 1) if (row >= startModule && row < endModule && column >= startModule && column < endModule) mask[row][column] = true;
92
+ return mask;
93
+ }
94
+ var QRCode_module_default = {
95
+ root: "_root_6mmnv_1",
96
+ svg: "_svg_6mmnv_15",
97
+ background: "_background_6mmnv_20",
98
+ modules: "_modules_6mmnv_24",
99
+ finderOuter: "_finderOuter_6mmnv_25",
100
+ finderInner: "_finderInner_6mmnv_26",
101
+ finderPattern: "_finderPattern_6mmnv_30",
102
+ image: "_image_6mmnv_33"
103
+ };
104
+ //#endregion
105
+ //#region src/QRCode.vue?vue&type=script&setup=true&lang.ts
106
+ var _hoisted_1 = ["viewBox", "aria-label"];
107
+ var _hoisted_2 = ["width", "height"];
108
+ var _hoisted_3 = ["d"];
109
+ var _hoisted_4 = ["d"];
110
+ var _hoisted_5 = ["d"];
111
+ var _hoisted_6 = [
112
+ "href",
113
+ "x",
114
+ "y",
115
+ "width",
116
+ "height",
117
+ "clip-path"
118
+ ];
119
+ var defaultProps = {
120
+ size: "md",
121
+ color: "dark",
122
+ background: "white",
123
+ errorCorrectionLevel: "M",
124
+ quietZone: 1,
125
+ dotStyle: "square",
126
+ cornerStyle: "square",
127
+ imageSize: .2,
128
+ imagePadding: 1,
129
+ imageExcavate: true
130
+ };
131
+ var varsResolver = (0, _mantine_vue_core.createVarsResolver)((theme, { size, radius, color, background }) => ({ root: {
132
+ "--qr-code-size": (0, _mantine_vue_core.getSize)(size, "qr-code-size"),
133
+ "--qr-code-radius": radius !== void 0 ? (0, _mantine_vue_core.getRadius)(radius) : void 0,
134
+ "--qr-code-color": color ? (0, _mantine_vue_core.getThemeColor)(color, theme) : void 0,
135
+ "--qr-code-background": background === "transparent" ? "transparent" : background ? (0, _mantine_vue_core.getThemeColor)(background, theme) : void 0
136
+ } }));
137
+ //#endregion
138
+ //#region src/QRCode.vue
139
+ var QRCode_default = /* @__PURE__ */ (0, vue.defineComponent)({
140
+ name: "QRCode",
141
+ inheritAttrs: false,
142
+ __name: "QRCode",
143
+ props: {
144
+ component: { default: void 0 },
145
+ rootRef: {
146
+ type: [Object, Function],
147
+ default: void 0
148
+ },
149
+ value: {},
150
+ size: { default: void 0 },
151
+ radius: { default: void 0 },
152
+ color: { default: void 0 },
153
+ background: { default: void 0 },
154
+ errorCorrectionLevel: { default: void 0 },
155
+ quietZone: { default: void 0 },
156
+ dotStyle: { default: void 0 },
157
+ cornerStyle: { default: void 0 },
158
+ image: { default: void 0 },
159
+ imageSize: { default: void 0 },
160
+ imageRadius: { default: void 0 },
161
+ imagePadding: { default: void 0 },
162
+ imageExcavate: {
163
+ type: Boolean,
164
+ default: void 0
165
+ },
166
+ classNames: { default: void 0 },
167
+ styles: { default: void 0 },
168
+ vars: { default: void 0 },
169
+ unstyled: { type: Boolean }
170
+ },
171
+ setup(__props, { expose: __expose }) {
172
+ const rawProps = __props;
173
+ const attrs = (0, vue.useAttrs)();
174
+ const props = (0, _mantine_vue_core.useProps)("QRCode", defaultProps, rawProps);
175
+ const getStyles = (0, _mantine_vue_core.useStyles)({
176
+ name: "QRCode",
177
+ props,
178
+ classes: QRCode_module_default,
179
+ get className() {
180
+ return attrs.class;
181
+ },
182
+ get style() {
183
+ return attrs.style;
184
+ },
185
+ classNames: props.classNames,
186
+ styles: props.styles,
187
+ vars: props.vars,
188
+ varsResolver,
189
+ unstyled: props.unstyled
190
+ });
191
+ const rootElement = (0, vue.ref)(null);
192
+ const setRootRef = (node) => {
193
+ rootElement.value = node;
194
+ (0, _mantine_vue_hooks.assignRef)(props.rootRef, node);
195
+ };
196
+ __expose({ rootElement });
197
+ const qrData = (0, vue.computed)(() => {
198
+ if (!props.value) return null;
199
+ try {
200
+ return generateQRMatrix(props.value, props.errorCorrectionLevel);
201
+ } catch {
202
+ return null;
203
+ }
204
+ });
205
+ const svgContent = (0, vue.computed)(() => {
206
+ if (!qrData.value) return null;
207
+ const { modules, size: matrixSize } = qrData.value;
208
+ const quietZone = props.quietZone ?? defaultProps.quietZone;
209
+ const imageSizeRatio = props.imageSize ?? defaultProps.imageSize;
210
+ const imagePadding = props.imagePadding ?? defaultProps.imagePadding;
211
+ const dotStyle = props.dotStyle ?? defaultProps.dotStyle;
212
+ const cornerStyle = props.cornerStyle ?? defaultProps.cornerStyle;
213
+ const viewBoxSize = matrixSize + quietZone * 2;
214
+ const excavationMask = props.image && props.imageExcavate ? getExcavationMask(matrixSize, Math.ceil(matrixSize * imageSizeRatio), imagePadding) : null;
215
+ let modulesPath = "";
216
+ for (let row = 0; row < matrixSize; row += 1) for (let column = 0; column < matrixSize; column += 1) {
217
+ if (!modules[row][column] || isFinderPattern(row, column, matrixSize) || excavationMask?.[row][column]) continue;
218
+ modulesPath += dotPath(column + quietZone, row + quietZone, 1, dotStyle);
219
+ }
220
+ const finders = [
221
+ {
222
+ key: "top-left",
223
+ row: 0,
224
+ column: 0
225
+ },
226
+ {
227
+ key: "top-right",
228
+ row: 0,
229
+ column: matrixSize - 7
230
+ },
231
+ {
232
+ key: "bottom-left",
233
+ row: matrixSize - 7,
234
+ column: 0
235
+ }
236
+ ].map((position) => ({
237
+ key: position.key,
238
+ ...finderPatternPaths(position.column + quietZone, position.row + quietZone, 1, cornerStyle)
239
+ }));
240
+ const imageElement = props.image ? (() => {
241
+ const imageSize = matrixSize * imageSizeRatio;
242
+ return {
243
+ x: (viewBoxSize - imageSize) / 2,
244
+ y: (viewBoxSize - imageSize) / 2,
245
+ size: imageSize,
246
+ radius: props.imageRadius !== void 0 ? (0, _mantine_vue_core.getRadius)(props.imageRadius) : "0"
247
+ };
248
+ })() : null;
249
+ return {
250
+ viewBoxSize,
251
+ modulesPath,
252
+ finders,
253
+ imageElement
254
+ };
255
+ });
256
+ return (_ctx, _cache) => {
257
+ return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_mantine_vue_core.Box), (0, vue.mergeProps)({
258
+ ...(0, vue.unref)(attrs),
259
+ ...(0, vue.unref)(getStyles)("root")
260
+ }, {
261
+ component: (0, vue.unref)(props).component,
262
+ "root-ref": setRootRef
263
+ }), {
264
+ default: (0, vue.withCtx)(() => [svgContent.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("svg", (0, vue.mergeProps)({ key: 0 }, (0, vue.unref)(getStyles)("svg"), {
265
+ viewBox: `0 0 ${svgContent.value.viewBoxSize} ${svgContent.value.viewBoxSize}`,
266
+ xmlns: "http://www.w3.org/2000/svg",
267
+ role: "img",
268
+ "aria-label": `QR Code: ${(0, vue.unref)(props).value}`
269
+ }), [
270
+ (0, vue.createElementVNode)("rect", (0, vue.mergeProps)((0, vue.unref)(getStyles)("background"), {
271
+ x: "0",
272
+ y: "0",
273
+ width: svgContent.value.viewBoxSize,
274
+ height: svgContent.value.viewBoxSize
275
+ }), null, 16, _hoisted_2),
276
+ svgContent.value.modulesPath ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("path", (0, vue.mergeProps)({ key: 0 }, (0, vue.unref)(getStyles)("modules"), {
277
+ d: svgContent.value.modulesPath,
278
+ "fill-rule": "nonzero"
279
+ }), null, 16, _hoisted_3)) : (0, vue.createCommentVNode)("", true),
280
+ ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(svgContent.value.finders, (finder) => {
281
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("g", (0, vue.mergeProps)({ key: finder.key }, { ref_for: true }, (0, vue.unref)(getStyles)("finderPattern")), [(0, vue.createElementVNode)("path", (0, vue.mergeProps)({ ref_for: true }, (0, vue.unref)(getStyles)("finderOuter"), {
282
+ d: finder.outer,
283
+ "fill-rule": "evenodd"
284
+ }), null, 16, _hoisted_4), (0, vue.createElementVNode)("path", (0, vue.mergeProps)({ ref_for: true }, (0, vue.unref)(getStyles)("finderInner"), { d: finder.inner }), null, 16, _hoisted_5)], 16);
285
+ }), 128)),
286
+ svgContent.value.imageElement ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("image", (0, vue.mergeProps)({ key: 1 }, (0, vue.unref)(getStyles)("image"), {
287
+ href: (0, vue.unref)(props).image,
288
+ x: svgContent.value.imageElement.x,
289
+ y: svgContent.value.imageElement.y,
290
+ width: svgContent.value.imageElement.size,
291
+ height: svgContent.value.imageElement.size,
292
+ "clip-path": `inset(0 round ${svgContent.value.imageElement.radius})`,
293
+ preserveAspectRatio: "xMidYMid slice"
294
+ }), null, 16, _hoisted_6)) : (0, vue.createCommentVNode)("", true)
295
+ ], 16, _hoisted_1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("svg", (0, vue.normalizeProps)((0, vue.mergeProps)({ key: 1 }, (0, vue.unref)(getStyles)("svg"))), null, 16))]),
296
+ _: 1
297
+ }, 16, ["component"]);
298
+ };
299
+ }
300
+ });
301
+ //#endregion
302
+ //#region src/QRCode.ts
303
+ var QRCode = (0, _mantine_vue_core.polymorphicFactory)(QRCode_default, {
304
+ classes: QRCode_module_default,
305
+ varsResolver
306
+ });
307
+ //#endregion
308
+ //#region src/use-qr-code-download.ts
309
+ function serializeSvg(svgElement) {
310
+ const clone = svgElement.cloneNode(true);
311
+ if (!clone.getAttribute("xmlns")) clone.setAttribute("xmlns", "http://www.w3.org/2000/svg");
312
+ const computedStyle = getComputedStyle(svgElement);
313
+ const background = computedStyle.getPropertyValue("--qr-code-background").trim() || "#ffffff";
314
+ const foreground = computedStyle.getPropertyValue("--qr-code-color").trim() || "#000000";
315
+ clone.querySelector("rect")?.setAttribute("fill", background);
316
+ clone.querySelectorAll("path").forEach((path) => {
317
+ const fill = path.getAttribute("fill");
318
+ if (!fill || fill === "currentColor") path.setAttribute("fill", foreground);
319
+ });
320
+ return new XMLSerializer().serializeToString(clone);
321
+ }
322
+ function createSvgBlob(svg) {
323
+ return new Blob([svg], { type: "image/svg+xml;charset=utf-8" });
324
+ }
325
+ async function svgToCanvas(svgElement, scale) {
326
+ const url = URL.createObjectURL(createSvgBlob(serializeSvg(svgElement)));
327
+ const viewBox = svgElement.viewBox.baseVal;
328
+ const width = (viewBox.width || svgElement.clientWidth) * scale;
329
+ const height = (viewBox.height || svgElement.clientHeight) * scale;
330
+ return new Promise((resolve, reject) => {
331
+ const image = new Image();
332
+ image.onload = () => {
333
+ const canvas = document.createElement("canvas");
334
+ canvas.width = width;
335
+ canvas.height = height;
336
+ const context = canvas.getContext("2d");
337
+ if (!context) {
338
+ URL.revokeObjectURL(url);
339
+ reject(/* @__PURE__ */ new Error("Unable to create a canvas rendering context"));
340
+ return;
341
+ }
342
+ context.fillStyle = "#ffffff";
343
+ context.fillRect(0, 0, width, height);
344
+ context.drawImage(image, 0, 0, width, height);
345
+ URL.revokeObjectURL(url);
346
+ resolve(canvas);
347
+ };
348
+ image.onerror = () => {
349
+ URL.revokeObjectURL(url);
350
+ reject(/* @__PURE__ */ new Error("Failed to load SVG as image"));
351
+ };
352
+ image.src = url;
353
+ });
354
+ }
355
+ function mimeType(format) {
356
+ return format === "jpeg" ? "image/jpeg" : format === "webp" ? "image/webp" : "image/png";
357
+ }
358
+ function triggerDownload(blob, fileName) {
359
+ const url = URL.createObjectURL(blob);
360
+ const link = document.createElement("a");
361
+ link.href = url;
362
+ link.download = fileName;
363
+ document.body.appendChild(link);
364
+ link.click();
365
+ link.remove();
366
+ URL.revokeObjectURL(url);
367
+ }
368
+ /** Provides SVG and high-resolution raster export for a `QRCode` root element. */
369
+ function useQRCodeDownload(options = {}) {
370
+ const defaultFormat = options.format ?? "png";
371
+ const defaultFileName = options.fileName ?? "qrcode";
372
+ const defaultScale = options.scale ?? 4;
373
+ const element = (0, vue.shallowRef)(null);
374
+ const ref = (node) => {
375
+ element.value = node;
376
+ };
377
+ const getSvgElement = () => element.value?.querySelector("svg") ?? null;
378
+ const getDataUrl = async (overrides = {}) => {
379
+ const svgElement = getSvgElement();
380
+ if (!svgElement) throw new Error("QRCode SVG element not found");
381
+ const format = overrides.format ?? defaultFormat;
382
+ if (format === "svg") {
383
+ const bytes = new TextEncoder().encode(serializeSvg(svgElement));
384
+ let binary = "";
385
+ bytes.forEach((byte) => binary += String.fromCharCode(byte));
386
+ return `data:image/svg+xml;base64,${btoa(binary)}`;
387
+ }
388
+ return (await svgToCanvas(svgElement, overrides.scale ?? defaultScale)).toDataURL(mimeType(format), 1);
389
+ };
390
+ const download = async (overrides = {}) => {
391
+ const svgElement = getSvgElement();
392
+ if (!svgElement) throw new Error("QRCode SVG element not found");
393
+ const format = overrides.format ?? defaultFormat;
394
+ const fileName = `${overrides.fileName ?? defaultFileName}.${format}`;
395
+ if (format === "svg") {
396
+ triggerDownload(createSvgBlob(serializeSvg(svgElement)), fileName);
397
+ return;
398
+ }
399
+ const canvas = await svgToCanvas(svgElement, overrides.scale ?? defaultScale);
400
+ const blob = await new Promise((resolve) => canvas.toBlob(resolve, mimeType(format), 1));
401
+ if (blob) triggerDownload(blob, fileName);
402
+ };
403
+ return {
404
+ ref,
405
+ download,
406
+ getDataUrl
407
+ };
408
+ }
409
+ //#endregion
410
+ exports.QRCode = QRCode;
411
+ exports.useQRCodeDownload = useQRCodeDownload;
412
+
413
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/utils/dot-shapes.ts","../src/utils/finder-shapes.ts","../src/utils/qr-encoder.ts","../src/utils/utils.ts","../src/QRCode.module.css","../src/QRCode.vue","../src/QRCode.vue","../src/QRCode.ts","../src/use-qr-code-download.ts"],"sourcesContent":["import type { QRCodeDotStyle } from '../QRCode.types'\n\n/** Generates SVG path data for one data module. */\nexport function dotPath(x: number, y: number, cellSize: number, style: QRCodeDotStyle): string {\n if (style === 'dots') {\n const radius = cellSize / 2\n const centerX = x + radius\n const centerY = y + radius\n return `M${centerX},${centerY - radius}a${radius},${radius} 0 1,1 0,${radius * 2}a${radius},${radius} 0 1,1 0,${-radius * 2}z`\n }\n\n if (style === 'rounded') {\n const radius = cellSize * 0.3\n return (\n `M${x + radius},${y}` +\n `h${cellSize - 2 * radius}` +\n `a${radius},${radius} 0 0,1 ${radius},${radius}` +\n `v${cellSize - 2 * radius}` +\n `a${radius},${radius} 0 0,1 ${-radius},${radius}` +\n `h${-(cellSize - 2 * radius)}` +\n `a${radius},${radius} 0 0,1 ${-radius},${-radius}` +\n `v${-(cellSize - 2 * radius)}` +\n `a${radius},${radius} 0 0,1 ${radius},${-radius}z`\n )\n }\n\n return `M${x},${y}h${cellSize}v${cellSize}h${-cellSize}z`\n}\n","import type { QRCodeCornerStyle } from '../QRCode.types'\n\nexport interface FinderPaths {\n outer: string\n inner: string\n}\n\nfunction roundedRect(x: number, y: number, width: number, height: number, radius: number) {\n return (\n `M${x + radius},${y}` +\n `h${width - 2 * radius}a${radius},${radius} 0 0,1 ${radius},${radius}` +\n `v${height - 2 * radius}a${radius},${radius} 0 0,1 ${-radius},${radius}` +\n `h${-(width - 2 * radius)}a${radius},${radius} 0 0,1 ${-radius},${-radius}` +\n `v${-(height - 2 * radius)}a${radius},${radius} 0 0,1 ${radius},${-radius}z`\n )\n}\n\nfunction roundedRectReverse(x: number, y: number, width: number, height: number, radius: number) {\n return (\n `M${x + radius},${y}` +\n `a${radius},${radius} 0 0,0 ${-radius},${radius}` +\n `v${height - 2 * radius}a${radius},${radius} 0 0,0 ${radius},${radius}` +\n `h${width - 2 * radius}a${radius},${radius} 0 0,0 ${radius},${-radius}` +\n `v${-(height - 2 * radius)}a${radius},${radius} 0 0,0 ${-radius},${-radius}z`\n )\n}\n\n/** Generates separate outer-ring and inner paths for a 7x7 finder pattern. */\nexport function finderPatternPaths(\n x: number,\n y: number,\n cellSize: number,\n style: QRCodeCornerStyle,\n): FinderPaths {\n if (style === 'square') {\n const outer =\n `M${x},${y}h${cellSize * 7}v${cellSize * 7}h${-cellSize * 7}z` +\n `M${x + cellSize},${y + cellSize}v${cellSize * 5}h${cellSize * 5}v${-cellSize * 5}z`\n const inner =\n `M${x + cellSize * 2},${y + cellSize * 2}` +\n `h${cellSize * 3}v${cellSize * 3}h${-cellSize * 3}z`\n return { outer, inner }\n }\n\n const outerRadius = style === 'dots' ? cellSize * 3.5 : cellSize * 1.2\n const holeRadius = style === 'dots' ? cellSize * 2.5 : cellSize * 0.8\n const innerRadius = style === 'dots' ? cellSize * 1.5 : cellSize * 0.6\n\n return {\n outer:\n roundedRect(x, y, cellSize * 7, cellSize * 7, outerRadius) +\n roundedRectReverse(x + cellSize, y + cellSize, cellSize * 5, cellSize * 5, holeRadius),\n inner: roundedRect(x + cellSize * 2, y + cellSize * 2, cellSize * 3, cellSize * 3, innerRadius),\n }\n}\n","import QRCodeLibrary from 'qrcode'\nimport type { QRCodeErrorCorrectionLevel } from '../QRCode.types'\n\nexport interface QRMatrix {\n /** Two-dimensional matrix where true represents a dark module. */\n modules: boolean[][]\n /** Number of modules on each side. */\n size: number\n}\n\nexport function generateQRMatrix(\n value: string,\n errorCorrectionLevel: QRCodeErrorCorrectionLevel = 'M',\n): QRMatrix {\n const qr = QRCodeLibrary.create(value, { errorCorrectionLevel })\n const size = qr.modules.size\n const matrix: boolean[][] = []\n\n for (let row = 0; row < size; row += 1) {\n const rowData: boolean[] = []\n for (let column = 0; column < size; column += 1) {\n rowData.push(qr.modules.data[row * size + column] === 1)\n }\n matrix.push(rowData)\n }\n\n return { modules: matrix, size }\n}\n\nexport function isFinderPattern(row: number, column: number, matrixSize: number): boolean {\n return (\n (row < 7 && column < 7) ||\n (row < 7 && column >= matrixSize - 7) ||\n (row >= matrixSize - 7 && column < 7)\n )\n}\n","/** Builds a mask identifying modules hidden by the center image and its padding. */\nexport function getExcavationMask(\n matrixSize: number,\n imageModuleSize: number,\n imagePadding: number,\n): boolean[][] {\n const mask = Array.from({ length: matrixSize }, () => Array<boolean>(matrixSize).fill(false))\n const totalImageModules = imageModuleSize + imagePadding * 2\n const startModule = Math.floor((matrixSize - totalImageModules) / 2)\n const endModule = startModule + totalImageModules\n\n for (let row = 0; row < matrixSize; row += 1) {\n for (let column = 0; column < matrixSize; column += 1) {\n if (row >= startModule && row < endModule && column >= startModule && column < endModule) {\n mask[row][column] = true\n }\n }\n }\n\n return mask\n}\n",".root {\n --qr-code-size-xs: 80px;\n --qr-code-size-sm: 120px;\n --qr-code-size-md: 160px;\n --qr-code-size-lg: 200px;\n --qr-code-size-xl: 256px;\n\n display: inline-flex;\n width: var(--qr-code-size);\n height: var(--qr-code-size);\n border-radius: var(--qr-code-radius);\n overflow: hidden;\n}\n\n.svg {\n width: 100%;\n height: 100%;\n}\n\n.background {\n fill: var(--qr-code-background);\n}\n\n.modules,\n.finderOuter,\n.finderInner {\n fill: var(--qr-code-color);\n}\n\n.finderPattern {\n}\n\n.image {\n}\n","<script lang=\"ts\">\nimport { createVarsResolver, getRadius, getSize, getThemeColor } from '@mantine-vue/core'\n\nconst defaultProps = {\n size: 'md',\n color: 'dark',\n background: 'white',\n errorCorrectionLevel: 'M',\n quietZone: 1,\n dotStyle: 'square',\n cornerStyle: 'square',\n imageSize: 0.2,\n imagePadding: 1,\n imageExcavate: true,\n} as const\n\nconst varsResolver = createVarsResolver<any>((theme, { size, radius, color, background }) => ({\n root: {\n '--qr-code-size': getSize(size, 'qr-code-size'),\n '--qr-code-radius': radius !== undefined ? getRadius(radius) : undefined,\n '--qr-code-color': color ? getThemeColor(color, theme) : undefined,\n '--qr-code-background':\n background === 'transparent'\n ? 'transparent'\n : background\n ? getThemeColor(background, theme)\n : undefined,\n },\n}))\n\nexport { defaultProps, varsResolver }\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { assignRef } from '@mantine-vue/hooks'\nimport { Box, getRadius as resolveRadius, useProps, useStyles } from '@mantine-vue/core'\nimport { dotPath } from './utils/dot-shapes'\nimport { finderPatternPaths } from './utils/finder-shapes'\nimport { generateQRMatrix, isFinderPattern } from './utils/qr-encoder'\nimport { getExcavationMask } from './utils/utils'\nimport type { QRCodeOwnProps } from './QRCode.types'\nimport classes from './QRCode.module.css'\n\ndefineOptions({\n name: 'QRCode',\n inheritAttrs: false,\n})\n\nconst rawProps = withDefaults(defineProps<QRCodeOwnProps>(), {\n component: undefined,\n rootRef: undefined,\n size: undefined,\n radius: undefined,\n color: undefined,\n background: undefined,\n errorCorrectionLevel: undefined,\n quietZone: undefined,\n dotStyle: undefined,\n cornerStyle: undefined,\n image: undefined,\n imageSize: undefined,\n imageRadius: undefined,\n imagePadding: undefined,\n imageExcavate: undefined,\n classNames: undefined,\n styles: undefined,\n vars: undefined,\n})\n\nconst attrs = useAttrs()\nconst props = useProps('QRCode', defaultProps, rawProps)\n\nconst getStyles = useStyles({\n name: 'QRCode',\n props,\n classes,\n get className() {\n return attrs.class\n },\n get style() {\n return attrs.style as any\n },\n classNames: props.classNames as any,\n styles: props.styles as any,\n vars: props.vars as any,\n varsResolver,\n unstyled: props.unstyled,\n})\n\nconst rootElement = ref<Element | null>(null)\nconst setRootRef = (node: Element | null) => {\n rootElement.value = node\n assignRef(props.rootRef, node)\n}\n\ndefineExpose({ rootElement })\n\nconst qrData = computed(() => {\n if (!props.value) {\n return null\n }\n\n try {\n return generateQRMatrix(props.value, props.errorCorrectionLevel)\n } catch {\n return null\n }\n})\n\nconst svgContent = computed(() => {\n if (!qrData.value) {\n return null\n }\n\n const { modules, size: matrixSize } = qrData.value\n const quietZone = props.quietZone ?? defaultProps.quietZone\n const imageSizeRatio = props.imageSize ?? defaultProps.imageSize\n const imagePadding = props.imagePadding ?? defaultProps.imagePadding\n const dotStyle = props.dotStyle ?? defaultProps.dotStyle\n const cornerStyle = props.cornerStyle ?? defaultProps.cornerStyle\n const viewBoxSize = matrixSize + quietZone * 2\n const excavationMask =\n props.image && props.imageExcavate\n ? getExcavationMask(matrixSize, Math.ceil(matrixSize * imageSizeRatio), imagePadding)\n : null\n\n let modulesPath = ''\n for (let row = 0; row < matrixSize; row += 1) {\n for (let column = 0; column < matrixSize; column += 1) {\n if (\n !modules[row][column] ||\n isFinderPattern(row, column, matrixSize) ||\n excavationMask?.[row][column]\n ) {\n continue\n }\n\n modulesPath += dotPath(column + quietZone, row + quietZone, 1, dotStyle)\n }\n }\n\n const finders = [\n { key: 'top-left', row: 0, column: 0 },\n { key: 'top-right', row: 0, column: matrixSize - 7 },\n { key: 'bottom-left', row: matrixSize - 7, column: 0 },\n ].map((position) => ({\n key: position.key,\n ...finderPatternPaths(position.column + quietZone, position.row + quietZone, 1, cornerStyle),\n }))\n\n const imageElement = props.image\n ? (() => {\n const imageSize = matrixSize * imageSizeRatio\n return {\n x: (viewBoxSize - imageSize) / 2,\n y: (viewBoxSize - imageSize) / 2,\n size: imageSize,\n radius: props.imageRadius !== undefined ? resolveRadius(props.imageRadius) : '0',\n }\n })()\n : null\n\n return { viewBoxSize, modulesPath, finders, imageElement }\n})\n</script>\n\n<template>\n <Box\n v-bind=\"{ ...attrs, ...getStyles('root') }\"\n :component=\"props.component\"\n :root-ref=\"setRootRef\"\n >\n <svg\n v-if=\"svgContent\"\n v-bind=\"getStyles('svg')\"\n :viewBox=\"`0 0 ${svgContent.viewBoxSize} ${svgContent.viewBoxSize}`\"\n xmlns=\"http://www.w3.org/2000/svg\"\n role=\"img\"\n :aria-label=\"`QR Code: ${props.value}`\"\n >\n <rect\n v-bind=\"getStyles('background')\"\n x=\"0\"\n y=\"0\"\n :width=\"svgContent.viewBoxSize\"\n :height=\"svgContent.viewBoxSize\"\n />\n <path\n v-if=\"svgContent.modulesPath\"\n v-bind=\"getStyles('modules')\"\n :d=\"svgContent.modulesPath\"\n fill-rule=\"nonzero\"\n />\n <g v-for=\"finder in svgContent.finders\" :key=\"finder.key\" v-bind=\"getStyles('finderPattern')\">\n <path v-bind=\"getStyles('finderOuter')\" :d=\"finder.outer\" fill-rule=\"evenodd\" />\n <path v-bind=\"getStyles('finderInner')\" :d=\"finder.inner\" />\n </g>\n <image\n v-if=\"svgContent.imageElement\"\n v-bind=\"getStyles('image')\"\n :href=\"props.image\"\n :x=\"svgContent.imageElement.x\"\n :y=\"svgContent.imageElement.y\"\n :width=\"svgContent.imageElement.size\"\n :height=\"svgContent.imageElement.size\"\n :clip-path=\"`inset(0 round ${svgContent.imageElement.radius})`\"\n preserveAspectRatio=\"xMidYMid slice\"\n />\n </svg>\n <svg v-else v-bind=\"getStyles('svg')\" />\n </Box>\n</template>\n","<script lang=\"ts\">\nimport { createVarsResolver, getRadius, getSize, getThemeColor } from '@mantine-vue/core'\n\nconst defaultProps = {\n size: 'md',\n color: 'dark',\n background: 'white',\n errorCorrectionLevel: 'M',\n quietZone: 1,\n dotStyle: 'square',\n cornerStyle: 'square',\n imageSize: 0.2,\n imagePadding: 1,\n imageExcavate: true,\n} as const\n\nconst varsResolver = createVarsResolver<any>((theme, { size, radius, color, background }) => ({\n root: {\n '--qr-code-size': getSize(size, 'qr-code-size'),\n '--qr-code-radius': radius !== undefined ? getRadius(radius) : undefined,\n '--qr-code-color': color ? getThemeColor(color, theme) : undefined,\n '--qr-code-background':\n background === 'transparent'\n ? 'transparent'\n : background\n ? getThemeColor(background, theme)\n : undefined,\n },\n}))\n\nexport { defaultProps, varsResolver }\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { assignRef } from '@mantine-vue/hooks'\nimport { Box, getRadius as resolveRadius, useProps, useStyles } from '@mantine-vue/core'\nimport { dotPath } from './utils/dot-shapes'\nimport { finderPatternPaths } from './utils/finder-shapes'\nimport { generateQRMatrix, isFinderPattern } from './utils/qr-encoder'\nimport { getExcavationMask } from './utils/utils'\nimport type { QRCodeOwnProps } from './QRCode.types'\nimport classes from './QRCode.module.css'\n\ndefineOptions({\n name: 'QRCode',\n inheritAttrs: false,\n})\n\nconst rawProps = withDefaults(defineProps<QRCodeOwnProps>(), {\n component: undefined,\n rootRef: undefined,\n size: undefined,\n radius: undefined,\n color: undefined,\n background: undefined,\n errorCorrectionLevel: undefined,\n quietZone: undefined,\n dotStyle: undefined,\n cornerStyle: undefined,\n image: undefined,\n imageSize: undefined,\n imageRadius: undefined,\n imagePadding: undefined,\n imageExcavate: undefined,\n classNames: undefined,\n styles: undefined,\n vars: undefined,\n})\n\nconst attrs = useAttrs()\nconst props = useProps('QRCode', defaultProps, rawProps)\n\nconst getStyles = useStyles({\n name: 'QRCode',\n props,\n classes,\n get className() {\n return attrs.class\n },\n get style() {\n return attrs.style as any\n },\n classNames: props.classNames as any,\n styles: props.styles as any,\n vars: props.vars as any,\n varsResolver,\n unstyled: props.unstyled,\n})\n\nconst rootElement = ref<Element | null>(null)\nconst setRootRef = (node: Element | null) => {\n rootElement.value = node\n assignRef(props.rootRef, node)\n}\n\ndefineExpose({ rootElement })\n\nconst qrData = computed(() => {\n if (!props.value) {\n return null\n }\n\n try {\n return generateQRMatrix(props.value, props.errorCorrectionLevel)\n } catch {\n return null\n }\n})\n\nconst svgContent = computed(() => {\n if (!qrData.value) {\n return null\n }\n\n const { modules, size: matrixSize } = qrData.value\n const quietZone = props.quietZone ?? defaultProps.quietZone\n const imageSizeRatio = props.imageSize ?? defaultProps.imageSize\n const imagePadding = props.imagePadding ?? defaultProps.imagePadding\n const dotStyle = props.dotStyle ?? defaultProps.dotStyle\n const cornerStyle = props.cornerStyle ?? defaultProps.cornerStyle\n const viewBoxSize = matrixSize + quietZone * 2\n const excavationMask =\n props.image && props.imageExcavate\n ? getExcavationMask(matrixSize, Math.ceil(matrixSize * imageSizeRatio), imagePadding)\n : null\n\n let modulesPath = ''\n for (let row = 0; row < matrixSize; row += 1) {\n for (let column = 0; column < matrixSize; column += 1) {\n if (\n !modules[row][column] ||\n isFinderPattern(row, column, matrixSize) ||\n excavationMask?.[row][column]\n ) {\n continue\n }\n\n modulesPath += dotPath(column + quietZone, row + quietZone, 1, dotStyle)\n }\n }\n\n const finders = [\n { key: 'top-left', row: 0, column: 0 },\n { key: 'top-right', row: 0, column: matrixSize - 7 },\n { key: 'bottom-left', row: matrixSize - 7, column: 0 },\n ].map((position) => ({\n key: position.key,\n ...finderPatternPaths(position.column + quietZone, position.row + quietZone, 1, cornerStyle),\n }))\n\n const imageElement = props.image\n ? (() => {\n const imageSize = matrixSize * imageSizeRatio\n return {\n x: (viewBoxSize - imageSize) / 2,\n y: (viewBoxSize - imageSize) / 2,\n size: imageSize,\n radius: props.imageRadius !== undefined ? resolveRadius(props.imageRadius) : '0',\n }\n })()\n : null\n\n return { viewBoxSize, modulesPath, finders, imageElement }\n})\n</script>\n\n<template>\n <Box\n v-bind=\"{ ...attrs, ...getStyles('root') }\"\n :component=\"props.component\"\n :root-ref=\"setRootRef\"\n >\n <svg\n v-if=\"svgContent\"\n v-bind=\"getStyles('svg')\"\n :viewBox=\"`0 0 ${svgContent.viewBoxSize} ${svgContent.viewBoxSize}`\"\n xmlns=\"http://www.w3.org/2000/svg\"\n role=\"img\"\n :aria-label=\"`QR Code: ${props.value}`\"\n >\n <rect\n v-bind=\"getStyles('background')\"\n x=\"0\"\n y=\"0\"\n :width=\"svgContent.viewBoxSize\"\n :height=\"svgContent.viewBoxSize\"\n />\n <path\n v-if=\"svgContent.modulesPath\"\n v-bind=\"getStyles('modules')\"\n :d=\"svgContent.modulesPath\"\n fill-rule=\"nonzero\"\n />\n <g v-for=\"finder in svgContent.finders\" :key=\"finder.key\" v-bind=\"getStyles('finderPattern')\">\n <path v-bind=\"getStyles('finderOuter')\" :d=\"finder.outer\" fill-rule=\"evenodd\" />\n <path v-bind=\"getStyles('finderInner')\" :d=\"finder.inner\" />\n </g>\n <image\n v-if=\"svgContent.imageElement\"\n v-bind=\"getStyles('image')\"\n :href=\"props.image\"\n :x=\"svgContent.imageElement.x\"\n :y=\"svgContent.imageElement.y\"\n :width=\"svgContent.imageElement.size\"\n :height=\"svgContent.imageElement.size\"\n :clip-path=\"`inset(0 round ${svgContent.imageElement.radius})`\"\n preserveAspectRatio=\"xMidYMid slice\"\n />\n </svg>\n <svg v-else v-bind=\"getStyles('svg')\" />\n </Box>\n</template>\n","import { polymorphicFactory } from '@mantine-vue/core'\nimport QRCodeComponent, { varsResolver } from './QRCode.vue'\nimport type { QRCodeFactory } from './QRCode.types'\nimport classes from './QRCode.module.css'\n\nexport const QRCode = polymorphicFactory<QRCodeFactory>(QRCodeComponent, {\n classes,\n varsResolver,\n})\n\nexport type {\n QRCodeCornerStyle,\n QRCodeCssVariables,\n QRCodeDotStyle,\n QRCodeErrorCorrectionLevel,\n QRCodeFactory,\n QRCodeOwnProps,\n QRCodeProps,\n QRCodeStylesNames,\n} from './QRCode.types'\n","import { shallowRef } from 'vue'\n\nexport type QRCodeDownloadFormat = 'svg' | 'png' | 'jpeg' | 'webp'\n\nexport interface UseQRCodeDownloadOptions {\n /** Default download format. @default 'png' */\n format?: QRCodeDownloadFormat\n /** Default file name without an extension. @default 'qrcode' */\n fileName?: string\n /** Raster output scale. @default 4 */\n scale?: number\n}\n\nexport interface QRCodeDownloadOptions {\n format?: QRCodeDownloadFormat\n fileName?: string\n scale?: number\n}\n\nexport interface UseQRCodeDownloadReturn {\n /** Callback ref to pass to `QRCode` as `root-ref`. */\n ref: (element: Element | null) => void\n /** Downloads the current QR code. */\n download: (options?: QRCodeDownloadOptions) => Promise<void>\n /** Returns a data URL for the current QR code. */\n getDataUrl: (options?: Omit<QRCodeDownloadOptions, 'fileName'>) => Promise<string>\n}\n\nfunction serializeSvg(svgElement: SVGSVGElement): string {\n const clone = svgElement.cloneNode(true) as SVGSVGElement\n if (!clone.getAttribute('xmlns')) {\n clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg')\n }\n\n const computedStyle = getComputedStyle(svgElement)\n const background = computedStyle.getPropertyValue('--qr-code-background').trim() || '#ffffff'\n const foreground = computedStyle.getPropertyValue('--qr-code-color').trim() || '#000000'\n clone.querySelector('rect')?.setAttribute('fill', background)\n clone.querySelectorAll('path').forEach((path) => {\n const fill = path.getAttribute('fill')\n if (!fill || fill === 'currentColor') {\n path.setAttribute('fill', foreground)\n }\n })\n\n return new XMLSerializer().serializeToString(clone)\n}\n\nfunction createSvgBlob(svg: string) {\n return new Blob([svg], { type: 'image/svg+xml;charset=utf-8' })\n}\n\nasync function svgToCanvas(svgElement: SVGSVGElement, scale: number) {\n const url = URL.createObjectURL(createSvgBlob(serializeSvg(svgElement)))\n const viewBox = svgElement.viewBox.baseVal\n const width = (viewBox.width || svgElement.clientWidth) * scale\n const height = (viewBox.height || svgElement.clientHeight) * scale\n\n return new Promise<HTMLCanvasElement>((resolve, reject) => {\n const image = new Image()\n image.onload = () => {\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n const context = canvas.getContext('2d')\n if (!context) {\n URL.revokeObjectURL(url)\n reject(new Error('Unable to create a canvas rendering context'))\n return\n }\n context.fillStyle = '#ffffff'\n context.fillRect(0, 0, width, height)\n context.drawImage(image, 0, 0, width, height)\n URL.revokeObjectURL(url)\n resolve(canvas)\n }\n image.onerror = () => {\n URL.revokeObjectURL(url)\n reject(new Error('Failed to load SVG as image'))\n }\n image.src = url\n })\n}\n\nfunction mimeType(format: QRCodeDownloadFormat) {\n return format === 'jpeg' ? 'image/jpeg' : format === 'webp' ? 'image/webp' : 'image/png'\n}\n\nfunction triggerDownload(blob: Blob, fileName: string) {\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = fileName\n document.body.appendChild(link)\n link.click()\n link.remove()\n URL.revokeObjectURL(url)\n}\n\n/** Provides SVG and high-resolution raster export for a `QRCode` root element. */\nexport function useQRCodeDownload(options: UseQRCodeDownloadOptions = {}): UseQRCodeDownloadReturn {\n const defaultFormat = options.format ?? 'png'\n const defaultFileName = options.fileName ?? 'qrcode'\n const defaultScale = options.scale ?? 4\n const element = shallowRef<Element | null>(null)\n const ref = (node: Element | null) => {\n element.value = node\n }\n\n const getSvgElement = () => element.value?.querySelector('svg') ?? null\n\n const getDataUrl: UseQRCodeDownloadReturn['getDataUrl'] = async (overrides = {}) => {\n const svgElement = getSvgElement()\n if (!svgElement) {\n throw new Error('QRCode SVG element not found')\n }\n\n const format = overrides.format ?? defaultFormat\n if (format === 'svg') {\n const bytes = new TextEncoder().encode(serializeSvg(svgElement))\n let binary = ''\n bytes.forEach((byte) => (binary += String.fromCharCode(byte)))\n return `data:image/svg+xml;base64,${btoa(binary)}`\n }\n\n const canvas = await svgToCanvas(svgElement, overrides.scale ?? defaultScale)\n return canvas.toDataURL(mimeType(format), 1)\n }\n\n const download: UseQRCodeDownloadReturn['download'] = async (overrides = {}) => {\n const svgElement = getSvgElement()\n if (!svgElement) {\n throw new Error('QRCode SVG element not found')\n }\n\n const format = overrides.format ?? defaultFormat\n const fileName = `${overrides.fileName ?? defaultFileName}.${format}`\n if (format === 'svg') {\n triggerDownload(createSvgBlob(serializeSvg(svgElement)), fileName)\n return\n }\n\n const canvas = await svgToCanvas(svgElement, overrides.scale ?? defaultScale)\n const blob = await new Promise<Blob | null>((resolve) =>\n canvas.toBlob(resolve, mimeType(format), 1),\n )\n if (blob) {\n triggerDownload(blob, fileName)\n }\n }\n\n return { ref, download, getDataUrl }\n}\n"],"mappings":"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"}
package/esm/index.mjs ADDED
@@ -0,0 +1,385 @@
1
+ import { Box, createVarsResolver, getRadius, getSize, getThemeColor, polymorphicFactory, useProps, useStyles } from "@mantine-vue/core";
2
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeProps, normalizeProps, openBlock, ref, renderList, shallowRef, unref, useAttrs, withCtx } from "vue";
3
+ import { assignRef } from "@mantine-vue/hooks";
4
+ import QRCodeLibrary from "qrcode";
5
+ //#region src/utils/dot-shapes.ts
6
+ /** Generates SVG path data for one data module. */
7
+ function dotPath(x, y, cellSize, style) {
8
+ if (style === "dots") {
9
+ const radius = cellSize / 2;
10
+ return `M${x + radius},${y + radius - radius}a${radius},${radius} 0 1,1 0,${radius * 2}a${radius},${radius} 0 1,1 0,${-radius * 2}z`;
11
+ }
12
+ if (style === "rounded") {
13
+ const radius = cellSize * .3;
14
+ return `M${x + radius},${y}h${cellSize - 2 * radius}a${radius},${radius} 0 0,1 ${radius},${radius}v${cellSize - 2 * radius}a${radius},${radius} 0 0,1 ${-radius},${radius}h${-(cellSize - 2 * radius)}a${radius},${radius} 0 0,1 ${-radius},${-radius}v${-(cellSize - 2 * radius)}a${radius},${radius} 0 0,1 ${radius},${-radius}z`;
15
+ }
16
+ return `M${x},${y}h${cellSize}v${cellSize}h${-cellSize}z`;
17
+ }
18
+ //#endregion
19
+ //#region src/utils/finder-shapes.ts
20
+ function roundedRect(x, y, width, height, radius) {
21
+ return `M${x + radius},${y}h${width - 2 * radius}a${radius},${radius} 0 0,1 ${radius},${radius}v${height - 2 * radius}a${radius},${radius} 0 0,1 ${-radius},${radius}h${-(width - 2 * radius)}a${radius},${radius} 0 0,1 ${-radius},${-radius}v${-(height - 2 * radius)}a${radius},${radius} 0 0,1 ${radius},${-radius}z`;
22
+ }
23
+ function roundedRectReverse(x, y, width, height, radius) {
24
+ return `M${x + radius},${y}a${radius},${radius} 0 0,0 ${-radius},${radius}v${height - 2 * radius}a${radius},${radius} 0 0,0 ${radius},${radius}h${width - 2 * radius}a${radius},${radius} 0 0,0 ${radius},${-radius}v${-(height - 2 * radius)}a${radius},${radius} 0 0,0 ${-radius},${-radius}z`;
25
+ }
26
+ /** Generates separate outer-ring and inner paths for a 7x7 finder pattern. */
27
+ function finderPatternPaths(x, y, cellSize, style) {
28
+ if (style === "square") return {
29
+ outer: `M${x},${y}h${cellSize * 7}v${cellSize * 7}h${-cellSize * 7}zM${x + cellSize},${y + cellSize}v${cellSize * 5}h${cellSize * 5}v${-cellSize * 5}z`,
30
+ inner: `M${x + cellSize * 2},${y + cellSize * 2}h${cellSize * 3}v${cellSize * 3}h${-cellSize * 3}z`
31
+ };
32
+ const outerRadius = style === "dots" ? cellSize * 3.5 : cellSize * 1.2;
33
+ const holeRadius = style === "dots" ? cellSize * 2.5 : cellSize * .8;
34
+ const innerRadius = style === "dots" ? cellSize * 1.5 : cellSize * .6;
35
+ return {
36
+ outer: roundedRect(x, y, cellSize * 7, cellSize * 7, outerRadius) + roundedRectReverse(x + cellSize, y + cellSize, cellSize * 5, cellSize * 5, holeRadius),
37
+ inner: roundedRect(x + cellSize * 2, y + cellSize * 2, cellSize * 3, cellSize * 3, innerRadius)
38
+ };
39
+ }
40
+ //#endregion
41
+ //#region src/utils/qr-encoder.ts
42
+ function generateQRMatrix(value, errorCorrectionLevel = "M") {
43
+ const qr = QRCodeLibrary.create(value, { errorCorrectionLevel });
44
+ const size = qr.modules.size;
45
+ const matrix = [];
46
+ for (let row = 0; row < size; row += 1) {
47
+ const rowData = [];
48
+ for (let column = 0; column < size; column += 1) rowData.push(qr.modules.data[row * size + column] === 1);
49
+ matrix.push(rowData);
50
+ }
51
+ return {
52
+ modules: matrix,
53
+ size
54
+ };
55
+ }
56
+ function isFinderPattern(row, column, matrixSize) {
57
+ return row < 7 && column < 7 || row < 7 && column >= matrixSize - 7 || row >= matrixSize - 7 && column < 7;
58
+ }
59
+ //#endregion
60
+ //#region src/utils/utils.ts
61
+ /** Builds a mask identifying modules hidden by the center image and its padding. */
62
+ function getExcavationMask(matrixSize, imageModuleSize, imagePadding) {
63
+ const mask = Array.from({ length: matrixSize }, () => Array(matrixSize).fill(false));
64
+ const totalImageModules = imageModuleSize + imagePadding * 2;
65
+ const startModule = Math.floor((matrixSize - totalImageModules) / 2);
66
+ const endModule = startModule + totalImageModules;
67
+ for (let row = 0; row < matrixSize; row += 1) for (let column = 0; column < matrixSize; column += 1) if (row >= startModule && row < endModule && column >= startModule && column < endModule) mask[row][column] = true;
68
+ return mask;
69
+ }
70
+ var QRCode_module_default = {
71
+ root: "_root_6mmnv_1",
72
+ svg: "_svg_6mmnv_15",
73
+ background: "_background_6mmnv_20",
74
+ modules: "_modules_6mmnv_24",
75
+ finderOuter: "_finderOuter_6mmnv_25",
76
+ finderInner: "_finderInner_6mmnv_26",
77
+ finderPattern: "_finderPattern_6mmnv_30",
78
+ image: "_image_6mmnv_33"
79
+ };
80
+ //#endregion
81
+ //#region src/QRCode.vue?vue&type=script&setup=true&lang.ts
82
+ var _hoisted_1 = ["viewBox", "aria-label"];
83
+ var _hoisted_2 = ["width", "height"];
84
+ var _hoisted_3 = ["d"];
85
+ var _hoisted_4 = ["d"];
86
+ var _hoisted_5 = ["d"];
87
+ var _hoisted_6 = [
88
+ "href",
89
+ "x",
90
+ "y",
91
+ "width",
92
+ "height",
93
+ "clip-path"
94
+ ];
95
+ var defaultProps = {
96
+ size: "md",
97
+ color: "dark",
98
+ background: "white",
99
+ errorCorrectionLevel: "M",
100
+ quietZone: 1,
101
+ dotStyle: "square",
102
+ cornerStyle: "square",
103
+ imageSize: .2,
104
+ imagePadding: 1,
105
+ imageExcavate: true
106
+ };
107
+ var varsResolver = createVarsResolver((theme, { size, radius, color, background }) => ({ root: {
108
+ "--qr-code-size": getSize(size, "qr-code-size"),
109
+ "--qr-code-radius": radius !== void 0 ? getRadius(radius) : void 0,
110
+ "--qr-code-color": color ? getThemeColor(color, theme) : void 0,
111
+ "--qr-code-background": background === "transparent" ? "transparent" : background ? getThemeColor(background, theme) : void 0
112
+ } }));
113
+ //#endregion
114
+ //#region src/QRCode.ts
115
+ var QRCode = polymorphicFactory(/* @__PURE__ */ defineComponent({
116
+ name: "QRCode",
117
+ inheritAttrs: false,
118
+ __name: "QRCode",
119
+ props: {
120
+ component: { default: void 0 },
121
+ rootRef: {
122
+ type: [Object, Function],
123
+ default: void 0
124
+ },
125
+ value: {},
126
+ size: { default: void 0 },
127
+ radius: { default: void 0 },
128
+ color: { default: void 0 },
129
+ background: { default: void 0 },
130
+ errorCorrectionLevel: { default: void 0 },
131
+ quietZone: { default: void 0 },
132
+ dotStyle: { default: void 0 },
133
+ cornerStyle: { default: void 0 },
134
+ image: { default: void 0 },
135
+ imageSize: { default: void 0 },
136
+ imageRadius: { default: void 0 },
137
+ imagePadding: { default: void 0 },
138
+ imageExcavate: {
139
+ type: Boolean,
140
+ default: void 0
141
+ },
142
+ classNames: { default: void 0 },
143
+ styles: { default: void 0 },
144
+ vars: { default: void 0 },
145
+ unstyled: { type: Boolean }
146
+ },
147
+ setup(__props, { expose: __expose }) {
148
+ const rawProps = __props;
149
+ const attrs = useAttrs();
150
+ const props = useProps("QRCode", defaultProps, rawProps);
151
+ const getStyles = useStyles({
152
+ name: "QRCode",
153
+ props,
154
+ classes: QRCode_module_default,
155
+ get className() {
156
+ return attrs.class;
157
+ },
158
+ get style() {
159
+ return attrs.style;
160
+ },
161
+ classNames: props.classNames,
162
+ styles: props.styles,
163
+ vars: props.vars,
164
+ varsResolver,
165
+ unstyled: props.unstyled
166
+ });
167
+ const rootElement = ref(null);
168
+ const setRootRef = (node) => {
169
+ rootElement.value = node;
170
+ assignRef(props.rootRef, node);
171
+ };
172
+ __expose({ rootElement });
173
+ const qrData = computed(() => {
174
+ if (!props.value) return null;
175
+ try {
176
+ return generateQRMatrix(props.value, props.errorCorrectionLevel);
177
+ } catch {
178
+ return null;
179
+ }
180
+ });
181
+ const svgContent = computed(() => {
182
+ if (!qrData.value) return null;
183
+ const { modules, size: matrixSize } = qrData.value;
184
+ const quietZone = props.quietZone ?? defaultProps.quietZone;
185
+ const imageSizeRatio = props.imageSize ?? defaultProps.imageSize;
186
+ const imagePadding = props.imagePadding ?? defaultProps.imagePadding;
187
+ const dotStyle = props.dotStyle ?? defaultProps.dotStyle;
188
+ const cornerStyle = props.cornerStyle ?? defaultProps.cornerStyle;
189
+ const viewBoxSize = matrixSize + quietZone * 2;
190
+ const excavationMask = props.image && props.imageExcavate ? getExcavationMask(matrixSize, Math.ceil(matrixSize * imageSizeRatio), imagePadding) : null;
191
+ let modulesPath = "";
192
+ for (let row = 0; row < matrixSize; row += 1) for (let column = 0; column < matrixSize; column += 1) {
193
+ if (!modules[row][column] || isFinderPattern(row, column, matrixSize) || excavationMask?.[row][column]) continue;
194
+ modulesPath += dotPath(column + quietZone, row + quietZone, 1, dotStyle);
195
+ }
196
+ const finders = [
197
+ {
198
+ key: "top-left",
199
+ row: 0,
200
+ column: 0
201
+ },
202
+ {
203
+ key: "top-right",
204
+ row: 0,
205
+ column: matrixSize - 7
206
+ },
207
+ {
208
+ key: "bottom-left",
209
+ row: matrixSize - 7,
210
+ column: 0
211
+ }
212
+ ].map((position) => ({
213
+ key: position.key,
214
+ ...finderPatternPaths(position.column + quietZone, position.row + quietZone, 1, cornerStyle)
215
+ }));
216
+ const imageElement = props.image ? (() => {
217
+ const imageSize = matrixSize * imageSizeRatio;
218
+ return {
219
+ x: (viewBoxSize - imageSize) / 2,
220
+ y: (viewBoxSize - imageSize) / 2,
221
+ size: imageSize,
222
+ radius: props.imageRadius !== void 0 ? getRadius(props.imageRadius) : "0"
223
+ };
224
+ })() : null;
225
+ return {
226
+ viewBoxSize,
227
+ modulesPath,
228
+ finders,
229
+ imageElement
230
+ };
231
+ });
232
+ return (_ctx, _cache) => {
233
+ return openBlock(), createBlock(unref(Box), mergeProps({
234
+ ...unref(attrs),
235
+ ...unref(getStyles)("root")
236
+ }, {
237
+ component: unref(props).component,
238
+ "root-ref": setRootRef
239
+ }), {
240
+ default: withCtx(() => [svgContent.value ? (openBlock(), createElementBlock("svg", mergeProps({ key: 0 }, unref(getStyles)("svg"), {
241
+ viewBox: `0 0 ${svgContent.value.viewBoxSize} ${svgContent.value.viewBoxSize}`,
242
+ xmlns: "http://www.w3.org/2000/svg",
243
+ role: "img",
244
+ "aria-label": `QR Code: ${unref(props).value}`
245
+ }), [
246
+ createElementVNode("rect", mergeProps(unref(getStyles)("background"), {
247
+ x: "0",
248
+ y: "0",
249
+ width: svgContent.value.viewBoxSize,
250
+ height: svgContent.value.viewBoxSize
251
+ }), null, 16, _hoisted_2),
252
+ svgContent.value.modulesPath ? (openBlock(), createElementBlock("path", mergeProps({ key: 0 }, unref(getStyles)("modules"), {
253
+ d: svgContent.value.modulesPath,
254
+ "fill-rule": "nonzero"
255
+ }), null, 16, _hoisted_3)) : createCommentVNode("", true),
256
+ (openBlock(true), createElementBlock(Fragment, null, renderList(svgContent.value.finders, (finder) => {
257
+ return openBlock(), createElementBlock("g", mergeProps({ key: finder.key }, { ref_for: true }, unref(getStyles)("finderPattern")), [createElementVNode("path", mergeProps({ ref_for: true }, unref(getStyles)("finderOuter"), {
258
+ d: finder.outer,
259
+ "fill-rule": "evenodd"
260
+ }), null, 16, _hoisted_4), createElementVNode("path", mergeProps({ ref_for: true }, unref(getStyles)("finderInner"), { d: finder.inner }), null, 16, _hoisted_5)], 16);
261
+ }), 128)),
262
+ svgContent.value.imageElement ? (openBlock(), createElementBlock("image", mergeProps({ key: 1 }, unref(getStyles)("image"), {
263
+ href: unref(props).image,
264
+ x: svgContent.value.imageElement.x,
265
+ y: svgContent.value.imageElement.y,
266
+ width: svgContent.value.imageElement.size,
267
+ height: svgContent.value.imageElement.size,
268
+ "clip-path": `inset(0 round ${svgContent.value.imageElement.radius})`,
269
+ preserveAspectRatio: "xMidYMid slice"
270
+ }), null, 16, _hoisted_6)) : createCommentVNode("", true)
271
+ ], 16, _hoisted_1)) : (openBlock(), createElementBlock("svg", normalizeProps(mergeProps({ key: 1 }, unref(getStyles)("svg"))), null, 16))]),
272
+ _: 1
273
+ }, 16, ["component"]);
274
+ };
275
+ }
276
+ }), {
277
+ classes: QRCode_module_default,
278
+ varsResolver
279
+ });
280
+ //#endregion
281
+ //#region src/use-qr-code-download.ts
282
+ function serializeSvg(svgElement) {
283
+ const clone = svgElement.cloneNode(true);
284
+ if (!clone.getAttribute("xmlns")) clone.setAttribute("xmlns", "http://www.w3.org/2000/svg");
285
+ const computedStyle = getComputedStyle(svgElement);
286
+ const background = computedStyle.getPropertyValue("--qr-code-background").trim() || "#ffffff";
287
+ const foreground = computedStyle.getPropertyValue("--qr-code-color").trim() || "#000000";
288
+ clone.querySelector("rect")?.setAttribute("fill", background);
289
+ clone.querySelectorAll("path").forEach((path) => {
290
+ const fill = path.getAttribute("fill");
291
+ if (!fill || fill === "currentColor") path.setAttribute("fill", foreground);
292
+ });
293
+ return new XMLSerializer().serializeToString(clone);
294
+ }
295
+ function createSvgBlob(svg) {
296
+ return new Blob([svg], { type: "image/svg+xml;charset=utf-8" });
297
+ }
298
+ async function svgToCanvas(svgElement, scale) {
299
+ const url = URL.createObjectURL(createSvgBlob(serializeSvg(svgElement)));
300
+ const viewBox = svgElement.viewBox.baseVal;
301
+ const width = (viewBox.width || svgElement.clientWidth) * scale;
302
+ const height = (viewBox.height || svgElement.clientHeight) * scale;
303
+ return new Promise((resolve, reject) => {
304
+ const image = new Image();
305
+ image.onload = () => {
306
+ const canvas = document.createElement("canvas");
307
+ canvas.width = width;
308
+ canvas.height = height;
309
+ const context = canvas.getContext("2d");
310
+ if (!context) {
311
+ URL.revokeObjectURL(url);
312
+ reject(/* @__PURE__ */ new Error("Unable to create a canvas rendering context"));
313
+ return;
314
+ }
315
+ context.fillStyle = "#ffffff";
316
+ context.fillRect(0, 0, width, height);
317
+ context.drawImage(image, 0, 0, width, height);
318
+ URL.revokeObjectURL(url);
319
+ resolve(canvas);
320
+ };
321
+ image.onerror = () => {
322
+ URL.revokeObjectURL(url);
323
+ reject(/* @__PURE__ */ new Error("Failed to load SVG as image"));
324
+ };
325
+ image.src = url;
326
+ });
327
+ }
328
+ function mimeType(format) {
329
+ return format === "jpeg" ? "image/jpeg" : format === "webp" ? "image/webp" : "image/png";
330
+ }
331
+ function triggerDownload(blob, fileName) {
332
+ const url = URL.createObjectURL(blob);
333
+ const link = document.createElement("a");
334
+ link.href = url;
335
+ link.download = fileName;
336
+ document.body.appendChild(link);
337
+ link.click();
338
+ link.remove();
339
+ URL.revokeObjectURL(url);
340
+ }
341
+ /** Provides SVG and high-resolution raster export for a `QRCode` root element. */
342
+ function useQRCodeDownload(options = {}) {
343
+ const defaultFormat = options.format ?? "png";
344
+ const defaultFileName = options.fileName ?? "qrcode";
345
+ const defaultScale = options.scale ?? 4;
346
+ const element = shallowRef(null);
347
+ const ref = (node) => {
348
+ element.value = node;
349
+ };
350
+ const getSvgElement = () => element.value?.querySelector("svg") ?? null;
351
+ const getDataUrl = async (overrides = {}) => {
352
+ const svgElement = getSvgElement();
353
+ if (!svgElement) throw new Error("QRCode SVG element not found");
354
+ const format = overrides.format ?? defaultFormat;
355
+ if (format === "svg") {
356
+ const bytes = new TextEncoder().encode(serializeSvg(svgElement));
357
+ let binary = "";
358
+ bytes.forEach((byte) => binary += String.fromCharCode(byte));
359
+ return `data:image/svg+xml;base64,${btoa(binary)}`;
360
+ }
361
+ return (await svgToCanvas(svgElement, overrides.scale ?? defaultScale)).toDataURL(mimeType(format), 1);
362
+ };
363
+ const download = async (overrides = {}) => {
364
+ const svgElement = getSvgElement();
365
+ if (!svgElement) throw new Error("QRCode SVG element not found");
366
+ const format = overrides.format ?? defaultFormat;
367
+ const fileName = `${overrides.fileName ?? defaultFileName}.${format}`;
368
+ if (format === "svg") {
369
+ triggerDownload(createSvgBlob(serializeSvg(svgElement)), fileName);
370
+ return;
371
+ }
372
+ const canvas = await svgToCanvas(svgElement, overrides.scale ?? defaultScale);
373
+ const blob = await new Promise((resolve) => canvas.toBlob(resolve, mimeType(format), 1));
374
+ if (blob) triggerDownload(blob, fileName);
375
+ };
376
+ return {
377
+ ref,
378
+ download,
379
+ getDataUrl
380
+ };
381
+ }
382
+ //#endregion
383
+ export { QRCode, useQRCodeDownload };
384
+
385
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/utils/dot-shapes.ts","../src/utils/finder-shapes.ts","../src/utils/qr-encoder.ts","../src/utils/utils.ts","../src/QRCode.module.css","../src/QRCode.vue","../src/QRCode.vue","../src/QRCode.ts","../src/use-qr-code-download.ts"],"sourcesContent":["import type { QRCodeDotStyle } from '../QRCode.types'\n\n/** Generates SVG path data for one data module. */\nexport function dotPath(x: number, y: number, cellSize: number, style: QRCodeDotStyle): string {\n if (style === 'dots') {\n const radius = cellSize / 2\n const centerX = x + radius\n const centerY = y + radius\n return `M${centerX},${centerY - radius}a${radius},${radius} 0 1,1 0,${radius * 2}a${radius},${radius} 0 1,1 0,${-radius * 2}z`\n }\n\n if (style === 'rounded') {\n const radius = cellSize * 0.3\n return (\n `M${x + radius},${y}` +\n `h${cellSize - 2 * radius}` +\n `a${radius},${radius} 0 0,1 ${radius},${radius}` +\n `v${cellSize - 2 * radius}` +\n `a${radius},${radius} 0 0,1 ${-radius},${radius}` +\n `h${-(cellSize - 2 * radius)}` +\n `a${radius},${radius} 0 0,1 ${-radius},${-radius}` +\n `v${-(cellSize - 2 * radius)}` +\n `a${radius},${radius} 0 0,1 ${radius},${-radius}z`\n )\n }\n\n return `M${x},${y}h${cellSize}v${cellSize}h${-cellSize}z`\n}\n","import type { QRCodeCornerStyle } from '../QRCode.types'\n\nexport interface FinderPaths {\n outer: string\n inner: string\n}\n\nfunction roundedRect(x: number, y: number, width: number, height: number, radius: number) {\n return (\n `M${x + radius},${y}` +\n `h${width - 2 * radius}a${radius},${radius} 0 0,1 ${radius},${radius}` +\n `v${height - 2 * radius}a${radius},${radius} 0 0,1 ${-radius},${radius}` +\n `h${-(width - 2 * radius)}a${radius},${radius} 0 0,1 ${-radius},${-radius}` +\n `v${-(height - 2 * radius)}a${radius},${radius} 0 0,1 ${radius},${-radius}z`\n )\n}\n\nfunction roundedRectReverse(x: number, y: number, width: number, height: number, radius: number) {\n return (\n `M${x + radius},${y}` +\n `a${radius},${radius} 0 0,0 ${-radius},${radius}` +\n `v${height - 2 * radius}a${radius},${radius} 0 0,0 ${radius},${radius}` +\n `h${width - 2 * radius}a${radius},${radius} 0 0,0 ${radius},${-radius}` +\n `v${-(height - 2 * radius)}a${radius},${radius} 0 0,0 ${-radius},${-radius}z`\n )\n}\n\n/** Generates separate outer-ring and inner paths for a 7x7 finder pattern. */\nexport function finderPatternPaths(\n x: number,\n y: number,\n cellSize: number,\n style: QRCodeCornerStyle,\n): FinderPaths {\n if (style === 'square') {\n const outer =\n `M${x},${y}h${cellSize * 7}v${cellSize * 7}h${-cellSize * 7}z` +\n `M${x + cellSize},${y + cellSize}v${cellSize * 5}h${cellSize * 5}v${-cellSize * 5}z`\n const inner =\n `M${x + cellSize * 2},${y + cellSize * 2}` +\n `h${cellSize * 3}v${cellSize * 3}h${-cellSize * 3}z`\n return { outer, inner }\n }\n\n const outerRadius = style === 'dots' ? cellSize * 3.5 : cellSize * 1.2\n const holeRadius = style === 'dots' ? cellSize * 2.5 : cellSize * 0.8\n const innerRadius = style === 'dots' ? cellSize * 1.5 : cellSize * 0.6\n\n return {\n outer:\n roundedRect(x, y, cellSize * 7, cellSize * 7, outerRadius) +\n roundedRectReverse(x + cellSize, y + cellSize, cellSize * 5, cellSize * 5, holeRadius),\n inner: roundedRect(x + cellSize * 2, y + cellSize * 2, cellSize * 3, cellSize * 3, innerRadius),\n }\n}\n","import QRCodeLibrary from 'qrcode'\nimport type { QRCodeErrorCorrectionLevel } from '../QRCode.types'\n\nexport interface QRMatrix {\n /** Two-dimensional matrix where true represents a dark module. */\n modules: boolean[][]\n /** Number of modules on each side. */\n size: number\n}\n\nexport function generateQRMatrix(\n value: string,\n errorCorrectionLevel: QRCodeErrorCorrectionLevel = 'M',\n): QRMatrix {\n const qr = QRCodeLibrary.create(value, { errorCorrectionLevel })\n const size = qr.modules.size\n const matrix: boolean[][] = []\n\n for (let row = 0; row < size; row += 1) {\n const rowData: boolean[] = []\n for (let column = 0; column < size; column += 1) {\n rowData.push(qr.modules.data[row * size + column] === 1)\n }\n matrix.push(rowData)\n }\n\n return { modules: matrix, size }\n}\n\nexport function isFinderPattern(row: number, column: number, matrixSize: number): boolean {\n return (\n (row < 7 && column < 7) ||\n (row < 7 && column >= matrixSize - 7) ||\n (row >= matrixSize - 7 && column < 7)\n )\n}\n","/** Builds a mask identifying modules hidden by the center image and its padding. */\nexport function getExcavationMask(\n matrixSize: number,\n imageModuleSize: number,\n imagePadding: number,\n): boolean[][] {\n const mask = Array.from({ length: matrixSize }, () => Array<boolean>(matrixSize).fill(false))\n const totalImageModules = imageModuleSize + imagePadding * 2\n const startModule = Math.floor((matrixSize - totalImageModules) / 2)\n const endModule = startModule + totalImageModules\n\n for (let row = 0; row < matrixSize; row += 1) {\n for (let column = 0; column < matrixSize; column += 1) {\n if (row >= startModule && row < endModule && column >= startModule && column < endModule) {\n mask[row][column] = true\n }\n }\n }\n\n return mask\n}\n",".root {\n --qr-code-size-xs: 80px;\n --qr-code-size-sm: 120px;\n --qr-code-size-md: 160px;\n --qr-code-size-lg: 200px;\n --qr-code-size-xl: 256px;\n\n display: inline-flex;\n width: var(--qr-code-size);\n height: var(--qr-code-size);\n border-radius: var(--qr-code-radius);\n overflow: hidden;\n}\n\n.svg {\n width: 100%;\n height: 100%;\n}\n\n.background {\n fill: var(--qr-code-background);\n}\n\n.modules,\n.finderOuter,\n.finderInner {\n fill: var(--qr-code-color);\n}\n\n.finderPattern {\n}\n\n.image {\n}\n","<script lang=\"ts\">\nimport { createVarsResolver, getRadius, getSize, getThemeColor } from '@mantine-vue/core'\n\nconst defaultProps = {\n size: 'md',\n color: 'dark',\n background: 'white',\n errorCorrectionLevel: 'M',\n quietZone: 1,\n dotStyle: 'square',\n cornerStyle: 'square',\n imageSize: 0.2,\n imagePadding: 1,\n imageExcavate: true,\n} as const\n\nconst varsResolver = createVarsResolver<any>((theme, { size, radius, color, background }) => ({\n root: {\n '--qr-code-size': getSize(size, 'qr-code-size'),\n '--qr-code-radius': radius !== undefined ? getRadius(radius) : undefined,\n '--qr-code-color': color ? getThemeColor(color, theme) : undefined,\n '--qr-code-background':\n background === 'transparent'\n ? 'transparent'\n : background\n ? getThemeColor(background, theme)\n : undefined,\n },\n}))\n\nexport { defaultProps, varsResolver }\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { assignRef } from '@mantine-vue/hooks'\nimport { Box, getRadius as resolveRadius, useProps, useStyles } from '@mantine-vue/core'\nimport { dotPath } from './utils/dot-shapes'\nimport { finderPatternPaths } from './utils/finder-shapes'\nimport { generateQRMatrix, isFinderPattern } from './utils/qr-encoder'\nimport { getExcavationMask } from './utils/utils'\nimport type { QRCodeOwnProps } from './QRCode.types'\nimport classes from './QRCode.module.css'\n\ndefineOptions({\n name: 'QRCode',\n inheritAttrs: false,\n})\n\nconst rawProps = withDefaults(defineProps<QRCodeOwnProps>(), {\n component: undefined,\n rootRef: undefined,\n size: undefined,\n radius: undefined,\n color: undefined,\n background: undefined,\n errorCorrectionLevel: undefined,\n quietZone: undefined,\n dotStyle: undefined,\n cornerStyle: undefined,\n image: undefined,\n imageSize: undefined,\n imageRadius: undefined,\n imagePadding: undefined,\n imageExcavate: undefined,\n classNames: undefined,\n styles: undefined,\n vars: undefined,\n})\n\nconst attrs = useAttrs()\nconst props = useProps('QRCode', defaultProps, rawProps)\n\nconst getStyles = useStyles({\n name: 'QRCode',\n props,\n classes,\n get className() {\n return attrs.class\n },\n get style() {\n return attrs.style as any\n },\n classNames: props.classNames as any,\n styles: props.styles as any,\n vars: props.vars as any,\n varsResolver,\n unstyled: props.unstyled,\n})\n\nconst rootElement = ref<Element | null>(null)\nconst setRootRef = (node: Element | null) => {\n rootElement.value = node\n assignRef(props.rootRef, node)\n}\n\ndefineExpose({ rootElement })\n\nconst qrData = computed(() => {\n if (!props.value) {\n return null\n }\n\n try {\n return generateQRMatrix(props.value, props.errorCorrectionLevel)\n } catch {\n return null\n }\n})\n\nconst svgContent = computed(() => {\n if (!qrData.value) {\n return null\n }\n\n const { modules, size: matrixSize } = qrData.value\n const quietZone = props.quietZone ?? defaultProps.quietZone\n const imageSizeRatio = props.imageSize ?? defaultProps.imageSize\n const imagePadding = props.imagePadding ?? defaultProps.imagePadding\n const dotStyle = props.dotStyle ?? defaultProps.dotStyle\n const cornerStyle = props.cornerStyle ?? defaultProps.cornerStyle\n const viewBoxSize = matrixSize + quietZone * 2\n const excavationMask =\n props.image && props.imageExcavate\n ? getExcavationMask(matrixSize, Math.ceil(matrixSize * imageSizeRatio), imagePadding)\n : null\n\n let modulesPath = ''\n for (let row = 0; row < matrixSize; row += 1) {\n for (let column = 0; column < matrixSize; column += 1) {\n if (\n !modules[row][column] ||\n isFinderPattern(row, column, matrixSize) ||\n excavationMask?.[row][column]\n ) {\n continue\n }\n\n modulesPath += dotPath(column + quietZone, row + quietZone, 1, dotStyle)\n }\n }\n\n const finders = [\n { key: 'top-left', row: 0, column: 0 },\n { key: 'top-right', row: 0, column: matrixSize - 7 },\n { key: 'bottom-left', row: matrixSize - 7, column: 0 },\n ].map((position) => ({\n key: position.key,\n ...finderPatternPaths(position.column + quietZone, position.row + quietZone, 1, cornerStyle),\n }))\n\n const imageElement = props.image\n ? (() => {\n const imageSize = matrixSize * imageSizeRatio\n return {\n x: (viewBoxSize - imageSize) / 2,\n y: (viewBoxSize - imageSize) / 2,\n size: imageSize,\n radius: props.imageRadius !== undefined ? resolveRadius(props.imageRadius) : '0',\n }\n })()\n : null\n\n return { viewBoxSize, modulesPath, finders, imageElement }\n})\n</script>\n\n<template>\n <Box\n v-bind=\"{ ...attrs, ...getStyles('root') }\"\n :component=\"props.component\"\n :root-ref=\"setRootRef\"\n >\n <svg\n v-if=\"svgContent\"\n v-bind=\"getStyles('svg')\"\n :viewBox=\"`0 0 ${svgContent.viewBoxSize} ${svgContent.viewBoxSize}`\"\n xmlns=\"http://www.w3.org/2000/svg\"\n role=\"img\"\n :aria-label=\"`QR Code: ${props.value}`\"\n >\n <rect\n v-bind=\"getStyles('background')\"\n x=\"0\"\n y=\"0\"\n :width=\"svgContent.viewBoxSize\"\n :height=\"svgContent.viewBoxSize\"\n />\n <path\n v-if=\"svgContent.modulesPath\"\n v-bind=\"getStyles('modules')\"\n :d=\"svgContent.modulesPath\"\n fill-rule=\"nonzero\"\n />\n <g v-for=\"finder in svgContent.finders\" :key=\"finder.key\" v-bind=\"getStyles('finderPattern')\">\n <path v-bind=\"getStyles('finderOuter')\" :d=\"finder.outer\" fill-rule=\"evenodd\" />\n <path v-bind=\"getStyles('finderInner')\" :d=\"finder.inner\" />\n </g>\n <image\n v-if=\"svgContent.imageElement\"\n v-bind=\"getStyles('image')\"\n :href=\"props.image\"\n :x=\"svgContent.imageElement.x\"\n :y=\"svgContent.imageElement.y\"\n :width=\"svgContent.imageElement.size\"\n :height=\"svgContent.imageElement.size\"\n :clip-path=\"`inset(0 round ${svgContent.imageElement.radius})`\"\n preserveAspectRatio=\"xMidYMid slice\"\n />\n </svg>\n <svg v-else v-bind=\"getStyles('svg')\" />\n </Box>\n</template>\n","<script lang=\"ts\">\nimport { createVarsResolver, getRadius, getSize, getThemeColor } from '@mantine-vue/core'\n\nconst defaultProps = {\n size: 'md',\n color: 'dark',\n background: 'white',\n errorCorrectionLevel: 'M',\n quietZone: 1,\n dotStyle: 'square',\n cornerStyle: 'square',\n imageSize: 0.2,\n imagePadding: 1,\n imageExcavate: true,\n} as const\n\nconst varsResolver = createVarsResolver<any>((theme, { size, radius, color, background }) => ({\n root: {\n '--qr-code-size': getSize(size, 'qr-code-size'),\n '--qr-code-radius': radius !== undefined ? getRadius(radius) : undefined,\n '--qr-code-color': color ? getThemeColor(color, theme) : undefined,\n '--qr-code-background':\n background === 'transparent'\n ? 'transparent'\n : background\n ? getThemeColor(background, theme)\n : undefined,\n },\n}))\n\nexport { defaultProps, varsResolver }\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useAttrs } from 'vue'\nimport { assignRef } from '@mantine-vue/hooks'\nimport { Box, getRadius as resolveRadius, useProps, useStyles } from '@mantine-vue/core'\nimport { dotPath } from './utils/dot-shapes'\nimport { finderPatternPaths } from './utils/finder-shapes'\nimport { generateQRMatrix, isFinderPattern } from './utils/qr-encoder'\nimport { getExcavationMask } from './utils/utils'\nimport type { QRCodeOwnProps } from './QRCode.types'\nimport classes from './QRCode.module.css'\n\ndefineOptions({\n name: 'QRCode',\n inheritAttrs: false,\n})\n\nconst rawProps = withDefaults(defineProps<QRCodeOwnProps>(), {\n component: undefined,\n rootRef: undefined,\n size: undefined,\n radius: undefined,\n color: undefined,\n background: undefined,\n errorCorrectionLevel: undefined,\n quietZone: undefined,\n dotStyle: undefined,\n cornerStyle: undefined,\n image: undefined,\n imageSize: undefined,\n imageRadius: undefined,\n imagePadding: undefined,\n imageExcavate: undefined,\n classNames: undefined,\n styles: undefined,\n vars: undefined,\n})\n\nconst attrs = useAttrs()\nconst props = useProps('QRCode', defaultProps, rawProps)\n\nconst getStyles = useStyles({\n name: 'QRCode',\n props,\n classes,\n get className() {\n return attrs.class\n },\n get style() {\n return attrs.style as any\n },\n classNames: props.classNames as any,\n styles: props.styles as any,\n vars: props.vars as any,\n varsResolver,\n unstyled: props.unstyled,\n})\n\nconst rootElement = ref<Element | null>(null)\nconst setRootRef = (node: Element | null) => {\n rootElement.value = node\n assignRef(props.rootRef, node)\n}\n\ndefineExpose({ rootElement })\n\nconst qrData = computed(() => {\n if (!props.value) {\n return null\n }\n\n try {\n return generateQRMatrix(props.value, props.errorCorrectionLevel)\n } catch {\n return null\n }\n})\n\nconst svgContent = computed(() => {\n if (!qrData.value) {\n return null\n }\n\n const { modules, size: matrixSize } = qrData.value\n const quietZone = props.quietZone ?? defaultProps.quietZone\n const imageSizeRatio = props.imageSize ?? defaultProps.imageSize\n const imagePadding = props.imagePadding ?? defaultProps.imagePadding\n const dotStyle = props.dotStyle ?? defaultProps.dotStyle\n const cornerStyle = props.cornerStyle ?? defaultProps.cornerStyle\n const viewBoxSize = matrixSize + quietZone * 2\n const excavationMask =\n props.image && props.imageExcavate\n ? getExcavationMask(matrixSize, Math.ceil(matrixSize * imageSizeRatio), imagePadding)\n : null\n\n let modulesPath = ''\n for (let row = 0; row < matrixSize; row += 1) {\n for (let column = 0; column < matrixSize; column += 1) {\n if (\n !modules[row][column] ||\n isFinderPattern(row, column, matrixSize) ||\n excavationMask?.[row][column]\n ) {\n continue\n }\n\n modulesPath += dotPath(column + quietZone, row + quietZone, 1, dotStyle)\n }\n }\n\n const finders = [\n { key: 'top-left', row: 0, column: 0 },\n { key: 'top-right', row: 0, column: matrixSize - 7 },\n { key: 'bottom-left', row: matrixSize - 7, column: 0 },\n ].map((position) => ({\n key: position.key,\n ...finderPatternPaths(position.column + quietZone, position.row + quietZone, 1, cornerStyle),\n }))\n\n const imageElement = props.image\n ? (() => {\n const imageSize = matrixSize * imageSizeRatio\n return {\n x: (viewBoxSize - imageSize) / 2,\n y: (viewBoxSize - imageSize) / 2,\n size: imageSize,\n radius: props.imageRadius !== undefined ? resolveRadius(props.imageRadius) : '0',\n }\n })()\n : null\n\n return { viewBoxSize, modulesPath, finders, imageElement }\n})\n</script>\n\n<template>\n <Box\n v-bind=\"{ ...attrs, ...getStyles('root') }\"\n :component=\"props.component\"\n :root-ref=\"setRootRef\"\n >\n <svg\n v-if=\"svgContent\"\n v-bind=\"getStyles('svg')\"\n :viewBox=\"`0 0 ${svgContent.viewBoxSize} ${svgContent.viewBoxSize}`\"\n xmlns=\"http://www.w3.org/2000/svg\"\n role=\"img\"\n :aria-label=\"`QR Code: ${props.value}`\"\n >\n <rect\n v-bind=\"getStyles('background')\"\n x=\"0\"\n y=\"0\"\n :width=\"svgContent.viewBoxSize\"\n :height=\"svgContent.viewBoxSize\"\n />\n <path\n v-if=\"svgContent.modulesPath\"\n v-bind=\"getStyles('modules')\"\n :d=\"svgContent.modulesPath\"\n fill-rule=\"nonzero\"\n />\n <g v-for=\"finder in svgContent.finders\" :key=\"finder.key\" v-bind=\"getStyles('finderPattern')\">\n <path v-bind=\"getStyles('finderOuter')\" :d=\"finder.outer\" fill-rule=\"evenodd\" />\n <path v-bind=\"getStyles('finderInner')\" :d=\"finder.inner\" />\n </g>\n <image\n v-if=\"svgContent.imageElement\"\n v-bind=\"getStyles('image')\"\n :href=\"props.image\"\n :x=\"svgContent.imageElement.x\"\n :y=\"svgContent.imageElement.y\"\n :width=\"svgContent.imageElement.size\"\n :height=\"svgContent.imageElement.size\"\n :clip-path=\"`inset(0 round ${svgContent.imageElement.radius})`\"\n preserveAspectRatio=\"xMidYMid slice\"\n />\n </svg>\n <svg v-else v-bind=\"getStyles('svg')\" />\n </Box>\n</template>\n","import { polymorphicFactory } from '@mantine-vue/core'\nimport QRCodeComponent, { varsResolver } from './QRCode.vue'\nimport type { QRCodeFactory } from './QRCode.types'\nimport classes from './QRCode.module.css'\n\nexport const QRCode = polymorphicFactory<QRCodeFactory>(QRCodeComponent, {\n classes,\n varsResolver,\n})\n\nexport type {\n QRCodeCornerStyle,\n QRCodeCssVariables,\n QRCodeDotStyle,\n QRCodeErrorCorrectionLevel,\n QRCodeFactory,\n QRCodeOwnProps,\n QRCodeProps,\n QRCodeStylesNames,\n} from './QRCode.types'\n","import { shallowRef } from 'vue'\n\nexport type QRCodeDownloadFormat = 'svg' | 'png' | 'jpeg' | 'webp'\n\nexport interface UseQRCodeDownloadOptions {\n /** Default download format. @default 'png' */\n format?: QRCodeDownloadFormat\n /** Default file name without an extension. @default 'qrcode' */\n fileName?: string\n /** Raster output scale. @default 4 */\n scale?: number\n}\n\nexport interface QRCodeDownloadOptions {\n format?: QRCodeDownloadFormat\n fileName?: string\n scale?: number\n}\n\nexport interface UseQRCodeDownloadReturn {\n /** Callback ref to pass to `QRCode` as `root-ref`. */\n ref: (element: Element | null) => void\n /** Downloads the current QR code. */\n download: (options?: QRCodeDownloadOptions) => Promise<void>\n /** Returns a data URL for the current QR code. */\n getDataUrl: (options?: Omit<QRCodeDownloadOptions, 'fileName'>) => Promise<string>\n}\n\nfunction serializeSvg(svgElement: SVGSVGElement): string {\n const clone = svgElement.cloneNode(true) as SVGSVGElement\n if (!clone.getAttribute('xmlns')) {\n clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg')\n }\n\n const computedStyle = getComputedStyle(svgElement)\n const background = computedStyle.getPropertyValue('--qr-code-background').trim() || '#ffffff'\n const foreground = computedStyle.getPropertyValue('--qr-code-color').trim() || '#000000'\n clone.querySelector('rect')?.setAttribute('fill', background)\n clone.querySelectorAll('path').forEach((path) => {\n const fill = path.getAttribute('fill')\n if (!fill || fill === 'currentColor') {\n path.setAttribute('fill', foreground)\n }\n })\n\n return new XMLSerializer().serializeToString(clone)\n}\n\nfunction createSvgBlob(svg: string) {\n return new Blob([svg], { type: 'image/svg+xml;charset=utf-8' })\n}\n\nasync function svgToCanvas(svgElement: SVGSVGElement, scale: number) {\n const url = URL.createObjectURL(createSvgBlob(serializeSvg(svgElement)))\n const viewBox = svgElement.viewBox.baseVal\n const width = (viewBox.width || svgElement.clientWidth) * scale\n const height = (viewBox.height || svgElement.clientHeight) * scale\n\n return new Promise<HTMLCanvasElement>((resolve, reject) => {\n const image = new Image()\n image.onload = () => {\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n const context = canvas.getContext('2d')\n if (!context) {\n URL.revokeObjectURL(url)\n reject(new Error('Unable to create a canvas rendering context'))\n return\n }\n context.fillStyle = '#ffffff'\n context.fillRect(0, 0, width, height)\n context.drawImage(image, 0, 0, width, height)\n URL.revokeObjectURL(url)\n resolve(canvas)\n }\n image.onerror = () => {\n URL.revokeObjectURL(url)\n reject(new Error('Failed to load SVG as image'))\n }\n image.src = url\n })\n}\n\nfunction mimeType(format: QRCodeDownloadFormat) {\n return format === 'jpeg' ? 'image/jpeg' : format === 'webp' ? 'image/webp' : 'image/png'\n}\n\nfunction triggerDownload(blob: Blob, fileName: string) {\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = fileName\n document.body.appendChild(link)\n link.click()\n link.remove()\n URL.revokeObjectURL(url)\n}\n\n/** Provides SVG and high-resolution raster export for a `QRCode` root element. */\nexport function useQRCodeDownload(options: UseQRCodeDownloadOptions = {}): UseQRCodeDownloadReturn {\n const defaultFormat = options.format ?? 'png'\n const defaultFileName = options.fileName ?? 'qrcode'\n const defaultScale = options.scale ?? 4\n const element = shallowRef<Element | null>(null)\n const ref = (node: Element | null) => {\n element.value = node\n }\n\n const getSvgElement = () => element.value?.querySelector('svg') ?? null\n\n const getDataUrl: UseQRCodeDownloadReturn['getDataUrl'] = async (overrides = {}) => {\n const svgElement = getSvgElement()\n if (!svgElement) {\n throw new Error('QRCode SVG element not found')\n }\n\n const format = overrides.format ?? defaultFormat\n if (format === 'svg') {\n const bytes = new TextEncoder().encode(serializeSvg(svgElement))\n let binary = ''\n bytes.forEach((byte) => (binary += String.fromCharCode(byte)))\n return `data:image/svg+xml;base64,${btoa(binary)}`\n }\n\n const canvas = await svgToCanvas(svgElement, overrides.scale ?? defaultScale)\n return canvas.toDataURL(mimeType(format), 1)\n }\n\n const download: UseQRCodeDownloadReturn['download'] = async (overrides = {}) => {\n const svgElement = getSvgElement()\n if (!svgElement) {\n throw new Error('QRCode SVG element not found')\n }\n\n const format = overrides.format ?? defaultFormat\n const fileName = `${overrides.fileName ?? defaultFileName}.${format}`\n if (format === 'svg') {\n triggerDownload(createSvgBlob(serializeSvg(svgElement)), fileName)\n return\n }\n\n const canvas = await svgToCanvas(svgElement, overrides.scale ?? defaultScale)\n const blob = await new Promise<Blob | null>((resolve) =>\n canvas.toBlob(resolve, mimeType(format), 1),\n )\n if (blob) {\n triggerDownload(blob, fileName)\n }\n }\n\n return { ref, download, getDataUrl }\n}\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare const QRCode: import("@mantine-vue/core").MantinePolymorphicComponent<{
2
+ props: Omit<import("./QRCode.types").QRCodeProps, "component" | "rootRef">;
3
+ ref: HTMLDivElement;
4
+ exposed: {
5
+ rootElement: Element | null;
6
+ };
7
+ defaultComponent: "div";
8
+ defaultRef: HTMLDivElement;
9
+ stylesNames: import("./QRCode.types").QRCodeStylesNames;
10
+ vars: import("./QRCode.types").QRCodeCssVariables;
11
+ }, "div">;
12
+ export type { QRCodeCornerStyle, QRCodeCssVariables, QRCodeDotStyle, QRCodeErrorCorrectionLevel, QRCodeFactory, QRCodeOwnProps, QRCodeProps, QRCodeStylesNames, } from './QRCode.types';
@@ -0,0 +1,58 @@
1
+ import type { BoxProps, MantineColor, MantineRadius, MantineSize, PolymorphicFactory } from '@mantine-vue/core';
2
+ import type { StylesApiProps } from '@mantine-vue/core/styles-api';
3
+ import type { VueRefTarget } from '@mantine-vue/hooks';
4
+ export type QRCodeErrorCorrectionLevel = 'L' | 'M' | 'Q' | 'H';
5
+ export type QRCodeDotStyle = 'square' | 'rounded' | 'dots';
6
+ export type QRCodeCornerStyle = 'square' | 'rounded' | 'dots';
7
+ /** Props declared by `QRCode` itself. See `QRCodeProps` for the full public type. */
8
+ export interface QRCodeOwnProps extends StylesApiProps<QRCodeFactory> {
9
+ /** Root element or component rendered by `QRCode`. @default 'div' */
10
+ component?: any;
11
+ /** Receives the root DOM node. */
12
+ rootRef?: VueRefTarget<Element>;
13
+ /** Data to encode in the QR code (URL, text, contact data, and so on). */
14
+ value: string;
15
+ /** QR code width and height. @default 'md' */
16
+ size?: MantineSize | (string & {}) | number;
17
+ /** Border radius of the outer container. */
18
+ radius?: MantineRadius;
19
+ /** Module foreground color from the Mantine theme. @default 'dark' */
20
+ color?: MantineColor;
21
+ /** Background color from the Mantine theme, or `transparent`. @default 'white' */
22
+ background?: MantineColor | 'transparent';
23
+ /** Error correction level: L (7%), M (15%), Q (25%), or H (30%). @default 'M' */
24
+ errorCorrectionLevel?: QRCodeErrorCorrectionLevel;
25
+ /** Number of quiet-zone modules around the QR code. @default 1 */
26
+ quietZone?: number;
27
+ /** Shape used for data modules. @default 'square' */
28
+ dotStyle?: QRCodeDotStyle;
29
+ /** Shape used for the three finder patterns. @default 'square' */
30
+ cornerStyle?: QRCodeCornerStyle;
31
+ /** URL of an image or logo rendered at the center. */
32
+ image?: string;
33
+ /** Image size relative to the QR matrix, from 0 to 1. @default 0.2 */
34
+ imageSize?: number;
35
+ /** Border radius of the center image. */
36
+ imageRadius?: MantineRadius;
37
+ /** Padding around the image measured in modules. @default 1 */
38
+ imagePadding?: number;
39
+ /** Removes QR modules behind the center image. @default true */
40
+ imageExcavate?: boolean;
41
+ }
42
+ export interface QRCodeProps extends Omit<BoxProps, keyof QRCodeOwnProps>, QRCodeOwnProps {
43
+ }
44
+ export type QRCodeStylesNames = 'root' | 'svg' | 'background' | 'modules' | 'finderPattern' | 'finderOuter' | 'finderInner' | 'image';
45
+ export type QRCodeCssVariables = {
46
+ root: '--qr-code-size' | '--qr-code-radius' | '--qr-code-color' | '--qr-code-background';
47
+ };
48
+ export type QRCodeFactory = PolymorphicFactory<{
49
+ props: Omit<QRCodeProps, 'component' | 'rootRef'>;
50
+ ref: HTMLDivElement;
51
+ exposed: {
52
+ rootElement: Element | null;
53
+ };
54
+ defaultComponent: 'div';
55
+ defaultRef: HTMLDivElement;
56
+ stylesNames: QRCodeStylesNames;
57
+ vars: QRCodeCssVariables;
58
+ }>;
@@ -0,0 +1,20 @@
1
+ import type { QRCodeOwnProps } from './QRCode.types';
2
+ declare const defaultProps: {
3
+ readonly size: "md";
4
+ readonly color: "dark";
5
+ readonly background: "white";
6
+ readonly errorCorrectionLevel: "M";
7
+ readonly quietZone: 1;
8
+ readonly dotStyle: "square";
9
+ readonly cornerStyle: "square";
10
+ readonly imageSize: 0.2;
11
+ readonly imagePadding: 1;
12
+ readonly imageExcavate: true;
13
+ };
14
+ declare const varsResolver: (theme: import("@mantine-vue/core").MantineTheme, props: any, ctx: Record<string, any>) => Record<string, Record<string, string | undefined>>;
15
+ export { defaultProps, varsResolver };
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
18
+ declare const __VLS_export: import("vue").DefineComponent<QRCodeOwnProps, {
19
+ rootElement: import("vue").Ref<Element | null, Element | null>;
20
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<QRCodeOwnProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -0,0 +1,4 @@
1
+ export { QRCode } from './QRCode';
2
+ export type { QRCodeCornerStyle, QRCodeCssVariables, QRCodeDotStyle, QRCodeErrorCorrectionLevel, QRCodeFactory, QRCodeOwnProps, QRCodeProps, QRCodeStylesNames, } from './QRCode.types';
3
+ export { useQRCodeDownload } from './use-qr-code-download';
4
+ export type { QRCodeDownloadFormat, QRCodeDownloadOptions, UseQRCodeDownloadOptions, UseQRCodeDownloadReturn, } from './use-qr-code-download';
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { QRCode } from './QRCode';
2
+ export type { QRCodeCornerStyle, QRCodeCssVariables, QRCodeDotStyle, QRCodeErrorCorrectionLevel, QRCodeFactory, QRCodeOwnProps, QRCodeProps, QRCodeStylesNames, } from './QRCode.types';
3
+ export { useQRCodeDownload } from './use-qr-code-download';
4
+ export type { QRCodeDownloadFormat, QRCodeDownloadOptions, UseQRCodeDownloadOptions, UseQRCodeDownloadReturn, } from './use-qr-code-download';
@@ -0,0 +1,24 @@
1
+ export type QRCodeDownloadFormat = 'svg' | 'png' | 'jpeg' | 'webp';
2
+ export interface UseQRCodeDownloadOptions {
3
+ /** Default download format. @default 'png' */
4
+ format?: QRCodeDownloadFormat;
5
+ /** Default file name without an extension. @default 'qrcode' */
6
+ fileName?: string;
7
+ /** Raster output scale. @default 4 */
8
+ scale?: number;
9
+ }
10
+ export interface QRCodeDownloadOptions {
11
+ format?: QRCodeDownloadFormat;
12
+ fileName?: string;
13
+ scale?: number;
14
+ }
15
+ export interface UseQRCodeDownloadReturn {
16
+ /** Callback ref to pass to `QRCode` as `root-ref`. */
17
+ ref: (element: Element | null) => void;
18
+ /** Downloads the current QR code. */
19
+ download: (options?: QRCodeDownloadOptions) => Promise<void>;
20
+ /** Returns a data URL for the current QR code. */
21
+ getDataUrl: (options?: Omit<QRCodeDownloadOptions, 'fileName'>) => Promise<string>;
22
+ }
23
+ /** Provides SVG and high-resolution raster export for a `QRCode` root element. */
24
+ export declare function useQRCodeDownload(options?: UseQRCodeDownloadOptions): UseQRCodeDownloadReturn;
@@ -0,0 +1,3 @@
1
+ import type { QRCodeDotStyle } from '../QRCode.types';
2
+ /** Generates SVG path data for one data module. */
3
+ export declare function dotPath(x: number, y: number, cellSize: number, style: QRCodeDotStyle): string;
@@ -0,0 +1,7 @@
1
+ import type { QRCodeCornerStyle } from '../QRCode.types';
2
+ export interface FinderPaths {
3
+ outer: string;
4
+ inner: string;
5
+ }
6
+ /** Generates separate outer-ring and inner paths for a 7x7 finder pattern. */
7
+ export declare function finderPatternPaths(x: number, y: number, cellSize: number, style: QRCodeCornerStyle): FinderPaths;
@@ -0,0 +1,9 @@
1
+ import type { QRCodeErrorCorrectionLevel } from '../QRCode.types';
2
+ export interface QRMatrix {
3
+ /** Two-dimensional matrix where true represents a dark module. */
4
+ modules: boolean[][];
5
+ /** Number of modules on each side. */
6
+ size: number;
7
+ }
8
+ export declare function generateQRMatrix(value: string, errorCorrectionLevel?: QRCodeErrorCorrectionLevel): QRMatrix;
9
+ export declare function isFinderPattern(row: number, column: number, matrixSize: number): boolean;
@@ -0,0 +1,2 @@
1
+ /** Builds a mask identifying modules hidden by the center image and its padding. */
2
+ export declare function getExcavationMask(matrixSize: number, imageModuleSize: number, imagePadding: number): boolean[][];
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@mantine-vue/qr-code",
3
+ "version": "3.4.0",
4
+ "description": "Customizable QR code component for Vue with image overlays and SVG or raster downloads",
5
+ "license": "MIT",
6
+ "files": [
7
+ "cjs",
8
+ "esm",
9
+ "lib",
10
+ "styles.css",
11
+ "styles.layer.css",
12
+ "styles"
13
+ ],
14
+ "sideEffects": [
15
+ "*.css"
16
+ ],
17
+ "main": "./cjs/index.cjs",
18
+ "module": "./esm/index.mjs",
19
+ "types": "./lib/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "import": {
23
+ "types": "./lib/index.d.mts",
24
+ "default": "./esm/index.mjs"
25
+ },
26
+ "require": {
27
+ "types": "./lib/index.d.ts",
28
+ "default": "./cjs/index.cjs"
29
+ }
30
+ },
31
+ "./styles.css": "./styles.css",
32
+ "./styles.layer.css": "./styles.layer.css"
33
+ },
34
+ "dependencies": {
35
+ "qrcode": "^1.5.4"
36
+ },
37
+ "devDependencies": {
38
+ "@mantine-vue/core": "workspace:*",
39
+ "@mantine-vue/hooks": "workspace:*",
40
+ "@types/qrcode": "^1.5.6",
41
+ "@vue/compiler-dom": "^3.5.0",
42
+ "@vue/test-utils": "^2.4.6",
43
+ "vue": "^3.5.0"
44
+ },
45
+ "peerDependencies": {
46
+ "@mantine-vue/core": "3.4.0",
47
+ "@mantine-vue/hooks": "3.4.0",
48
+ "vue": "^3.5.0"
49
+ },
50
+ "mantineVue": {
51
+ "cssLayer": "mantine-qr-code"
52
+ }
53
+ }
package/styles.css ADDED
@@ -0,0 +1,35 @@
1
+ ._root_6mmnv_1 {
2
+ --qr-code-size-xs: calc(5rem * var(--mantine-scale));
3
+ --qr-code-size-sm: calc(7.5rem * var(--mantine-scale));
4
+ --qr-code-size-md: calc(10rem * var(--mantine-scale));
5
+ --qr-code-size-lg: calc(12.5rem * var(--mantine-scale));
6
+ --qr-code-size-xl: calc(16rem * var(--mantine-scale));
7
+
8
+ display: inline-flex;
9
+ width: var(--qr-code-size);
10
+ height: var(--qr-code-size);
11
+ border-radius: var(--qr-code-radius);
12
+ overflow: hidden;
13
+ }
14
+
15
+ ._svg_6mmnv_15 {
16
+ width: 100%;
17
+ height: 100%;
18
+ }
19
+
20
+ ._background_6mmnv_20 {
21
+ fill: var(--qr-code-background);
22
+ }
23
+
24
+ ._modules_6mmnv_24,
25
+ ._finderOuter_6mmnv_25,
26
+ ._finderInner_6mmnv_26 {
27
+ fill: var(--qr-code-color);
28
+ }
29
+
30
+ ._finderPattern_6mmnv_30 {
31
+ }
32
+
33
+ ._image_6mmnv_33 {
34
+ }
35
+ /*$vite$:1*/
@@ -0,0 +1,37 @@
1
+ @layer mantine-qr-code {
2
+ ._root_6mmnv_1 {
3
+ --qr-code-size-xs: calc(5rem * var(--mantine-scale));
4
+ --qr-code-size-sm: calc(7.5rem * var(--mantine-scale));
5
+ --qr-code-size-md: calc(10rem * var(--mantine-scale));
6
+ --qr-code-size-lg: calc(12.5rem * var(--mantine-scale));
7
+ --qr-code-size-xl: calc(16rem * var(--mantine-scale));
8
+
9
+ display: inline-flex;
10
+ width: var(--qr-code-size);
11
+ height: var(--qr-code-size);
12
+ border-radius: var(--qr-code-radius);
13
+ overflow: hidden;
14
+ }
15
+
16
+ ._svg_6mmnv_15 {
17
+ width: 100%;
18
+ height: 100%;
19
+ }
20
+
21
+ ._background_6mmnv_20 {
22
+ fill: var(--qr-code-background);
23
+ }
24
+
25
+ ._modules_6mmnv_24,
26
+ ._finderOuter_6mmnv_25,
27
+ ._finderInner_6mmnv_26 {
28
+ fill: var(--qr-code-color);
29
+ }
30
+
31
+ ._finderPattern_6mmnv_30 {
32
+ }
33
+
34
+ ._image_6mmnv_33 {
35
+ }
36
+ /*$vite$:1*/
37
+ }