@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
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Command as CommandPrimitive } from "cmdk"
|
|
3
|
+
import { Search } from "lucide-react"
|
|
4
|
+
import { cn } from "../../../lib/utils"
|
|
5
|
+
|
|
6
|
+
const Command = React.forwardRef<
|
|
7
|
+
React.ElementRef<typeof CommandPrimitive>,
|
|
8
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
|
9
|
+
>(({ className, ...props }, ref) => (
|
|
10
|
+
<CommandPrimitive
|
|
11
|
+
ref={ref}
|
|
12
|
+
className={cn(
|
|
13
|
+
"flex h-full w-full flex-col overflow-hidden rounded-md bg-white text-slate-950",
|
|
14
|
+
className
|
|
15
|
+
)}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
))
|
|
19
|
+
Command.displayName = CommandPrimitive.displayName
|
|
20
|
+
|
|
21
|
+
const CommandInput = React.forwardRef<
|
|
22
|
+
React.ElementRef<typeof CommandPrimitive.Input>,
|
|
23
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
|
24
|
+
>(({ className, ...props }, ref) => (
|
|
25
|
+
<div className="flex items-center border-b border-slate-200 px-3" cmdk-input-wrapper="">
|
|
26
|
+
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
27
|
+
<CommandPrimitive.Input
|
|
28
|
+
ref={ref}
|
|
29
|
+
className={cn(
|
|
30
|
+
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-slate-500 disabled:cursor-not-allowed disabled:opacity-50",
|
|
31
|
+
className
|
|
32
|
+
)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
36
|
+
))
|
|
37
|
+
CommandInput.displayName = CommandPrimitive.Input.displayName
|
|
38
|
+
|
|
39
|
+
const CommandList = React.forwardRef<
|
|
40
|
+
React.ElementRef<typeof CommandPrimitive.List>,
|
|
41
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
|
42
|
+
>(({ className, ...props }, ref) => (
|
|
43
|
+
<CommandPrimitive.List
|
|
44
|
+
ref={ref}
|
|
45
|
+
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
))
|
|
49
|
+
CommandList.displayName = CommandPrimitive.List.displayName
|
|
50
|
+
|
|
51
|
+
const CommandEmpty = React.forwardRef<
|
|
52
|
+
React.ElementRef<typeof CommandPrimitive.Empty>,
|
|
53
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
|
54
|
+
>((props, ref) => (
|
|
55
|
+
<CommandPrimitive.Empty
|
|
56
|
+
ref={ref}
|
|
57
|
+
className="py-6 text-center text-sm text-slate-500"
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
))
|
|
61
|
+
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
|
|
62
|
+
|
|
63
|
+
const CommandGroup = React.forwardRef<
|
|
64
|
+
React.ElementRef<typeof CommandPrimitive.Group>,
|
|
65
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
|
66
|
+
>(({ className, ...props }, ref) => (
|
|
67
|
+
<CommandPrimitive.Group
|
|
68
|
+
ref={ref}
|
|
69
|
+
className={cn(
|
|
70
|
+
"overflow-hidden p-1 text-slate-950 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-slate-500",
|
|
71
|
+
className
|
|
72
|
+
)}
|
|
73
|
+
{...props}
|
|
74
|
+
/>
|
|
75
|
+
))
|
|
76
|
+
CommandGroup.displayName = CommandPrimitive.Group.displayName
|
|
77
|
+
|
|
78
|
+
const CommandItem = React.forwardRef<
|
|
79
|
+
React.ElementRef<typeof CommandPrimitive.Item>,
|
|
80
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
|
81
|
+
>(({ className, ...props }, ref) => (
|
|
82
|
+
<CommandPrimitive.Item
|
|
83
|
+
ref={ref}
|
|
84
|
+
className={cn(
|
|
85
|
+
"relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-blue-50 data-[selected=true]:text-blue-900 data-[disabled=true]:opacity-50",
|
|
86
|
+
className
|
|
87
|
+
)}
|
|
88
|
+
{...props}
|
|
89
|
+
/>
|
|
90
|
+
))
|
|
91
|
+
CommandItem.displayName = CommandPrimitive.Item.displayName
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
Command,
|
|
95
|
+
CommandInput,
|
|
96
|
+
CommandList,
|
|
97
|
+
CommandEmpty,
|
|
98
|
+
CommandGroup,
|
|
99
|
+
CommandItem,
|
|
100
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
|
3
|
+
import { X } from "lucide-react"
|
|
4
|
+
import { cn } from "../../../lib/utils"
|
|
5
|
+
|
|
6
|
+
const Dialog = DialogPrimitive.Root
|
|
7
|
+
const DialogTrigger = DialogPrimitive.Trigger
|
|
8
|
+
const DialogPortal = DialogPrimitive.Portal
|
|
9
|
+
const DialogClose = DialogPrimitive.Close
|
|
10
|
+
|
|
11
|
+
const DialogOverlay = React.forwardRef<
|
|
12
|
+
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
|
13
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
14
|
+
>(({ className, ...props }, ref) => (
|
|
15
|
+
<DialogPrimitive.Overlay
|
|
16
|
+
ref={ref}
|
|
17
|
+
className={cn(
|
|
18
|
+
"fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
))
|
|
24
|
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
|
25
|
+
|
|
26
|
+
const DialogContent = React.forwardRef<
|
|
27
|
+
React.ElementRef<typeof DialogPrimitive.Content>,
|
|
28
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
|
29
|
+
>(({ className, children, ...props }, ref) => (
|
|
30
|
+
<DialogPortal>
|
|
31
|
+
<DialogOverlay />
|
|
32
|
+
<DialogPrimitive.Content
|
|
33
|
+
ref={ref}
|
|
34
|
+
className={cn(
|
|
35
|
+
"fixed left-[50%] top-[50%] z-50 w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-slate-200 bg-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
|
36
|
+
className
|
|
37
|
+
)}
|
|
38
|
+
{...props}
|
|
39
|
+
>
|
|
40
|
+
{children}
|
|
41
|
+
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-slate-100">
|
|
42
|
+
<X className="h-4 w-4" />
|
|
43
|
+
<span className="sr-only">Chiudi</span>
|
|
44
|
+
</DialogPrimitive.Close>
|
|
45
|
+
</DialogPrimitive.Content>
|
|
46
|
+
</DialogPortal>
|
|
47
|
+
))
|
|
48
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName
|
|
49
|
+
|
|
50
|
+
const DialogHeader = ({
|
|
51
|
+
className,
|
|
52
|
+
...props
|
|
53
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
54
|
+
<div
|
|
55
|
+
className={cn(
|
|
56
|
+
"flex flex-col space-y-1.5 text-center sm:text-left",
|
|
57
|
+
className
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
)
|
|
62
|
+
DialogHeader.displayName = "DialogHeader"
|
|
63
|
+
|
|
64
|
+
const DialogTitle = React.forwardRef<
|
|
65
|
+
React.ElementRef<typeof DialogPrimitive.Title>,
|
|
66
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
|
67
|
+
>(({ className, ...props }, ref) => (
|
|
68
|
+
<DialogPrimitive.Title
|
|
69
|
+
ref={ref}
|
|
70
|
+
className={cn(
|
|
71
|
+
"text-lg font-semibold leading-none tracking-tight text-slate-900",
|
|
72
|
+
className
|
|
73
|
+
)}
|
|
74
|
+
{...props}
|
|
75
|
+
/>
|
|
76
|
+
))
|
|
77
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
Dialog,
|
|
81
|
+
DialogPortal,
|
|
82
|
+
DialogOverlay,
|
|
83
|
+
DialogClose,
|
|
84
|
+
DialogTrigger,
|
|
85
|
+
DialogContent,
|
|
86
|
+
DialogHeader,
|
|
87
|
+
DialogTitle,
|
|
88
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
|
3
|
+
import { cn } from "../../../lib/utils"
|
|
4
|
+
|
|
5
|
+
const Popover = PopoverPrimitive.Root
|
|
6
|
+
const PopoverTrigger = PopoverPrimitive.Trigger
|
|
7
|
+
const PopoverAnchor = PopoverPrimitive.Anchor
|
|
8
|
+
|
|
9
|
+
const PopoverContent = React.forwardRef<
|
|
10
|
+
React.ElementRef<typeof PopoverPrimitive.Content>,
|
|
11
|
+
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
|
12
|
+
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
|
13
|
+
<PopoverPrimitive.Portal>
|
|
14
|
+
<PopoverPrimitive.Content
|
|
15
|
+
ref={ref}
|
|
16
|
+
align={align}
|
|
17
|
+
sideOffset={sideOffset}
|
|
18
|
+
className={cn(
|
|
19
|
+
"z-50 w-72 rounded-md border border-slate-200 bg-white p-4 text-slate-950 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
20
|
+
className
|
|
21
|
+
)}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
</PopoverPrimitive.Portal>
|
|
25
|
+
))
|
|
26
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
|
27
|
+
|
|
28
|
+
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
package/src/demo.tsx
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { createRoot } from "react-dom/client"
|
|
3
|
+
import { BookingSearch } from "./components/booking-search"
|
|
4
|
+
import type { BookingSearchPayload, SearchLocation, AvailabilityDay } from "./types/booking"
|
|
5
|
+
import "./styles/output.css"
|
|
6
|
+
|
|
7
|
+
// Sample location data
|
|
8
|
+
const sampleLocations: SearchLocation[] = [
|
|
9
|
+
{
|
|
10
|
+
id: "1",
|
|
11
|
+
name: "Roma, Italia",
|
|
12
|
+
type: "Città",
|
|
13
|
+
countryCode: "IT",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: "2",
|
|
17
|
+
name: "Firenze, Italia",
|
|
18
|
+
type: "Città",
|
|
19
|
+
countryCode: "IT",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: "3",
|
|
23
|
+
name: "Venezia, Italia",
|
|
24
|
+
type: "Città",
|
|
25
|
+
countryCode: "IT",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "4",
|
|
29
|
+
name: "Milano, Italia",
|
|
30
|
+
type: "Città",
|
|
31
|
+
countryCode: "IT",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "5",
|
|
35
|
+
name: "Napoli, Italia",
|
|
36
|
+
type: "Città",
|
|
37
|
+
countryCode: "IT",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "6",
|
|
41
|
+
name: "Torino, Italia",
|
|
42
|
+
type: "Città",
|
|
43
|
+
countryCode: "IT",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "7",
|
|
47
|
+
name: "Cagliari, Italia",
|
|
48
|
+
type: "Città",
|
|
49
|
+
countryCode: "IT",
|
|
50
|
+
},
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
// Function to generate sample availability data
|
|
54
|
+
function generateAvailability(): AvailabilityDay[] {
|
|
55
|
+
const availability: AvailabilityDay[] = []
|
|
56
|
+
const today = new Date()
|
|
57
|
+
|
|
58
|
+
// Generate 90 days of availability
|
|
59
|
+
for (let i = 0; i < 90; i++) {
|
|
60
|
+
const date = new Date(today)
|
|
61
|
+
date.setDate(date.getDate() + i)
|
|
62
|
+
|
|
63
|
+
// Simulate random availability
|
|
64
|
+
const isWeekend = date.getDay() === 0 || date.getDay() === 6
|
|
65
|
+
const basePrice = isWeekend ? 150 : 100
|
|
66
|
+
const priceVariation = Math.floor(Math.random() * 50)
|
|
67
|
+
const isAvailable = Math.random() > 0.1 // 90% availability
|
|
68
|
+
|
|
69
|
+
availability.push({
|
|
70
|
+
date: date.toISOString().split('T')[0] || "",
|
|
71
|
+
price: basePrice + priceVariation,
|
|
72
|
+
isAvailable,
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return availability
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function Demo() {
|
|
80
|
+
const [availability] = React.useState(generateAvailability())
|
|
81
|
+
|
|
82
|
+
const handleSearch = (payload: BookingSearchPayload) => {
|
|
83
|
+
console.log("🔍 Search performed:", payload)
|
|
84
|
+
|
|
85
|
+
if (payload.checkIn && payload.checkOut) {
|
|
86
|
+
const checkInStr = payload.checkIn.toISOString().split('T')[0]
|
|
87
|
+
const checkOutStr = payload.checkOut.toISOString().split('T')[0]
|
|
88
|
+
|
|
89
|
+
const relevantDays = availability.filter(day => {
|
|
90
|
+
if(checkInStr && checkOutStr)
|
|
91
|
+
return day.date >= checkInStr && day.date < checkOutStr
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
const totalPrice = relevantDays.reduce((sum, day) => sum + day.price, 0)
|
|
95
|
+
|
|
96
|
+
console.log(`💰 Estimated total price: €${totalPrice}`)
|
|
97
|
+
console.log(`📅 Number of nights: ${relevantDays.length}`)
|
|
98
|
+
|
|
99
|
+
alert(
|
|
100
|
+
`Search completed!\n\n` +
|
|
101
|
+
`📍 Destination: ${payload.location?.name || 'Not selected'}\n` +
|
|
102
|
+
`📅 Check-in: ${payload.checkIn.toLocaleDateString('it-IT')}\n` +
|
|
103
|
+
`📅 Check-out: ${payload.checkOut.toLocaleDateString('it-IT')}\n` +
|
|
104
|
+
`👥 Guests: ${payload.adults} adults, ${payload.children} children\n` +
|
|
105
|
+
`🌙 Nights: ${relevantDays.length}\n` +
|
|
106
|
+
`💰 Estimated price: €${totalPrice}`
|
|
107
|
+
)
|
|
108
|
+
} else {
|
|
109
|
+
alert("Please select check-in and check-out dates")
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 p-4 md:p-8">
|
|
115
|
+
<div className="mx-auto max-w-6xl">
|
|
116
|
+
<div className="mb-8 text-center">
|
|
117
|
+
<h1 className="text-4xl font-bold text-slate-900 md:text-5xl">
|
|
118
|
+
BookingSearch Widget
|
|
119
|
+
</h1>
|
|
120
|
+
<p className="mt-2 text-lg text-slate-600">
|
|
121
|
+
Agnostic React component for booking search
|
|
122
|
+
</p>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<BookingSearch
|
|
126
|
+
locations={sampleLocations}
|
|
127
|
+
availability={availability}
|
|
128
|
+
onSearch={handleSearch}
|
|
129
|
+
minNights={2}
|
|
130
|
+
maxAdults={10}
|
|
131
|
+
maxChildren={5}
|
|
132
|
+
/>
|
|
133
|
+
|
|
134
|
+
<div className="mt-8 rounded-lg bg-white p-6 shadow-lg">
|
|
135
|
+
<h2 className="mb-4 text-xl font-semibold text-slate-900">
|
|
136
|
+
📋 Features
|
|
137
|
+
</h2>
|
|
138
|
+
<ul className="space-y-2 text-slate-700">
|
|
139
|
+
<li className="flex items-start gap-2">
|
|
140
|
+
<span className="text-green-500">✓</span>
|
|
141
|
+
<span><strong>Location Combobox:</strong> Smart search with Command pattern (Shadcn)</span>
|
|
142
|
+
</li>
|
|
143
|
+
<li className="flex items-start gap-2">
|
|
144
|
+
<span className="text-green-500">✓</span>
|
|
145
|
+
<span><strong>Date Range Picker:</strong> Calendar with inline prices and availability</span>
|
|
146
|
+
</li>
|
|
147
|
+
<li className="flex items-start gap-2">
|
|
148
|
+
<span className="text-green-500">✓</span>
|
|
149
|
+
<span><strong>Guest Selector:</strong> Stepper for adults and children</span>
|
|
150
|
+
</li>
|
|
151
|
+
<li className="flex items-start gap-2">
|
|
152
|
+
<span className="text-green-500">✓</span>
|
|
153
|
+
<span><strong>Responsive Design:</strong> Horizontal bar on desktop, Dialog on mobile</span>
|
|
154
|
+
</li>
|
|
155
|
+
<li className="flex items-start gap-2">
|
|
156
|
+
<span className="text-green-500">✓</span>
|
|
157
|
+
<span><strong>Accessibility:</strong> ARIA attributes, full keyboard navigation</span>
|
|
158
|
+
</li>
|
|
159
|
+
<li className="flex items-start gap-2">
|
|
160
|
+
<span className="text-green-500">✓</span>
|
|
161
|
+
<span><strong>Type-Safe:</strong> TypeScript with complete interfaces</span>
|
|
162
|
+
</li>
|
|
163
|
+
<li className="flex items-start gap-2">
|
|
164
|
+
<span className="text-green-500">✓</span>
|
|
165
|
+
<span><strong>Agnostic:</strong> Input data via props, results via callback</span>
|
|
166
|
+
</li>
|
|
167
|
+
</ul>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<div className="mt-6 rounded-lg bg-slate-900 p-6 text-white">
|
|
171
|
+
<h2 className="mb-4 text-xl font-semibold">💻 Usage</h2>
|
|
172
|
+
<pre className="overflow-x-auto text-sm">
|
|
173
|
+
<code>{`import { BookingSearch } from './components/booking-search'
|
|
174
|
+
import type { BookingSearchPayload } from './types/booking'
|
|
175
|
+
|
|
176
|
+
function App() {
|
|
177
|
+
const handleSearch = (payload: BookingSearchPayload) => {
|
|
178
|
+
// Handle the search
|
|
179
|
+
console.log(payload)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<BookingSearch
|
|
184
|
+
locations={locations}
|
|
185
|
+
availability={availability}
|
|
186
|
+
onSearch={handleSearch}
|
|
187
|
+
/>
|
|
188
|
+
)
|
|
189
|
+
}`}</code>
|
|
190
|
+
</pre>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const root = createRoot(document.getElementById("root")!)
|
|
198
|
+
root.render(<Demo />)
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BookingSearch Component
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import "./styles/output.css"
|
|
6
|
+
|
|
7
|
+
export { BookingSearch } from "./components/booking-search"
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
LocationCombobox,
|
|
11
|
+
DateRangePicker,
|
|
12
|
+
GuestSelector,
|
|
13
|
+
} from "./components/booking-search"
|
|
14
|
+
|
|
15
|
+
export type {
|
|
16
|
+
AvailabilityDay,
|
|
17
|
+
SearchLocation,
|
|
18
|
+
GuestData,
|
|
19
|
+
BookingSearchPayload,
|
|
20
|
+
BookingSearchProps,
|
|
21
|
+
LocationComboboxProps,
|
|
22
|
+
DateRangePickerProps,
|
|
23
|
+
GuestSelectorProps,
|
|
24
|
+
GuestStepperProps,
|
|
25
|
+
} from "./types/booking"
|
|
26
|
+
|
|
27
|
+
export { cn } from "./lib/utils"
|
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
@import "react-day-picker/dist/style.css";
|
|
2
|
+
|
|
3
|
+
@tailwind base;
|
|
4
|
+
@tailwind components;
|
|
5
|
+
@tailwind utilities;
|
|
6
|
+
|
|
7
|
+
@layer base {
|
|
8
|
+
:root {
|
|
9
|
+
--background: 0 0% 100%;
|
|
10
|
+
--foreground: 222.2 84% 4.9%;
|
|
11
|
+
--card: 0 0% 100%;
|
|
12
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
13
|
+
--popover: 0 0% 100%;
|
|
14
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
15
|
+
--primary: 221.2 83.2% 53.3%;
|
|
16
|
+
--primary-foreground: 210 40% 98%;
|
|
17
|
+
--secondary: 210 40% 96.1%;
|
|
18
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
19
|
+
--muted: 210 40% 96.1%;
|
|
20
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
21
|
+
--accent: 210 40% 96.1%;
|
|
22
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
23
|
+
--destructive: 0 84.2% 60.2%;
|
|
24
|
+
--destructive-foreground: 210 40% 98%;
|
|
25
|
+
--border: 214.3 31.8% 91.4%;
|
|
26
|
+
--input: 214.3 31.8% 91.4%;
|
|
27
|
+
--ring: 221.2 83.2% 53.3%;
|
|
28
|
+
--radius: 0.5rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
* {
|
|
32
|
+
@apply border-border;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
body {
|
|
36
|
+
@apply bg-background text-foreground;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* React Day Picker Custom Styles */
|
|
41
|
+
.rdp {
|
|
42
|
+
--rdp-cell-size: 56px;
|
|
43
|
+
--rdp-accent-color: #3b82f6;
|
|
44
|
+
--rdp-background-color: #eff6ff;
|
|
45
|
+
margin: 0;
|
|
46
|
+
font-family: inherit;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.rdp-custom {
|
|
50
|
+
--rdp-cell-size: 56px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.rdp-months {
|
|
54
|
+
gap: 2rem;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.rdp-month {
|
|
58
|
+
margin: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.rdp-table {
|
|
62
|
+
max-width: none;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.rdp-caption {
|
|
66
|
+
display: flex;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
padding: 0.5rem 0 1rem;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.rdp-caption_label {
|
|
72
|
+
font-size: 1rem;
|
|
73
|
+
font-weight: 600;
|
|
74
|
+
color: #0f172a;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.rdp-head_cell {
|
|
78
|
+
font-weight: 500;
|
|
79
|
+
font-size: 0.875rem;
|
|
80
|
+
color: #64748b;
|
|
81
|
+
text-transform: uppercase;
|
|
82
|
+
padding-bottom: 0.5rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.rdp-cell {
|
|
86
|
+
width: 56px;
|
|
87
|
+
height: 56px;
|
|
88
|
+
padding: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.rdp-day {
|
|
92
|
+
overflow: visible !important;
|
|
93
|
+
border-radius: 0.5rem !important;
|
|
94
|
+
border: none !important;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.rdp-button {
|
|
98
|
+
width: 100%;
|
|
99
|
+
height: 100%;
|
|
100
|
+
border-radius: 0.5rem;
|
|
101
|
+
font-size: 0.875rem;
|
|
102
|
+
transition: all 0.2s;
|
|
103
|
+
position: relative;
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
106
|
+
align-items: center;
|
|
107
|
+
justify-content: center;
|
|
108
|
+
gap: 4px;
|
|
109
|
+
padding: 4px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.rdp-button:hover:not(.rdp-day_disabled) {
|
|
113
|
+
background-color: #f1f5f9;
|
|
114
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.rdp-day_range_start,
|
|
118
|
+
.rdp-day_range_end {
|
|
119
|
+
background-color: #3b82f6 !important;
|
|
120
|
+
color: white !important;
|
|
121
|
+
font-weight: 600;
|
|
122
|
+
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.rdp-day_range_start span,
|
|
126
|
+
.rdp-day_range_end span {
|
|
127
|
+
color: white !important;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.rdp-day_range_start:hover,
|
|
131
|
+
.rdp-day_range_end:hover {
|
|
132
|
+
background-color: #2563eb !important;
|
|
133
|
+
box-shadow: 0 6px 16px rgba(37, 99, 235, 0.5);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.rdp-day_range_middle {
|
|
137
|
+
background-color: #dbeafe;
|
|
138
|
+
color: #1e40af;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.rdp-day_range_middle span {
|
|
142
|
+
color: #ffffff !important;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.rdp-day_today {
|
|
146
|
+
font-weight: 700;
|
|
147
|
+
color: #3b82f6;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.rdp-day_disabled {
|
|
151
|
+
opacity: 0.4;
|
|
152
|
+
cursor: not-allowed;
|
|
153
|
+
text-decoration: line-through;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.rdp-day_disabled:hover {
|
|
157
|
+
background-color: transparent !important;
|
|
158
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
.rdp{--rdp-cell-size:40px;--rdp-caption-font-size:18px;--rdp-accent-color:#00f;--rdp-background-color:#e7edff;--rdp-accent-color-dark:#3003e1;--rdp-background-color-dark:#180270;--rdp-outline:2px solid var(--rdp-accent-color);--rdp-outline-selected:3px solid var(--rdp-accent-color);--rdp-selected-color:#fff;margin:1em}.rdp-vhidden{box-sizing:border-box;margin:0;background:transparent;-moz-appearance:none;-webkit-appearance:none;appearance:none;position:absolute!important;top:0;width:1px!important;height:1px!important;padding:0!important;overflow:hidden!important;clip:rect(1px,1px,1px,1px)!important;border:0!important}.rdp-button_reset{appearance:none;position:relative;margin:0;padding:0;cursor:default;color:inherit;background:none;font:inherit;-moz-appearance:none;-webkit-appearance:none}.rdp-button_reset:focus-visible{outline:none}.rdp-button{border:2px solid transparent}.rdp-button[disabled]:not(.rdp-day_selected){opacity:.25}.rdp-button:not([disabled]){cursor:pointer}.rdp-button:focus-visible:not([disabled]){color:inherit;background-color:var(--rdp-background-color);border:var(--rdp-outline)}.rdp-button:hover:not([disabled]):not(.rdp-day_selected){background-color:var(--rdp-background-color)}.rdp-months{display:flex}.rdp-month{margin:0 1em}.rdp-month:first-child{margin-left:0}.rdp-month:last-child{margin-right:0}.rdp-table{margin:0;max-width:calc(var(--rdp-cell-size)*7);border-collapse:collapse}.rdp-with_weeknumber .rdp-table{max-width:calc(var(--rdp-cell-size)*8);border-collapse:collapse}.rdp-caption{align-items:center;justify-content:space-between;padding:0;text-align:left}.rdp-multiple_months .rdp-caption{position:relative;display:block;text-align:center}.rdp-caption_dropdowns,.rdp-caption_label{position:relative;display:inline-flex}.rdp-caption_label{z-index:1;align-items:center;margin:0;padding:0 .25em;white-space:nowrap;color:currentColor;border:2px solid transparent;font-family:inherit;font-size:var(--rdp-caption-font-size);font-weight:700}.rdp-nav{white-space:nowrap}.rdp-multiple_months .rdp-caption_start .rdp-nav{position:absolute;top:50%;left:0;transform:translateY(-50%)}.rdp-multiple_months .rdp-caption_end .rdp-nav{position:absolute;top:50%;right:0;transform:translateY(-50%)}.rdp-nav_button{display:inline-flex;align-items:center;justify-content:center;width:var(--rdp-cell-size);height:var(--rdp-cell-size);padding:.25em;border-radius:100%}.rdp-dropdown_month,.rdp-dropdown_year{position:relative;display:inline-flex;align-items:center}.rdp-dropdown{-webkit-appearance:none;-moz-appearance:none;appearance:none;position:absolute;z-index:2;top:0;bottom:0;left:0;width:100%;margin:0;padding:0;cursor:inherit;opacity:0;border:none;background-color:transparent;font-family:inherit;font-size:inherit;line-height:inherit}.rdp-dropdown[disabled]{opacity:unset;color:unset}.rdp-dropdown:focus-visible:not([disabled])+.rdp-caption_label{background-color:var(--rdp-background-color);border:var(--rdp-outline);border-radius:6px}.rdp-dropdown_icon{margin:0 0 0 5px}.rdp-head{border:0}.rdp-head_row,.rdp-row{height:100%}.rdp-head_cell{vertical-align:middle;font-size:.75em;font-weight:700;text-align:center;height:100%;height:var(--rdp-cell-size);padding:0}.rdp-tbody{border:0}.rdp-tfoot{margin:.5em}.rdp-cell{width:var(--rdp-cell-size);height:100%;height:var(--rdp-cell-size);text-align:center}.rdp-weeknumber{font-size:.75em}.rdp-day,.rdp-weeknumber{display:flex;overflow:hidden;align-items:center;justify-content:center;box-sizing:border-box;width:var(--rdp-cell-size);max-width:var(--rdp-cell-size);height:var(--rdp-cell-size);margin:0;border:2px solid transparent;border-radius:100%}.rdp-day_today:not(.rdp-day_outside){font-weight:700}.rdp-day_selected,.rdp-day_selected:focus-visible,.rdp-day_selected:hover{color:var(--rdp-selected-color);opacity:1;background-color:var(--rdp-accent-color)}.rdp-day_outside{opacity:.5}.rdp-day_selected:focus-visible{outline:var(--rdp-outline);outline-offset:2px;z-index:1}.rdp:not([dir=rtl]) .rdp-day_range_start:not(.rdp-day_range_end){border-top-right-radius:0;border-bottom-right-radius:0}.rdp:not([dir=rtl]) .rdp-day_range_end:not(.rdp-day_range_start),.rdp[dir=rtl] .rdp-day_range_start:not(.rdp-day_range_end){border-top-left-radius:0;border-bottom-left-radius:0}.rdp[dir=rtl] .rdp-day_range_end:not(.rdp-day_range_start){border-top-right-radius:0;border-bottom-right-radius:0}.rdp-day_range_end.rdp-day_range_start{border-radius:100%}.rdp-day_range_middle{border-radius:0}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }
|
|
2
|
+
|
|
3
|
+
/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--background:0 0% 100%;--foreground:222.2 84% 4.9%;--card:0 0% 100%;--card-foreground:222.2 84% 4.9%;--popover:0 0% 100%;--popover-foreground:222.2 84% 4.9%;--primary:221.2 83.2% 53.3%;--primary-foreground:210 40% 98%;--secondary:210 40% 96.1%;--secondary-foreground:222.2 47.4% 11.2%;--muted:210 40% 96.1%;--muted-foreground:215.4 16.3% 46.9%;--accent:210 40% 96.1%;--accent-foreground:222.2 47.4% 11.2%;--destructive:0 84.2% 60.2%;--destructive-foreground:210 40% 98%;--border:214.3 31.8% 91.4%;--input:214.3 31.8% 91.4%;--ring:221.2 83.2% 53.3%;--radius:0.5rem}*{border-color:hsl(var(--border))}body{background-color:hsl(var(--background));color:hsl(var(--foreground))}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.left-\[50\%\]{left:50%}.right-4{right:1rem}.top-4{top:1rem}.top-\[50\%\]{top:50%}.z-10{z-index:10}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-4{margin-bottom:1rem}.mb-8{margin-bottom:2rem}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.inline{display:inline}.flex{display:flex}.h-11{height:2.75rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-8{height:2rem}.h-full{height:100%}.max-h-\[300px\]{max-height:300px}.max-h-\[90vh\]{max-height:90vh}.min-h-screen{min-height:100vh}.w-4{width:1rem}.w-5{width:1.25rem}.w-72{width:18rem}.w-8{width:2rem}.w-\[320px\]{width:320px}.w-\[var\(--radix-popover-trigger-width\)\]{width:var(--radix-popover-trigger-width)}.w-auto{width:auto}.w-full{width:100%}.min-w-0{min-width:0}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.translate-x-\[-50\%\]{--tw-translate-x:-50%}.translate-x-\[-50\%\],.translate-y-\[-50\%\]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-\[-50\%\]{--tw-translate-y:-50%}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.border-slate-300{--tw-border-opacity:1;border-color:rgb(203 213 225/var(--tw-border-opacity,1))}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-slate-900{--tw-bg-opacity:1;background-color:rgb(15 23 42/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-blue-50{--tw-gradient-from:#eff6ff var(--tw-gradient-from-position);--tw-gradient-to:rgba(239,246,255,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-indigo-100{--tw-gradient-to:#e0e7ff var(--tw-gradient-to-position)}.p-0{padding:0}.p-1{padding:.25rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pt-3{padding-top:.75rem}.text-left{text-align:left}.text-center{text-align:center}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[10px\]{font-size:10px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.leading-none{line-height:1}.tracking-tight{letter-spacing:-.025em}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-green-500{--tw-text-opacity:1;color:rgb(34 197 94/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.text-slate-950{--tw-text-opacity:1;color:rgb(2 6 23/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-md,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-blue-500{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246/var(--tw-ring-opacity,1))}.ring-offset-white{--tw-ring-offset-color:#fff}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.rdp{--rdp-cell-size:56px;--rdp-accent-color:#3b82f6;--rdp-background-color:#eff6ff;margin:0;font-family:inherit}.rdp-custom{--rdp-cell-size:56px}.rdp-months{gap:2rem}.rdp-month{margin:0}.rdp-table{max-width:none}.rdp-caption{display:flex;justify-content:center;padding:.5rem 0 1rem}.rdp-caption_label{font-size:1rem;font-weight:600;color:#0f172a}.rdp-head_cell{font-weight:500;font-size:.875rem;color:#64748b;text-transform:uppercase;padding-bottom:.5rem}.rdp-cell{width:56px;height:56px;padding:0}.rdp-day{overflow:visible!important;border-radius:.5rem!important;border:none!important}.rdp-button{width:100%;height:100%;border-radius:.5rem;font-size:.875rem;transition:all .2s;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:4px}.rdp-button:hover:not(.rdp-day_disabled){background-color:#f1f5f9;box-shadow:0 2px 8px rgba(0,0,0,.1)}.rdp-day_range_end,.rdp-day_range_start{background-color:#3b82f6!important;color:#fff!important;font-weight:600;box-shadow:0 4px 12px rgba(59,130,246,.4)}.rdp-day_range_end span,.rdp-day_range_start span{color:#fff!important}.rdp-day_range_end:hover,.rdp-day_range_start:hover{background-color:#2563eb!important;box-shadow:0 6px 16px rgba(37,99,235,.5)}.rdp-day_range_middle{background-color:#dbeafe;color:#1e40af}.rdp-day_range_middle span{color:#fff!important}.rdp-day_today{font-weight:700;color:#3b82f6}.rdp-day_disabled{opacity:.4;cursor:not-allowed;text-decoration:line-through}.rdp-day_disabled:hover{background-color:transparent!important}.placeholder\:text-slate-500::-moz-placeholder{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.placeholder\:text-slate-500::placeholder{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.hover\:bg-blue-50:hover{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.hover\:bg-blue-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.hover\:opacity-100:hover{opacity:1}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246/var(--tw-ring-opacity,1))}.focus\:ring-slate-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(100 116 139/var(--tw-ring-opacity,1))}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}.focus-visible\:ring-0:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:border-slate-300:disabled{--tw-border-opacity:1;border-color:rgb(203 213 225/var(--tw-border-opacity,1))}.disabled\:bg-slate-300:disabled{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity,1))}.disabled\:text-slate-300:disabled{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:hover\:bg-slate-300:hover:disabled{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity,1))}.disabled\:hover\:bg-transparent:hover:disabled{background-color:transparent}.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true]{pointer-events:none}.data-\[selected\=true\]\:bg-blue-50[data-selected=true]{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.data-\[state\=open\]\:bg-slate-100[data-state=open]{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.data-\[selected\=true\]\:text-blue-900[data-selected=true]{--tw-text-opacity:1;color:rgb(30 58 138/var(--tw-text-opacity,1))}.data-\[disabled\=true\]\:opacity-50[data-disabled=true]{opacity:.5}@media (min-width:640px){.sm\:max-w-\[600px\]{max-width:600px}.sm\:rounded-lg{border-radius:var(--radius)}.sm\:text-left{text-align:left}}@media (min-width:768px){.md\:w-auto{width:auto}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:gap-2{gap:.5rem}.md\:rounded-none{border-radius:0}.md\:rounded-l-lg{border-top-left-radius:var(--radius);border-bottom-left-radius:var(--radius)}.md\:rounded-r-none{border-top-right-radius:0;border-bottom-right-radius:0}.md\:p-8{padding:2rem}.md\:pl-2{padding-left:.5rem}.md\:text-5xl{font-size:3rem;line-height:1}}.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-left:.5rem;padding-right:.5rem}.\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading]{padding-top:.375rem;padding-bottom:.375rem}.\[\&_\[cmdk-group-heading\]\]\:text-xs [cmdk-group-heading]{font-size:.75rem;line-height:1rem}.\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{font-weight:500}.\[\&_\[cmdk-group-heading\]\]\:text-slate-500 [cmdk-group-heading]{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}
|
|
4
|
+
/*# sourceMappingURL=output.css.map */
|