diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 822c55b1..f31c1193 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -4,7 +4,6 @@ about: Create a report to help us improve title: '' labels: '' assignees: '' - --- **Describe the bug** @@ -17,12 +16,14 @@ Please provide a link to a minimal reproduction of the bug. For example on jsFid If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] + +- OS: [e.g. iOS] +- Browser [e.g. chrome, safari] +- Version [e.g. 22] **Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] + +- Device: [e.g. iPhone6] +- OS: [e.g. iOS8.1] +- Browser [e.g. stock browser, safari] +- Version [e.g. 22] diff --git a/.lintstagedrc b/.lintstagedrc index c4b0aa5d..83fc3d02 100644 --- a/.lintstagedrc +++ b/.lintstagedrc @@ -1,3 +1,4 @@ { - "*.{js,jsx,vue}": ["pnpm lint --fix", "git add"] + "**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts}": ["pnpm lint"], + "**/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts,json,md}": ["pnpm format"] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 1f477646..65a19653 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { "editor.defaultFormatter": "esbenp.prettier-vscode" -} \ No newline at end of file +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 32ddc4c4..6185fc9f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -Your contributions are welcome. +Your contributions are welcome. Don't hesitate to open an issue if you have trouble. ### Setup Dev Environment @@ -12,7 +12,7 @@ Clone the repository and run pnpm install ``` -We use a locally served version of the [demo page](https://vue-qrcode-reader.netlify.app/) during development. +We use a locally served version of the [demo page](https://vue-qrcode-reader.netlify.app/) during development. To get that started run ``` @@ -21,5 +21,5 @@ npm run docs:dev ### Commit Messages -The version number of releases is automatically determined form commit messages. +The version number of releases is automatically determined form commit messages. This only works if we follow [Angular Commit Message Conventions](https://github.com/semantic-release/semantic-release#commit-message-format). diff --git a/README.md b/README.md index 479d76a5..c912555e 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,6 @@ npm current version -
@@ -63,9 +62,9 @@ A set of Vue.js components for detecting QR codes and [various other barcode for - :put_litter_in_its_place: `QrcodeDropZone` is an empty region where you can drag-and-drop images to be decoded. - :open_file_folder: `QrcodeCapture` is a classic file upload field, instantly scanning all files you select. -All components are responsive. -Beyond that, close to zero styling. -Make them fit your layout. +All components are responsive. +Beyond that, close to zero styling. +Make them fit your layout. Usage is simple and straight forward: ```html @@ -117,10 +116,10 @@ const MyComponent = { or register all of them globally right away ```javascript -import Vue from "vue"; -import VueQrcodeReader from "vue-qrcode-reader"; +import Vue from 'vue' +import VueQrcodeReader from 'vue-qrcode-reader' -Vue.use(VueQrcodeReader); +Vue.use(VueQrcodeReader) ``` ## Without NPM @@ -149,17 +148,17 @@ Use kebab-case to reference them in your templates: #### I don't see the camera when using `QrcodeStream`. -- Check if it works on the demo page. Especially the [Handle Errors](https://vue-qrcode-reader.netlify.app/demos/HandleErrors.html) demo, - since it renders error messages. +- Check if it works on the demo page. Especially the [Handle Errors](https://vue-qrcode-reader.netlify.app/demos/HandleErrors.html) demo, + since it renders error messages. - The demo works but it doesn't work in my project: Listen for the `error` event to investigate errors. - - The demo doesn't work: Carefully review the Browser Support section above. + - The demo doesn't work: Carefully review the Browser Support section above. Maybe your device is just not supported. #### I'm running a dev server on localhost. How to test on my mobile device without HTTPS? - If your setup is Desktop Chrome + Android Chrome, use [Remote Debugging](https://developers.google.com/web/tools/chrome-devtools/remote-debugging/) which allows your Android device to [access your local server as localhost](https://developers.google.com/web/tools/chrome-devtools/remote-debugging/local-server). - Otherwise use a reverse proxy like [ngrok](https://ngrok.com/) or [serveo](https://serveo.net/) to temporarily make your local server publicly available with HTTPS. -- There are also loads of serverless/static hosting services that have HTTPS enabled by default and where you can deploy your web app for free (e.g. *GitHub Pages*, *GitLab Pages*, *Google Firebase*, *Netlify*, *Heroku*, *ZEIT Now*, ...) +- There are also loads of serverless/static hosting services that have HTTPS enabled by default and where you can deploy your web app for free (e.g. _GitHub Pages_, _GitLab Pages_, _Google Firebase_, _Netlify_, _Heroku_, _ZEIT Now_, ...) #### Some of my QR codes are not being detected. @@ -168,28 +167,28 @@ Use kebab-case to reference them in your templates: #### How to make it work with Vue 2? -Support is dropped but you can downgrade to vue-qrcode-reader v3.* or lower. +Support is dropped but you can downgrade to vue-qrcode-reader v3.\* or lower. #### I get a "Failed to fetch" error at runtime for some Wasm file. -That Wasm file implements the QR code detector. +That Wasm file implements the QR code detector. Unfortunately, it's not very convenient to bundle this file with the package. So by default we fetch it at runtime from a CDN. -That's an issue for offline applications or applications that run in a network with strict CSP policy. +That's an issue for offline applications or applications that run in a network with strict CSP policy. For a workaround see: https://github.com/gruhn/vue-qrcode-reader/issues/354 -### `torch` is not supported on my device, although it has a flashlight. +#### `torch` is not supported on my device, although it has a flashlight. Support for `torch` is inconsistent across devices, cameras and browsers and operating systems. On some devices the rear camera supports `torch` but the front camera doesn't, even if the front camera actually has a flashlight. -Furthermore, `torch` is not supported on iOS at all (last checked iOS 17.1). +Furthermore, `torch` is not supported on iOS at all (last checked iOS 17.1). Visit [this page](https://vue-qrcode-reader.netlify.app/select-camera-demo.html) with your device. -The list of links represents all cameras installed on the device. -If you click, the camera should be loaded. -Below the camera view the JSON object of "capabilities" is printed. +The list of links represents all cameras installed on the device. +If you click, the camera should be loaded. +Below the camera view the JSON object of "capabilities" is printed. If it doesn't contain the key/value pair `"torch": true` then flashlight is not supported for that camera. This JSON object provided as payload of the [`camera-on` event](https://vue-qrcode-reader.netlify.app/api/QrcodeStream.html#camera-on). diff --git a/docs/.vitepress/components/demos/CustomTracking.vue b/docs/.vitepress/components/demos/CustomTracking.vue index 782105d1..45a082fb 100644 --- a/docs/.vitepress/components/demos/CustomTracking.vue +++ b/docs/.vitepress/components/demos/CustomTracking.vue @@ -3,13 +3,20 @@

Track function:

- + diff --git a/docs/.vitepress/components/demos/CustomTrackingWithFormats.vue b/docs/.vitepress/components/demos/CustomTrackingWithFormats.vue index c9d468d5..5f749ccc 100644 --- a/docs/.vitepress/components/demos/CustomTrackingWithFormats.vue +++ b/docs/.vitepress/components/demos/CustomTrackingWithFormats.vue @@ -2,8 +2,15 @@

Barcodeformat: - + @@ -11,13 +18,21 @@

Track function:

- +
@@ -37,11 +52,33 @@ export default { const selected = options[1] - const barcodeTypes = ["aztec", "code_128", "code_39", "code_93", "codabar", "databar", "databar_expanded", "data_matrix", "dx_film_edge", "ean_13", "ean_8", "itf", "maxi_code", "micro_qr_code", "pdf417", "qr_code", "rm_qr_code", "upc_a", "upc_e", "linear_codes", "matrix_codes"] + const barcodeTypes = [ + 'aztec', + 'code_128', + 'code_39', + 'code_93', + 'codabar', + 'databar', + 'databar_expanded', + 'data_matrix', + 'dx_film_edge', + 'ean_13', + 'ean_8', + 'itf', + 'maxi_code', + 'micro_qr_code', + 'pdf417', + 'qr_code', + 'rm_qr_code', + 'upc_a', + 'upc_e', + 'linear_codes', + 'matrix_codes' + ] - const selectedBarcodeTypes = ["qr_code"] + const selectedBarcodeTypes = ['qr_code'] - return { selected, options, selectedBarcodeTypes, barcodeTypes} + return { selected, options, selectedBarcodeTypes, barcodeTypes } }, methods: { diff --git a/docs/.vitepress/components/demos/DeviceId.vue b/docs/.vitepress/components/demos/DeviceId.vue index 1cd628fd..b9055ef5 100644 --- a/docs/.vitepress/components/demos/DeviceId.vue +++ b/docs/.vitepress/components/demos/DeviceId.vue @@ -2,16 +2,29 @@

-
- -

No cameras on this device

-
+
+ +

+ No cameras on this device +

+
@@ -23,12 +36,13 @@ const selected = ref(null) const devices = ref([]) onMounted(async () => { - devices.value = (await navigator.mediaDevices.enumerateDevices()) - .filter(({ kind }) => kind === 'videoinput') + devices.value = (await navigator.mediaDevices.enumerateDevices()).filter( + ({ kind }) => kind === 'videoinput' + ) - if (devices.value.length > 0) { - selected.value = devices.value[0] - } + if (devices.value.length > 0) { + selected.value = devices.value[0] + } }) diff --git a/docs/.vitepress/components/demos/DragDrop.vue b/docs/.vitepress/components/demos/DragDrop.vue index 1d38059b..77ab2611 100644 --- a/docs/.vitepress/components/demos/DragDrop.vue +++ b/docs/.vitepress/components/demos/DragDrop.vue @@ -4,12 +4,24 @@ Last result: {{ result }}

-

+

{{ error }}

- -
DROP SOME IMAGES HERE
+ +
+ DROP SOME IMAGES HERE +
@@ -32,9 +44,7 @@ export default { onDetect(detectedCodes) { console.log(detectedCodes) - this.result = JSON.stringify( - detectedCodes.map(code => code.rawValue) - ) + this.result = JSON.stringify(detectedCodes.map((code) => code.rawValue)) }, logErrors(error) { diff --git a/docs/.vitepress/components/demos/Fullscreen.vue b/docs/.vitepress/components/demos/Fullscreen.vue index b6914755..393818db 100644 --- a/docs/.vitepress/components/demos/Fullscreen.vue +++ b/docs/.vitepress/components/demos/Fullscreen.vue @@ -1,8 +1,18 @@ @@ -20,14 +23,14 @@ const result = ref('') const error = ref('') // methods -const onDetect = detectedCodes => { +const onDetect = (detectedCodes) => { console.log(detectedCodes) - const [ firstCode ] = detectedCodes + const [firstCode] = detectedCodes result.value = firstCode.rawValue } -const onError = err => { +const onError = (err) => { error.value = `[${err.name}]: ` if (err.name === 'NotAllowedError') { @@ -43,7 +46,8 @@ const onError = err => { } else if (err.name === 'StreamApiNotSupportedError') { error.value += 'Stream API is not supported in this browser' } else if (err.name === 'InsecureContextError') { - error.value += 'Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.' + error.value += + 'Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.' } else { error.value += err.message } diff --git a/docs/.vitepress/components/demos/LoadingIndicator.vue b/docs/.vitepress/components/demos/LoadingIndicator.vue index 4c33809f..f8f3d70d 100644 --- a/docs/.vitepress/components/demos/LoadingIndicator.vue +++ b/docs/.vitepress/components/demos/LoadingIndicator.vue @@ -2,8 +2,16 @@
- -
Loading...
+ +
+ Loading... +
diff --git a/docs/.vitepress/components/demos/ScanSameQrcodeMoreThanOnce.vue b/docs/.vitepress/components/demos/ScanSameQrcodeMoreThanOnce.vue index dd4962a9..f11ede6e 100644 --- a/docs/.vitepress/components/demos/ScanSameQrcodeMoreThanOnce.vue +++ b/docs/.vitepress/components/demos/ScanSameQrcodeMoreThanOnce.vue @@ -4,9 +4,22 @@ Last result: {{ result }}

- -
- Checkmark + +
+ Checkmark
@@ -23,7 +36,7 @@ export default { data() { return { paused: false, - result: "", + result: '', showScanConfirmation: false } }, @@ -40,9 +53,7 @@ export default { onError: console.error, async onDetect(detectedCodes) { - this.result = JSON.stringify( - detectedCodes.map(code => code.rawValue) - ) + this.result = JSON.stringify(detectedCodes.map((code) => code.rawValue)) this.paused = true await this.timeout(500) diff --git a/docs/.vitepress/components/demos/SwitchCamera.vue b/docs/.vitepress/components/demos/SwitchCamera.vue index 58ae0099..f1f7d047 100644 --- a/docs/.vitepress/components/demos/SwitchCamera.vue +++ b/docs/.vitepress/components/demos/SwitchCamera.vue @@ -1,12 +1,28 @@ @@ -43,9 +50,7 @@ export default { onDetect(detectedCodes) { console.log(detectedCodes) - this.result = JSON.stringify( - detectedCodes.map(code => code.rawValue) - ) + this.result = JSON.stringify(detectedCodes.map((code) => code.rawValue)) } } } diff --git a/docs/.vitepress/components/demos/Validate.vue b/docs/.vitepress/components/demos/Validate.vue index b8c5e783..c0a908d4 100644 --- a/docs/.vitepress/components/demos/Validate.vue +++ b/docs/.vitepress/components/demos/Validate.vue @@ -4,12 +4,32 @@ Last result: {{ result }}

- -
This is a URL
- -
This is NOT a URL!
- -
Long validation in progress...
+ +
+ This is a URL +
+ +
+ This is NOT a URL! +
+ +
+ Long validation in progress... +
@@ -49,7 +69,7 @@ export default { this.isValid = undefined }, - async onDetect([ firstDetectedCode ]) { + async onDetect([firstDetectedCode]) { this.result = firstDetectedCode.rawValue this.paused = true diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index ebe0f07e..5c8d178e 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,146 +1,148 @@ import { defineConfig } from 'vitepress' import { withPwa } from '@vite-pwa/vitepress' -export default withPwa(defineConfig({ - description: 'A set of Vue.js components for detecting and decoding QR codes.', - lang: 'en-US', - lastUpdated: true, - themeConfig: { - editLink: { - pattern: 'https://github.com/gruhn/vue-qrcode-reader/edit/main/docs/:path' - }, - footer: { - message: 'Released under the MIT License.' - }, - nav: [ - { text: 'Home', link: '/' }, - { text: 'Live Demos', link: '/demos/CustomTracking' }, - { text: 'API Reference', link: '/api/QrcodeStream' } - ], - search: { - provider: 'local' - }, - sidebar: { - '/demos/': [ - { - text: 'Simple', - link: '/demos/Simple' - }, - { - text: 'Handle Errors', - link: '/demos/HandleErrors' - }, - { - text: 'Visual Tracking', - link: '/demos/CustomTracking' - }, - { - text: 'Visual Tracking with Formats', - link: '/demos/CustomTrackingWithFormats' - }, - { - text: 'Show Loading Indicator', - link: '/demos/LoadingIndicator' - }, - { - text: 'Scan Same Qrcode More Than Once', - link: '/demos/ScanSameQrcodeMoreThanOnce' - }, - { - text: 'Pause & Validate', - link: '/demos/Validate' - }, - { - text: 'Switch to Front Camera', - link: '/demos/SwitchCamera' - }, - { - text: 'Fullscreen', - link: '/demos/Fullscreen' - }, - { - text: 'Torch (Flashlight)', - link: '/demos/Torch' - }, - { - text: 'Enumerate Cameras', - link: '/demos/DeviceId' - }, - { - text: 'Decode by Drag&Drop', - link: '/demos/DragDrop' - }, - { - text: 'Decode by Upload', - link: '/demos/Upload' - } +export default withPwa( + defineConfig({ + description: 'A set of Vue.js components for detecting and decoding QR codes.', + lang: 'en-US', + lastUpdated: true, + themeConfig: { + editLink: { + pattern: 'https://github.com/gruhn/vue-qrcode-reader/edit/main/docs/:path' + }, + footer: { + message: 'Released under the MIT License.' + }, + nav: [ + { text: 'Home', link: '/' }, + { text: 'Live Demos', link: '/demos/CustomTracking' }, + { text: 'API Reference', link: '/api/QrcodeStream' } ], - '/api/': [ - { - text: 'QrcodeStream', - link: '/api/QrcodeStream', - }, - { - text: 'QrcodeDropZone', - link: '/api/QrcodeDropZone', - }, - { - text: 'QrcodeCapture', - link: '/api/QrcodeCapture', + search: { + provider: 'local' + }, + sidebar: { + '/demos/': [ + { + text: 'Simple', + link: '/demos/Simple' + }, + { + text: 'Handle Errors', + link: '/demos/HandleErrors' + }, + { + text: 'Visual Tracking', + link: '/demos/CustomTracking' + }, + { + text: 'Visual Tracking with Formats', + link: '/demos/CustomTrackingWithFormats' + }, + { + text: 'Show Loading Indicator', + link: '/demos/LoadingIndicator' + }, + { + text: 'Scan Same Qrcode More Than Once', + link: '/demos/ScanSameQrcodeMoreThanOnce' + }, + { + text: 'Pause & Validate', + link: '/demos/Validate' + }, + { + text: 'Switch to Front Camera', + link: '/demos/SwitchCamera' + }, + { + text: 'Fullscreen', + link: '/demos/Fullscreen' + }, + { + text: 'Torch (Flashlight)', + link: '/demos/Torch' + }, + { + text: 'Enumerate Cameras', + link: '/demos/DeviceId' + }, + { + text: 'Decode by Drag&Drop', + link: '/demos/DragDrop' + }, + { + text: 'Decode by Upload', + link: '/demos/Upload' + } + ], + '/api/': [ + { + text: 'QrcodeStream', + link: '/api/QrcodeStream' + }, + { + text: 'QrcodeDropZone', + link: '/api/QrcodeDropZone' + }, + { + text: 'QrcodeCapture', + link: '/api/QrcodeCapture' + } + ] + }, + socialLinks: [{ icon: 'github', link: 'https://github.com/gruhn/vue-qrcode-reader' }] + }, + title: 'Vue Qrcode Reader', + vite: { + // build: { + // rollupOptions: { + // external: ["vue"], + // output: { + // globals: { + // vue: "Vue", + // }, + // }, + // }, + // }, + resolve: { + alias: { + '@': __dirname } - ] + } }, - socialLinks: [{ icon: 'github', link: 'https://github.com/gruhn/vue-qrcode-reader' }] - }, - title: 'Vue Qrcode Reader', - vite: { - // build: { - // rollupOptions: { - // external: ["vue"], - // output: { - // globals: { - // vue: "Vue", - // }, - // }, - // }, - // }, - resolve: { - alias: { - '@': __dirname + pwa: { + mode: 'development', + base: '/', + scope: '/', + registerType: 'autoUpdate', + // injectRegister: 'inline', + includeAssets: ['favicon.svg'], + manifest: { + name: 'Vue Qrcode Reader', + short_name: 'Vue QR', + theme_color: '#10b981', + icons: [ + { + src: 'pwa-192x192.png', + sizes: '192x192', + type: 'image/png' + }, + { + src: 'pwa-512x512.png', + sizes: '512x512', + type: 'image/png' + } + ] + }, + workbox: { + globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'] + }, + devOptions: { + enabled: true, + suppressWarnings: true, + navigateFallback: '/' } } - }, - pwa: { - mode: 'development', - base: '/', - scope: '/', - registerType: 'autoUpdate', - // injectRegister: 'inline', - includeAssets: ['favicon.svg'], - manifest: { - name: 'Vue Qrcode Reader', - short_name: 'Vue QR', - theme_color: '#10b981', - icons: [ - { - src: 'pwa-192x192.png', - sizes: '192x192', - type: 'image/png', - }, - { - src: 'pwa-512x512.png', - sizes: '512x512', - type: 'image/png', - } - ], - }, - workbox: { - globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'], - }, - devOptions: { - enabled: true, - suppressWarnings: true, - navigateFallback: '/', - }, - }, -})) + }) +) diff --git a/docs/api/QrcodeCapture.md b/docs/api/QrcodeCapture.md index 820da1b1..3ec7b98a 100644 --- a/docs/api/QrcodeCapture.md +++ b/docs/api/QrcodeCapture.md @@ -5,15 +5,16 @@ The newest API this component depend on is the [FileReader API](https://caniuse.com/#feat=filereader). Vue Native is not supported (see [#206](https://github.com/gruhn/vue-qrcode-reader/issues/206)). | ![Internet Explorer](./ie_32x32.png) | ![Edge](./edge2019_32x32.png) | ![Firefox](./firefox_32x32.png) | ![Chrome](./chrome_32x32.png) | ![Safari](./safari_32x32.png) | -| :---------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: | -| 10+ | Yes | Yes | Yes | Yes¹ | +| :----------------------------------: | :---------------------------: | :-----------------------------: | :---------------------------: | :---------------------------: | +| 10+ | Yes | Yes | Yes | Yes¹ | 1. It doesn't work in web apps added to home screen (PWA mode) on iOS prior to 11.3 (see [this StackOverflow question](https://stackoverflow.com/questions/46228218/how-to-access-camera-on-ios11-home-screen-web-app)) ## Events ### `detect` -* **Payload Type:** `DetectedBarcode[]` + +- **Payload Type:** `DetectedBarcode[]` The component renders to a simple file picker `input` element. Clicking opens a file dialog. @@ -28,21 +29,20 @@ The structure of the event payload is the same as for the `detect` event on `Qrc Use `detect` instead. TODO: link old docs. - ## Props ### `formats` -* **Payload Type:** `BarcodeDetectorOptions['formats']` -* **Default:** `['qr_code']` + +- **Payload Type:** `BarcodeDetectorOptions['formats']` +- **Default:** `['qr_code']` The `formats` prop defines which barcode formats are detected. - [Supported Formats](https://github.com/Sec-ant/barcode-detector?tab=readme-ov-file#barcode-detector). +[Supported Formats](https://github.com/Sec-ant/barcode-detector?tab=readme-ov-file#barcode-detector). ```html ``` - Checkout the components template of `QrcodeCapture`: ```html @@ -67,7 +67,10 @@ Because the `input` element is the root element of the component and because Vue You can even remove or replace already defined attributes: ```html - + ``` ## Slots diff --git a/docs/api/QrcodeDropZone.md b/docs/api/QrcodeDropZone.md index 2e339abc..6b49caa5 100644 --- a/docs/api/QrcodeDropZone.md +++ b/docs/api/QrcodeDropZone.md @@ -6,14 +6,14 @@ The newest API this component depend on is the [FileReader API](https://caniuse. Vue Native is not supported (see [#206](https://github.com/gruhn/vue-qrcode-reader/issues/206)). | ![Internet Explorer](./ie_32x32.png) | ![Edge](./edge2019_32x32.png) | ![Firefox](./firefox_32x32.png) | ![Chrome](./chrome_32x32.png) | ![Safari](./safari_32x32.png) | -| :---------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: | -| 10+ | Yes | Yes | Yes | Yes | - +| :----------------------------------: | :---------------------------: | :-----------------------------: | :---------------------------: | :---------------------------: | +| 10+ | Yes | Yes | Yes | Yes | ## Events ### `detect` -* **Payload Type:** `DetectedBarcode[]` + +- **Payload Type:** `DetectedBarcode[]` You can drag-and-drop image files from your desktop or images embedded into other web pages anywhere in the area the component occupies. The images are directly scanned and positive results are indicated by the `detect` event. @@ -28,9 +28,10 @@ Error events are emitted when a dropped url can't be fetched due to CORS or a dr ```html - + ``` + ```javascript methods: { onError (error) { @@ -47,18 +48,20 @@ methods: { ``` ### `formats` -* **Payload Type:** `BarcodeDetectorOptions['formats']` -* **Default:** `['qr_code']` + +- **Payload Type:** `BarcodeDetectorOptions['formats']` +- **Default:** `['qr_code']` The `formats` prop defines which barcode formats are detected. - [Supported Formats](https://github.com/Sec-ant/barcode-detector?tab=readme-ov-file#barcode-detector). +[Supported Formats](https://github.com/Sec-ant/barcode-detector?tab=readme-ov-file#barcode-detector). ```html ``` ### `dragover` -* **Payload Type:** `Boolean` + +- **Payload Type:** `Boolean` When the user is dragging something over the the component you might want to apply some emphasizing styling. Do that by reacting to the `dragover` event. @@ -69,6 +72,7 @@ When the user is dragging something over the the component you might want to app
``` + ```javascript data () { return { diff --git a/docs/api/QrcodeStream.md b/docs/api/QrcodeStream.md index b817e858..9086eb4c 100644 --- a/docs/api/QrcodeStream.md +++ b/docs/api/QrcodeStream.md @@ -6,8 +6,8 @@ This component fundamentally depends on the [Stream API](https://caniuse.com/#fe Vue Native is not supported (see [#206](https://github.com/gruhn/vue-qrcode-reader/issues/206)). | ![Internet Explorer](./ie_32x32.png) | ![Edge](./edge2019_32x32.png) | ![Firefox](./firefox_32x32.png) | ![Chrome](./chrome_32x32.png) | ![Safari](./safari_32x32.png) | -| :---------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: | -| No | Yes | Yes | Yes¹ | Yes² | +| :----------------------------------: | :---------------------------: | :-----------------------------: | :---------------------------: | :---------------------------: | +| No | Yes | Yes | Yes¹ | Yes² | 1. Chrome requires [HTTPS or localhost](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins) (see _Troubleshooting_ for help) 2. Safari also requires HTTPS **even** on localhost (see [#48](https://github.com/gruhn/vue-qrcode-reader/issues/48)). Support is limited for: @@ -15,11 +15,11 @@ Vue Native is not supported (see [#206](https://github.com/gruhn/vue-qrcode-read - iOS browsers other than Safari (_Chrome for iOS_, _Firefox for iOS_, ...): at least **iOS 14.3** (see [#29](https://github.com/gruhn/vue-qrcode-reader/issues/29)) - WkWebView component in native iOS apps: at least **iOS 14.3** (see [#29](https://github.com/gruhn/vue-qrcode-reader/issues/29)) - ## Events ### `detect` -* **Payload Type:** `DetectedBarcode[]` + +- **Payload Type:** `DetectedBarcode[]` Once a stream from the users camera is loaded, it's displayed and continuously scanned for QR codes. Results are indicated by the `detect` event. @@ -27,6 +27,7 @@ Results are indicated by the `detect` event. ```html ``` + ```javascript methods: { onDetect (detectedCodes) { @@ -34,6 +35,7 @@ methods: { } } ``` + The payload is an array of **one or multiple** detected codes (only QR codes supported at the moment). The structure of the array items is accroding to the [Barcode Detection API spec](https://wicg.github.io/shape-detection-api/#detectedbarcode-section). Here is an example: @@ -41,7 +43,16 @@ Here is an example: ```json [ { - "boundingBox": { "x": 82, "y": 70, "width": 178, "height": 188, "top": 70, "right": 260, "bottom": 258, "left": 82 }, + "boundingBox": { + "x": 82, + "y": 70, + "width": 178, + "height": 188, + "top": 70, + "right": 260, + "bottom": 258, + "left": 82 + }, "rawValue": "https://wikipedia.org", "format": "qr_code", "cornerPoints": [ @@ -50,8 +61,18 @@ Here is an example: { "x": 260, "y": 240 }, { "x": 94, "y": 258 } ] - }, { - "boundingBox": { "x": 322, "y": 135, "width": 244, "height": 240, "top": 135, "right": 566, "bottom": 375, "left": 322 }, + }, + { + "boundingBox": { + "x": 322, + "y": 135, + "width": 244, + "height": 240, + "top": 135, + "right": 566, + "bottom": 375, + "left": 322 + }, "rawValue": "Hello, world!", "format": "qr_code", "cornerPoints": [ @@ -72,18 +93,20 @@ However changing the value of `paused` resets this internal cache. ::: ### `formats` -* **Payload Type:** `BarcodeDetectorOptions['formats']` -* **Default:** `['qr_code']` + +- **Payload Type:** `BarcodeDetectorOptions['formats']` +- **Default:** `['qr_code']` The `formats` prop defines which barcode formats are detected. - [Supported Formats](https://github.com/Sec-ant/barcode-detector?tab=readme-ov-file#barcode-detector). +[Supported Formats](https://github.com/Sec-ant/barcode-detector?tab=readme-ov-file#barcode-detector). ```html ``` ### `camera-on` -* **Payload Type:** `Promise` + +- **Payload Type:** `Promise` It might take a while before the component is ready and the scanning process starts. The user has to be asked for camera access permission first and the camera stream has to be loaded. @@ -96,6 +119,7 @@ It carries a promise which resolves with the cameras [MediaTrackCapabilities](ht ```html ``` + ```javascript methods: { onReady(capabilities) { @@ -112,14 +136,16 @@ Otherwise they might panic and deny and then get frustrated because they don't k ::: ### `camera-off` -* **Payload Type:** `void` + +- **Payload Type:** `void` Emitted whenever the camera is turned off. This happens whenever the camera constraints are modified and the camera has to be restarted or a different camera is started. For example when switching between front and rear camera. ### `error` -* **Payload Type:** `Error` + +- **Payload Type:** `Error` Error events are emitted in particular when camera initialization fails. This can happen [a couple of reasons](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#Exceptions). @@ -127,6 +153,7 @@ This can happen [a couple of reasons](https://developer.mozilla.org/en-US/docs/W ```html ``` + ```javascript methods: { onError(error) { @@ -168,16 +195,18 @@ Use `constraints` instead. ## Props ### `paused` -* **Input Type:** `Boolean` -* **Default:** `false` + +- **Input Type:** `Boolean` +- **Default:** `false` Setting this prop to `true` freezes the camera. Useful if you want to show some microinteraction after successful scans. When you unpause the camera is restarted so the `camera-on` event is emitted again. ### `track` -* **Input Type:** `Function` -* **Default:** `undefined` + +- **Input Type:** `Function` +- **Default:** `undefined` You can visually highlight detected QR codes in real-time. A transparent canvas overlays the camera stream. @@ -196,10 +225,10 @@ So if you want to go easy on your target device you might not want to enable tra Avoid access to reactive properties in this function (like stuff in `data`, `computed` or your Vuex store). The function is called several times a second and might cause memory leaks. To be safe don't access `this` at all. ::: - ### `constraints` -* **Input Type:** `MediaTrackConstraints` -* **Default:** `{ facingMode: "environment" }` + +- **Input Type:** `MediaTrackConstraints` +- **Default:** `{ facingMode: "environment" }` With this prop you can pass an object with various camera configuration options. For example whether to use front- or rear camera. @@ -220,8 +249,12 @@ You can catch errors with the `error` event. An error can occur for example when you try to use the front camera on a device that doesn't have one. ```html - + ``` + ```js data () { return { @@ -246,8 +279,9 @@ methods: { ``` ### `torch` -* **Input Type:** `Boolean` -* **Default:** `false` + +- **Input Type:** `Boolean` +- **Default:** `false` With the `torch` prop you can turn a devices flashlight on/off. This is not consistently supported by all devices and browsers. @@ -261,10 +295,13 @@ This will tell you whether or not `torch` is supported. Due to API limitations the camera stream must be reloaded when turning the torch on/off. That means the `camera-on` event will be emitted again. - ```html - + ``` + ```js methods: { onInit (capabilities) { diff --git a/docs/demos/Upload.md b/docs/demos/Upload.md index 7ac8621b..92a50150 100644 --- a/docs/demos/Upload.md +++ b/docs/demos/Upload.md @@ -8,7 +8,6 @@ you are not prompted with a file dialog but with your camera. So you can directly take the picture to be uploaded. Adjust this behavior with the following dropdown: - diff --git a/docs/index.md b/docs/index.md index 1263e4db..7836a574 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,7 @@ layout: home titleTemplate: ':title' hero: - name: "Vue Qrcode Reader" + name: 'Vue Qrcode Reader' tagline: A set of Vue.js components for detecting and decoding QR codes. image: src: /logo.png @@ -15,7 +15,6 @@ hero: - theme: alt text: View on GitHub link: https://github.com/gruhn/vue-qrcode-reader - # features: # - title: Feature A # details: Lorem ipsum dolor sit amet, consectetur adipiscing elit diff --git a/package.json b/package.json index c231fcda..930456b4 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "docs:dev": "vitepress dev docs", "docs:build": "vitepress build docs", "docs:preview": "vitepress preview docs", - "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", + "lint": "eslint **/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts} --fix --ignore-path .gitignore", + "format": "prettier **/*.{vue,js,jsx,cjs,mjs,ts,tsx,cts,mts,json,md} --write --ignore-path .gitignore --ignore-path docs/.gitignore", "type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false", "prepack": "pnpm run build", "prepare": "husky install"