@thinkpixellab-public/px-vue 4.1.31 → 5.0.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/components/PxQrCode.vue +84 -64
- package/package.json +2 -2
package/components/PxQrCode.vue
CHANGED
|
@@ -45,14 +45,14 @@ export default {
|
|
|
45
45
|
const rectEls = svg?.querySelectorAll(':scope > rect');
|
|
46
46
|
const imageEls = svg?.querySelectorAll(':scope > image');
|
|
47
47
|
|
|
48
|
-
const marginPx = (this.percentageMargin / 100) * svg
|
|
49
|
-
const scale = (svg
|
|
48
|
+
const marginPx = (this.percentageMargin / 100) * svg?.clientWidth;
|
|
49
|
+
const scale = (svg?.clientWidth - marginPx * 2) / svg?.clientWidth;
|
|
50
50
|
|
|
51
51
|
// the second rect is the qrcode
|
|
52
52
|
const qrRect = rectEls?.[1];
|
|
53
53
|
const qrImage = imageEls?.[0];
|
|
54
54
|
|
|
55
|
-
if (!qrRect || !qrImage) {
|
|
55
|
+
if (!qrRect || !qrImage || !svg) {
|
|
56
56
|
if (retryCount < MAX_RETRIES) {
|
|
57
57
|
setTimeout(() => {
|
|
58
58
|
this.setScale(retryCount + 1);
|
|
@@ -69,86 +69,106 @@ export default {
|
|
|
69
69
|
qrRect.style.transform = `scale(${scale})`;
|
|
70
70
|
qrImage.style.transform = `scale(${scale})`;
|
|
71
71
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
imageOptions: {
|
|
86
|
-
hideBackgroundDots: false,
|
|
87
|
-
imageSize: this.imageSettings?.size || 0.1,
|
|
88
|
-
margin: 0,
|
|
89
|
-
crossOrigin: 'anonymous',
|
|
90
|
-
},
|
|
91
|
-
data: this.content,
|
|
92
|
-
...rest,
|
|
93
|
-
type: 'svg',
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
if (!this.percentageMargin) {
|
|
97
|
-
this.isRendered = true;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
this.qrCode = new QRCodeStyling(options);
|
|
72
|
+
setupQRCode() {
|
|
73
|
+
this.size = Math.min(this.$el.clientWidth, this.$el.clientHeight);
|
|
74
|
+
|
|
75
|
+
if (this.size <= 0) {
|
|
76
|
+
// setup a size observer to wait for a size, if size is 0 the qr code throws an exception
|
|
77
|
+
this.setupSizeObserver = new ResizeObserver(entries => {
|
|
78
|
+
const size = Math.min(this.$el.clientWidth, this.$el.clientHeight);
|
|
79
|
+
if (size > 0) {
|
|
80
|
+
this.setupSizeObserver.disconnect();
|
|
81
|
+
this.setupSizeObserver = null;
|
|
82
|
+
this.setupQRCode();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
101
85
|
|
|
102
|
-
|
|
103
|
-
const containerSize = Math.min(this.$el.clientWidth, this.$el.clientHeight);
|
|
104
|
-
this.size = containerSize;
|
|
86
|
+
this.setupSizeObserver.observe(this.$el);
|
|
105
87
|
|
|
106
|
-
if (!this.qrCode._qr) {
|
|
107
88
|
return;
|
|
108
89
|
}
|
|
109
90
|
|
|
110
|
-
|
|
111
|
-
|
|
91
|
+
const { margin, ...rest } = this.qrCodeConfig || {};
|
|
92
|
+
|
|
93
|
+
// margin is a percentage of the svg width
|
|
94
|
+
this.percentageMargin = margin ? Math.min(Math.max(0, margin), 100) : 0;
|
|
95
|
+
|
|
96
|
+
const options = {
|
|
97
|
+
width: this.size,
|
|
98
|
+
height: this.size,
|
|
99
|
+
image: this.imageSettings?.src || null,
|
|
100
|
+
imageOptions: {
|
|
101
|
+
hideBackgroundDots: false,
|
|
102
|
+
imageSize: this.imageSettings?.size || 0.1,
|
|
103
|
+
margin: 0,
|
|
104
|
+
crossOrigin: 'anonymous',
|
|
105
|
+
},
|
|
106
|
+
data: this.content,
|
|
107
|
+
...rest,
|
|
108
|
+
type: 'svg',
|
|
109
|
+
};
|
|
112
110
|
|
|
113
|
-
|
|
111
|
+
if (!this.percentageMargin) {
|
|
112
|
+
this.isRendered = true;
|
|
113
|
+
}
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
const moduleSize = Math.floor(naturalModSize);
|
|
115
|
+
this.qrCode = new QRCodeStyling(options);
|
|
117
116
|
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
this.onSizeChange = () => {
|
|
118
|
+
const containerSize = Math.min(this.$el.clientWidth, this.$el.clientHeight);
|
|
119
|
+
this.size = containerSize;
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
if (!this.qrCode._qr) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
// 1. Get module count
|
|
126
|
+
const moduleCount = this.qrCode._qr.getModuleCount();
|
|
126
127
|
|
|
127
|
-
|
|
128
|
-
this.setScale();
|
|
129
|
-
});
|
|
130
|
-
};
|
|
128
|
+
const naturalModSize = containerSize / moduleCount;
|
|
131
129
|
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
// 2. the qr code lib uses integer pixel sizes, so we need to round down
|
|
131
|
+
const moduleSize = Math.floor(naturalModSize);
|
|
134
132
|
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
// 3. recalculate actual size to position the qr code in the top left corner
|
|
134
|
+
const qrSize = moduleCount * moduleSize;
|
|
137
135
|
|
|
138
|
-
|
|
136
|
+
// 4. Update QR options
|
|
137
|
+
options.width = qrSize;
|
|
138
|
+
options.height = qrSize;
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
this
|
|
144
|
-
this.setScale();
|
|
145
|
-
});
|
|
140
|
+
this.qrCode.update(options);
|
|
141
|
+
|
|
142
|
+
this.$nextTick(() => {
|
|
143
|
+
this.setScale();
|
|
146
144
|
});
|
|
147
|
-
}
|
|
148
|
-
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
this.resizeObserver = new ResizeObserver(this.onSizeChange);
|
|
148
|
+
this.resizeObserver.observe(this.$el);
|
|
149
|
+
|
|
150
|
+
this.$nextTick(() => {
|
|
151
|
+
this.qrCode.append(this.$refs.qrCode);
|
|
152
|
+
|
|
153
|
+
this.onSizeChange();
|
|
154
|
+
|
|
155
|
+
if (this.percentageMargin) {
|
|
156
|
+
this.qrCode.getRawData('svg').then(() => {
|
|
157
|
+
// QR code has been rendered
|
|
158
|
+
this.$nextTick(() => {
|
|
159
|
+
this.setScale();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
mounted() {
|
|
167
|
+
this.setupQRCode();
|
|
149
168
|
},
|
|
150
169
|
beforeUnmount() {
|
|
151
170
|
this.resizeObserver?.disconnect();
|
|
171
|
+
this.setupSizeObserver?.disconnect();
|
|
152
172
|
},
|
|
153
173
|
};
|
|
154
174
|
</script>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thinkpixellab-public/px-vue",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "General purpose Vue components and helpers that can be used across projects.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Pixel Lab"
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@babel/core": "^7.26.10",
|
|
45
45
|
"@chromatic-com/storybook": "^3.2.6",
|
|
46
|
-
"@nuxt/kit": "^
|
|
46
|
+
"@nuxt/kit": "^4.2.1",
|
|
47
47
|
"@rushstack/eslint-patch": "^1.11.0",
|
|
48
48
|
"@storybook/addon-essentials": "^8.6.7",
|
|
49
49
|
"@storybook/addon-interactions": "^8.6.7",
|