# Scanner API The Scanner API enables an extension to access scanner data and available scanning sources supported by the device. ## ScannerApi ### ScannerApiContent ### scannerDataSubscribable value: `RemoteSubscribable` Creates a subscription to scan events Provides an initial value and a callback to subscribe to value changes. Currently supports only one subscription. You can utilize `makeStatefulSubscribable` on a `RemoteSubscribable` to implement multiple subscriptions. Using `makeStatefulSubscribable` or the corresponding hooks counts as a subscription. ### scannerSourcesSubscribable value: `RemoteSubscribable` Creates a subscription to the scanning sources available on the POS device. Provides an initial value and a callback to subscribe to value changes. Currently supports only one subscription. You can utilize `makeStatefulSubscribable` on a `RemoteSubscribable` to implement multiple subscriptions. Using `makeStatefulSubscribable` or the corresponding hooks counts as a subscription. ### ScannerSubscriptionResult ### data value: `string` The string data from the last scanner event received. ### source value: `ScannerSource` The scanning source from which the scan event came. ## Examples The Scanner API enables an extension to access scanner data and available scanning sources supported by the device. ```tsx import React from 'react'; import { Navigator, Screen, Stack, Text, useScannerDataSubscription, reactExtension, } from '@shopify/ui-extensions-react/point-of-sale'; const SmartGridModal = () => { const {data, source} = useScannerDataSubscription(); return ( {`Scanned data: ${data || ''} with ${source || ''}`} ); }; export default reactExtension('pos.home.modal.render', () => ( )); ``` ```ts import { Navigator, Screen, Stack, Text, extension, } from '@shopify/ui-extensions/point-of-sale'; export default extension('pos.home.modal.render', (root, api) => { const dataText = root.createComponent('Text', null, 'Scanned data: '); const sourceText = root.createComponent( 'Text', null, 'Scanned data source: ', ); const stack1 = root.createComponent(Stack, { direction: 'horizontal', }); const screen = root.createComponent(Screen, { title: 'Home', name: 'Home', }); const navigator = root.createComponent(Navigator); stack1.append(dataText); stack1.append(sourceText); screen.append(stack1); navigator.append(screen); root.append(navigator); api.scanner.scannerDataSubscribable.subscribe((data, source) => { dataText.replaceChildren(`Scanned data: ${data || ''}`); sourceText.updateProps(`Scanned data source: ${source || ''}`); }); }); ``` ```tsx import React from 'react'; import { Navigator, Screen, Stack, Text, useScannerSourcesSubscription, reactExtension, } from '@shopify/ui-extensions-react/point-of-sale'; const SmartGridModal = () => { const scannerSources = useScannerSourcesSubscription(); return ( {`Available scanner sources: ${scannerSources}`} ); }; export default reactExtension('pos.home.modal.render', () => ( )); ``` ```ts import { Navigator, Screen, Stack, Text, extension, } from '@shopify/ui-extensions/point-of-sale'; export default extension('pos.home.modal.render', (root, api) => { const scannerSourcesText = root.createComponent( 'Text', null, 'Available scanner sources: ', ); const stack1 = root.createComponent(Stack, { direction: 'horizontal', }); const screen = root.createComponent(Screen, { title: 'Home', name: 'Home', }); const navigator = root.createComponent(Navigator); stack1.append(scannerSourcesText); screen.append(stack1); navigator.append(screen); root.append(navigator); api.scanner.scannerSourcesSubscribable.subscribe((sources) => { scannerSourcesText.replaceChildren(`Available scanner sources: ${sources}`); }); }); ``` ### Use cases ```tsx import React from 'react'; import { Navigator, Screen, Stack, Text, useScannerDataSubscription, useApi, reactExtension, } from '@shopify/ui-extensions-react/point-of-sale'; const SmartGridModal = () => { const api = useApi<'pos.home.modal.render'>(); const {data} = useScannerDataSubscription(); return ( {`Scanned data: ${data || ''}`} ); }; export default reactExtension('pos.home.modal.render', () => ( )); ``` ```ts import React from 'react'; import { Navigator, Screen, Stack, Text, extension, } from '@shopify/ui-extensions/point-of-sale'; export default extension('pos.home.modal.render', (root, api) => { const text = root.createComponent('Text', null, 'Scanned data: '); const stack = root.createComponent(Stack, { direction: 'horizontal', }); const screen = root.createComponent(Screen, { title: 'Home', name: 'Home', }); const navigator = root.createComponent(Navigator); stack.append(text); screen.append(stack); navigator.append(screen); root.append(navigator); api.scanner.scannerDataSubscribable.subscribe((data) => { text.replaceChildren(`Scanned data: ${data || ''}`); }); }); ``` ```tsx import React from 'react'; import { CameraScanner, Navigator, Screen, Stack, Text, useScannerDataSubscription, useScannerSourcesSubscription, reactExtension, } from '@shopify/ui-extensions-react/point-of-sale'; const SmartGridModal = () => { const {data, source} = useScannerDataSubscription(); const availableScanners = useScannerSourcesSubscription(); const hasCameraScanner = availableScanners.includes('camera'); return ( {hasCameraScanner ? ( ) : ( {`Scanned data: ${data || ''}`} {`Scanned data source: ${source || ''}`} )} ); }; export default reactExtension('pos.home.modal.render', () => ( )); ``` ```ts import { CameraScanner, Navigator, Screen, Stack, Text, extension, } from '@shopify/ui-extensions/point-of-sale'; export default extension('pos.home.modal.render', (root, api) => { const dataText = root.createComponent('Text', null, 'Scanned data: '); const sourceText = root.createComponent( 'Text', null, 'Scanned data source: ', ); const cameraScanner = root.createComponent(CameraScanner); const stack1 = root.createComponent(Stack, { direction: 'horizontal', }); const stack2 = root.createComponent(Stack, { direction: 'vertical', alignment: 'space-evenly', }); const screen = root.createComponent(Screen, { title: 'Home', name: 'Home', }); const navigator = root.createComponent(Navigator); screen.append(stack1); navigator.append(screen); root.append(navigator); api.scanner.scannerDataSubscribable.subscribe((data, source) => { dataText.replaceChildren(`Scanned data: ${data || ''}`); sourceText.replaceChildren(`Scanned data source: ${source || ''}`); }); api.scanner.scannerSourcesSubscribable.subscribe((sources) => { // Clear previous children to avoid duplicate appending stack1.children = []; stack2.children = []; if (sources.include('camera')) { stack1.append(cameraScanner); } else { stack2.append(dataText); stack2.append(sourceText); stack1.append(stack2); } }); }); ```