@bailierich/booking-components 2.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/README.md +319 -0
- package/TENANT_DATA_INTEGRATION.md +402 -0
- package/TENANT_SETUP.md +316 -0
- package/components/BookingFlow/BookingFlow.tsx +790 -0
- package/components/BookingFlow/index.ts +5 -0
- package/components/BookingFlow/steps/AddonsSelection.tsx +118 -0
- package/components/BookingFlow/steps/Confirmation.tsx +185 -0
- package/components/BookingFlow/steps/ContactForm.tsx +292 -0
- package/components/BookingFlow/steps/CycleAwareDateSelection.tsx +277 -0
- package/components/BookingFlow/steps/DateSelection.tsx +473 -0
- package/components/BookingFlow/steps/ServiceSelection.tsx +315 -0
- package/components/BookingFlow/steps/TimeSelection.tsx +230 -0
- package/components/BookingFlow/steps/index.ts +10 -0
- package/components/BottomSheet/index.tsx +120 -0
- package/components/Forms/FormBlock.tsx +283 -0
- package/components/Forms/FormField.tsx +385 -0
- package/components/Forms/FormRenderer.tsx +216 -0
- package/components/Forms/FormValidation.ts +122 -0
- package/components/Forms/index.ts +4 -0
- package/components/HoldTimer/HoldTimer.tsx +266 -0
- package/components/HoldTimer/index.ts +2 -0
- package/components/SectionRenderer.tsx +558 -0
- package/components/Sections/About.tsx +145 -0
- package/components/Sections/BeforeAfter.tsx +81 -0
- package/components/Sections/BookingSection.tsx +76 -0
- package/components/Sections/Contact.tsx +103 -0
- package/components/Sections/FAQSection.tsx +239 -0
- package/components/Sections/FeatureContent.tsx +113 -0
- package/components/Sections/FeaturedLink.tsx +103 -0
- package/components/Sections/FixedInfoCard.tsx +189 -0
- package/components/Sections/Gallery.tsx +83 -0
- package/components/Sections/Header.tsx +78 -0
- package/components/Sections/Hero.tsx +178 -0
- package/components/Sections/ImageSection.tsx +147 -0
- package/components/Sections/InstagramFeed.tsx +38 -0
- package/components/Sections/LinkList.tsx +76 -0
- package/components/Sections/LocationMap.tsx +202 -0
- package/components/Sections/Logo.tsx +61 -0
- package/components/Sections/MinimalFooter.tsx +78 -0
- package/components/Sections/MinimalHeader.tsx +81 -0
- package/components/Sections/MinimalNavigation.tsx +63 -0
- package/components/Sections/Navbar.tsx +258 -0
- package/components/Sections/PricingTable.tsx +106 -0
- package/components/Sections/ScrollingTextDivider.tsx +138 -0
- package/components/Sections/ScrollingTextDivider.tsx.bak +138 -0
- package/components/Sections/ServicesPreview.tsx +129 -0
- package/components/Sections/SocialBar.tsx +177 -0
- package/components/Sections/Team.tsx +80 -0
- package/components/Sections/Testimonials.tsx +92 -0
- package/components/Sections/TextSection.tsx +116 -0
- package/components/Sections/VideoSection.tsx +178 -0
- package/components/Sections/index.ts +57 -0
- package/components/index.ts +21 -0
- package/dist/index-DAai7Glf.d.mts +474 -0
- package/dist/index-DAai7Glf.d.ts +474 -0
- package/dist/index.d.mts +1075 -0
- package/dist/index.d.ts +1075 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +22 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles/index.d.mts +1 -0
- package/dist/styles/index.d.ts +1 -0
- package/dist/styles/index.js +2 -0
- package/dist/styles/index.js.map +1 -0
- package/dist/styles/index.mjs +2 -0
- package/dist/styles/index.mjs.map +1 -0
- package/docs/API.md +849 -0
- package/docs/CALLBACKS.md +760 -0
- package/docs/COMPLETE_SESSION_SUMMARY.md +404 -0
- package/docs/DATA_SHAPES.md +684 -0
- package/docs/MIGRATION.md +662 -0
- package/docs/PAYMENT_INTEGRATION.md +766 -0
- package/docs/SESSION_SUMMARY.md +185 -0
- package/docs/STYLING.md +735 -0
- package/index.ts +4 -0
- package/lib/storage.ts +239 -0
- package/package.json +59 -0
- package/styles/animations.ts +210 -0
- package/styles/index.ts +1 -0
- package/tsconfig.json +32 -0
- package/tsup.config.ts +13 -0
- package/types/index.ts +369 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
export interface VideoSectionProps {
|
|
4
|
+
videoUrl: string;
|
|
5
|
+
aspectRatio?: '16:9' | '4:3' | '1:1' | '9:16';
|
|
6
|
+
autoplay?: boolean;
|
|
7
|
+
loop?: boolean;
|
|
8
|
+
muted?: boolean;
|
|
9
|
+
controls?: boolean;
|
|
10
|
+
allowFullScreen?: boolean;
|
|
11
|
+
coverImage?: string;
|
|
12
|
+
maxWidth?: 'full' | 'large' | 'medium' | 'small';
|
|
13
|
+
alignment?: 'left' | 'center' | 'right';
|
|
14
|
+
borderRadius?: number;
|
|
15
|
+
colors: {
|
|
16
|
+
primary: string;
|
|
17
|
+
text: string;
|
|
18
|
+
};
|
|
19
|
+
typography?: {
|
|
20
|
+
headingFont?: string;
|
|
21
|
+
};
|
|
22
|
+
enableInlineEditing?: boolean;
|
|
23
|
+
sectionId?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function VideoSection({
|
|
27
|
+
videoUrl,
|
|
28
|
+
aspectRatio = '16:9',
|
|
29
|
+
autoplay = false,
|
|
30
|
+
loop = false,
|
|
31
|
+
muted = true,
|
|
32
|
+
controls = true,
|
|
33
|
+
allowFullScreen = true,
|
|
34
|
+
coverImage,
|
|
35
|
+
maxWidth = 'large',
|
|
36
|
+
alignment = 'center',
|
|
37
|
+
borderRadius = 12,
|
|
38
|
+
colors,
|
|
39
|
+
enableInlineEditing = false,
|
|
40
|
+
sectionId = ''
|
|
41
|
+
}: VideoSectionProps) {
|
|
42
|
+
// Helper to extract video ID from YouTube/Vimeo URLs
|
|
43
|
+
const getEmbedUrl = (url: string): { type: 'youtube' | 'vimeo' | 'direct'; embedUrl: string } | null => {
|
|
44
|
+
// YouTube
|
|
45
|
+
const youtubeMatch = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]+)/);
|
|
46
|
+
if (youtubeMatch) {
|
|
47
|
+
const videoId = youtubeMatch[1];
|
|
48
|
+
const params = new URLSearchParams({
|
|
49
|
+
...(autoplay ? { autoplay: '1' } : {}),
|
|
50
|
+
...(loop ? { loop: '1', playlist: videoId } : {}),
|
|
51
|
+
...(muted ? { mute: '1' } : {}),
|
|
52
|
+
...(controls ? {} : { controls: '0' }),
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
type: 'youtube',
|
|
56
|
+
embedUrl: `https://www.youtube.com/embed/${videoId}?${params.toString()}`
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Vimeo
|
|
61
|
+
const vimeoMatch = url.match(/(?:vimeo\.com\/)(\d+)/);
|
|
62
|
+
if (vimeoMatch) {
|
|
63
|
+
const videoId = vimeoMatch[1];
|
|
64
|
+
const params = new URLSearchParams({
|
|
65
|
+
...(autoplay ? { autoplay: '1' } : {}),
|
|
66
|
+
...(loop ? { loop: '1' } : {}),
|
|
67
|
+
...(muted ? { muted: '1' } : {}),
|
|
68
|
+
...(controls ? {} : { controls: '0' }),
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
type: 'vimeo',
|
|
72
|
+
embedUrl: `https://player.vimeo.com/video/${videoId}?${params.toString()}`
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Direct video URL (mp4, webm, etc.)
|
|
77
|
+
if (url.match(/\.(mp4|webm|ogg)$/i)) {
|
|
78
|
+
return {
|
|
79
|
+
type: 'direct',
|
|
80
|
+
embedUrl: url
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return null;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const embedData = getEmbedUrl(videoUrl);
|
|
88
|
+
|
|
89
|
+
// Aspect ratio padding hack
|
|
90
|
+
const aspectRatioMap = {
|
|
91
|
+
'16:9': '56.25%',
|
|
92
|
+
'4:3': '75%',
|
|
93
|
+
'1:1': '100%',
|
|
94
|
+
'9:16': '177.78%'
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Max width classes
|
|
98
|
+
const maxWidthMap = {
|
|
99
|
+
full: 'max-w-full',
|
|
100
|
+
large: 'max-w-6xl',
|
|
101
|
+
medium: 'max-w-4xl',
|
|
102
|
+
small: 'max-w-2xl'
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const alignmentClass = alignment === 'center' ? 'mx-auto' : alignment === 'right' ? 'ml-auto' : 'mr-auto';
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<div className="container mx-auto px-4">
|
|
109
|
+
<div className={`${maxWidthMap[maxWidth]} ${alignmentClass}`}>
|
|
110
|
+
<div
|
|
111
|
+
className="relative w-full overflow-hidden"
|
|
112
|
+
style={{
|
|
113
|
+
paddingBottom: aspectRatioMap[aspectRatio],
|
|
114
|
+
borderRadius: `${borderRadius}px`
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
{embedData ? (
|
|
118
|
+
embedData.type === 'direct' ? (
|
|
119
|
+
// Direct video
|
|
120
|
+
<video
|
|
121
|
+
src={embedData.embedUrl}
|
|
122
|
+
autoPlay={autoplay}
|
|
123
|
+
loop={loop}
|
|
124
|
+
muted={muted}
|
|
125
|
+
controls={controls}
|
|
126
|
+
poster={coverImage}
|
|
127
|
+
className="absolute top-0 left-0 w-full h-full object-cover"
|
|
128
|
+
/>
|
|
129
|
+
) : (
|
|
130
|
+
// YouTube or Vimeo iframe
|
|
131
|
+
<iframe
|
|
132
|
+
src={embedData.embedUrl}
|
|
133
|
+
className="absolute top-0 left-0 w-full h-full"
|
|
134
|
+
frameBorder="0"
|
|
135
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
136
|
+
allowFullScreen={allowFullScreen}
|
|
137
|
+
title="Video"
|
|
138
|
+
/>
|
|
139
|
+
)
|
|
140
|
+
) : (
|
|
141
|
+
// Fallback placeholder
|
|
142
|
+
<div
|
|
143
|
+
className="absolute top-0 left-0 w-full h-full flex items-center justify-center"
|
|
144
|
+
style={{ backgroundColor: `${colors.primary}20` }}
|
|
145
|
+
>
|
|
146
|
+
<div className="text-center px-4">
|
|
147
|
+
<svg
|
|
148
|
+
className="w-16 h-16 mx-auto mb-4"
|
|
149
|
+
fill="none"
|
|
150
|
+
stroke={colors.primary}
|
|
151
|
+
viewBox="0 0 24 24"
|
|
152
|
+
>
|
|
153
|
+
<path
|
|
154
|
+
strokeLinecap="round"
|
|
155
|
+
strokeLinejoin="round"
|
|
156
|
+
strokeWidth={2}
|
|
157
|
+
d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"
|
|
158
|
+
/>
|
|
159
|
+
<path
|
|
160
|
+
strokeLinecap="round"
|
|
161
|
+
strokeLinejoin="round"
|
|
162
|
+
strokeWidth={2}
|
|
163
|
+
d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
164
|
+
/>
|
|
165
|
+
</svg>
|
|
166
|
+
<p style={{ color: colors.text, opacity: 0.6 }}>
|
|
167
|
+
{videoUrl ? 'Invalid video URL' : 'Add a video URL to display'}
|
|
168
|
+
</p>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
)}
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export default VideoSection;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export { Logo } from './Logo';
|
|
2
|
+
export { Header } from './Header';
|
|
3
|
+
export { FeaturedLink } from './FeaturedLink';
|
|
4
|
+
export { LinkList } from './LinkList';
|
|
5
|
+
export { SocialBar } from './SocialBar';
|
|
6
|
+
export { Hero } from './Hero';
|
|
7
|
+
export { About } from './About';
|
|
8
|
+
export { ServicesPreview } from './ServicesPreview';
|
|
9
|
+
export { Gallery } from './Gallery';
|
|
10
|
+
export { Testimonials } from './Testimonials';
|
|
11
|
+
export { Team } from './Team';
|
|
12
|
+
export { Contact } from './Contact';
|
|
13
|
+
export { MinimalHeader } from './MinimalHeader';
|
|
14
|
+
export { MinimalNavigation } from './MinimalNavigation';
|
|
15
|
+
export { MinimalFooter } from './MinimalFooter';
|
|
16
|
+
export { FeatureContent } from './FeatureContent';
|
|
17
|
+
export { BeforeAfter } from './BeforeAfter';
|
|
18
|
+
export { PricingTable } from './PricingTable';
|
|
19
|
+
export { InstagramFeed } from './InstagramFeed';
|
|
20
|
+
export { FixedInfoCard } from './FixedInfoCard';
|
|
21
|
+
export { BookingSection } from './BookingSection';
|
|
22
|
+
export { VideoSection } from './VideoSection';
|
|
23
|
+
export { ScrollingTextDivider } from './ScrollingTextDivider';
|
|
24
|
+
export { LocationMap } from './LocationMap';
|
|
25
|
+
export { ImageSection } from './ImageSection';
|
|
26
|
+
export { FAQSection } from './FAQSection';
|
|
27
|
+
export { Navbar } from './Navbar';
|
|
28
|
+
export { TextSection } from './TextSection';
|
|
29
|
+
|
|
30
|
+
export type * from './Logo';
|
|
31
|
+
export type * from './Header';
|
|
32
|
+
export type * from './FeaturedLink';
|
|
33
|
+
export type * from './LinkList';
|
|
34
|
+
export type * from './SocialBar';
|
|
35
|
+
export type * from './Hero';
|
|
36
|
+
export type * from './About';
|
|
37
|
+
export type * from './ServicesPreview';
|
|
38
|
+
export type * from './Gallery';
|
|
39
|
+
export type * from './Testimonials';
|
|
40
|
+
export type * from './Team';
|
|
41
|
+
export type * from './Contact';
|
|
42
|
+
export type * from './MinimalHeader';
|
|
43
|
+
export type * from './MinimalNavigation';
|
|
44
|
+
export type * from './MinimalFooter';
|
|
45
|
+
export type * from './FeatureContent';
|
|
46
|
+
export type * from './BeforeAfter';
|
|
47
|
+
export type * from './PricingTable';
|
|
48
|
+
export type * from './InstagramFeed';
|
|
49
|
+
export type * from './FixedInfoCard';
|
|
50
|
+
export type * from './BookingSection';
|
|
51
|
+
export type * from './VideoSection';
|
|
52
|
+
export type * from './ScrollingTextDivider';
|
|
53
|
+
export type * from './LocationMap';
|
|
54
|
+
export type * from './ImageSection';
|
|
55
|
+
export type * from './FAQSection';
|
|
56
|
+
export type * from './Navbar';
|
|
57
|
+
export type * from './TextSection';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Section Components
|
|
2
|
+
export * from './Sections';
|
|
3
|
+
|
|
4
|
+
// Booking Flow Components
|
|
5
|
+
export { BookingFlow } from './BookingFlow';
|
|
6
|
+
export * from './BookingFlow/steps';
|
|
7
|
+
export type { BookingFlowProps, BookingFlowConfig } from './BookingFlow';
|
|
8
|
+
|
|
9
|
+
// UI Components
|
|
10
|
+
export { BottomSheet } from './BottomSheet';
|
|
11
|
+
export type { BottomSheetProps } from '../types';
|
|
12
|
+
|
|
13
|
+
export { HoldTimer } from './HoldTimer';
|
|
14
|
+
export type { HoldTimerProps } from './HoldTimer';
|
|
15
|
+
|
|
16
|
+
// Section Renderer
|
|
17
|
+
export { SectionRenderer } from './SectionRenderer';
|
|
18
|
+
export type { SectionRendererProps } from './SectionRenderer';
|
|
19
|
+
|
|
20
|
+
// Form Components
|
|
21
|
+
export * from './Forms';
|