# GrailPay BankLink Widget

A JavaScript SDK for integrating GrailPay's Bank Link Widget into your web application.

## Installation

```bash
npm install @grailpay/banklink
```

## Usage

The package can be used both as an ES module in modern JavaScript frameworks and as a CDN script in traditional websites.

### ES Module Usage (React, Vue, etc.)

```javascript
import GPBankLink from "@grailpay/banklink";

// Initialize the widget
const bankLink = new GPBankLink({
	token: "your-token",
	userId: "optional-user-id",
	billingMerchantUserUuid: null,
	sandbox: false, // Set to true for sandbox (test) mode; false for production
	role: "business", // "business" or "person"
	theme: {
		branding_name: "Your Company",
		branding_logo: "https://example.com/logo.png",
		screens: {
			finder: {
				subtitle: "Connect your bank account",
				searchPlaceholder: "Search for banks",
			},
		},
	},
	onError: (error) => {
		console.error("Error:", error);
	},
	onUserCreated: (data) => {
		console.log("User created:", data);
	},
	onBankConnected: (data) => {
		console.log("Bank connected:", data);
	},
	onLinkedDefaultAccount: (data) => {
		console.log("Default account linked:", data);
	},
	onLinkExit: (data) => {
		console.log("Link exited:", data);
	},
});

// Open the widget
bankLink.open();

// Close the widget
bankLink.close();
```

### React Component Example

```jsx
import React, { useEffect } from "react";
import GPBankLink from "@grailpay/banklink";

function BankLinkComponent() {
	useEffect(() => {
		const bankLink = new GPBankLink({
			token: "your-token",
			userId: "optional-user-id",
			billingMerchantUserUuid: null,
			sandbox: false,
			role: "business",
			theme: {
				branding_name: "Your Company",
				branding_logo: "https://example.com/logo.png",
				screens: {
					finder: {
						subtitle: "Connect your bank account",
						searchPlaceholder: "Search for banks",
					},
				},
			},
			onError: (error) => console.error(error),
			onUserCreated: (data) => console.log("User created", data),
			onBankConnected: (data) => console.log("Bank connected", data),
			onLinkedDefaultAccount: (data) => console.log("Default account", data),
			onLinkExit: (data) => console.log("Link exited", data),
		});

		// Open the bank link widget
		bankLink.open();

		// Cleanup on unmount
		return () => {
			bankLink.close();
		};
	}, []);

	return <div>Bank Link Component</div>;
}
```

### CDN Usage

```html
<script src="https://cdn.jsdelivr.net/npm/@grailpay/banklink/index.js"></script>
<script>
	// Global variable available
	const bankLink = new GPBankLink({
		token: "your-token",
		userId: "optional-user-id",
		billingMerchantUserUuid: null,
		sandbox: false,
		role: "business",
		theme: {
			branding_name: "Your Company",
			branding_logo: "https://example.com/logo.png",
			screens: {
				finder: {
					subtitle: "Connect your bank account",
					searchPlaceholder: "Search for banks",
				},
			},
		},
		onError: function (error) {
			console.error(error);
		},
		onUserCreated: function (data) {
			console.log("User created", data);
		},
		onBankConnected: function (data) {
			console.log("Bank connected", data);
		},
		onLinkedDefaultAccount: function (data) {
			console.log("Default account", data);
		},
		onLinkExit: function (data) {
			console.log("Link exited", data);
		},
	});

	// Open the bank link widget
	bankLink.open();
</script>
```

## API Reference

### Configuration Options

| Option                   | Type     | Required | Description                                                    |
| ------------------------ | -------- | -------- | -------------------------------------------------------------- |
| token                    | string   | Yes      | Authentication token for the widget                            |
| userId                   | string   | No       | User UUID for returning users                                  |
| sandbox                  | boolean  | No       | Set to `true` for sandbox mode, `false` for production         |
| role                     | string   | No       | User type: `"business"` or `"person"` (default: `"business"`)  |
| theme                    | object   | No       | Branding customization options (see Branding Configuration below) |
| billingMerchantUserUuid  | string   | No       | UUID of a specific merchant for billing attribution            |
| onError                  | function | No       | Callback for error events                                      |
| onUserCreated            | function | No       | Callback when a new user is created                            |
| onBankConnected          | function | No       | Callback when bank accounts are connected                      |
| onLinkedDefaultAccount   | function | No       | Callback when a default account is selected                    |
| onLinkExit               | function | No       | Callback when the user exits the widget                        |

### Branding Configuration (theme)

GrailPay allows you to customize the Bank Link Widget with your own branding:

```javascript
theme: {
  branding_name: "Your Company",           // Max 20 characters
  branding_logo: "https://example.com/logo.png",
  screens: {
    finder: {
      subtitle: "Connect your bank account",    // Max 100 characters
      searchPlaceholder: "Search for banks",    // Max 30 characters
    },
  },
}
```

| Property                            | Type   | Description                                           | Limit          |
| ----------------------------------- | ------ | ----------------------------------------------------- | -------------- |
| theme.branding_name                 | string | Display name shown as the widget title                | Max 20 chars   |
| theme.branding_logo                 | string | Public URL of your brand logo displayed in the widget | Valid image URL|
| theme.screens.finder.subtitle       | string | Subtitle text below branding name on finder screen    | Max 100 chars  |
| theme.screens.finder.searchPlaceholder | string | Placeholder text for bank search input             | Max 30 chars   |

