@getchange/change-drop-in
Advanced tools
Comparing version 1.0.4 to 1.1.0
@@ -1,2 +0,2 @@ | ||
import{b as t,r as e,n as o,s as i,$ as r,y as n}from"./query-assigned-elements-1579f20e.js"; | ||
import{b as t,r as o,n as e,s as i,$ as n,y as r,w as a}from"./query-assigned-elements-98220a8b.js"; | ||
/** | ||
@@ -6,3 +6,3 @@ * @license | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/const a=(t,e)=>"method"===e.kind&&e.descriptor&&!("value"in e.descriptor)?{...e,finisher(o){o.createProperty(e.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:e.key,initializer(){"function"==typeof e.initializer&&(this[e.key]=e.initializer.call(this))},finisher(o){o.createProperty(e.key,t)}};function s(t){return(e,o)=>void 0!==o?((t,e,o)=>{e.constructor.createProperty(o,t)})(t,e,o):a(t,e) | ||
*/const s=(t,o)=>"method"===o.kind&&o.descriptor&&!("value"in o.descriptor)?{...o,finisher(e){e.createProperty(o.key,t)}}:{kind:"field",key:Symbol(),placement:"own",descriptor:{},originalKey:o.key,initializer(){"function"==typeof o.initializer&&(this[o.key]=o.initializer.call(this))},finisher(e){e.createProperty(o.key,t)}};function l(t){return(o,e)=>void 0!==e?((t,o,e)=>{o.constructor.createProperty(e,t)})(t,o,e):s(t,o) | ||
/** | ||
@@ -12,3 +12,3 @@ * @license | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/}function c(t){return s({...t,state:!0})} | ||
*/}function u(t){return l({...t,state:!0})} | ||
/** | ||
@@ -24,3 +24,3 @@ * @license | ||
*/ | ||
function l(t,e){return(({finisher:t,descriptor:e})=>(o,i)=>{var r;if(void 0===i){const i=null!==(r=o.originalKey)&&void 0!==r?r:o.key,n=null!=e?{kind:"method",placement:"prototype",key:i,descriptor:e(o.key)}:{...o,key:i};return null!=t&&(n.finisher=function(e){t(e,i)}),n}{const r=o.constructor;void 0!==e&&Object.defineProperty(o,i,e(i)),null==t||t(r,i)}})({descriptor:o=>{const i={get(){var e,o;return null!==(o=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==o?o:null},enumerable:!0,configurable:!0};if(e){const e="symbol"==typeof o?Symbol():"__"+o;i.get=function(){var o,i;return void 0===this[e]&&(this[e]=null!==(i=null===(o=this.renderRoot)||void 0===o?void 0:o.querySelector(t))&&void 0!==i?i:null),this[e]}}return i}})} | ||
function c(t,o){return(({finisher:t,descriptor:o})=>(e,i)=>{var n;if(void 0===i){const i=null!==(n=e.originalKey)&&void 0!==n?n:e.key,r=null!=o?{kind:"method",placement:"prototype",key:i,descriptor:o(e.key)}:{...e,key:i};return null!=t&&(r.finisher=function(o){t(o,i)}),r}{const n=e.constructor;void 0!==o&&Object.defineProperty(e,i,o(i)),null==t||t(n,i)}})({descriptor:e=>{const i={get(){var o,e;return null!==(e=null===(o=this.renderRoot)||void 0===o?void 0:o.querySelector(t))&&void 0!==e?e:null},enumerable:!0,configurable:!0};if(o){const o="symbol"==typeof e?Symbol():"__"+e;i.get=function(){var e,i;return void 0===this[o]&&(this[o]=null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null),this[o]}}return i}})} | ||
/** | ||
@@ -30,3 +30,3 @@ * @license | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/const u=1; | ||
*/const d=1; | ||
/** | ||
@@ -37,2 +37,2 @@ * @license | ||
*/ | ||
const d=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,o){this._$Ct=t,this._$AM=e,this._$Ci=o}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}{constructor(t){var e;if(super(t),t.type!==u||"class"!==t.name||(null===(e=t.strings)||void 0===e?void 0:e.length)>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return" "+Object.keys(t).filter((e=>t[e])).join(" ")+" "}update(e,[o]){var i,r;if(void 0===this.et){this.et=new Set,void 0!==e.strings&&(this.st=new Set(e.strings.join(" ").split(/\s/).filter((t=>""!==t))));for(const t in o)o[t]&&!(null===(i=this.st)||void 0===i?void 0:i.has(t))&&this.et.add(t);return this.render(o)}const n=e.element.classList;this.et.forEach((t=>{t in o||(n.remove(t),this.et.delete(t))}));for(const t in o){const e=!!o[t];e===this.et.has(t)||(null===(r=this.st)||void 0===r?void 0:r.has(t))||(e?(n.add(t),this.et.add(t)):(n.remove(t),this.et.delete(t)))}return t}});var p=function(t,e,o,i){var r,n=arguments.length,a=n<3?e:null===i?i=Object.getOwnPropertyDescriptor(e,o):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,o,i);else for(var s=t.length-1;s>=0;s--)(r=t[s])&&(a=(n<3?r(a):n>3?r(e,o,a):r(e,o))||a);return n>3&&a&&Object.defineProperty(e,o,a),a};let m=class extends i{constructor(){super(...arguments),this.quickAmounts=[10,20,50],this.formValid=!1,this.state="form",this.VERSION="1.0.4",this.settings=this.fetchSettings()}render(){return r`<form @submit="${t=>this.handleSubmit(t)}"><h1>Make a donation</h1><div id="amount-buttons">${this.quickAmounts.map(((t,e)=>r`<button type="button" @click="${()=>this.handleQuickAmountClick(e)}" class="amount-button ${d({selected:e===this.selectedQuickAmount})}">$${t}</button>`))}</div><div class="input-container"><input placeholder="Custom amount" @input="${()=>this.handleCustomAmountInput()}" name="custom-amount" type="number"> <span class="input-prefix">$</span></div><input placeholder="First name" autocomplete="given-name" @input="${()=>this.checkFormValidity()}" name="first-name" required minlength="1"> <input placeholder="Last name" autocomplete="family-name" @input="${()=>this.checkFormValidity()}" name="last-name" required minlength="1"> <button id="coinbase" type="submit" ?disabled="${!this.formValid||"loading"==this.state||"paying"==this.state}" @click="${()=>this.handleCoinbaseClick()}">${this.coinbaseButtonText()}</button></form><div id="powered-by-container"><span>powered by</span><img src="https://d2m0e1zy3fwxmp.cloudfront.net/change-logo.svg"></div>`}firstUpdated(){this.applySettings()}async fetchSettings(){return fetch(`https://api.getchange.io/api/v1/drop_in/donation_form/settings?component_version=${this.VERSION}`).then((t=>t.json())).catch((()=>({})))}async applySettings(){await this.settings}coinbaseButtonText(){switch(this.state){case"form":return"Continue with Coinbase";case"loading":return n`<svg height="12" viewBox="0 0 400 150" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="100" r="50" fill="white"/><circle cx="200" cy="100" r="50" fill="white"/><circle cx="350" cy="100" r="50" fill="white"/></svg>`;case"paying":return"Pay in new tab"}}get amount(){return void 0!==this.selectedQuickAmount?this.quickAmounts[this.selectedQuickAmount]:Number(this.customAmountInput.value)}handleQuickAmountClick(t){this.selectedQuickAmount=t,this.customAmountInput.value="",this.checkFormValidity()}handleCustomAmountInput(){this.selectedQuickAmount=void 0,this.checkFormValidity()}handleSubmit(t){console.log("submit"),t.preventDefault(),this.formValid&&this.submitForm()}handleCoinbaseClick(){this.submitForm()}async submitForm(){void 0!==this.nonprofitId&&void 0!==this.publicKey&&(this.state="loading",async function(t,e,o,i,r){return fetch("https://api.getchange.io/api/v1/payments/crypto_checkout_link",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({amount:t,nonprofit_id:e,public_key:r,metadata:{first_name:o,last_name:i}})}).then((t=>t.json())).then((t=>t.checkout_url))}(100*this.amount,this.nonprofitId,this.firstNameInput.value,this.lastNameInput.value,this.publicKey).then((t=>{window.open(t,"_blank"),this.state="paying"})).catch((()=>{this.state="form"})))}checkFormValidity(){const t=this.amount>0,e=this.firstNameInput.validity.valid&&this.lastNameInput.validity.valid;this.formValid=t&&e}};m.styles=e`:host{--color:black;--background-color:#f7f9fa;--color-primary:white;--color-disabled:#fff;--background-color-primary:#1da1f2;--background-color-primary-hover:#43b2f7;--background-color-disabled:#ccc;--input-border-color:#ddd;--input-border-radius:0.3em;--input-color:black;--input-background-color:white;--input-background-color-hover:#f5f5f5;--input-color-hover:#f7f7f7;--input-placeholder-color:#999;display:block;font-family:sans-serif;background-color:var(--background-color);max-width:400px}form{color:var(--color);display:flex;flex-direction:column;align-items:center;padding:1.5em}form>*{width:100%;max-width:100%}form>:not(:last-child){margin-bottom:.8em}h1{margin:.5em 0;font-size:1.5em;text-align:center}button{transition:all .1s ease-out}input{color:var(--input-color);background:var(--input-background-color)}input::placeholder{color:var(--input-placeholder-color)}#amount-buttons{display:flex}.amount-button{flex:1;border-radius:0;padding:.8em .6em;font-weight:700;border:1px solid var(--input-border-color);color:var(--input-color);background:var(--input-background-color);border-right:none}.amount-button:hover{background-color:var(--input-background-color-hover)}.amount-button:first-of-type{border-top-left-radius:var(--input-border-radius);border-bottom-left-radius:var(--input-border-radius)}.amount-button:last-of-type{border-top-right-radius:var(--input-border-radius);border-bottom-right-radius:var(--input-border-radius);border-right:1px solid var(--input-border-color)}.amount-button.selected{background-color:var(--background-color-primary);color:var(--color-primary)}input[name=custom-amount]{padding-left:2em}.input-container{position:relative}.input-container input{width:100%}.input-prefix{display:flex;content:"$";position:absolute;height:100%;top:-.04em;left:1em;align-items:center;color:var(--input-placeholder-color)}button#coinbase{background-color:var(--background-color-primary);color:var(--color-primary);border-radius:999em;padding:.9em 1.1em;font-weight:700;max-width:17em}button#coinbase:hover:not(:active){background-color:var(--background-color-primary-hover)}input{padding:.8em .6em .8em 1em;border:1px solid var(--input-border-color);border-radius:var(--input-border-radius)}button[disabled]{background-color:var(--background-color-disabled)!important;color:var(--color-disabled)!important;cursor:not-allowed}#powered-by-container{display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.5);color:var(--color);font-size:.8em;padding:1em;margin-top:.5em}#powered-by-container span{opacity:.5}#powered-by-container img{height:1em;margin-left:.4em}circle{animation-name:bounce;animation-duration:1s;animation-iteration-count:infinite}circle:nth-of-type(2){animation-delay:.1s}circle:nth-of-type(3){animation-delay:.2s}@keyframes bounce{0%{transform:translateY(0)}20%{transform:translateY(-50px)}40%{transform:translateY(0)}}button{cursor:pointer;border:none}button,input{font-size:1em;font-family:inherit}*{box-sizing:border-box}`,p([s({type:String,attribute:"nonprofit-id"})],m.prototype,"nonprofitId",void 0),p([s({type:String,attribute:"public-key"})],m.prototype,"publicKey",void 0),p([c()],m.prototype,"selectedQuickAmount",void 0),p([c()],m.prototype,"formValid",void 0),p([c()],m.prototype,"state",void 0),p([l("input[name=custom-amount]")],m.prototype,"customAmountInput",void 0),p([l("input[name=first-name]")],m.prototype,"firstNameInput",void 0),p([l("input[name=last-name]")],m.prototype,"lastNameInput",void 0),m=p([o("change-donation-form")],m);export{m as ChangeDonationForm}; | ||
const p=(t=>(...o)=>({_$litDirective$:t,values:o}))(class extends class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,o,e){this._$Ct=t,this._$AM=o,this._$Ci=e}_$AS(t,o){return this.update(t,o)}update(t,o){return this.render(...o)}}{constructor(t){var o;if(super(t),t.type!==d||"class"!==t.name||(null===(o=t.strings)||void 0===o?void 0:o.length)>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return" "+Object.keys(t).filter((o=>t[o])).join(" ")+" "}update(o,[e]){var i,n;if(void 0===this.et){this.et=new Set,void 0!==o.strings&&(this.st=new Set(o.strings.join(" ").split(/\s/).filter((t=>""!==t))));for(const t in e)e[t]&&!(null===(i=this.st)||void 0===i?void 0:i.has(t))&&this.et.add(t);return this.render(e)}const r=o.element.classList;this.et.forEach((t=>{t in e||(r.remove(t),this.et.delete(t))}));for(const t in e){const o=!!e[t];o===this.et.has(t)||(null===(n=this.st)||void 0===n?void 0:n.has(t))||(o?(r.add(t),this.et.add(t)):(r.remove(t),this.et.delete(t)))}return t}});var m=function(t,o,e,i){var n,r=arguments.length,a=r<3?o:null===i?i=Object.getOwnPropertyDescriptor(o,e):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,o,e,i);else for(var s=t.length-1;s>=0;s--)(n=t[s])&&(a=(r<3?n(a):r>3?n(o,e,a):n(o,e))||a);return r>3&&a&&Object.defineProperty(o,e,a),a};let h=class extends i{constructor(){super(...arguments),this.solana=!1,this.quickAmounts=[10,20,50],this.formValid=!1,this.state="form",this.VERSION="1.1.0",this.settings=this.fetchSettings()}render(){return n`<form @submit="${t=>this.handleSubmit(t)}"><h1>Make a donation</h1><div id="amount-buttons">${this.quickAmounts.map(((t,o)=>n`<button type="button" @click="${()=>this.handleQuickAmountClick(o)}" class="amount-button ${p({selected:o===this.selectedQuickAmount})}">$${t}</button>`))}</div><div class="input-container"><input placeholder="Custom amount" @input="${()=>this.handleCustomAmountInput()}" name="custom-amount" type="number"> <span class="input-prefix">$</span></div><input placeholder="First name" autocomplete="given-name" @input="${()=>this.checkFormValidity()}" name="first-name" required minlength="1"> <input placeholder="Last name" autocomplete="family-name" @input="${()=>this.checkFormValidity()}" name="last-name" required minlength="1"> ${this.renderSubmitButtons()}</form><div id="powered-by-container"><span>powered by</span><img src="https://d2m0e1zy3fwxmp.cloudfront.net/change-logo.svg"></div>`}firstUpdated(){this.applySettings()}async fetchSettings(){return fetch(`https://api.getchange.io/api/v1/drop_in/donation_form/settings?component_version=${this.VERSION}`).then((t=>t.json())).catch((()=>({})))}async applySettings(){await this.settings}renderSubmitButtons(){return"paying"==this.state?n`<button type="submit" disabled="disabled">Pay in new tab</button>`:n`<div id="submit-button-container">${this.solana?n`<button id="solana" type="submit" ?disabled="${!this.formValid||"loading"==this.state}">${"solana"===this.loadingPaymentMethod?y():"Continue with Solana"}</button>`:a} <button id="coinbase" type="submit" ?disabled="${!this.formValid||"loading"==this.state}">${"coinbase"===this.loadingPaymentMethod?y():"Continue with Coinbase"}</button></div>`}get amount(){return void 0!==this.selectedQuickAmount?this.quickAmounts[this.selectedQuickAmount]:Number(this.customAmountInput.value)}handleQuickAmountClick(t){this.selectedQuickAmount=t,this.customAmountInput.value="",this.checkFormValidity()}handleCustomAmountInput(){this.selectedQuickAmount=void 0,this.checkFormValidity()}handleSubmit(t){var o;if(console.log("submit"),t.preventDefault(),!this.formValid)return;const e="coinbase"===(null===(o=t.submitter)||void 0===o?void 0:o.id)?"coinbase":"solana";this.submitForm(e)}async submitForm(t){if(void 0===this.nonprofitId||void 0===this.publicKey)return;this.state="loading",this.loadingPaymentMethod=t;("solana"===t?f:b)(this.amount,this.nonprofitId,this.firstNameInput.value,this.lastNameInput.value,this.publicKey).then((t=>{window.open(t,"_blank"),this.state="paying"})).catch((t=>{console.error(t),this.state="form"}))}checkFormValidity(){const t=this.amount>0,o=this.firstNameInput.validity.valid&&this.lastNameInput.validity.valid;this.formValid=t&&o}};async function b(t,o,e,i,n){return fetch("https://api.getchange.io/api/v1/payments/crypto_checkout_link",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({amount:100*t,nonprofit_id:o,public_key:n,metadata:{first_name:e,last_name:i}})}).then((t=>t.json())).then((t=>t.checkout_url))}async function f(t,o,e,i,n){return fetch(`https://api.getchange.io/api/v1/nonprofit_basics?ids[]=${o}&public_key=${n}`,{method:"GET"}).then((t=>t.json())).then((t=>t.nonprofits[0].crypto.solana_address)).then((o=>`https://getchange.io/solana/cause/${o}?donation-intent&amount=${t}&first-name=${e}&last-name=${i}`))}function y(){return r`<svg height="12" viewBox="0 0 400 150" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="100" r="50" fill="white"/><circle cx="200" cy="100" r="50" fill="white"/><circle cx="350" cy="100" r="50" fill="white"/></svg>`}h.styles=o`:host{--color:black;--background-color:#f7f9fa;--color-primary:white;--color-disabled:#fff;--background-color-primary:#1da1f2;--background-color-primary-hover:#43b2f7;--background-color-disabled:#ccc;--input-border-color:#ddd;--input-border-radius:0.3em;--input-color:black;--input-background-color:white;--input-background-color-hover:#f5f5f5;--input-color-hover:#f7f7f7;--input-placeholder-color:#999;display:block;font-family:sans-serif;background-color:var(--background-color);max-width:400px}form{color:var(--color);display:flex;flex-direction:column;align-items:center;padding:1.5em}form>*{width:100%;max-width:100%}form>:not(:last-child){margin-bottom:.8em}h1{margin:.5em 0;font-size:1.5em;text-align:center}button{transition:all .1s ease-out}input{color:var(--input-color);background:var(--input-background-color)}input::placeholder{color:var(--input-placeholder-color)}#amount-buttons{display:flex}.amount-button{flex:1;border-radius:0;padding:.8em .6em;font-weight:700;border:1px solid var(--input-border-color);color:var(--input-color);background:var(--input-background-color);border-right:none}.amount-button:hover{background-color:var(--input-background-color-hover)}.amount-button:first-of-type{border-top-left-radius:var(--input-border-radius);border-bottom-left-radius:var(--input-border-radius)}.amount-button:last-of-type{border-top-right-radius:var(--input-border-radius);border-bottom-right-radius:var(--input-border-radius);border-right:1px solid var(--input-border-color)}.amount-button.selected{background-color:var(--background-color-primary);color:var(--color-primary)}input[name=custom-amount]{padding-left:2em}.input-container{position:relative}.input-container input{width:100%}.input-prefix{display:flex;content:"$";position:absolute;height:100%;top:-.04em;left:1em;align-items:center;color:var(--input-placeholder-color)}#submit-button-container{display:flex;flex-wrap:wrap;justify-content:center}button[type=submit]{background-color:var(--background-color-primary);color:var(--color-primary);border-radius:999em;padding:.9em 1.1em;font-weight:700;width:17em;max-width:100%;margin:.3em;white-space:nowrap}button[type=submit]:hover:not(:active){background-color:var(--background-color-primary-hover)}input{padding:.8em .6em .8em 1em;border:1px solid var(--input-border-color);border-radius:var(--input-border-radius)}button[disabled]{background-color:var(--background-color-disabled)!important;color:var(--color-disabled)!important;cursor:not-allowed}#powered-by-container{display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.5);color:var(--color);font-size:.8em;padding:1em;margin-top:.5em}#powered-by-container span{opacity:.5}#powered-by-container img{height:1em;margin-left:.4em}circle{animation-name:bounce;animation-duration:1s;animation-iteration-count:infinite}circle:nth-of-type(2){animation-delay:.1s}circle:nth-of-type(3){animation-delay:.2s}@keyframes bounce{0%{transform:translateY(0)}20%{transform:translateY(-50px)}40%{transform:translateY(0)}}button{cursor:pointer;border:none}button,input{font-size:1em;font-family:inherit}*{box-sizing:border-box}`,m([l({type:String,attribute:"nonprofit-id"})],h.prototype,"nonprofitId",void 0),m([l({type:String,attribute:"public-key"})],h.prototype,"publicKey",void 0),m([l({type:Boolean})],h.prototype,"solana",void 0),m([u()],h.prototype,"selectedQuickAmount",void 0),m([u()],h.prototype,"formValid",void 0),m([u()],h.prototype,"state",void 0),m([u()],h.prototype,"loadingPaymentMethod",void 0),m([c("input[name=custom-amount]")],h.prototype,"customAmountInput",void 0),m([c("input[name=first-name]")],h.prototype,"firstNameInput",void 0),m([c("input[name=last-name]")],h.prototype,"lastNameInput",void 0),h=m([e("change-donation-form")],h);export{h as ChangeDonationForm}; |
@@ -1,1 +0,1 @@ | ||
import{n as e,s as t,$ as r}from"./query-assigned-elements-1579f20e.js";var n=function(e,t,r,n){var o,c=arguments.length,f=c<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)f=Reflect.decorate(e,t,r,n);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(f=(c<3?o(f):c>3?o(t,r,f):o(t,r))||f);return c>3&&f&&Object.defineProperty(t,r,f),f};let o=class extends t{render(){return r`Coming soon!`}};o=n([e("change-drop-in")],o);export{o as ChangeDropIn}; | ||
import{n as e,s as t,$ as r}from"./query-assigned-elements-98220a8b.js";var n=function(e,t,r,n){var o,c=arguments.length,f=c<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,r):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)f=Reflect.decorate(e,t,r,n);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(f=(c<3?o(f):c>3?o(t,r,f):o(t,r))||f);return c>3&&f&&Object.defineProperty(t,r,f),f};let o=class extends t{render(){return r`Coming soon!`}};o=n([e("change-drop-in")],o);export{o as ChangeDropIn}; |
{ | ||
"name": "@getchange/change-drop-in", | ||
"version": "1.0.4", | ||
"version": "1.1.0", | ||
"description": "UI element that lets users donate crypto", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -25,4 +25,12 @@ # change-drop-in | ||
Once you've signed up, set the `public-key` to match your account. You can find your account's public key at https://api.getchange.io/developers. | ||
Once you've signed up, set the `public-key` attribute to match your account. You can find your account's public key at https://api.getchange.io/developers. | ||
#### All attributes | ||
| Property | Description | | ||
| -------- | ----------- | | ||
| public-key (\*required) | The public key of your Change account. You can find your account's public key at https://api.getchange.io/developers. | | ||
| nonprofit-id (\*required) | The ID of the nonprofit you'd like to accept donations for. You can find nonprofit IDs at https://api.getchange.io. | | ||
| solana | Add this attribute to accept SOL (Solana) donations. A second payment method option will appear in the form. | | ||
### Styles | ||
@@ -29,0 +37,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { LitElement, html, css, svg } from "lit"; | ||
import { LitElement, html, css, svg, nothing } from "lit"; | ||
import { customElement, state, query, property } from "lit/decorators.js"; | ||
@@ -7,2 +7,4 @@ import { classMap } from "lit/directives/class-map.js"; | ||
type PaymentMethod = "coinbase" | "solana"; | ||
@customElement("change-donation-form") | ||
@@ -12,2 +14,3 @@ export class ChangeDonationForm extends LitElement { | ||
@property({ type: String, attribute: "public-key" }) publicKey?: string; | ||
@property({ type: Boolean }) solana?: boolean = false; | ||
@@ -18,2 +21,5 @@ quickAmounts = [10, 20, 50]; | ||
@state() state: "form" | "loading" | "paying" = "form"; | ||
// Whichever payment method is current loading. This only affects the visual state of the | ||
// payment method buttons. | ||
@state() loadingPaymentMethod?: PaymentMethod; | ||
@@ -24,3 +30,3 @@ @query("input[name=custom-amount]") customAmountInput!: HTMLInputElement; | ||
VERSION = "1.0.4"; | ||
VERSION = "1.1.0"; | ||
@@ -77,12 +83,3 @@ settings = this.fetchSettings(); | ||
<button | ||
id="coinbase" | ||
type="submit" | ||
?disabled=${!this.formValid || | ||
this.state == "loading" || | ||
this.state == "paying"} | ||
@click=${() => this.handleCoinbaseClick()} | ||
> | ||
${this.coinbaseButtonText()} | ||
</button> | ||
${this.renderSubmitButtons()} | ||
</form> | ||
@@ -114,11 +111,35 @@ <div id="powered-by-container"> | ||
private coinbaseButtonText() { | ||
switch (this.state) { | ||
case "form": | ||
return "Continue with Coinbase"; | ||
case "loading": | ||
return loadingImage(); | ||
case "paying": | ||
return "Pay in new tab"; | ||
private renderSubmitButtons() { | ||
if (this.state == "paying") { | ||
return html`<button type="submit" disabled>Pay in new tab</button>`; | ||
} | ||
return html` | ||
<div id="submit-button-container"> | ||
${this.solana | ||
? html` | ||
<!-- Note: the ID of this button affects which payment method to use. --> | ||
<button | ||
id="solana" | ||
type="submit" | ||
?disabled=${!this.formValid || this.state == "loading"} | ||
> | ||
${this.loadingPaymentMethod === "solana" | ||
? loadingImage() | ||
: "Continue with Solana"} | ||
</button> | ||
` | ||
: nothing} | ||
<!-- Note: the ID of this button affects which payment method to use. --> | ||
<button | ||
id="coinbase" | ||
type="submit" | ||
?disabled=${!this.formValid || this.state == "loading"} | ||
> | ||
${this.loadingPaymentMethod === "coinbase" | ||
? loadingImage() | ||
: "Continue with Coinbase"} | ||
</button> | ||
</div> | ||
`; | ||
} | ||
@@ -150,10 +171,9 @@ | ||
} | ||
this.submitForm(); | ||
} | ||
handleCoinbaseClick() { | ||
this.submitForm(); | ||
const paymentMethod = | ||
e.submitter?.id === "coinbase" ? "coinbase" : "solana"; | ||
this.submitForm(paymentMethod); | ||
} | ||
async submitForm() { | ||
async submitForm(paymentMethod: PaymentMethod) { | ||
if (this.nonprofitId === undefined || this.publicKey === undefined) { | ||
@@ -164,4 +184,7 @@ return; | ||
this.state = "loading"; | ||
fetchCoinbaseLink( | ||
this.amount * 100.0, | ||
this.loadingPaymentMethod = paymentMethod; | ||
const linkFetcher = | ||
paymentMethod === "solana" ? fetchSolanaLink : fetchCoinbaseLink; | ||
linkFetcher( | ||
this.amount, | ||
this.nonprofitId, | ||
@@ -176,3 +199,4 @@ this.firstNameInput.value, | ||
}) | ||
.catch(() => { | ||
.catch((e) => { | ||
console.error(e); | ||
this.state = "form"; | ||
@@ -293,3 +317,8 @@ }); | ||
button#coinbase { | ||
#submit-button-container { | ||
display: flex; | ||
flex-wrap: wrap; | ||
justify-content: center; | ||
} | ||
button[type="submit"] { | ||
background-color: var(--background-color-primary); | ||
@@ -300,5 +329,8 @@ color: var(--color-primary); | ||
font-weight: bold; | ||
max-width: 17em; | ||
width: 17em; | ||
max-width: 100%; | ||
margin: 0.3em; | ||
white-space: nowrap; | ||
} | ||
button#coinbase:hover:not(:active) { | ||
button[type="submit"]:hover:not(:active) { | ||
background-color: var(--background-color-primary-hover); | ||
@@ -394,3 +426,3 @@ } | ||
body: JSON.stringify({ | ||
amount: amount, | ||
amount: amount * 100.0, | ||
nonprofit_id: nonprofitId, | ||
@@ -409,2 +441,21 @@ public_key: publicKey, | ||
async function fetchSolanaLink( | ||
amount: number, | ||
nonprofitId: string, | ||
firstName: string, | ||
lastName: string, | ||
publicKey: string | ||
) { | ||
return fetch( | ||
`https://api.getchange.io/api/v1/nonprofit_basics?ids[]=${nonprofitId}&public_key=${publicKey}`, | ||
{ method: "GET" } | ||
) | ||
.then((response) => response.json()) | ||
.then((response) => response.nonprofits[0].crypto.solana_address as string) | ||
.then( | ||
(solana_address) => | ||
`https://getchange.io/solana/cause/${solana_address}?donation-intent&amount=${amount}&first-name=${firstName}&last-name=${lastName}` | ||
); | ||
} | ||
function loadingImage() { | ||
@@ -411,0 +462,0 @@ return svg` |
193217
10
682
75
3