diff --git a/.storybook/config.js b/.storybook/config.js index 007c2d7..661944b 100644 --- a/.storybook/config.js +++ b/.storybook/config.js @@ -15,7 +15,7 @@ setOptions({ addDecorator(withKnobs); addDecorator(story => { - return
{story()}
; + return
{story()}
; }); const req = require.context('../src', true, /story.tsx$/); diff --git a/README.md b/README.md index 4dcb5ee..66a433b 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Note: this package is built with TypeScript and already contains the relevant Ty To initiate a payment, use the `ReblocksPayment` component. The `ReblocksPayment` takes in the following props: - `accountId` {string} account to send funds to -- `amount` {string} ammount of `rai` to send (Note: 1 rai = 1/1,000,000 XRB) +- `amount` {string} ammount of `xrb` to send (Note: 1 xrb = 1/1,000,000 XRB) - `onPaymentSuccess` {function} function to run on successful payment. This is passed { token: 'TOKEN'} Link to [demo](https://goldcaddy77.github.io/reblocks/?selectedKind=ReblocksPayment) @@ -65,6 +65,24 @@ To display the current value of XRB in a fiat currency, use the `ReblocksFiatCon Link to [demo](https://goldcaddy77.github.io/reblocks/?selectedKind=ReblocksFiatConversion) +### ReblocksQRCode + +To create a QR code for payments, use the `ReblocksQRCode` component. The `ReblocksQRCode` component takes in the +following props: + +- `accountId` {string} account to send funds to +- `amount` {string - optional} ammount of `xrb` to send (Note: 1 xrb = 1/1,000,000 XRB) +- `label` {string - optional} see - [RaiBlocks QR Code specification](https://github.com/clemahieu/raiblocks/wiki/URI-and-QR-Code-Standard) +- `message` {string - optional} see - [RaiBlocks QR Code specification](https://github.com/clemahieu/raiblocks/wiki/URI-and-QR-Code-Standard) + +You can also style the QR Code itself using the params we pass into [qrcode.react](https://github.com/zpao/qrcode.react): + +- `size` {number - optional} Size +- `bgColor` {string (CSS color) - optional} Background color +- `fgColor` {string (CSS color) - optional} Foreground color + +Link to [demo](https://goldcaddy77.github.io/reblocks/?selectedKind=ReblocksQRCode) + ## Donate If you like this project and want to help support future development, test it out by buying me a 🍺: diff --git a/package.json b/package.json index 5bdd695..0c53110 100644 --- a/package.json +++ b/package.json @@ -55,11 +55,15 @@ "mapCoverage": true }, "dependencies": { + "@types/qrcode.react": "^0.6.2", + "@types/query-string": "^5.0.1", "@types/react-select": "^1.1.0", "css-loader": "^0.28.7", "file-loader": "^1.1.6", "gh-pages": "^1.1.0", "prettier-eslint-cli": "^4.7.0", + "qrcode.react": "^0.7.2", + "query-string": "^5.0.1", "react-dom": "^15.5.0", "react-dom-factories": "^1.0.2", "react-select": "^1.2.1", diff --git a/src/components/ReblocksFiatConversion/ReblocksFiatConversion.story.tsx b/src/components/ReblocksFiatConversion/ReblocksFiatConversion.story.tsx index a0b357f..c6c2a47 100644 --- a/src/components/ReblocksFiatConversion/ReblocksFiatConversion.story.tsx +++ b/src/components/ReblocksFiatConversion/ReblocksFiatConversion.story.tsx @@ -53,7 +53,7 @@ class DynamicCurrencyWrapper extends React.Component<{}, State> { storiesOf('ReblocksFiatConversion', module) .add('Default (USD)', () => { return ( -
+
@@ -63,7 +63,7 @@ storiesOf('ReblocksFiatConversion', module) }) .add('EUR', () => { return ( -
+
@@ -73,7 +73,7 @@ storiesOf('ReblocksFiatConversion', module) }) .add('JPY', () => { return ( -
+
@@ -83,7 +83,7 @@ storiesOf('ReblocksFiatConversion', module) }) .add('Choose Currency', () => { return ( -
+
); diff --git a/src/components/ReblocksPayment/ReblocksPayment.story.tsx b/src/components/ReblocksPayment/ReblocksPayment.story.tsx index a052e61..036b929 100644 --- a/src/components/ReblocksPayment/ReblocksPayment.story.tsx +++ b/src/components/ReblocksPayment/ReblocksPayment.story.tsx @@ -73,7 +73,7 @@ storiesOf('ReblocksPayment', module) action('Click the button to start payment')(); return ( -
+

The button below will prompt you to send a test transaction of 1000 rai (~2 cents)

@@ -81,14 +81,14 @@ storiesOf('ReblocksPayment', module) }) .add('Dynamic Button', () => { return ( -
+
); }) .add('Buy Dan a 🍺', () => { return ( -
+

If you want to help support the project, you can donate a beer's worth of rai using this form diff --git a/src/components/ReblocksQRCode/ReblocksQRCode.story.tsx b/src/components/ReblocksQRCode/ReblocksQRCode.story.tsx new file mode 100644 index 0000000..a75df63 --- /dev/null +++ b/src/components/ReblocksQRCode/ReblocksQRCode.story.tsx @@ -0,0 +1,36 @@ +import { storiesOf } from '@storybook/react'; +import * as React from 'react'; + +import { ReblocksQRCode } from './ReblocksQRCode'; + +import { ACCOUNT_ID } from '../../lib/'; + +storiesOf('ReblocksQRCode', module) + .add('Default', () => { + return ; + }) + .add('Default with Address', () => { + return ; + }) + .add('With Amount', () => { + return ; + }) + .add('With Amount and Label', () => { + return ( + + ); + }) + .add('Amount, Label and Message', () => { + return ( + + ); + }) + .add('RaiBlocks Purple', () => { + return ; + }); diff --git a/src/components/ReblocksQRCode/ReblocksQRCode.tsx b/src/components/ReblocksQRCode/ReblocksQRCode.tsx new file mode 100644 index 0000000..8771c7d --- /dev/null +++ b/src/components/ReblocksQRCode/ReblocksQRCode.tsx @@ -0,0 +1,58 @@ +import * as QRCode from 'qrcode.react'; +import * as queryString from 'query-string'; +import * as React from 'react'; + +export interface OptionalProps { + amount?: number; + bgColor?: string; + fgColor?: string; + label?: string; + message?: string; + size?: number; + showUrl?: boolean; +} + +export interface Props extends OptionalProps { + accountId: string; +} + +const ReblocksQRCode: React.StatelessComponent = (props): JSX.Element => { + const { accountId, amount, label, message, showUrl, ...otherProps } = props; + let address = `xrb:${accountId}`; + + const params: OptionalProps = {}; + if (amount) { + params.amount = amount; + } + if (label) { + params.label = label; + } + if (message) { + params.message = message; + } + + const qs = queryString.stringify(params); + address = qs ? `${address}?${qs}` : address; + + const qrComponent = ; + + if (showUrl) { + return ( +

+ {qrComponent} +
{address}
+
+ ); + } + + return qrComponent; +}; + +ReblocksQRCode.defaultProps = { + bgColor: '#FFFFFF', + fgColor: '#000000', + showUrl: false, + size: 128 +}; + +export { ReblocksQRCode }; diff --git a/src/reblocks.ts b/src/reblocks.ts index 66bb66c..9422f09 100644 --- a/src/reblocks.ts +++ b/src/reblocks.ts @@ -1,4 +1,5 @@ export { PaymentResponse, ReblocksPayment } from './components/ReblocksPayment/ReblocksPayment'; export { ReblocksFiatConversion } from './components/ReblocksFiatConversion/ReblocksFiatConversion'; +export { ReblocksQRCode } from './components/ReblocksQRCode/ReblocksQRCode'; export * from './lib'; diff --git a/yarn.lock b/yarn.lock index eea9e22..63fd711 100644 --- a/yarn.lock +++ b/yarn.lock @@ -334,6 +334,16 @@ version "15.5.2" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.2.tgz#3c6b8dceb2906cc87fe4358e809f9d20c8d59be1" +"@types/qrcode.react@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@types/qrcode.react/-/qrcode.react-0.6.2.tgz#c3c09a1f01c8f1378b2dc9cde27a15cc1529cf19" + dependencies: + "@types/react" "*" + +"@types/query-string@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@types/query-string/-/query-string-5.0.1.tgz#6cb41c724cb1644d56c2d1dae7c7b204e706b39e" + "@types/react-select@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@types/react-select/-/react-select-1.1.0.tgz#b3ddf7a58f033f69d3c47c825587a54fec1629c6" @@ -7303,6 +7313,17 @@ q@^1.1.2, q@^1.4.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" +qr.js@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" + +qrcode.react@^0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-0.7.2.tgz#72a5718fd56baafe15c2c153fe436628d83aa286" + dependencies: + prop-types "^15.5.8" + qr.js "0.0.0" + qs@6.5.1, qs@^6.5.1, qs@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"