### Callback Events

#### onError

Triggered when an error occurs during the flow.

```javascript
onError: (error) => {
  console.log(error.message);  // Error message
  console.log(error.userId);   // User UUID
}
```

**Response Example:**
```json
{
  "message": "Error message describing what went wrong",
  "userId": "usr_xxxxxxxxxxxxxxxxxxxx"
}
```

#### onUserCreated

Triggered when a new user is successfully created.

```javascript
onUserCreated: (data) => {
  console.log(data.userId);     // Created user UUID
  console.log(data.role);       // "business" or "person"
  console.log(data.created_at); // Creation timestamp
}
```

**Response Example:**
```json
{
  "userId": "usr_xxxxxxxxxxxxxxxxxxxx",
  "role": "business",
  "created_at": "2025-01-15 10:30:00"
}
```

#### onBankConnected

Triggered after successful bank account connections. Returns an array of all linked accounts with their details.

```javascript
onBankConnected: (accounts) => {
  accounts.forEach(account => {
    console.log(account.account_uuid);   // Account UUID
    console.log(account.user_uuid);      // User UUID
    console.log(account.account_id);     // Account ID
    console.log(account.account_number); // Account number
    console.log(account.routing_number); // Routing number
    console.log(account.name);           // Account name
    console.log(account.account_type);   // "checking" or "savings"
    console.log(account.account_status); // "complete", "pending", or "failed"
    console.log(account.provider_name);  // Bank provider name
    console.log(account.aggregator_type);// Aggregator type
    console.log(account.created_at);     // Creation timestamp
    console.log(account.updated_at);     // Last update timestamp
  });
}
```

**Response Example:**
```json
[
  {
    "account_uuid": "acc_xxxxxxxxxxxxxxxxxxxx",
    "user_uuid": "usr_xxxxxxxxxxxxxxxxxxxx",
    "aggregator_type": "bank_link",
    "created_at": "2025-01-15 10:30:00",
    "updated_at": "2025-01-15 10:30:05",
    "account_id": "acc_xxxxxxxxxxxxxxxxxxxx",
    "account_number": "****1234",
    "provider_name": "Example Bank",
    "routing_number": "121000358",
    "name": "Checking Account",
    "account_type": "checking",
    "account_status": "complete"
  }
]
```

#### onLinkedDefaultAccount

Triggered when a default bank account is selected.

```javascript
onLinkedDefaultAccount: (data) => {
  console.log(data.account_uuid);   // Account UUID
  console.log(data.user_uuid);      // User UUID
  console.log(data.account_id);     // Account ID
  console.log(data.account_number); // Account number
  console.log(data.routing_number); // Routing number
  console.log(data.name);           // Account name
  console.log(data.account_type);   // "checking" or "savings"
  console.log(data.account_status); // "complete", "pending", or "failed"
  console.log(data.provider_name);  // Bank provider name
  console.log(data.aggregator_type);// Aggregator type
  console.log(data.created_at);     // Creation timestamp
  console.log(data.updated_at);     // Last update timestamp
}
```

**Response Example:**
```json
{
  "account_uuid": "acc_xxxxxxxxxxxxxxxxxxxx",
  "user_uuid": "usr_xxxxxxxxxxxxxxxxxxxx",
  "aggregator_type": "bank_link",
  "created_at": "2025-01-15 10:30:00",
  "updated_at": "2025-01-15 10:30:05",
  "account_id": "acc_xxxxxxxxxxxxxxxxxxxx",
  "account_number": "****1234",
  "provider_name": "Example Bank",
  "routing_number": "121000358",
  "name": "Checking Account",
  "account_type": "checking",
  "account_status": "complete"
}
```

#### onLinkExit

Triggered when the user exits the bank link process.

```javascript
onLinkExit: (data) => {
  console.log(data.status);        // "SUCCESS", "FAILED", or "ACTION_ABANDONED"
  console.log(data.reason);        // Exit reason (null on success)
  console.log(data.userId);        // User UUID
  console.log(data.provider_name); // Bank provider name
}
```

**Response Example:**
```json
{
  "status": "SUCCESS",
  "reason": null,
  "userId": "usr_xxxxxxxxxxxxxxxxxxxx",
  "provider_name": "Example Bank"
}
```

### Methods

| Method       | Description                              |
| ------------ | ---------------------------------------- |
| init(config) | Initialize the widget with configuration |
| open()       | Open the widget UI                       |
| close()      | Close the widget UI                      |

## Browser Compatibility

The GrailPay BankLink Widget supports the latest versions of major browsers:

| Browser            | Supported Version               |
| ------------------ | ------------------------------- |
| Chrome             | ✅ Chrome 110 and above         |
| Firefox            | ✅ Firefox 113 and above        |
| Safari             | ✅ Safari 14 and above          |
| Microsoft Edge     | ✅ Microsoft Edge 110 and above |
| Chrome for Android | ✅ Yes                          |
| Safari on iOS      | ✅ Yes                          |
| Internet Explorer  | ❌ No                           |

## License

ISC
