pxsol-booking-search-widget
v0.3.10
Published
Embeddable booking engine search widget with React and Web Component builds.
Maintainers
Readme
@pxsol/booking-search-widget
Embeddable booking engine search widget that ships a React component and a framework-agnostic Web Component. Both builds reuse the same headless state utilities and formatting helpers so you can embed the widget inside modern React apps or legacy pages with a single configuration.
Features
- Airbnb-style search form with date range, guests/rooms, POS, language, currency, and product selector.
- Emits stable lifecycle events (
ready,change,validate_error,search_start,search_success,search_error). - Integrates with the Pxsol Search API via client-side
fetchcalls using a public token. - Shadow DOM styling for the Web Component with themable CSS variables (
--yw-bg,--yw-fg,--yw-accent). - Dual outputs: React (ESM + CJS, peer React) and Custom Element (ESM + IIFE legacy bundle).
- Headless helpers for formatting, validation, and request payload creation.
Installation
npm install @pxsol/booking-search-widget
# or
pnpm add @pxsol/booking-search-widgetScripts
npm run build– produce all distribution bundles viatsup.npm run dev– watch builds for local iteration.npm run typecheck– static analysis usingtsc --noEmit.npm run demo– build once and launch a static server at http://localhost:4173.
Local demo
npm run demoThe command runs a one-off build and serves demo/index.html plus the compiled bundles from dist/. Visit http://localhost:4173 to interact with the widget, inspect emitted events, and iterate on configuration quickly.
React usage
import React from 'react';
import { BookingSearchWidget } from 'pxsol-booking-search-widget';
// ✅ CSS styles are automatically included - no need to import CSS separately
const config = {
token: 'PUBLIC_SEARCH_TOKEN',
theme: 'light',
locale: 'es',
currency: 'ARS',
pos: 'HotelEscuela',
productId: 2475,
initialStart: '2024-07-01',
initialEnd: '2024-07-05',
onEvent: (event) => {
if (event.type === 'search_success') {
console.log('Search result', event.payload);
}
},
};
export function Demo() {
return <BookingSearchWidget {...config} />;
}Web Component usage
Modern browsers (ES Modules)
<script type="module">
import 'pxsol-booking-search-widget/wc';
</script>
<your-widget
token="PUBLIC_SEARCH_TOKEN"
theme="dark"
locale="es"
currency="ARS"
pos="HotelEscuela"
product-id="2475"
initial-start="2024-07-01"
initial-end="2024-07-05"
></your-widget>
<script>
document.querySelector('your-widget').addEventListener('yw:event', (event) => {
console.log('Widget event', event.detail);
});
</script>Legacy pages (IIFE bundle)
<script src="/dist/your-widget.iife.js"></script>
<your-widget token="PUBLIC_SEARCH_TOKEN"></your-widget>The IIFE build self-registers the custom element and exposes a registerYourWidget() helper when needed.
Minimal demo snippet
See demo/index.html for a copy-paste ready template that logs widget events to the screen. The page is served automatically by npm run demo.
For detailed integration guides (React via npm and plain HTML via CDN), read docs/INTEGRATION.md.
Events
| Event | Payload | Description |
| --- | --- | --- |
| ready | { state: WidgetState } | Widget is mounted and hydrated. |
| change | { state: WidgetState } | Any user change to the internal state. |
| validate_error | { valid: false; errors: Record<string, string> } | Validation failed prior to calling the API. |
| search_start | SearchRequest | Outgoing payload before calling the API. |
| search_success | { request: SearchRequest; response: SearchResponse } | Successful response from the API. |
| search_error | { request: SearchRequest; error: Error } | Network or API error. |
On the Web Component build these events are dispatched through CustomEvent('yw:event', { detail }) with the widget event in detail.
Theming
Override the following CSS variables on the host element:
--yw-bg– primary surface background.--yw-fg– text color.--yw-accent– primary button color.
Example:
your-widget {
--yw-bg: #0f172a;
--yw-fg: #e2e8f0;
--yw-accent: #38bdf8;
}Search API integration
The widget calls POST https://gateway-prod.pxsol.com/v2/search with a public bearer token. Responses include booking_engine_url that is automatically opened when redirect is enabled. All requests are client-side, so ensure the provided token has the correct CORS permissions. Do not embed private keys or secrets in markup.
Security & CSP
- Ship the ESM build and apply a CSP like
script-src 'self' https://cdn.yourdomain.comso the widget loads from a trusted CDN. - Avoid
unsafe-eval; the bundles are plain ESM/CJS/IIFE with no dynamic code execution. - When embedding in PCI-sensitive contexts, consider wrapping the Web Component in an iframe with a hardened
sandboxattribute and communicate viapostMessage.
Change log
See CHANGELOG.md for release notes.
