Skip to content

Commit

Permalink
Merge pull request #61 from getAlby/feat/launch-modal
Browse files Browse the repository at this point in the history
feat: programmatically launch modal
  • Loading branch information
rolznz authored Sep 27, 2023
2 parents bcba915 + fa176b5 commit 05696a4
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 37 deletions.
72 changes: 51 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This project includes web components for connecting to Lightning wallets and ena

## 🛝 Try it out here

https://getalby.github.io/bitcoin-connect
[Bitcoin Connect Landing](https://getalby.github.io/bitcoin-connect)

## 🚀 Quick Start

Expand All @@ -22,22 +22,46 @@ https://getalby.github.io/bitcoin-connect

You can use Bitcoin Connect without any build tools:

```
```html
<script src="https://cdn.jsdelivr.net/npm/@getalby/[email protected]/dist/index.browser.js"></script>
```

## 🤙 Usage

### React

```jsx
import {Button, Modal, launchModal} from '@getalby/bitcoin-connect-react';

// render a button
<Button onConnect={() => alert('Connected!')} />
// include the modal on the page (will not be rendered unless launchModal is called)
<Modal onConnect={() => alert('Connected!')} />

// open modal programmatically
<button onClick={launchModal}>
Programmatically launch modal
</button>
```

### Pure HTML

#### Components

Bitcoin Connect exposes the following web components for allowing users to connect their desired Lightning wallet:

- `<bc-button/>` - launches the Bitcoin Connect Modal on click
- Optional Arguments:
- `icon-only` - display the button as an icon without "Connect wallet"
- `disabled` - mark the button as disabled
- `<bc-modal/>` - render the modal on its own
- `<bc-modal/>` - render the modal on its own.
- Optional Arguments:
- `open` - make the modal appear
- `<bc-connector-list/>` - render the list of connectors on their own
- _more components coming soon_

#### Window Events

Bitcoin Connect exposes the following events:

- `bc:connected` window event which fires when a wallet is connected and window.webln is ready to use
Expand All @@ -46,15 +70,15 @@ Bitcoin Connect exposes the following events:
- `bc:modalopened` window event which fires when Bitcoin Connect modal is opened
- `bc:modalclosed` window event which fires when Bitcoin Connect modal is closed

Current wallets supported:
#### Programmatically launching the modal

- [Alby Browser extension](https://getalby.com)
- [Alby NWC](https://nwc.getalby.com)
- [Generic NWC URL](https://github.com/nostr-protocol/nips/blob/master/47.md)
`<bc-modal/>` needs to be rendered somewhere on the page. The modal can then be launched with:

`document.querySelector('bc-modal').setAttribute('open', true)`

### Styling

- the following CSS variables can be configured:
The following CSS variables can be configured:

```css
html {
Expand All @@ -68,39 +92,39 @@ html {
}
```

# Demos
## Demos

### Pure HTML
### Pure HTML Demo

See [Pure HTML](./demos/html/README.md)

> Example codepen: https://codepen.io/rolznz/pen/ZEmXGLd
> [Example codepen](https://codepen.io/rolznz/pen/ZEmXGLd)
### React
### React Demo

See [React](./demos/react/README.md)

> Example replit: https://replit.com/@rolznz/make-me-an-image-nwc-version
> [Example replit](https://replit.com/@rolznz/make-me-an-image-nwc-version)
### More demos

Open [demos](demos/README.md)

# 🛠️ Development
## 🛠️ Development

## Install
### Install

Run `yarn install && (cd dev/vite && yarn install)`

## Run Vite
### Run Vite

Run `yarn dev`

## Other dev options
### Other dev options

Open [dev](dev/README.md)

## Production Build
### Production Build

`yarn build`

Expand All @@ -112,11 +136,11 @@ Open [dev](dev/README.md)

`yarn dev:build:browser`

## Testing
### Testing

`yarn test`

# Need help?
## Need help?

We are happy to help, please contact us or create an issue.

Expand Down Expand Up @@ -161,7 +185,13 @@ You should have a certain level of trust on the website you decide to connect yo
1. add the "Connect Wallet" button
2. wait for a connection event (using window.addEventListener) and then request to pay the invoice with window.webln

# 🔥 Lit
### What connectors are supported?

- [Alby Browser extension](https://getalby.com)
- [Alby NWC](https://nwc.getalby.com)
- [Generic NWC URL](https://github.com/nostr-protocol/nips/blob/master/47.md)

## 🔥 Lit

This project is powered by Lit.

Expand Down
5 changes: 3 additions & 2 deletions demos/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
},
"dependencies": {
"@getalby/bitcoin-connect-react": "^1.0.1",
"alby-tools": "^3.2.1",
"@getalby/lightning-tools": "^4.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1"
},
"devDependencies": {
"@types/react": "^18.2.15",
Expand Down
12 changes: 9 additions & 3 deletions demos/react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import {LightningAddress} from 'alby-tools';
import {Button} from '@getalby/bitcoin-connect-react';
import {LightningAddress} from '@getalby/lightning-tools';
import {Button, Modal, launchModal} from '@getalby/bitcoin-connect-react';
import toast, {Toaster} from 'react-hot-toast';

function App() {
const [invoice, setInvoice] = React.useState<string | undefined>(undefined);
Expand Down Expand Up @@ -41,8 +42,10 @@ function App() {

return (
<>
<Toaster />
<h1>Bitcoin Connect React</h1>
<Button onConnect={() => alert('Connected!')} />
<Modal onConnect={() => toast('Modal Connected!')} />
<Button onConnect={() => toast('Connected!')} />
<div style={{marginTop: '16px'}}>
{preimage ? (
<p>
Expand All @@ -55,6 +58,9 @@ function App() {
<p>Loading invoice...</p>
)}
</div>
<button style={{marginTop: '16px'}} onClick={launchModal}>
Programmatically launch modal
</button>
</>
);
}
Expand Down
28 changes: 20 additions & 8 deletions demos/react/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,14 @@
lit "^2.2.4"
zustand "^4.4.1"

"@getalby/lightning-tools@^4.0.2":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@getalby/lightning-tools/-/lightning-tools-4.0.2.tgz#a6f5127ca768de28e87cff101508cd2d90590b60"
integrity sha512-6EOo4iqjc4BB37KPtzkTR2Fn/Bf5W7Zqb7sYW4pdPRHKTwbtPSgCFqsankAqn6pXxvnvy/kn0ueFz6af7zYijg==
dependencies:
crypto-js "^4.1.1"
light-bolt11-decoder "^3.0.0"

"@getalby/sdk@^2.2.3":
version "2.2.3"
resolved "https://registry.yarnpkg.com/@getalby/sdk/-/sdk-2.2.3.tgz#fda6de0bc241b59e7ed813204067c4d14b794668"
Expand Down Expand Up @@ -494,14 +502,6 @@ ajv@^6.12.4:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"

alby-tools@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/alby-tools/-/alby-tools-3.2.1.tgz#60f15983454b6635cd90da40f097d32fd0875308"
integrity sha512-dSQ6dBD/qXeBfF40g3PtzLo6yvN5w9zaQ9qeGFkez6feQ4qVMFq+iuxurCDTaR2KFxAf5fboWNZechl7DuH5Sw==
dependencies:
crypto-js "^4.1.1"
light-bolt11-decoder "^3.0.0"

ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
Expand Down Expand Up @@ -874,6 +874,11 @@ globby@^11.1.0:
merge2 "^1.4.1"
slash "^3.0.0"

goober@^2.1.10:
version "2.1.13"
resolved "https://registry.yarnpkg.com/goober/-/goober-2.1.13.tgz#e3c06d5578486212a76c9eba860cbc3232ff6d7c"
integrity sha512-jFj3BQeleOoy7t93E9rZ2de+ScC4lQICLwiAQmKMg9F6roKGaLSHoCDYKkWlSafg138jejvq/mTdvmnwDQgqoQ==

graphemer@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
Expand Down Expand Up @@ -1183,6 +1188,13 @@ react-dom@^18.2.0:
loose-envify "^1.1.0"
scheduler "^0.23.0"

react-hot-toast@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
integrity sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==
dependencies:
goober "^2.1.10"

react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
Expand Down
8 changes: 8 additions & 0 deletions dev/vite/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@
</style>
</head>
<body>
<h1>Programmatic Access</h1>
<button
onclick="document.querySelector('bc-modal').setAttribute('open', true)"
>
Open modal
</button>
<bc-modal></bc-modal>

<h1>Components</h1>
<h2>Button</h2>
<h3>Light</h3>
Expand Down
10 changes: 10 additions & 0 deletions react/src/components/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,13 @@ export const Modal: React.FC<ModalProps> = (props) => {
// @ts-ignore
return <bc-modal />;
};

export function launchModal() {
const modal = document.querySelector('bc-modal');
if (!modal) {
throw new Error(
'bc-modal does not exist in the dom. Did you render the Modal somewhere on this page?'
);
}
modal.setAttribute('open', 'true');
}
1 change: 1 addition & 0 deletions react/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './components/Button';
export * from './components/Modal';
8 changes: 5 additions & 3 deletions src/components/bc-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,11 @@ export class Button extends withTwind()(BitcoinConnectElement) {
>`
: null}
</div>
${this._modalOpen
? html`<bc-modal .onClose=${this._closeModal}></bc-modal>`
: null}
<bc-modal
.open=${this._modalOpen}
.onClose=${this._closeModal}
></bc-modal>
</div>`;
}

Expand Down
9 changes: 9 additions & 0 deletions src/components/bc-modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export class Modal extends withTwind()(BitcoinConnectElement) {
@state()
protected _closing = false;

@property()
open?: boolean = false;

constructor() {
super();

Expand All @@ -46,6 +49,10 @@ export class Modal extends withTwind()(BitcoinConnectElement) {
}

override render() {
if (!this.open) {
return null;
}

return html` <div
class="fixed top-0 left-0 w-full h-full flex justify-center items-end sm:items-center z-[21000]"
>
Expand All @@ -72,6 +79,8 @@ export class Modal extends withTwind()(BitcoinConnectElement) {
private _handleClose = () => {
this._closing = true;
setTimeout(() => {
this.open = false;
this._closing = false;
// Reset after close
// TODO: is there a better way to reset state when the modal is closed?
store.getState().setRoute('/start');
Expand Down

0 comments on commit 05696a4

Please sign in to comment.