@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.
Files changed (83) hide show
  1. package/README.md +319 -0
  2. package/TENANT_DATA_INTEGRATION.md +402 -0
  3. package/TENANT_SETUP.md +316 -0
  4. package/components/BookingFlow/BookingFlow.tsx +790 -0
  5. package/components/BookingFlow/index.ts +5 -0
  6. package/components/BookingFlow/steps/AddonsSelection.tsx +118 -0
  7. package/components/BookingFlow/steps/Confirmation.tsx +185 -0
  8. package/components/BookingFlow/steps/ContactForm.tsx +292 -0
  9. package/components/BookingFlow/steps/CycleAwareDateSelection.tsx +277 -0
  10. package/components/BookingFlow/steps/DateSelection.tsx +473 -0
  11. package/components/BookingFlow/steps/ServiceSelection.tsx +315 -0
  12. package/components/BookingFlow/steps/TimeSelection.tsx +230 -0
  13. package/components/BookingFlow/steps/index.ts +10 -0
  14. package/components/BottomSheet/index.tsx +120 -0
  15. package/components/Forms/FormBlock.tsx +283 -0
  16. package/components/Forms/FormField.tsx +385 -0
  17. package/components/Forms/FormRenderer.tsx +216 -0
  18. package/components/Forms/FormValidation.ts +122 -0
  19. package/components/Forms/index.ts +4 -0
  20. package/components/HoldTimer/HoldTimer.tsx +266 -0
  21. package/components/HoldTimer/index.ts +2 -0
  22. package/components/SectionRenderer.tsx +558 -0
  23. package/components/Sections/About.tsx +145 -0
  24. package/components/Sections/BeforeAfter.tsx +81 -0
  25. package/components/Sections/BookingSection.tsx +76 -0
  26. package/components/Sections/Contact.tsx +103 -0
  27. package/components/Sections/FAQSection.tsx +239 -0
  28. package/components/Sections/FeatureContent.tsx +113 -0
  29. package/components/Sections/FeaturedLink.tsx +103 -0
  30. package/components/Sections/FixedInfoCard.tsx +189 -0
  31. package/components/Sections/Gallery.tsx +83 -0
  32. package/components/Sections/Header.tsx +78 -0
  33. package/components/Sections/Hero.tsx +178 -0
  34. package/components/Sections/ImageSection.tsx +147 -0
  35. package/components/Sections/InstagramFeed.tsx +38 -0
  36. package/components/Sections/LinkList.tsx +76 -0
  37. package/components/Sections/LocationMap.tsx +202 -0
  38. package/components/Sections/Logo.tsx +61 -0
  39. package/components/Sections/MinimalFooter.tsx +78 -0
  40. package/components/Sections/MinimalHeader.tsx +81 -0
  41. package/components/Sections/MinimalNavigation.tsx +63 -0
  42. package/components/Sections/Navbar.tsx +258 -0
  43. package/components/Sections/PricingTable.tsx +106 -0
  44. package/components/Sections/ScrollingTextDivider.tsx +138 -0
  45. package/components/Sections/ScrollingTextDivider.tsx.bak +138 -0
  46. package/components/Sections/ServicesPreview.tsx +129 -0
  47. package/components/Sections/SocialBar.tsx +177 -0
  48. package/components/Sections/Team.tsx +80 -0
  49. package/components/Sections/Testimonials.tsx +92 -0
  50. package/components/Sections/TextSection.tsx +116 -0
  51. package/components/Sections/VideoSection.tsx +178 -0
  52. package/components/Sections/index.ts +57 -0
  53. package/components/index.ts +21 -0
  54. package/dist/index-DAai7Glf.d.mts +474 -0
  55. package/dist/index-DAai7Glf.d.ts +474 -0
  56. package/dist/index.d.mts +1075 -0
  57. package/dist/index.d.ts +1075 -0
  58. package/dist/index.js +22 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/index.mjs +22 -0
  61. package/dist/index.mjs.map +1 -0
  62. package/dist/styles/index.d.mts +1 -0
  63. package/dist/styles/index.d.ts +1 -0
  64. package/dist/styles/index.js +2 -0
  65. package/dist/styles/index.js.map +1 -0
  66. package/dist/styles/index.mjs +2 -0
  67. package/dist/styles/index.mjs.map +1 -0
  68. package/docs/API.md +849 -0
  69. package/docs/CALLBACKS.md +760 -0
  70. package/docs/COMPLETE_SESSION_SUMMARY.md +404 -0
  71. package/docs/DATA_SHAPES.md +684 -0
  72. package/docs/MIGRATION.md +662 -0
  73. package/docs/PAYMENT_INTEGRATION.md +766 -0
  74. package/docs/SESSION_SUMMARY.md +185 -0
  75. package/docs/STYLING.md +735 -0
  76. package/index.ts +4 -0
  77. package/lib/storage.ts +239 -0
  78. package/package.json +59 -0
  79. package/styles/animations.ts +210 -0
  80. package/styles/index.ts +1 -0
  81. package/tsconfig.json +32 -0
  82. package/tsup.config.ts +13 -0
  83. 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';