@ticketboothapp/booking 0.1.19 → 0.1.20

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 (154) hide show
  1. package/package.json +1 -1
  2. package/src/components/BookingWidget.tsx +282 -26
  3. package/src/components/ManageBookingView.tsx +75 -23
  4. package/src/components/booking/BookingProductGrid.tsx +1 -1
  5. package/src/components/booking/Calendar.module.css +3 -3
  6. package/src/components/booking/CheckoutForm.tsx +1 -1
  7. package/src/components/booking/InfoTooltip.tsx +2 -13
  8. package/src/components/booking/PickupLocationSelector.tsx +2 -2
  9. package/src/components/booking/PriceBreakdown.tsx +11 -34
  10. package/src/index.ts +3 -1
  11. package/src/app/photo-sessions/photo-packages.ts +0 -75
  12. package/src/assets/icons/minus.svg +0 -7
  13. package/src/assets/icons/partner-logos/getyourguide.svg +0 -8
  14. package/src/assets/icons/plus.svg +0 -3
  15. package/src/colours.css +0 -23
  16. package/src/components/BookingDetails.module.css +0 -1591
  17. package/src/components/BookingDetails.tsx +0 -2264
  18. package/src/components/JobApplicationDialog.module.css +0 -440
  19. package/src/components/JobApplicationDialog.tsx +0 -620
  20. package/src/components/PhoneInputWithCountry.module.css +0 -131
  21. package/src/components/PhoneInputWithCountry.tsx +0 -44
  22. package/src/components/PickupLocationDialog.module.css +0 -360
  23. package/src/components/PickupLocationDialog.tsx +0 -357
  24. package/src/components/PickupLocationMap.tsx +0 -110
  25. package/src/components/PostBookingDependentAddOnUpsell.module.css +0 -174
  26. package/src/components/PostBookingDependentAddOnUpsell.tsx +0 -407
  27. package/src/components/accordion.css +0 -27
  28. package/src/components/accordion.tsx +0 -29
  29. package/src/components/analytics/AnalyticsConsentRestore.tsx +0 -19
  30. package/src/components/analytics/AnalyticsScripts.tsx +0 -106
  31. package/src/components/analytics/CookieConsentBanner.css +0 -86
  32. package/src/components/analytics/CookieConsentBanner.tsx +0 -102
  33. package/src/components/bottom-sheet.module.css +0 -78
  34. package/src/components/bottom-sheet.tsx +0 -60
  35. package/src/components/breadcrumb.module.css +0 -40
  36. package/src/components/breadcrumb.tsx +0 -36
  37. package/src/components/button.css +0 -245
  38. package/src/components/button.tsx +0 -152
  39. package/src/components/client-bottom-sheet.tsx +0 -14
  40. package/src/components/colorable-svg.tsx +0 -29
  41. package/src/components/conditional-footer.tsx +0 -27
  42. package/src/components/contact-us.module.css +0 -147
  43. package/src/components/contact-us.tsx +0 -49
  44. package/src/components/email-signup.css +0 -151
  45. package/src/components/email-signup.tsx +0 -63
  46. package/src/components/faq-wrapper.module.css +0 -47
  47. package/src/components/faq-wrapper.tsx +0 -15
  48. package/src/components/footer.css +0 -187
  49. package/src/components/footer.tsx +0 -143
  50. package/src/components/global-simple-modal.tsx +0 -33
  51. package/src/components/google-review-summary.module.css +0 -77
  52. package/src/components/google-review-summary.tsx +0 -50
  53. package/src/components/hero-image.css +0 -13
  54. package/src/components/hero-image.tsx +0 -44
  55. package/src/components/image.css +0 -29
  56. package/src/components/image.tsx +0 -113
  57. package/src/components/language-aware-link.tsx +0 -72
  58. package/src/components/language-switcher.module.css +0 -124
  59. package/src/components/language-switcher.tsx +0 -75
  60. package/src/components/map-section.css +0 -59
  61. package/src/components/map-section.tsx +0 -63
  62. package/src/components/navbar.module.css +0 -152
  63. package/src/components/navbar.tsx +0 -125
  64. package/src/components/parallax-provider.tsx +0 -11
  65. package/src/components/product-tag.module.css +0 -30
  66. package/src/components/product-tag.tsx +0 -34
  67. package/src/components/product-theme-pages/best-option.module.css +0 -70
  68. package/src/components/product-theme-pages/best-option.tsx +0 -35
  69. package/src/components/product-theme-pages/extended-tour-options.module.css +0 -22
  70. package/src/components/product-theme-pages/extended-tour-options.tsx +0 -11
  71. package/src/components/product-theme-pages/image-modal.tsx +0 -248
  72. package/src/components/product-theme-pages/photo-gallery.module.css +0 -200
  73. package/src/components/product-theme-pages/photo-gallery.tsx +0 -90
  74. package/src/components/product-theme-pages/product-theme-page-layout.module.css +0 -13
  75. package/src/components/product-theme-pages/product-theme-page-layout.tsx +0 -67
  76. package/src/components/product-theme-pages/top-of-fold.module.css +0 -179
  77. package/src/components/product-theme-pages/top-of-fold.tsx +0 -80
  78. package/src/components/product-tile/image-only-product-tile-desktop.module.css +0 -106
  79. package/src/components/product-tile/image-only-product-tile-desktop.tsx +0 -56
  80. package/src/components/product-tile/image-only-product-tile-mobile.module.css +0 -122
  81. package/src/components/product-tile/image-only-product-tile-mobile.tsx +0 -89
  82. package/src/components/product-tile/image-only-product-tile.tsx +0 -44
  83. package/src/components/product-tile/product-tile-card.module.css +0 -84
  84. package/src/components/product-tile/product-tile-card.tsx +0 -61
  85. package/src/components/review-highlights-section.css +0 -85
  86. package/src/components/review-highlights-section.tsx +0 -127
  87. package/src/components/season-closure-overlay.module.css +0 -99
  88. package/src/components/season-closure-overlay.tsx +0 -98
  89. package/src/components/simple-modal.tsx +0 -69
  90. package/src/components/simple-top-of-fold.module.css +0 -76
  91. package/src/components/simple-top-of-fold.tsx +0 -34
  92. package/src/components/spacer.css +0 -41
  93. package/src/components/spacer.tsx +0 -23
  94. package/src/components/star-rating.module.css +0 -74
  95. package/src/components/star-rating.tsx +0 -48
  96. package/src/components/terms/TermsContent.tsx +0 -178
  97. package/src/components/title-subtitle.module.css +0 -10
  98. package/src/components/title-subtitle.tsx +0 -30
  99. package/src/components/translatable-reviews.tsx +0 -75
  100. package/src/components/value-pill.module.css +0 -59
  101. package/src/components/value-pill.tsx +0 -46
  102. package/src/components/value-props.css +0 -185
  103. package/src/components/value-props.tsx +0 -88
  104. package/src/constants/booking-guide-quiz.ts +0 -64
  105. package/src/constants/contact-info.ts +0 -2
  106. package/src/constants/faq.ts +0 -44
  107. package/src/constants/images.ts +0 -556
  108. package/src/constants/json-ld/faq-json-ld.tsx +0 -170
  109. package/src/constants/json-ld/homepage-json-ld.tsx +0 -138
  110. package/src/constants/json-ld/job-posting-json-ld.tsx +0 -92
  111. package/src/constants/json-ld/organization-json-ld.tsx +0 -62
  112. package/src/constants/json-ld/page-json-ld.tsx +0 -6
  113. package/src/constants/json-ld/product-json-ld.tsx +0 -154
  114. package/src/constants/json-ld/review-json-ld.tsx +0 -377
  115. package/src/constants/navigation-links/footer-links.ts +0 -48
  116. package/src/constants/navigation-links/nav-bar-links.ts +0 -41
  117. package/src/constants/navigation-links/navigation-link.ts +0 -6
  118. package/src/constants/pill-values.ts +0 -210
  119. package/src/constants/products.ts +0 -155
  120. package/src/constants/quiz-recommendations.ts +0 -506
  121. package/src/constants/reviews.ts +0 -75
  122. package/src/constants/staff.ts +0 -197
  123. package/src/constants/value-props.ts +0 -58
  124. package/src/data/dap-descriptions/session-couples-families-friends.en.json +0 -61
  125. package/src/data/dap-descriptions/session-elopements.en.json +0 -60
  126. package/src/data/dap-descriptions/session-proposals.en.json +0 -60
  127. package/src/data/product-descriptions/afternoon-delight.en.json +0 -35
  128. package/src/data/product-descriptions/emerald-lake-escape.en.json +0 -68
  129. package/src/data/product-descriptions/lake-louise-adventure.en.json +0 -74
  130. package/src/data/product-descriptions/moraine-lake-adventure.en.json +0 -78
  131. package/src/data/product-descriptions/moraine-lake-sunrise-lake-louise-golden-hour.en.json +0 -65
  132. package/src/data/product-descriptions/moraine-lake-sunrise.en.json +0 -64
  133. package/src/data/product-descriptions/private-tour.en.json +0 -80
  134. package/src/data/product-descriptions/two-lakes-combo.en.json +0 -65
  135. package/src/data/products-config.json +0 -101
  136. package/src/hooks/use-bottom-sheet.tsx +0 -15
  137. package/src/hooks/use-simple-modal.tsx +0 -27
  138. package/src/hooks/useBookingSourceMetadataFromLocation.ts +0 -21
  139. package/src/hooks/useEmailSubscription.tsx +0 -103
  140. package/src/hooks/useEmbeddedInIframe.ts +0 -16
  141. package/src/hooks/useIsBookingLaunchLive.ts +0 -49
  142. package/src/hooks/useQuiz.tsx +0 -210
  143. package/src/providers/bottom-sheet-provider.tsx +0 -40
  144. package/src/providers/dependent-add-on-dialog-provider.tsx +0 -105
  145. package/src/radius.css +0 -5
  146. package/src/spacing.css +0 -7
  147. package/src/strings/en.json +0 -1774
  148. package/src/strings/es.json +0 -1573
  149. package/src/strings/fr.json +0 -1573
  150. package/src/strings/index.js +0 -23
  151. package/src/text-style.css +0 -97
  152. package/src/types/fareharbor.d.ts +0 -12
  153. package/src/types/quiz.ts +0 -59
  154. package/src/utils/currency-converter.ts +0 -101
