# Cloudbeds Payment Element Web Component

A web component wrapper for the Cloudbeds Payment SDK, enabling easy integration of payment processing into any website or application. This package provides both CDN and NPM distribution methods for maximum flexibility.

## Features

- 🚀 **Easy Integration**: Drop-in web component that works with any framework
- 🌐 **Universal Compatibility**: Works with vanilla HTML, Vue, Angular, etc.
- 🎨 **Customizable**: Full theming support and customizable styling
- 🔒 **PCI Compliant**: Secure tokenization with industry-standard security
- 🌍 **Internationalization**: Multi-language support

## Installation

## React

If your project is built with React, instead use [@cloudbeds/payment-sdk](https://www.npmjs.com/package/@cloudbeds/payment-sdk).

### Via NPM (Recommended for bundled projects)

```bash
npm install @cloudbeds/payment-element-webcomponent
```

### Via CDN (For direct HTML usage)

```html
<script src="https://cdn.jsdelivr.net/npm/@cloudbeds/payment-element-webcomponent/cloudbeds-payment-element.min.js"></script>
```

## Quick Start

### CDN Usage

```html
<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/@cloudbeds/payment-element-webcomponent/cloudbeds-payment-element.min.js"></script>
</head>
<body>
  <cloudbeds-payment-element
    api-key="YOUR_API_KEY"
    property-id="YOUR_PROPERTY_ID"
    amount="100.00"
    currency="usd"
    env="prod"
  ></cloudbeds-payment-element>

  <button id="submit-btn">Submit Payment</button>

  <script>
    let paymentHandles = null;
    const paymentElement = document.querySelector('cloudbeds-payment-element');

    // Get handles for submit and validate functions
    paymentElement['on-render'] = (handles) => {
      paymentHandles = handles;
    };

    // Submit payment
    document.getElementById('submit-btn').addEventListener('click', async () => {
      if (!paymentHandles) return;

      const isValid = await paymentHandles.validate();
      if (!isValid) {
        alert('Please complete all required fields');
        return;
      }

      const result = await paymentHandles.submit();
      console.log('Payment hash:', result?.paymentData?.paymentMethodHash);
    });
  </script>
</body>
</html>
```

### NPM Module Usage

#### ES Modules (Import)

```javascript
import { PaymentElementWebComponent } from '@cloudbeds/payment-element-webcomponent';

// Register the web component (if not already registered)
if (!customElements.get('cloudbeds-payment-element')) {
  customElements.define('cloudbeds-payment-element', PaymentElementWebComponent);
}
```

#### CommonJS (Require)

```javascript
const { PaymentElementWebComponent } = require('@cloudbeds/payment-element-webcomponent');

// Register the web component (if not already registered)
if (!customElements.get('cloudbeds-payment-element')) {
  customElements.define('cloudbeds-payment-element', PaymentElementWebComponent);
}
```

#### TypeScript

```typescript
import { PaymentElementWebComponent, PaymentHandles } from '@cloudbeds/payment-element-webcomponent';

// Register the web component (if not already registered)
if (!customElements.get('cloudbeds-payment-element')) {
  customElements.define('cloudbeds-payment-element', PaymentElementWebComponent);
}

// Type-safe event handling
const paymentElement = document.querySelector('cloudbeds-payment-element') as PaymentElementWebComponent;
let paymentHandles: PaymentHandles = null;
paymentElement['on-render'] = (handles: PaymentHandles) => {
  // handles.submit() and handles.validate() are properly typed
  paymentHandles = handles;
};
```

## API Reference

### Attributes

| Attribute | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `api-key` | string | ✅ | - | Your Cloudbeds API key |
| `property-id` | string | ✅ | - | Your property ID |
| `amount` | string | ✅ | - | Payment amount (e.g., "100.00") |
| `currency` | string | ❌ | Property's currency setting (`"usd"` if none) | Currency code in lowercase, e.g. "usd", "eur" |
| `env` | string | ❌ | `"prod"` | Environment: "prod", "stage", "dev", or "local" |
| `lang` | string | ❌ | `"en"` | Language code for localization (e.g. "en", "es") |
| `guest` | string | ❌ | `null` | Guest information as JSON string |
| `theme` | string | ❌ | SDK default theme object | Custom theme configuration as JSON string |
| `allowed-payment-methods` | string | ❌ | All payment method the property allows | Allowed payment methods as JSON array |
| `scoped-css` | string | ❌ | `"false"` | Enable scoped CSS ("true" or "false") |
| `capture` | string | ❌ | `"auto"` | Payment capture mode ("auto" or "manual") |

### Event Handlers

| Event | Description | Callback Data | Required |
|-------|-------------|---------------|----------|
| `on-render` | Fired when component renders | `PaymentHandles` object | ✅ |
| `on-change` | Fired when form data changes | Form data object | ❌ |
| `on-error` | Fired when an error occurs | Error object | ❌ |
| `on-submit` | Fired after payment submission | Submission result | ❌ |

### PaymentHandles Methods

```typescript
interface PaymentHandles {
  submit(): Promise<PaymentResult>;
  validate(): Promise<boolean>;
}
```

## Setting Amount Dynamically

Instead of hardcoding the amount in HTML, you can set it from a JavaScript
variable:

```javascript
const paymentElement = document.getElementById('cloudbeds-payment-element');
paymentElement.setAttribute('amount', 12.21);
```

### Example

```html
<payment-element-webcomponent
  id="payment-element"
  api-key="YOUR_API_KEY"
  property-id="YOUR_PROPERTY_ID"
  currency="usd"
  env="prod"
></payment-element-webcomponent>

<script>
  // Calculate amount from your cart/order
  const amount = calculateAmount();

  // Set the amount attribute
  document
    .getElementById('payment-element')
    .setAttribute('amount', amount.toFixed(2));
</script>
```

**Note:** Always use `.toFixed(2)` to ensure proper decimal formatting.

## Complete Example

See the included [example html file](https://unpkg.com/@cloudbeds/payment-element-webcomponent@0.0.29/demo/index.html) for a comprehensive example showing:
- Multiple payment methods
- Event handling
- Validation
- Error handling

## Framework Integration

This web component works seamlessly with any JavaScript framework:

- **Vanilla HTML/JS**: Use directly with script tags
- **React**: For React-specific components, see [@cloudbeds/payment-sdk](https://www.npmjs.com/package/@cloudbeds/payment-sdk)
- **Vue.js**: Compatible with Vue 2 and Vue 3
- **Angular**: Works with any Angular version
- **Other frameworks**: Compatible with Svelte, Lit, and other modern frameworks

## Browser Support

- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Mobile browsers (iOS Safari, Chrome Mobile)

## Files in this Distribution

- `cloudbeds-payment-element.min.js` - Standalone UMD bundle for CDN usage
- `index.js` - CommonJS module for Node.js require()
- `index.esm.js` - ES module for import statements
- `index.d.ts` - TypeScript type definitions
- `demo/*` - folder containing [an application demo running directly on the CDN](https://unpkg.com/@cloudbeds/payment-element-webcomponent@0.0.29/demo/index.html)

## Support

For issues and questions, please contact support@cloudbeds.com
