@balby/booking-search 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +254 -0
- package/dist/index.css +1668 -0
- package/dist/index.js +12681 -0
- package/package.json +84 -0
- package/src/components/booking-search/date-range-picker.tsx +240 -0
- package/src/components/booking-search/guest-selector.tsx +181 -0
- package/src/components/booking-search/index.tsx +199 -0
- package/src/components/booking-search/location-combobox.tsx +93 -0
- package/src/components/booking-search/tests/date-range-picker.test.tsx +308 -0
- package/src/components/booking-search/tests/guest-selector.test.tsx +358 -0
- package/src/components/booking-search/tests/index.test.tsx +424 -0
- package/src/components/booking-search/tests/location-combobox.test.tsx +263 -0
- package/src/components/booking-search/ui/command.tsx +100 -0
- package/src/components/booking-search/ui/dialog.tsx +88 -0
- package/src/components/booking-search/ui/popover.tsx +28 -0
- package/src/demo.tsx +198 -0
- package/src/index.ts +27 -0
- package/src/lib/utils.ts +6 -0
- package/src/styles/globals.css +158 -0
- package/src/styles/output.css +4 -0
- package/src/styles/output.css.map +1 -0
- package/src/types/booking.ts +155 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 (albertobarrago@gmail.com) alBz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# BookingSearch (React)
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@booking-search/react)
|
|
4
|
+
[](./coverage)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](./src/components/booking-search/tests/)
|
|
8
|
+
|
|
9
|
+
A framework-agnostic, high-performance, and accessible React component for booking searches, inspired by the Booking.com search bar.
|
|
10
|
+
|
|
11
|
+
## ๐ Features
|
|
12
|
+
|
|
13
|
+
* โ
**Fully Agnostic**: Data flows in via props, results flow out via callbacks
|
|
14
|
+
* โ
**TypeScript First**: Complete, type-safe interfaces
|
|
15
|
+
* โ
**Accessibility**: Full keyboard navigation and ARIA attributes (Radix UI)
|
|
16
|
+
* โ
**Responsive**: Horizontal layout on desktop, Dialog on mobile
|
|
17
|
+
* โ
**Modular Components**:
|
|
18
|
+
|
|
19
|
+
* `LocationCombobox`: Location search using the Command pattern (Shadcn)
|
|
20
|
+
* `DateRangePicker`: Calendar with inline prices and availability
|
|
21
|
+
* `GuestSelector`: Stepper for adults and children
|
|
22
|
+
* โ
**Styled with Tailwind CSS**: Modern and easily customizable
|
|
23
|
+
* โ
**Built with Bun**: Optimized performance
|
|
24
|
+
|
|
25
|
+
## ๐ฆ Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @balby/booking-search
|
|
29
|
+
# or
|
|
30
|
+
yarn add @balby/booking-search
|
|
31
|
+
# or
|
|
32
|
+
bun add @balby/booking-search
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Peer Dependencies
|
|
36
|
+
This component requires React 19 and Tailwind CSS. Make sure they are installed:
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install react react-dom tailwindcss
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## ๐ฏ Quick Start
|
|
44
|
+
|
|
45
|
+
### Basic Usage
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { BookingSearch } from '@booking-search/react'
|
|
49
|
+
import type { BookingSearchPayload, Location, AvailabilityDay } from '@booking-search/react'
|
|
50
|
+
|
|
51
|
+
const locations: Location[] = [
|
|
52
|
+
{ id: '1', name: 'Rome, Italy', type: 'City', countryCode: 'IT' },
|
|
53
|
+
{ id: '2', name: 'Florence, Italy', type: 'City', countryCode: 'IT' },
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
const availability: AvailabilityDay[] = [
|
|
57
|
+
{ date: '2025-01-15', price: 120, isAvailable: true },
|
|
58
|
+
{ date: '2025-01-16', price: 150, isAvailable: true },
|
|
59
|
+
{ date: '2025-01-17', price: 0, isAvailable: false },
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
function App() {
|
|
63
|
+
const handleSearch = (payload: BookingSearchPayload) => {
|
|
64
|
+
console.log('Search:', payload)
|
|
65
|
+
// Send data to your backend or API
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<BookingSearch
|
|
70
|
+
locations={locations}
|
|
71
|
+
availability={availability}
|
|
72
|
+
onSearch={handleSearch}
|
|
73
|
+
searchButtonText="Search availability"
|
|
74
|
+
minNights={1}
|
|
75
|
+
maxAdults={10}
|
|
76
|
+
maxChildren={5}
|
|
77
|
+
/>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## ๐ API
|
|
83
|
+
|
|
84
|
+
### BookingSearchProps
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Description |
|
|
87
|
+
| --------------------- | ----------------------------------------- | ------------------------ | ------------------------------------------------ |
|
|
88
|
+
| `locations` | `Location[]` | **Required** | List of available locations for search |
|
|
89
|
+
| `availability` | `AvailabilityDay[]` | **Required** | Availability and prices by date |
|
|
90
|
+
| `onSearch` | `(payload: BookingSearchPayload) => void` | **Required** | Callback triggered when the user starts a search |
|
|
91
|
+
| `defaultValues` | `Partial<BookingSearchPayload>` | `undefined` | Initial values (optional) |
|
|
92
|
+
| `searchButtonText` | `string` | `"Search"` | Search button text |
|
|
93
|
+
| `locationPlaceholder` | `string` | `"Where are you going?"` | Placeholder for the location field |
|
|
94
|
+
| `minNights` | `number` | `1` | Minimum number of nights required |
|
|
95
|
+
| `maxAdults` | `number` | `30` | Maximum number of adults |
|
|
96
|
+
| `maxChildren` | `number` | `10` | Maximum number of children |
|
|
97
|
+
| `className` | `string` | `undefined` | Custom CSS class |
|
|
98
|
+
|
|
99
|
+
### TypeScript Interfaces
|
|
100
|
+
|
|
101
|
+
#### AvailabilityDay
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
interface AvailabilityDay {
|
|
105
|
+
date: string // ISO format (YYYY-MM-DD)
|
|
106
|
+
price: number // Price for this date
|
|
107
|
+
isAvailable: boolean // Availability
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Location
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
interface Location {
|
|
115
|
+
id: string
|
|
116
|
+
name: string
|
|
117
|
+
type?: string // Location type (city, hotel, etc.)
|
|
118
|
+
countryCode?: string // ISO country code
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### BookingSearchPayload
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
interface BookingSearchPayload {
|
|
126
|
+
location: Location | null
|
|
127
|
+
checkIn: Date | null
|
|
128
|
+
checkOut: Date | null
|
|
129
|
+
adults: number
|
|
130
|
+
children: number
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## ๐จ Customization
|
|
135
|
+
|
|
136
|
+
The component uses Tailwind CSS for styling. You can customize colors and themes via `tailwind.config.js`:
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
export default {
|
|
140
|
+
theme: {
|
|
141
|
+
extend: {
|
|
142
|
+
colors: {
|
|
143
|
+
// Your custom colors
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## ๐ง Standalone Sub-components
|
|
151
|
+
|
|
152
|
+
You can also use individual sub-components:
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { LocationCombobox, DateRangePicker, GuestSelector } from '@booking-search/react';
|
|
156
|
+
|
|
157
|
+
// LocationCombobox
|
|
158
|
+
<LocationCombobox
|
|
159
|
+
locations={locations}
|
|
160
|
+
value={selectedLocation}
|
|
161
|
+
onChange={setSelectedLocation}
|
|
162
|
+
/>
|
|
163
|
+
|
|
164
|
+
// DateRangePicker
|
|
165
|
+
<DateRangePicker
|
|
166
|
+
availability={availability}
|
|
167
|
+
value={{ from: checkIn, to: checkOut }}
|
|
168
|
+
onChange={setDateRange}
|
|
169
|
+
minNights={1}
|
|
170
|
+
/>
|
|
171
|
+
|
|
172
|
+
// GuestSelector
|
|
173
|
+
<GuestSelector
|
|
174
|
+
value={{ adults: 2, children: 0 }}
|
|
175
|
+
onChange={setGuests}
|
|
176
|
+
maxAdults={10}
|
|
177
|
+
maxChildren={5}
|
|
178
|
+
/>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## โฟ Accessibility
|
|
182
|
+
|
|
183
|
+
The component follows accessibility best practices:
|
|
184
|
+
|
|
185
|
+
* **Full keyboard navigation**: Tab, Enter, Escape, arrow keys
|
|
186
|
+
* **ARIA attributes**: All components include appropriate ARIA attributes
|
|
187
|
+
* **Screen reader friendly**: Labels and descriptions for all interactive elements
|
|
188
|
+
* **Focus management**: Focus trapping in popovers and dialogs
|
|
189
|
+
* **Responsive design**: Optimized for all devices
|
|
190
|
+
|
|
191
|
+
## ๐๏ธ Project Structure
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
BookingWidget/
|
|
195
|
+
โโโ src/
|
|
196
|
+
โ โโโ components/
|
|
197
|
+
โ โ โโโ booking-search/
|
|
198
|
+
โ โ โโโ index.tsx # Main component
|
|
199
|
+
โ โ โโโ location-combobox.tsx # Location combobox
|
|
200
|
+
โ โ โโโ date-range-picker.tsx # Date picker
|
|
201
|
+
โ โ โโโ guest-selector.tsx # Guest selector
|
|
202
|
+
โ โ โโโ ui/ # Base UI components (Shadcn)
|
|
203
|
+
โ โโโ types/
|
|
204
|
+
โ โ โโโ booking.ts # TypeScript interfaces
|
|
205
|
+
โ โโโ lib/
|
|
206
|
+
โ โ โโโ utils.ts # Utility functions
|
|
207
|
+
โ โโโ styles/
|
|
208
|
+
โ โ โโโ globals.css # Global styles
|
|
209
|
+
โ โโโ demo.tsx # Interactive demo
|
|
210
|
+
โ โโโ index.ts # Library entry point
|
|
211
|
+
โโโ index.html # Demo HTML
|
|
212
|
+
โโโ index.ts # Bun server
|
|
213
|
+
โโโ tailwind.config.js # Tailwind configuration
|
|
214
|
+
โโโ tsconfig.json # TypeScript configuration
|
|
215
|
+
โโโ package.json
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## ๐งช Testing
|
|
219
|
+
|
|
220
|
+
The project includes 63 tests with 94.73% coverage.
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# Run tests
|
|
225
|
+
npm test
|
|
226
|
+
|
|
227
|
+
# Run tests with coverage
|
|
228
|
+
npm run test:coverage
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## ๐ฆ Production Build
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
bun run build
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The optimized bundle will be available in the `dist/` folder.
|
|
238
|
+
|
|
239
|
+
## ๐ค Contributing
|
|
240
|
+
|
|
241
|
+
Contributions, issues, and feature requests are welcome!
|
|
242
|
+
|
|
243
|
+
## ๐ License
|
|
244
|
+
|
|
245
|
+
MIT
|
|
246
|
+
|
|
247
|
+
## ๐ Credits
|
|
248
|
+
|
|
249
|
+
* Inspired by [Booking.com](https://www.booking.com)
|
|
250
|
+
* UI components: [Shadcn/UI](https://ui.shadcn.com)
|
|
251
|
+
* Primitives: [Radix UI](https://www.radix-ui.com)
|
|
252
|
+
* Icons: [Lucide React](https://lucide.dev)
|
|
253
|
+
* Date picker: [react-day-picker](https://react-day-picker.js.org)
|
|
254
|
+
* Built with [Bun](https://bun.sh)
|