@@ -1,99 +0,0 @@
1
- .closureOverlayBackdrop {
2
- position: absolute;
3
- top: 0;
4
- left: 0;
5
- right: 0;
6
- bottom: 0;
7
- background: rgba(0, 0, 0, 0.5);
8
- backdrop-filter: blur(3px);
9
- z-index: 3;
10
- display: flex;
11
- align-items: center;
12
- justify-content: center;
13
- }
14
-
15
- .seasonClosureCallout {
16
- width: 90%;
17
- max-width: 500px;
18
- z-index: 4;
19
- display: flex;
20
- flex-direction: column;
21
- align-items: center;
22
- text-align: center;
23
- gap: 0.5rem;
24
- pointer-events: none;
25
- }
26
-
27
- .seasonClosureCallout * {
28
- pointer-events: auto;
29
- }
30
-
31
- .closureOverlayTop {
32
- display: flex;
33
- flex-direction: column;
34
- align-items: center;
35
- text-align: center;
36
- gap: 0.1rem;
37
- }
38
-
39
- .closureOverlayBottom {
40
- display: flex;
41
- flex-direction: column;
42
- align-items: center;
43
- text-align: center;
44
- }
45
-
46
- .closureTitle {
47
- font-size: 3rem;
48
- line-height: 0.7;
49
- font-weight: 900;
50
- color: #fff;
51
- text-shadow: 0 0 8px rgba(0,0,0,0.4);
52
- font-family: 'Snell Roundhand', sans-serif;
53
- text-transform: lowercase;
54
- text-align: center;
55
- margin-bottom: -0.2rem;
56
- }
57
-
58
- .closureSubtitle {
59
- font-size: 2rem;
60
- line-height: 1;
61
- font-weight: 400;
62
- color: #fff;
63
- text-shadow: 0 0 8px rgba(0,0,0,0.4);
64
- letter-spacing: 0.5px;
65
- font-family: 'Northlake', sans-serif;
66
- text-transform: lowercase;
67
- text-align: center;
68
- margin-top: 2rem;
69
- margin-bottom: 0.25rem;
70
- }
71
-
72
- .closureCountdownTime {
73
- font-size: 0.9rem;
74
- line-height: 1;
75
- font-weight: 400;
76
- color: rgba(255, 255, 255, 0.9);
77
- text-shadow: 0 0 6px rgba(0,0,0,0.3);
78
- letter-spacing: 0.1em;
79
- font-variant-numeric: tabular-nums;
80
- text-align: center;
81
- }
82
-
83
- .closureOpeningDate {
84
- font-size: 1.2rem;
85
- line-height: 1.1;
86
- font-weight: 400;
87
- color: #fff;
88
- text-shadow: 0 0 8px rgba(0,0,0,0.4);
89
- letter-spacing: 0.5px;
90
- font-family: 'Northlake', sans-serif;
91
- text-transform: lowercase;
92
- text-align: center;
93
- margin-top: 0.5rem;
94
- }
95
-
96
- .browseOurToursButton {
97
- margin-top: 1rem;
98
- background-color: var(--accent-turquoise);
99
- }
@@ -1,98 +0,0 @@
1
- "use client";
2
-
3
- import { useState, useEffect } from 'react';
4
- import { motion } from 'framer-motion';
5
- import EmailSignup from '@/components/email-signup';
6
- import styles from './season-closure-overlay.module.css';
7
- import Link from 'next/link';
8
- import Button, { PresetButtonActions } from './button';
9
-
10
- // Tomorrow at 8:00 AM MDT (MDT = UTC-6, so 8 AM MDT = 14:00 UTC)
11
- function getReopenDate(now: Date): Date {
12
- const denverDateStr = now.toLocaleDateString('en-CA', { timeZone: 'America/Denver' }); // YYYY-MM-DD
13
- const [y, m, d] = denverDateStr.split('-').map(Number);
14
- return new Date(Date.UTC(y, m - 1, d + 1, 14, 0, 0, 0));
15
- }
16
-
17
- function pad2(n: number): string {
18
- return String(n).padStart(2, '0');
19
- }
20
- function pad3(n: number): string {
21
- return String(n).padStart(3, '0');
22
- }
23
-
24
- function getCountdown(now: Date): { days: number; timeText: string } {
25
- const diff = getReopenDate(now).getTime() - now.getTime();
26
- if (diff <= 0) return { days: -1, timeText: "00:00:00.000" };
27
- const totalSeconds = Math.floor(diff / 1000);
28
- const days = Math.floor(totalSeconds / 86400);
29
- const hours = Math.floor((totalSeconds % 86400) / 3600);
30
- const minutes = Math.floor((totalSeconds % 3600) / 60);
31
- const seconds = totalSeconds % 60;
32
- const ms = Math.floor(diff % 1000);
33
- const timeText = `${pad2(hours)}:${pad2(minutes)}:${pad2(seconds)}.${pad3(ms)}`;
34
- return { days, timeText };
35
- }
36
-
37
- interface SeasonClosureOverlayProps {
38
- strings: any;
39
- className?: string;
40
- showBackdrop?: boolean;
41
- }
42
-
43
- export default function SeasonClosureOverlay({ strings, className = "", showBackdrop = true }: SeasonClosureOverlayProps) {
44
- const [countdown, setCountdown] = useState(() => getCountdown(new Date()));
45
- const sc = strings.home.seasonClosure;
46
-
47
- useEffect(() => {
48
- const tick = () => setCountdown(getCountdown(new Date()));
49
- tick();
50
- // 50ms = 20 updates/sec. Smooth enough for ms display, much lighter than 10ms (100/sec).
51
- const id = setInterval(tick, 50);
52
- return () => clearInterval(id);
53
- }, []);
54
-
55
- const content = (
56
- <motion.div
57
- className={styles.seasonClosureCallout}
58
- initial={{ y: 20, opacity: 0, scale: 0.95 }}
59
- animate={{ y: 0, opacity: 1, scale: 1 }}
60
- transition={{
61
- duration: 0.6,
62
- delay: 0.3,
63
- type: "spring",
64
- }}
65
- >
66
- <div className={styles.closureOverlayTop} data-reopen-date="2026-03-11T15:00:00.000Z">
67
- <span className={styles.closureTitle}>{sc.title}</span>
68
- <span className={styles.closureSubtitle}>{sc.daysLine}</span>
69
- <span className={styles.closureCountdownTime}>{countdown.timeText}</span>
70
- <span className={styles.closureOpeningDate}><Link href="https://calendar.google.com/calendar/event?action=TEMPLATE&tmeid=NXU3aTNhaWQ3N2sxZ21lcWVscXZ1bjN0c2IgY184OTI4ZDA1OTdhMzIwZjdhMGVlNDcyNzM5YjFkMzBkMmQ1MTNiYjgwZGI4OTU3Y2M5MGJjNzViM2U2OGFlOTI5QGc&tmsrc=c_8928d0597a320f7a0ee472739b1d30d2d513bb80db8957cc90bc75b3e68ae929%40group.calendar.google.com" target="_blank">{sc.openingDate}</Link></span>
71
- </div>
72
- <div className={styles.closureOverlayBottom}>
73
- <EmailSignup strings={strings} source="hero-closure" />
74
- <Button
75
- action={PresetButtonActions.BOOK_ALL}
76
- className={styles.browseOurToursButton}
77
- isLarge={true}
78
- >
79
- {strings.home.seasonClosure.browseOurTours}
80
- </Button>
81
- </div>
82
- </motion.div>
83
- );
84
-
85
- if (showBackdrop) {
86
- return (
87
- <div className={`${styles.closureOverlayBackdrop} ${className}`}>
88
- {content}
89
- </div>
90
- );
91
- }
92
-
93
- return (
94
- <div className={className}>
95
- {content}
96
- </div>
97
- );
98
- }
@@ -1,69 +0,0 @@
1
- "use client";
2
-
3
- import EmailSignup from "./email-signup";
4
- import styles from './season-closure-overlay.module.css';
5
- import strings from '@/strings';
6
-
7
- interface SimpleModalProps {
8
- isOpen: boolean;
9
- onClose: () => void;
10
- }
11
-
12
- export default function SimpleModal({ isOpen, onClose }: SimpleModalProps) {
13
- if (!isOpen) return null;
14
-
15
- return (
16
- <div
17
- style={{
18
- position: 'fixed',
19
- top: 0,
20
- left: 0,
21
- right: 0,
22
- bottom: 0,
23
- background: 'rgba(0, 0, 0, 0.5)',
24
- display: 'flex',
25
- alignItems: 'center',
26
- justifyContent: 'center',
27
- zIndex: 9999,
28
- padding: '1rem'
29
- }}
30
- onClick={onClose}
31
- >
32
- <div
33
- style={{
34
- background: 'white',
35
- padding: '2rem',
36
- borderRadius: '8px',
37
- boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
38
- maxWidth: '600px',
39
- width: '100%'
40
- }}
41
- onClick={(e) => e.stopPropagation()}
42
- >
43
- <div className={styles.closureOverlayTop}>
44
- <span className={styles.closureTitle} style={{ color: 'var(--accent-orange)', textShadow: 'none' }}>{strings.home.seasonClosure.title}</span>
45
- <span className={styles.closureSubtitle} style={{ color: 'var(--accent-orange)', textShadow: 'none' }}>{strings.home.seasonClosure.subtitle}</span>
46
- <span className={styles.closureSubSubtitle} style={{ color: 'var(--accent-orange)', textShadow: 'none' }}>{strings.home.seasonClosure.message}</span>
47
- </div>
48
-
49
- <p style={{
50
- fontFamily: 'Figtree, sans-serif',
51
- marginTop: '1.5rem',
52
- marginBottom: '1.5rem',
53
- lineHeight: '0.8rem',
54
- color: '#333',
55
- fontSize: '0.8rem',
56
- textAlign: 'center',
57
- }}>
58
- Moraine Lake Road is closed by Parks Canada every year for the winter season. ❄️<br></br> See you next summer!
59
- </p>
60
-
61
- <div className={styles.closureOverlayBottom}>
62
- <div className="email-signup-modal">
63
- <EmailSignup strings={strings} source="simple-modal" />
64
- </div>
65
- </div>
66
- </div>
67
- </div>
68
- );
69
- }
@@ -1,76 +0,0 @@
1
- .topOfFold {
2
- position: relative;
3
- width: 100vw;
4
- overflow: hidden;
5
- }
6
-
7
- .heroImageWrapper {
8
- position: absolute;
9
- top: 0;
10
- left: 0;
11
- right: 0;
12
- width: 100%;
13
- height: 100%;
14
- z-index: 2;
15
- }
16
-
17
- .heroImageWrapper :global(img) {
18
- width: 100%;
19
- height: 100%;
20
- object-fit: cover;
21
- }
22
-
23
- .heroOverlayContent {
24
- position: absolute;
25
- width: 100%;
26
- z-index: 2;
27
- display: flex;
28
- flex-direction: column;
29
- justify-content: center;
30
- align-items: center;
31
- margin-top: 14rem;
32
- }
33
-
34
- .heroTitle {
35
- color: var(--accent-white);
36
- font-size: 5rem;
37
- line-height: 1.2;
38
- text-align: center;
39
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
40
- text-transform: none;
41
- }
42
-
43
- .heroSubtitle {
44
- color: var(--accent-white);
45
- font-size: 2rem;
46
- text-align: center;
47
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
48
- }
49
-
50
- .heroSubsubtitle {
51
- color: var(--accent-white);
52
- font-size: 1.5rem;
53
- text-align: center;
54
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
55
- text-transform: uppercase;
56
- }
57
-
58
- @media (min-width: 1024px) {
59
- .topOfFold {
60
- height: calc(100vh - 98px);
61
- }
62
- }
63
-
64
- @media (max-width: 1023px) {
65
- .heroTitle {
66
- font-size: 3rem;
67
- }
68
-
69
- .heroSubtitle {
70
- font-size: 1.2rem;
71
- }
72
-
73
- .topOfFold {
74
- height: 100vh;
75
- }
76
- }
@@ -1,34 +0,0 @@
1
- import styles from './simple-top-of-fold.module.css';
2
- import { ImageData } from '@/constants/images';
3
- import HeroImage from '@/components/hero-image';
4
-
5
- export type ImagePosition = 'top' | 'center' | 'bottom';
6
-
7
- export interface SimpleTopOfFoldProps {
8
- image: ImageData;
9
- title: string;
10
- subtitle: string;
11
- subsubtitle?: string;
12
- imagePosition?: ImagePosition;
13
- }
14
-
15
- export default function SimpleTopOfFold(props: SimpleTopOfFoldProps) {
16
- const { image, title, subtitle, subsubtitle, imagePosition = 'center' } = props;
17
- return (
18
- <div className={`${styles.topOfFold} global-top-fold`}>
19
- <div className={`${styles.heroImageWrapper} ${styles[imagePosition]}`}>
20
- <HeroImage
21
- imageId={image.id}
22
- alt={image.alt}
23
- objectPosition={imagePosition}
24
- />
25
- </div>
26
-
27
- <div className={styles.heroOverlayContent}>
28
- <h1 className={styles.heroTitle}>{title}</h1>
29
- <h2 className={styles.heroSubtitle}>{subtitle}</h2>
30
- {subsubtitle && <h3 className={styles.heroSubsubtitle}>{subsubtitle}</h3>}
31
- </div>
32
- </div>
33
- );
34
- }
@@ -1,41 +0,0 @@
1
- .spacer {
2
- display: block;
3
- }
4
-
5
- .spacer-vertical {
6
- width: 100%;
7
- }
8
-
9
- .spacer-horizontal {
10
- height: 100%;
11
- display: inline-block;
12
- }
13
-
14
- /* Vertical spacing */
15
- .spacer-small {
16
- height: var(--spacing-small);
17
- }
18
-
19
- .spacer-medium {
20
- height: var(--spacing-medium);
21
- }
22
-
23
- .spacer-large {
24
- height: var(--spacing-large);
25
- }
26
-
27
- /* Horizontal spacing */
28
- .spacer-horizontal.spacer-small {
29
- width: var(--spacing-small);
30
- height: auto;
31
- }
32
-
33
- .spacer-horizontal.spacer-medium {
34
- width: var(--spacing-medium);
35
- height: auto;
36
- }
37
-
38
- .spacer-horizontal.spacer-large {
39
- width: var(--spacing-large);
40
- height: auto;
41
- }
@@ -1,23 +0,0 @@
1
- import './spacer.css';
2
-
3
- const SPACER_SIZES = {
4
- S: 'small',
5
- M: 'medium',
6
- L: 'large'
7
- } as const;
8
-
9
- type SpacerSize = keyof typeof SPACER_SIZES;
10
-
11
- interface SpacerProps {
12
- size?: SpacerSize;
13
- horizontal?: boolean;
14
- className?: string;
15
- }
16
-
17
- const Spacer = ({ className = '', size = 'M', horizontal = false }: SpacerProps) => {
18
- const spacerClass = `spacer spacer-${SPACER_SIZES[size]} ${horizontal ? 'spacer-horizontal' : 'spacer-vertical'} ${className}`;
19
-
20
- return <div className={spacerClass} />;
21
- };
22
-
23
- export default Spacer;
@@ -1,74 +0,0 @@
1
- .container {
2
- display: flex;
3
- align-items: center;
4
- gap: 8px;
5
- }
6
-
7
- .starRating {
8
- display: flex;
9
- gap: 2px;
10
- }
11
-
12
- .starRating.gradientSpacing {
13
- gap: 2px;
14
- }
15
-
16
- /* Add extra spacing around the large center star */
17
- .starRating.gradientSpacing .starLarge {
18
- margin: 0 4px; /* Additional margin on left and right of the center star */
19
- }
20
-
21
- .star {
22
- width: 16px;
23
- height: 16px;
24
- opacity: 0.3;
25
- }
26
-
27
- .star.filled {
28
- opacity: 1;
29
- }
30
-
31
- .verified {
32
- width: 16px;
33
- height: 16px;
34
- position: relative;
35
- }
36
-
37
- .verified:hover::after {
38
- content: "Trustindex verifies that the original source of the review is Google.";
39
- position: absolute;
40
- bottom: 100%;
41
- left: 50%;
42
- transform: translateX(-50%);
43
- background: rgba(0, 0, 0, 0.8);
44
- color: white;
45
- padding: 8px 12px;
46
- border-radius: 4px;
47
- font-size: 12px;
48
- white-space: nowrap;
49
- z-index: 1000;
50
- }
51
-
52
- .align-left {
53
- justify-content: flex-start;
54
- }
55
-
56
- .align-center {
57
- justify-content: center;
58
- }
59
-
60
- .align-right {
61
- justify-content: flex-end;
62
- }
63
-
64
- .starSmall {
65
- transform: scale(0.8);
66
- }
67
-
68
- .starMedium {
69
- transform: scale(1);
70
- }
71
-
72
- .starLarge {
73
- transform: scale(1.4);
74
- }
@@ -1,48 +0,0 @@
1
- import StarIcon from '@/assets/icons/star.svg';
2
- import VerifiedIcon from '@/assets/icons/verified.svg';
3
- import styles from './star-rating.module.css';
4
-
5
- interface StarRatingProps {
6
- rating: number; // Expects a number between 0-5
7
- showVerified?: boolean;
8
- align?: 'left' | 'center' | 'right';
9
- useGradientSize?: boolean; // New prop to control star size pattern
10
- }
11
-
12
- export default function StarRating({
13
- rating,
14
- showVerified = true,
15
- align = 'left',
16
- useGradientSize = false
17
- }: StarRatingProps) {
18
- // Helper function to get size class based on star position
19
- const getStarSizeClass = (position: number) => {
20
- if (!useGradientSize) return '';
21
-
22
- if (position === 3) return styles.starLarge;
23
- if (position === 2 || position === 4) return styles.starMedium;
24
- return styles.starSmall;
25
- };
26
-
27
- return (
28
- <div className={`${styles.container} ${styles[`align-${align}`]}`}>
29
- <div className={`${styles.starRating} ${useGradientSize ? styles.gradientSpacing : ''}`}>
30
- {[1, 2, 3, 4, 5].map((star) => (
31
- <StarIcon
32
- key={star}
33
- className={`
34
- ${styles.star}
35
- ${star <= rating ? styles.filled : styles.empty}
36
- ${getStarSizeClass(star)}
37
- `}
38
- />
39
- ))}
40
- </div>
41
- {showVerified && (
42
- <div className={styles.verified} title="Trustindex verifies that the original source of the review is Google.">
43
- <VerifiedIcon />
44
- </div>
45
- )}
46
- </div>
47
- );
48
- }