├── public
├── favicon.ico
├── manifest.json
└── index.html
├── src
├── App.test.js
├── index.css
├── index.js
├── App.js
├── logo.svg
├── serviceWorker.js
├── components
│ └── PaymentForm.js
└── App.css
├── .gitignore
├── package.json
└── README.md
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mootrichard/square-react-online-payments/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | ReactDOM.unmountComponentAtNode(div);
9 | });
10 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
5 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
6 | sans-serif;
7 | -webkit-font-smoothing: antialiased;
8 | -moz-osx-font-smoothing: grayscale;
9 | }
10 |
11 | code {
12 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
13 | monospace;
14 | }
15 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import * as serviceWorker from './serviceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 |
9 | // If you want your app to work offline and load faster, you can change
10 | // unregister() to register() below. Note this comes with some pitfalls.
11 | // Learn more about service workers: http://bit.ly/CRA-PWA
12 | serviceWorker.unregister();
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sq-payment-form-react",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.5.2",
7 | "react-dom": "^16.5.2",
8 | "react-scripts": "2.0.5"
9 | },
10 | "scripts": {
11 | "start": "react-scripts start",
12 | "build": "react-scripts build",
13 | "test": "react-scripts test",
14 | "eject": "react-scripts eject"
15 | },
16 | "eslintConfig": {
17 | "extends": "react-app"
18 | },
19 | "browserslist": [
20 | ">0.2%",
21 | "not dead",
22 | "not ie <= 11",
23 | "not op_mini all"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Example Implementation of Square Online Payments Form using React
2 |
3 | > UPDATE: You can use the official [Square React Payment Form](https://github.com/square/react-square-payment-form) to handle implementing the payment form in React now!
4 |
5 | [Find the associated blog post on Medium](https://medium.com/square-corner-blog/online-payments-form-react-9ecf164880bf)
6 |
7 | Learn how to implement the Square Online Payments form using React
8 |
9 | There are a lot of different ways to accept payments online, so it'd be nice to implement a single form that could accept as many forms of payment as we want at one time. Here is an example of how.
10 |
11 | Want to see this done with React's Hooks API, just tweet me @wootmoot and I'll get one going!
12 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './App.css';
3 | import PaymentForm from './components/PaymentForm';
4 |
5 | class App extends Component {
6 | constructor(props){
7 | super(props)
8 | this.state = {
9 | loaded: false
10 | }
11 | }
12 |
13 | componentWillMount(){
14 | const that = this;
15 | let sqPaymentScript = document.createElement('script');
16 | sqPaymentScript.src = "https://js.squareup.com/v2/paymentform";
17 | sqPaymentScript.type = "text/javascript"
18 | sqPaymentScript.async = false;
19 | sqPaymentScript.onload = ()=>{that.setState({
20 | loaded: true
21 | })};
22 | document.getElementsByTagName("head")[0].appendChild(sqPaymentScript);
23 | }
24 |
25 | render() {
26 | return (
27 | this.state.loaded &&
28 |
31 | );
32 | }
33 | }
34 |
35 | export default App;
36 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
22 | React App
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read http://bit.ly/CRA-PWA.
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | installingWorker.onstatechange = () => {
64 | if (installingWorker.state === 'installed') {
65 | if (navigator.serviceWorker.controller) {
66 | // At this point, the updated precached content has been fetched,
67 | // but the previous service worker will still serve the older
68 | // content until all client tabs are closed.
69 | console.log(
70 | 'New content is available and will be used when all ' +
71 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
72 | );
73 |
74 | // Execute callback
75 | if (config && config.onUpdate) {
76 | config.onUpdate(registration);
77 | }
78 | } else {
79 | // At this point, everything has been precached.
80 | // It's the perfect time to display a
81 | // "Content is cached for offline use." message.
82 | console.log('Content is cached for offline use.');
83 |
84 | // Execute callback
85 | if (config && config.onSuccess) {
86 | config.onSuccess(registration);
87 | }
88 | }
89 | }
90 | };
91 | };
92 | })
93 | .catch(error => {
94 | console.error('Error during service worker registration:', error);
95 | });
96 | }
97 |
98 | function checkValidServiceWorker(swUrl, config) {
99 | // Check if the service worker can be found. If it can't reload the page.
100 | fetch(swUrl)
101 | .then(response => {
102 | // Ensure service worker exists, and that we really are getting a JS file.
103 | if (
104 | response.status === 404 ||
105 | response.headers.get('content-type').indexOf('javascript') === -1
106 | ) {
107 | // No service worker found. Probably a different app. Reload the page.
108 | navigator.serviceWorker.ready.then(registration => {
109 | registration.unregister().then(() => {
110 | window.location.reload();
111 | });
112 | });
113 | } else {
114 | // Service worker found. Proceed as normal.
115 | registerValidSW(swUrl, config);
116 | }
117 | })
118 | .catch(() => {
119 | console.log(
120 | 'No internet connection found. App is running in offline mode.'
121 | );
122 | });
123 | }
124 |
125 | export function unregister() {
126 | if ('serviceWorker' in navigator) {
127 | navigator.serviceWorker.ready.then(registration => {
128 | registration.unregister();
129 | });
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/components/PaymentForm.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | const styles = {
4 | name: {
5 | verticalAlign: 'top',
6 | display: 'none',
7 | margin: 0,
8 | border: 'none',
9 | fontSize: "16px",
10 | fontFamily: "Helvetica Neue",
11 | padding: "16px",
12 | color: "#373F4A",
13 | backgroundColor: "transparent",
14 | lineHeight: "1.15em",
15 | placeholderColor: "#000",
16 | _webkitFontSmoothing: "antialiased",
17 | _mozOsxFontSmoothing: "grayscale",
18 | },
19 | leftCenter: {
20 | float: 'left',
21 | textAlign: 'center'
22 | },
23 | blockRight: {
24 | display: 'block',
25 | float: 'right'
26 | },
27 | center: {
28 | textAlign: 'center'
29 | }
30 | }
31 |
32 | export default class PaymentForm extends Component {
33 | constructor(props){
34 | super(props);
35 | this.state = {
36 | cardBrand: "",
37 | nonce: undefined,
38 | googlePay: false,
39 | applePay: false,
40 | masterpass: false
41 | }
42 | this.requestCardNonce = this.requestCardNonce.bind(this);
43 | }
44 |
45 | requestCardNonce(){
46 | this.paymentForm.requestCardNonce();
47 | }
48 |
49 | componentDidMount(){
50 | const config = {
51 | applicationId: "sq0idp-rARHLPiahkGtp6mMz2OeCA",
52 | locationId: "GMT96A77XABR1",
53 | inputClass: "sq-input",
54 | autoBuild: false,
55 | inputStyles: [
56 | {
57 | fontSize: "16px",
58 | fontFamily: "Helvetica Neue",
59 | padding: "16px",
60 | color: "#373F4A",
61 | backgroundColor: "transparent",
62 | lineHeight: "1.15em",
63 | placeholderColor: "#000",
64 | _webkitFontSmoothing: "antialiased",
65 | _mozOsxFontSmoothing: "grayscale"
66 | }
67 | ],
68 | applePay: {
69 | elementId: 'sq-apple-pay'
70 | },
71 | masterpass: {
72 | elementId: 'sq-masterpass'
73 | },
74 | googlePay: {
75 | elementId: 'sq-google-pay'
76 | },
77 | cardNumber: {
78 | elementId: "sq-card-number",
79 | placeholder: "• • • • • • • • • • • • • • • •"
80 | },
81 | cvv: {
82 | elementId: "sq-cvv",
83 | placeholder: "CVV"
84 | },
85 | expirationDate: {
86 | elementId: "sq-expiration-date",
87 | placeholder: "MM/YY"
88 | },
89 | postalCode: {
90 | elementId: "sq-postal-code",
91 | placeholder: "Zip"
92 | },
93 | callbacks: {
94 | methodsSupported: (methods) => {
95 | if(methods.googlePay){
96 | this.setState({
97 | googlePay: methods.googlePay
98 | })
99 | }
100 | if(methods.applePay){
101 | this.setState({
102 | applePay: methods.applePay
103 | })
104 | }
105 | if(methods.masterpass){
106 | this.setState({
107 | masterpass: methods.masterpass
108 | })
109 | }
110 | return;
111 | },
112 | createPaymentRequest: () => {
113 | return {
114 | requestShippingAddress: false,
115 | requestBillingInfo: true,
116 | currencyCode: "USD",
117 | countryCode: "US",
118 | total: {
119 | label: "MERCHANT NAME",
120 | amount: "100",
121 | pending: false
122 | },
123 | lineItems: [
124 | {
125 | label: "Subtotal",
126 | amount: "100",
127 | pending: false
128 | }
129 | ]
130 | };
131 | },
132 | cardNonceResponseReceived: (errors, nonce, cardData) => {
133 | if (errors) {
134 | // Log errors from nonce generation to the Javascript console
135 | console.log("Encountered errors:");
136 | errors.forEach(function(error) {
137 | console.log(" " + error.message);
138 | });
139 |
140 | return;
141 | }
142 | this.setState({
143 | nonce: nonce
144 | })
145 | },
146 | unsupportedBrowserDetected: () => {
147 | },
148 | inputEventReceived: (inputEvent) => {
149 | switch (inputEvent.eventType) {
150 | case "focusClassAdded":
151 | break;
152 | case "focusClassRemoved":
153 | break;
154 | case "errorClassAdded":
155 | document.getElementById("error").innerHTML =
156 | "Please fix card information errors before continuing.";
157 | break;
158 | case "errorClassRemoved":
159 | document.getElementById("error").style.display = "none";
160 | break;
161 | case "cardBrandChanged":
162 | if(inputEvent.cardBrand !== "unknown"){
163 | this.setState({
164 | cardBrand: inputEvent.cardBrand
165 | })
166 | } else {
167 | this.setState({
168 | cardBrand: ""
169 | })
170 | }
171 | break;
172 | case "postalCodeChanged":
173 | break;
174 | default:
175 | break;
176 | }
177 | },
178 | paymentFormLoaded: function() {
179 | document.getElementById('name').style.display = "inline-flex";
180 | }
181 | }
182 | };
183 | this.paymentForm = new this.props.paymentForm(config);
184 | this.paymentForm.build();
185 | }
186 |
187 | render(){
188 | return (
189 |
230 | )
231 | }
232 | }
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | #sq-cvv {
2 | width: 60px;
3 | }
4 |
5 | #sq-expiration-date {
6 | width: 75px;
7 | }
8 |
9 | .container {
10 | width: 425px;
11 | margin: 0 auto
12 | }
13 |
14 | #sq-postal-code {
15 | width: 75px;
16 | text-align: center;
17 | }
18 |
19 | #sq-ccbox {
20 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
21 | line-height: 1;
22 | position: relative;
23 | min-width: 315px;
24 | border-radius: 10px;
25 | transition: all 400ms linear;
26 | width: 365px;
27 | height: 200px;
28 | background-color: rgb(60, 121, 253);
29 | padding: 10px;
30 | margin: 0 auto;
31 | color: #CCC;
32 | font-weight: 600;
33 | }
34 |
35 | #sq-walletbox {
36 | margin: 0 auto;
37 | width: 385px;
38 | text-align: center;
39 | }
40 |
41 | #sq-card-number {
42 | width: 200px;
43 | }
44 |
45 | #cc-field-wrapper {
46 | padding-top: 50px;
47 | margin: 0;
48 | display: inline-flex;
49 | }
50 |
51 | button.button-credit-card {
52 | display: block;
53 | line-height: 1.25em;
54 | vertical-align: middle;
55 | height: 45px;
56 | width: 385px;
57 | border-radius: 10px;
58 | text-align: center;
59 | margin: 5px auto;
60 | font-size: 22px;
61 | font-weight: 600;
62 | background-color: #000;
63 | color: #FFF;
64 | }
65 |
66 | button.wallet-button {
67 | display: block;
68 | margin: 5px auto;
69 | border-radius: 10px;
70 | height: 45px;
71 | width: 300px;
72 | overflow: hidden;
73 | background-clip: border-box;
74 | background-position: center;
75 | }
76 |
77 | #form-container {
78 | width: 100%;
79 | }
80 |
81 | /* Customize the Apple Pay on the Web button */
82 | #sq-apple-pay {
83 | width: 100%;
84 | margin: 24px 0 16px 0;
85 | background-image: url(https://docs.connect.squareup.com/assets/docs/sqpaymentform/Apple_Pay_Mark_RGB_SMALL_052318-a40c688402e8a6684ee6938a380ba825e15163872bae3b9909f70ac028a9b780.png);
86 | background-color: black;
87 | background-size: 110%;
88 | background-repeat: no-repeat;
89 | background-position: center;
90 | border-radius: 4px;
91 | cursor: pointer;
92 | display: none;
93 | }
94 |
95 | /* Customize the Masterpass button */
96 | #sq-masterpass {
97 | width: 100%;
98 | height: 48px;
99 | padding: 0;
100 | margin: 24px 0 24px;
101 | background-image: url("https://masterpass.com/dyn/img/acc/global/mp_mark_hor_wht.svg");
102 | background-color: black;
103 | background-size: 100% 60%;
104 | background-repeat: no-repeat;
105 | background-position: calc((100% - 32px) / 2) 50%;
106 | border-radius: 4px;
107 | cursor: pointer;
108 | display: none;
109 | }
110 |
111 | #sq-masterpass::after {
112 | box-sizing: border-box;
113 | float: right;
114 | width: 32px;
115 | height: 48px;
116 | padding-top: 12px;
117 | content: url("data:image/svg+xml; utf8, ");
118 | background-color: #E6761F;
119 | border-radius: 0 4px 4px 0;
120 | }
121 |
122 | /* Customize the Google Pay button */
123 | #sq-google-pay {
124 | min-width: 385px;
125 | min-height: 40px;
126 | padding: 11px 24px;
127 | margin: 10px auto;
128 | background-color: #000;
129 | background-image: url(data:image/svg+xml,%3Csvg%20width%3D%22103%22%20height%3D%2217%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cpath%20d%3D%22M.148%202.976h3.766c.532%200%201.024.117%201.477.35.453.233.814.555%201.085.966.27.41.406.863.406%201.358%200%20.495-.124.924-.371%201.288s-.572.64-.973.826v.084c.504.177.912.471%201.225.882.313.41.469.891.469%201.442a2.6%202.6%200%200%201-.427%201.47c-.285.43-.667.763-1.148%201.001A3.5%203.5%200%200%201%204.082%2013H.148V2.976zm3.696%204.2c.448%200%20.81-.14%201.085-.42.275-.28.413-.602.413-.966s-.133-.684-.399-.959c-.266-.275-.614-.413-1.043-.413H1.716v2.758h2.128zm.238%204.368c.476%200%20.856-.15%201.141-.448.285-.299.427-.644.427-1.036%200-.401-.147-.749-.441-1.043-.294-.294-.688-.441-1.183-.441h-2.31v2.968h2.366zm5.379.903c-.453-.518-.679-1.239-.679-2.163V5.86h1.54v4.214c0%20.579.138%201.013.413%201.302.275.29.637.434%201.085.434.364%200%20.686-.096.966-.287.28-.191.495-.446.644-.763a2.37%202.37%200%200%200%20.224-1.022V5.86h1.54V13h-1.456v-.924h-.084c-.196.336-.5.611-.91.826-.41.215-.845.322-1.302.322-.868%200-1.528-.259-1.981-.777zm9.859.161L16.352%205.86h1.722l2.016%204.858h.056l1.96-4.858H23.8l-4.41%2010.164h-1.624l1.554-3.416zm8.266-6.748h1.666l1.442%205.11h.056l1.61-5.11h1.582l1.596%205.11h.056l1.442-5.11h1.638L36.392%2013h-1.624L33.13%207.876h-.042L31.464%2013h-1.596l-2.282-7.14zm12.379-1.337a1%201%200%200%201-.301-.735%201%201%200%200%201%20.301-.735%201%201%200%200%201%20.735-.301%201%201%200%200%201%20.735.301%201%201%200%200%201%20.301.735%201%201%200%200%201-.301.735%201%201%200%200%201-.735.301%201%201%200%200%201-.735-.301zM39.93%205.86h1.54V13h-1.54V5.86zm5.568%207.098a1.967%201.967%200%200%201-.686-.406c-.401-.401-.602-.947-.602-1.638V7.218h-1.246V5.86h1.246V3.844h1.54V5.86h1.736v1.358H45.75v3.36c0%20.383.075.653.224.812.14.187.383.28.728.28.159%200%20.299-.021.42-.063.121-.042.252-.11.392-.203v1.498c-.308.14-.681.21-1.12.21-.317%200-.616-.051-.896-.154zm3.678-9.982h1.54v2.73l-.07%201.092h.07c.205-.336.511-.614.917-.833.406-.22.842-.329%201.309-.329.868%200%201.53.254%201.988.763.457.509.686%201.202.686%202.079V13h-1.54V8.688c0-.541-.142-.947-.427-1.218-.285-.27-.656-.406-1.113-.406-.345%200-.656.098-.931.294a2.042%202.042%200%200%200-.651.777%202.297%202.297%200%200%200-.238%201.029V13h-1.54V2.976zm32.35-.341v4.083h2.518c.6%200%201.096-.202%201.488-.605.403-.402.605-.882.605-1.437%200-.544-.202-1.018-.605-1.422-.392-.413-.888-.62-1.488-.62h-2.518zm0%205.52v4.736h-1.504V1.198h3.99c1.013%200%201.873.337%202.582%201.012.72.675%201.08%201.497%201.08%202.466%200%20.991-.36%201.819-1.08%202.482-.697.665-1.559.996-2.583.996h-2.485v.001zm7.668%202.287c0%20.392.166.718.499.98.332.26.722.391%201.168.391.633%200%201.196-.234%201.692-.701.497-.469.744-1.019.744-1.65-.469-.37-1.123-.555-1.962-.555-.61%200-1.12.148-1.528.442-.409.294-.613.657-.613%201.093m1.946-5.815c1.112%200%201.989.297%202.633.89.642.594.964%201.408.964%202.442v4.932h-1.439v-1.11h-.065c-.622.914-1.45%201.372-2.486%201.372-.882%200-1.621-.262-2.215-.784-.594-.523-.891-1.176-.891-1.96%200-.828.313-1.486.94-1.976s1.463-.735%202.51-.735c.892%200%201.629.163%202.206.49v-.344c0-.522-.207-.966-.621-1.33a2.132%202.132%200%200%200-1.455-.547c-.84%200-1.504.353-1.995%201.062l-1.324-.834c.73-1.045%201.81-1.568%203.238-1.568m11.853.262l-5.02%2011.53H96.42l1.864-4.034-3.302-7.496h1.635l2.387%205.749h.032l2.322-5.75z%22%20fill%3D%22%23FFF%22%2F%3E%3Cpath%20d%3D%22M75.448%207.134c0-.473-.04-.93-.116-1.366h-6.344v2.588h3.634a3.11%203.11%200%200%201-1.344%202.042v1.68h2.169c1.27-1.17%202.001-2.9%202.001-4.944%22%20fill%3D%22%234285F4%22%2F%3E%3Cpath%20d%3D%22M68.988%2013.7c1.816%200%203.344-.595%204.459-1.621l-2.169-1.681c-.603.406-1.38.643-2.29.643-1.754%200-3.244-1.182-3.776-2.774h-2.234v1.731a6.728%206.728%200%200%200%206.01%203.703%22%20fill%3D%22%2334A853%22%2F%3E%3Cpath%20d%3D%22M65.212%208.267a4.034%204.034%200%200%201%200-2.572V3.964h-2.234a6.678%206.678%200%200%200-.717%203.017c0%201.085.26%202.11.717%203.017l2.234-1.731z%22%20fill%3D%22%23FABB05%22%2F%3E%3Cpath%20d%3D%22M68.988%202.921c.992%200%201.88.34%202.58%201.008v.001l1.92-1.918c-1.165-1.084-2.685-1.75-4.5-1.75a6.728%206.728%200%200%200-6.01%203.702l2.234%201.731c.532-1.592%202.022-2.774%203.776-2.774%22%20fill%3D%22%23E94235%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E);
130 | background-origin: content-box;
131 | background-position: center;
132 | background-repeat: no-repeat;
133 | background-size: contain;
134 | border: 0;
135 | border-radius: 4px;
136 | box-shadow: 0 1px 1px 0 rgba(60, 64, 67, 0.30), 0 1px 3px 1px rgba(60, 64, 67, 0.15);
137 | cursor: pointer;
138 | display: none;
139 | }
140 |
141 | input::placeholder {
142 | color: #000;
143 | }
144 |
145 | .sq-input--focus {
146 | outline: -webkit-focus-ring-color auto 5px;
147 | }
148 |
149 | .sq-input--error {
150 | box-shadow: inset 0px 0px 0px 3px rgba(255,0,0,0.5);
151 | }
--------------------------------------------------------------------------------