npm package: @nuitee/booking-widget
Description: A beautiful, customizable booking widget modal that can be embedded in any website. Supports vanilla JavaScript, React, and Vue.js.
Latest version: 1.0.14

# Booking Engine Widget

A customizable booking widget modal you can embed in any website. It works with **vanilla JavaScript**, **React**, and **Vue**. API and payment configuration are loaded by the widget at runtime; you only need to install the package and pass options (e.g. `propertyKey` for real data).

## Features

- Modern UI with smooth transitions
- Responsive layout
- **Vanilla JS**, **React**, and **Vue** integrations
- Step-by-step flow: dates → rooms → rates → checkout → confirmation
- Room selection with images and amenities
- Rate selection with pricing
- Full checkout with Stripe (handled by the widget)
- Customizable colors
- Lucide icons (shadcn-style)

## Installation

### NPM

```bash
npm install @nuitee/booking-widget
```

### Yarn

```bash
yarn add @nuitee/booking-widget
```

### PNPM

```bash
pnpm add @nuitee/booking-widget
```

### With React

```bash
npm install @nuitee/booking-widget react react-dom lucide-react
```

### With Vue

```bash
npm install @nuitee/booking-widget vue lucide-vue-next
```

*(Use `lucide-vue-next` for Vue 3 or the appropriate Lucide Vue package for your version.)*

---

## Usage

### Vanilla JavaScript (ES modules)

```javascript
import BookingWidget from '@nuitee/booking-widget';
import '@nuitee/booking-widget/css';

const widget = new BookingWidget({
  containerId: 'booking-widget-container',
  propertyKey: 'your-property-key',  // optional; omit for demo data
  colors: {
    background: '#1a1a1a',
    text: '#e0e0e0',
    primary: '#3b82f6',
    primaryText: '#ffffff'
  },
  onOpen: () => console.log('widgetOpened'),
  onClose: () => console.log('Widget closed'),
  onComplete: (bookingData) => console.log('Booking completed', bookingData)
});

widget.open();
```

### Vanilla JavaScript (CommonJS)

```javascript
const BookingWidget = require('@nuitee/booking-widget');
require('@nuitee/booking-widget/css');

const widget = new BookingWidget({
  containerId: 'booking-widget-container',
  propertyKey: 'your-property-key'
});

widget.open();
```

### Vanilla JavaScript (standalone script)

No bundler: load the script and CSS from the CDN, then create the widget.

```html
<link rel="stylesheet" href="https://cdn.thehotelplanet.com/booking-widget/v1.0.14/dist/booking-widget.css">
<script src="https://cdn.thehotelplanet.com/booking-widget/v1.0.14/dist/booking-widget-standalone.js"></script>

<div id="booking-widget-container"></div>

<script>
  const widget = new BookingWidget({
    containerId: 'booking-widget-container',
    cssUrl: 'https://cdn.thehotelplanet.com/booking-widget/v1.0.14/dist/booking-widget.css',
    propertyKey: 'your-property-key',
    onOpen: () => console.log('Opened'),
    onClose: () => console.log('Closed'),
    onComplete: (data) => console.log('Completed', data)
  });
  widget.init();
  widget.open();
</script>
```

### React

```jsx
import { useState } from 'react';
import BookingWidget from '@nuitee/booking-widget/react';
import '@nuitee/booking-widget/css';

function App() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsOpen(true)}>Book now</button>
      <BookingWidget
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        propertyKey="your-property-key"
        colors={{
          background: '#1a1a1a',
          text: '#e0e0e0',
          primary: '#3b82f6',
          primaryText: '#ffffff'
        }}
        onComplete={(data) => {
          console.log('Booking completed', data);
        }}
      />
    </>
  );
}
```

### Vue

```vue
<template>
  <div>
    <button @click="isOpen = true">Book now</button>
    <BookingWidget
      :is-open="isOpen"
      :property-key="propertyKey"
      :colors="customColors"
      @close="isOpen = false"
      @complete="handleComplete"
    />
  </div>
</template>

<script>
import BookingWidget from '@nuitee/booking-widget/vue';
import '@nuitee/booking-widget/css';

export default {
  components: { BookingWidget },
  data() {
    return {
      isOpen: false,
      propertyKey: 'your-property-key',
      customColors: {
        background: '#1a1a1a',
        text: '#e0e0e0',
        primary: '#3b82f6',
        primaryText: '#ffffff'
      }
    };
  },
  methods: {
    handleComplete(data) {
      console.log('Booking completed', data);
    }
  }
};
</script>
```

---

## Property key and data

- **Real rooms/rates/booking:** pass `propertyKey` (string) so the widget can load data for that property. Omit it to use built-in demo data.
- **Vanilla:** `new BookingWidget({ propertyKey: '...', ... })`
- **React:** `<BookingWidget propertyKey="..." ... />`
- **Vue:** `<BookingWidget :property-key="propertyKey" ... />`

API base URLs, Stripe, and related config are provided by the widget at runtime; you do not configure them in your app.

---

## API reference

### Constructor options (Vanilla JS)

| Option | Type | Description |
|--------|------|-------------|
| `containerId` | string | ID of the container element (default: `'booking-widget-container'`) |
| `cssUrl` | string | URL to the CSS file (optional if CSS is already loaded) |
| `propertyKey` | string | Property key for real data; omit for demo |
| `onOpen` | function | Callback when the widget opens |
| `onClose` | function | Callback when the widget closes |
| `onComplete` | function | Callback when booking is completed `(bookingData) => void` |
| `colors` | object | `{ background, text, primary, primaryText }` |

### React / Vue props

| Prop | Type | Description |
|------|------|-------------|
| `isOpen` | boolean | Controls widget visibility |
| `onClose` | function | Called when the user closes the widget |
| `onComplete` | function | Called when booking is completed |
| `onOpen` | function | Optional; called when the widget opens |
| `propertyKey` | string | Property key for real data; omit for demo |
| `colors` | object | Optional; same shape as above |

### Vanilla methods

- `open()` — open the modal (calls `init()` if needed)
- `close()` — close the modal
- `goToStep(step)` — go to step: `'dates'`, `'rooms'`, `'rates'`, `'checkout'`, `'confirmation'`
- `init()` — mount the widget into the container (required for standalone before `open()`)

---

## Import paths

- `@nuitee/booking-widget` — main entry (vanilla JS)
- `@nuitee/booking-widget/react` — React component
- `@nuitee/booking-widget/vue` — Vue component
- `@nuitee/booking-widget/css` — styles
- `@nuitee/booking-widget/standalone` — standalone script entry

---

## Examples

- `index.html` — vanilla integration
- `examples/react-app/` — React app example
- `examples/vue-app/` — Vue app example

See **[USAGE.md](./USAGE.md)** for more detailed usage by framework.

---

## Development

```bash
npm install
npm run build
npm run dev
```

## License

MIT