@times-components/ts-components 1.145.1-cfea81c4084e6f91221ea00fec9fc730d5b933cb.4 → 1.145.1-e871182934034874ea6a75e1e684090e5504df44.2

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 (136) hide show
  1. package/dist/components/travel-mini-cta/index.d.ts +3 -0
  2. package/dist/components/travel-mini-cta/index.js +86 -0
  3. package/dist/components/travel-mini-cta/styles.d.ts +42 -0
  4. package/dist/components/travel-mini-cta/styles.js +273 -0
  5. package/dist/components/travel-mini-cta/travel-mini-cta.stories.d.ts +110 -0
  6. package/dist/components/travel-mini-cta/travel-mini-cta.stories.js +121 -0
  7. package/dist/components/travel-mini-cta/types.d.ts +10 -0
  8. package/dist/components/{trip-cards → travel-mini-cta}/types.js +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.js +2 -2
  11. package/dist/utils/applyDarkMode.d.ts +1 -0
  12. package/dist/utils/applyDarkMode.js +12 -0
  13. package/dist/utils/getMediaQuery.d.ts +11 -0
  14. package/dist/utils/getMediaQuery.js +19 -0
  15. package/dist/utils/index.d.ts +2 -0
  16. package/dist/utils/index.js +3 -0
  17. package/package.json +3 -3
  18. package/rnw.js +1 -1
  19. package/src/components/travel-mini-cta/index.tsx +164 -0
  20. package/src/components/travel-mini-cta/styles.ts +336 -0
  21. package/src/components/travel-mini-cta/travel-mini-cta.stories.tsx +157 -0
  22. package/src/components/travel-mini-cta/types.ts +10 -0
  23. package/src/index.ts +1 -2
  24. package/src/utils/applyDarkMode.ts +12 -0
  25. package/src/utils/getMediaQuery.ts +25 -0
  26. package/src/utils/index.ts +2 -0
  27. package/dist/components/carousel-component/CarouselComponent.stories.d.ts +0 -1
  28. package/dist/components/carousel-component/CarouselComponent.stories.js +0 -146
  29. package/dist/components/carousel-component/CarouselItem.d.ts +0 -3
  30. package/dist/components/carousel-component/CarouselItem.js +0 -11
  31. package/dist/components/carousel-component/DefaultNavigationArrow.d.ts +0 -8
  32. package/dist/components/carousel-component/DefaultNavigationArrow.js +0 -6
  33. package/dist/components/carousel-component/DefaultPageDot.d.ts +0 -8
  34. package/dist/components/carousel-component/DefaultPageDot.js +0 -4
  35. package/dist/components/carousel-component/__tests__/CarouselComponent.test.d.ts +0 -1
  36. package/dist/components/carousel-component/__tests__/CarouselComponent.test.js +0 -163
  37. package/dist/components/carousel-component/__tests__/CarouselItem.test.d.ts +0 -1
  38. package/dist/components/carousel-component/__tests__/CarouselItem.test.js +0 -80
  39. package/dist/components/carousel-component/__tests__/DefaultNavigationArrow.test.d.ts +0 -1
  40. package/dist/components/carousel-component/__tests__/DefaultNavigationArrow.test.js +0 -62
  41. package/dist/components/carousel-component/__tests__/DefaultPageDot.test.d.ts +0 -1
  42. package/dist/components/carousel-component/__tests__/DefaultPageDot.test.js +0 -68
  43. package/dist/components/carousel-component/hooks/__tests__/useCarousel.test.d.ts +0 -1
  44. package/dist/components/carousel-component/hooks/__tests__/useCarousel.test.js +0 -314
  45. package/dist/components/carousel-component/hooks/useCarousel.d.ts +0 -2
  46. package/dist/components/carousel-component/hooks/useCarousel.js +0 -140
  47. package/dist/components/carousel-component/index.d.ts +0 -4
  48. package/dist/components/carousel-component/index.js +0 -20
  49. package/dist/components/carousel-component/styles.d.ts +0 -30
  50. package/dist/components/carousel-component/styles.js +0 -120
  51. package/dist/components/carousel-component/types.d.ts +0 -46
  52. package/dist/components/carousel-component/types.js +0 -2
  53. package/dist/components/trip-cards/SkeletonCard.d.ts +0 -2
  54. package/dist/components/trip-cards/SkeletonCard.js +0 -21
  55. package/dist/components/trip-cards/TripCard.d.ts +0 -3
  56. package/dist/components/trip-cards/TripCard.js +0 -47
  57. package/dist/components/trip-cards/TripCards.stories.d.ts +0 -1
  58. package/dist/components/trip-cards/TripCards.stories.js +0 -40
  59. package/dist/components/trip-cards/TripCardsLayout.d.ts +0 -3
  60. package/dist/components/trip-cards/TripCardsLayout.js +0 -26
  61. package/dist/components/trip-cards/__tests__/SkeletonCard.test.d.ts +0 -1
  62. package/dist/components/trip-cards/__tests__/SkeletonCard.test.js +0 -139
  63. package/dist/components/trip-cards/__tests__/TripCard.test.d.ts +0 -1
  64. package/dist/components/trip-cards/__tests__/TripCard.test.js +0 -95
  65. package/dist/components/trip-cards/__tests__/TripCardsLayout.test.d.ts +0 -1
  66. package/dist/components/trip-cards/__tests__/TripCardsLayout.test.js +0 -277
  67. package/dist/components/trip-cards/__tests__/assets.test.d.ts +0 -1
  68. package/dist/components/trip-cards/__tests__/assets.test.js +0 -165
  69. package/dist/components/trip-cards/__tests__/helpers.test.d.ts +0 -1
  70. package/dist/components/trip-cards/__tests__/helpers.test.js +0 -135
  71. package/dist/components/trip-cards/__tests__/index.test.d.ts +0 -1
  72. package/dist/components/trip-cards/__tests__/index.test.js +0 -437
  73. package/dist/components/trip-cards/__tests__/mockData.test.d.ts +0 -1
  74. package/dist/components/trip-cards/__tests__/mockData.test.js +0 -57
  75. package/dist/components/trip-cards/__tests__/skeletonStyles.test.d.ts +0 -1
  76. package/dist/components/trip-cards/__tests__/skeletonStyles.test.js +0 -194
  77. package/dist/components/trip-cards/assets/BoatIcon.d.ts +0 -1
  78. package/dist/components/trip-cards/assets/BoatIcon.js +0 -4
  79. package/dist/components/trip-cards/assets/CalendarIcon.d.ts +0 -1
  80. package/dist/components/trip-cards/assets/CalendarIcon.js +0 -4
  81. package/dist/components/trip-cards/assets/ChevronRightIcon.d.ts +0 -1
  82. package/dist/components/trip-cards/assets/ChevronRightIcon.js +0 -4
  83. package/dist/components/trip-cards/assets/LocationIcon.d.ts +0 -1
  84. package/dist/components/trip-cards/assets/LocationIcon.js +0 -4
  85. package/dist/components/trip-cards/assets/MoonIcon.d.ts +0 -1
  86. package/dist/components/trip-cards/assets/MoonIcon.js +0 -4
  87. package/dist/components/trip-cards/assets/index.d.ts +0 -6
  88. package/dist/components/trip-cards/assets/index.js +0 -7
  89. package/dist/components/trip-cards/helpers.d.ts +0 -4
  90. package/dist/components/trip-cards/helpers.js +0 -74
  91. package/dist/components/trip-cards/index.d.ts +0 -4
  92. package/dist/components/trip-cards/index.js +0 -70
  93. package/dist/components/trip-cards/mockData.d.ts +0 -3
  94. package/dist/components/trip-cards/mockData.js +0 -323
  95. package/dist/components/trip-cards/skeletonStyles.d.ts +0 -9
  96. package/dist/components/trip-cards/skeletonStyles.js +0 -37
  97. package/dist/components/trip-cards/styles.d.ts +0 -39
  98. package/dist/components/trip-cards/styles.js +0 -387
  99. package/dist/components/trip-cards/types.d.ts +0 -87
  100. package/src/components/carousel-component/CarouselComponent.stories.tsx +0 -220
  101. package/src/components/carousel-component/CarouselItem.tsx +0 -20
  102. package/src/components/carousel-component/DefaultNavigationArrow.tsx +0 -37
  103. package/src/components/carousel-component/DefaultPageDot.tsx +0 -20
  104. package/src/components/carousel-component/__tests__/CarouselComponent.test.tsx +0 -259
  105. package/src/components/carousel-component/__tests__/CarouselItem.test.tsx +0 -140
  106. package/src/components/carousel-component/__tests__/DefaultNavigationArrow.test.tsx +0 -153
  107. package/src/components/carousel-component/__tests__/DefaultPageDot.test.tsx +0 -105
  108. package/src/components/carousel-component/hooks/__tests__/useCarousel.test.ts +0 -438
  109. package/src/components/carousel-component/hooks/useCarousel.ts +0 -187
  110. package/src/components/carousel-component/index.tsx +0 -88
  111. package/src/components/carousel-component/styles.ts +0 -140
  112. package/src/components/carousel-component/types.ts +0 -51
  113. package/src/components/trip-cards/SkeletonCard.tsx +0 -54
  114. package/src/components/trip-cards/TripCard.tsx +0 -135
  115. package/src/components/trip-cards/TripCards.stories.tsx +0 -67
  116. package/src/components/trip-cards/TripCardsLayout.tsx +0 -75
  117. package/src/components/trip-cards/__tests__/SkeletonCard.test.tsx +0 -169
  118. package/src/components/trip-cards/__tests__/TripCard.test.tsx +0 -120
  119. package/src/components/trip-cards/__tests__/TripCardsLayout.test.tsx +0 -532
  120. package/src/components/trip-cards/__tests__/assets.test.tsx +0 -206
  121. package/src/components/trip-cards/__tests__/helpers.test.ts +0 -165
  122. package/src/components/trip-cards/__tests__/index.test.tsx +0 -499
  123. package/src/components/trip-cards/__tests__/mockData.test.ts +0 -67
  124. package/src/components/trip-cards/__tests__/skeletonStyles.test.tsx +0 -256
  125. package/src/components/trip-cards/assets/BoatIcon.tsx +0 -17
  126. package/src/components/trip-cards/assets/CalendarIcon.tsx +0 -17
  127. package/src/components/trip-cards/assets/ChevronRightIcon.tsx +0 -20
  128. package/src/components/trip-cards/assets/LocationIcon.tsx +0 -17
  129. package/src/components/trip-cards/assets/MoonIcon.tsx +0 -17
  130. package/src/components/trip-cards/assets/index.ts +0 -7
  131. package/src/components/trip-cards/helpers.ts +0 -99
  132. package/src/components/trip-cards/index.tsx +0 -104
  133. package/src/components/trip-cards/mockData.ts +0 -351
  134. package/src/components/trip-cards/skeletonStyles.ts +0 -46
  135. package/src/components/trip-cards/styles.ts +0 -426
  136. package/src/components/trip-cards/types.ts +0 -91
@@ -0,0 +1,164 @@
1
+ import React, { FC, useState, useRef, useEffect, MouseEvent } from 'react';
2
+ import { TravelMiniCTAProps } from './types';
3
+ import {
4
+ Container,
5
+ ContentWrapper,
6
+ LeftSection,
7
+ LogoContainer,
8
+ LogoBox,
9
+ LogoText,
10
+ TextContainer,
11
+ Label,
12
+ MobileLabel,
13
+ Description,
14
+ RightSection,
15
+ ContactInfo,
16
+ PhoneLabel,
17
+ PhoneNumber,
18
+ WorkingHoursContainer,
19
+ WorkingHoursText,
20
+ ButtonsContainer,
21
+ PrimaryButton,
22
+ SecondaryButton
23
+ } from './styles';
24
+
25
+ export const TravelMiniCTA: FC<TravelMiniCTAProps> = ({
26
+ description,
27
+ phoneLabel,
28
+ phoneNumber,
29
+ workingHours,
30
+ primaryButtonText,
31
+ secondaryButtonText,
32
+ secondaryButtonUrl,
33
+ isApp
34
+ }) => {
35
+ const [chatReady, setChatReady] = useState(false);
36
+ const [chatFailed, setChatFailed] = useState(false);
37
+ const chatDivRef = useRef<HTMLDivElement>(null);
38
+
39
+ const formattedWorkingHours = workingHours
40
+ ? workingHours.split(',').map(hour => hour.trim())
41
+ : [];
42
+
43
+ const handlePrimaryButtonClick = (
44
+ e: MouseEvent<HTMLButtonElement | HTMLAnchorElement>
45
+ ) => {
46
+ e.preventDefault();
47
+
48
+ const chatDiv = chatDivRef.current;
49
+ if (chatDiv) {
50
+ const lpEventElement = chatDiv.querySelector(
51
+ '[data-lp-event]'
52
+ ) as HTMLElement;
53
+ if (lpEventElement) {
54
+ lpEventElement.click();
55
+ }
56
+ }
57
+ };
58
+
59
+ useEffect(
60
+ () => {
61
+ const chatDiv = chatDivRef.current;
62
+ if (!chatDiv || typeof window === 'undefined') {
63
+ return;
64
+ }
65
+
66
+ let timeoutId: NodeJS.Timeout | null = null;
67
+ let previouslyFound = false;
68
+
69
+ const observer = new MutationObserver(() => {
70
+ const lpEventElement = chatDiv.querySelector(
71
+ '[data-lp-event]'
72
+ ) as HTMLElement;
73
+
74
+ if (lpEventElement && !previouslyFound) {
75
+ previouslyFound = true;
76
+ setChatReady(true);
77
+ setChatFailed(false);
78
+
79
+ if (primaryButtonText) {
80
+ lpEventElement.textContent = primaryButtonText;
81
+ }
82
+
83
+ // Clear timeout since chat loaded successfully
84
+ if (timeoutId) {
85
+ clearTimeout(timeoutId);
86
+ timeoutId = null;
87
+ }
88
+ } else if (!lpEventElement && previouslyFound) {
89
+ previouslyFound = false;
90
+ setChatReady(false);
91
+ setChatFailed(false);
92
+ }
93
+ });
94
+
95
+ observer.observe(chatDiv, { childList: true, subtree: true });
96
+
97
+ timeoutId = setTimeout(() => {
98
+ if (!previouslyFound) {
99
+ observer.disconnect();
100
+ setChatFailed(true);
101
+ }
102
+ }, 15000);
103
+
104
+ return () => {
105
+ observer.disconnect();
106
+ if (timeoutId) {
107
+ clearTimeout(timeoutId);
108
+ }
109
+ };
110
+ },
111
+ [primaryButtonText]
112
+ );
113
+
114
+ return (
115
+ <Container data-testid="travel-mini-cta" isApp={isApp}>
116
+ <ContentWrapper>
117
+ <LeftSection>
118
+ <LogoContainer>
119
+ <LogoBox isApp={isApp}>
120
+ <LogoText isApp={isApp}>T</LogoText>
121
+ </LogoBox>
122
+ <MobileLabel isApp={isApp}>VISIT TIMES HOLIDAYS</MobileLabel>
123
+ </LogoContainer>
124
+ <TextContainer>
125
+ <Label isApp={isApp}>VISIT TIMES HOLIDAYS</Label>
126
+ <Description isApp={isApp}>{description}</Description>
127
+ </TextContainer>
128
+ </LeftSection>
129
+
130
+ <RightSection>
131
+ <ContactInfo>
132
+ <PhoneLabel href={`tel:${phoneNumber}`} isApp={isApp}>
133
+ {phoneLabel}{' '}
134
+ <PhoneNumber isApp={isApp}>{phoneNumber}</PhoneNumber>
135
+ </PhoneLabel>
136
+ <WorkingHoursContainer>
137
+ {formattedWorkingHours.map((hours, index) => (
138
+ <WorkingHoursText key={index} isApp={isApp}>
139
+ {hours}
140
+ </WorkingHoursText>
141
+ ))}
142
+ </WorkingHoursContainer>
143
+ </ContactInfo>
144
+ <ButtonsContainer>
145
+ <PrimaryButton
146
+ as="button"
147
+ type="button"
148
+ onClick={handlePrimaryButtonClick}
149
+ isApp={isApp}
150
+ disabled={!chatReady}
151
+ >
152
+ {chatFailed && 'Chat unavailable'}
153
+ {!chatReady && !chatFailed && 'Loading chat...'}
154
+ <div id="LP_DIV_TRAVEL_1239001" ref={chatDivRef} />
155
+ </PrimaryButton>
156
+ <SecondaryButton href={secondaryButtonUrl} isApp={isApp}>
157
+ {secondaryButtonText}
158
+ </SecondaryButton>
159
+ </ButtonsContainer>
160
+ </RightSection>
161
+ </ContentWrapper>
162
+ </Container>
163
+ );
164
+ };
@@ -0,0 +1,336 @@
1
+ import styled from 'styled-components';
2
+ import { getMediaQuery, applyDarkMode } from '../../utils';
3
+
4
+ const BaseLabel = styled.div<{ isApp?: boolean }>`
5
+ font-family: 'Roboto';
6
+ font-weight: 500;
7
+ line-height: 1.125;
8
+ font-size: 0.875rem;
9
+ letter-spacing: 0em;
10
+ color: #01000d;
11
+ text-transform: uppercase;
12
+
13
+ ${({ isApp }) =>
14
+ applyDarkMode(
15
+ `
16
+ color: #f5f5f5 !important;
17
+ `,
18
+ isApp
19
+ )};
20
+ `;
21
+
22
+ export const Container = styled.div<{ isApp?: boolean }>`
23
+ background-color: #ffffff;
24
+ padding: 24px;
25
+ border-top: 1px dashed;
26
+ border-bottom: 1px dashed;
27
+ border-color: #cccccc;
28
+
29
+ ${({ isApp }) =>
30
+ applyDarkMode(
31
+ `
32
+ background-color: #f5f5f5 !important;
33
+ border-color: #e4e4e4 !important;
34
+ `,
35
+ isApp
36
+ )};
37
+ `;
38
+
39
+ export const ContentWrapper = styled.div`
40
+ display: flex;
41
+ flex-direction: row;
42
+ justify-content: space-between;
43
+ align-items: flex-start;
44
+ gap: 20px;
45
+
46
+ ${getMediaQuery('xs', 'md')} {
47
+ flex-direction: column;
48
+ gap: 24px;
49
+ }
50
+ `;
51
+
52
+ export const LeftSection = styled.div`
53
+ display: flex;
54
+ flex-direction: row;
55
+ align-items: flex-start;
56
+ width: 50%;
57
+ gap: 24px;
58
+
59
+ ${getMediaQuery('xs', 'md')} {
60
+ width: 100%;
61
+ flex-direction: column;
62
+ gap: 16px;
63
+ }
64
+ `;
65
+
66
+ export const LogoContainer = styled.div`
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ flex-shrink: 0;
71
+
72
+ ${getMediaQuery('xs', 'md')} {
73
+ flex-direction: row-reverse;
74
+ justify-content: flex-start;
75
+ justify-content: space-between;
76
+ width: 100%;
77
+ }
78
+ `;
79
+
80
+ export const LogoBox = styled.div<{ isApp?: boolean }>`
81
+ width: 40px;
82
+ height: 40px;
83
+ position: relative;
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ background-color: #aaaaaa;
88
+
89
+ ${({ isApp }) =>
90
+ applyDarkMode(
91
+ `
92
+ background-color: #c2c2c2 !important;
93
+ `,
94
+ isApp
95
+ )};
96
+ `;
97
+
98
+ export const LogoText = styled.span<{ isApp?: boolean }>`
99
+ font-family: 'Times Modern', serif;
100
+ font-weight: 700;
101
+ font-size: 40px;
102
+ line-height: 1.125;
103
+ letter-spacing: 0.02em;
104
+ color: #ffffff;
105
+ padding-top: 4px;
106
+
107
+ ${({ isApp }) =>
108
+ applyDarkMode(
109
+ `
110
+ color: #1d1d1b !important;
111
+ `,
112
+ isApp
113
+ )};
114
+ `;
115
+
116
+ export const TextContainer = styled.div`
117
+ display: flex;
118
+ flex-direction: column;
119
+ gap: 16px;
120
+ max-width: 375px;
121
+
122
+ ${getMediaQuery('xs', 'md')} {
123
+ gap: 24px;
124
+ }
125
+ `;
126
+
127
+ export const Label = styled(BaseLabel)`
128
+ ${getMediaQuery('xs', 'md')} {
129
+ display: none;
130
+ }
131
+ `;
132
+
133
+ export const MobileLabel = styled(BaseLabel)`
134
+ display: none;
135
+
136
+ ${getMediaQuery('xs', 'md')} {
137
+ display: block;
138
+ }
139
+ `;
140
+
141
+ export const Description = styled.div<{ isApp?: boolean }>`
142
+ font-family: 'Times Modern';
143
+ font-weight: 700;
144
+ line-height: 1.125;
145
+ font-size: 1.5rem;
146
+ letter-spacing: 0em;
147
+ color: #333333;
148
+
149
+ ${({ isApp }) =>
150
+ applyDarkMode(
151
+ `
152
+ color: #cccccc !important;
153
+ `,
154
+ isApp
155
+ )};
156
+
157
+ ${getMediaQuery('xs', 'md')} {
158
+ margin-right: 64px;
159
+ }
160
+ `;
161
+
162
+ export const RightSection = styled.div`
163
+ display: flex;
164
+ flex-direction: column;
165
+ gap: 24px;
166
+ width: 50%;
167
+
168
+ ${getMediaQuery('xs', 'md')} {
169
+ gap: 32px;
170
+ width: 100%;
171
+ }
172
+ `;
173
+
174
+ export const ContactInfo = styled.div`
175
+ display: flex;
176
+ flex-direction: column;
177
+ gap: 16px;
178
+ `;
179
+
180
+ export const PhoneLabel = styled.a<{ isApp?: boolean }>`
181
+ text-decoration: none;
182
+ display: inline;
183
+ font-family: 'Times Digital W04 Regular';
184
+ font-weight: 400;
185
+ line-height: 1.5;
186
+ font-size: 1.125rem;
187
+ letter-spacing: 0em;
188
+ color: #333333;
189
+ cursor: pointer;
190
+
191
+ ${({ isApp }) =>
192
+ applyDarkMode(
193
+ `
194
+ color: #c2c2c2 !important;
195
+ `,
196
+ isApp
197
+ )};
198
+
199
+ &:hover {
200
+ text-decoration: underline;
201
+ }
202
+ `;
203
+
204
+ export const PhoneNumber = styled.span<{ isApp?: boolean }>`
205
+ font-family: 'Times Modern';
206
+ font-weight: 700;
207
+ line-height: 1.125;
208
+ font-size: 1.5rem;
209
+ letter-spacing: 0em;
210
+ color: #333333;
211
+ font-size: 2.2rem;
212
+
213
+ ${({ isApp }) =>
214
+ applyDarkMode(
215
+ `
216
+ color: #c2c2c2 !important;
217
+ `,
218
+ isApp
219
+ )};
220
+ `;
221
+
222
+ export const WorkingHoursContainer = styled.div`
223
+ display: flex;
224
+ flex-direction: row;
225
+ gap: 8px;
226
+ flex-wrap: wrap;
227
+
228
+ ${getMediaQuery('xs', 'md')} {
229
+ flex-direction: column;
230
+ }
231
+ `;
232
+
233
+ export const WorkingHoursText = styled.div<{ isApp?: boolean }>`
234
+ font-family: 'Times Digital W04 Regular';
235
+ font-weight: 400;
236
+ line-height: 1.5;
237
+ font-size: 1.125rem;
238
+ letter-spacing: 0em;
239
+ color: #333333;
240
+
241
+ ${({ isApp }) =>
242
+ applyDarkMode(
243
+ `
244
+ color: #cccccc !important;
245
+ `,
246
+ isApp
247
+ )};
248
+ `;
249
+
250
+ export const ButtonsContainer = styled.div`
251
+ display: flex;
252
+ flex-direction: row;
253
+ gap: 16px;
254
+
255
+ ${getMediaQuery('xs', 'md')} {
256
+ flex-direction: column;
257
+ }
258
+ `;
259
+
260
+ const BaseButton = styled.a`
261
+ text-decoration: none;
262
+ border-radius: 0px;
263
+ width: 100%;
264
+ min-height: 44px;
265
+ font-family: 'Roboto';
266
+ font-weight: 500;
267
+ line-height: 1.5;
268
+ font-size: 1rem;
269
+ letter-spacing: 0em;
270
+ display: flex;
271
+ align-items: center;
272
+ justify-content: center;
273
+ padding: 12px;
274
+ cursor: pointer;
275
+ transition: all 0.2s ease;
276
+ `;
277
+
278
+ export const PrimaryButton = styled(BaseButton)<{
279
+ disabled?: boolean;
280
+ isApp?: boolean;
281
+ }>`
282
+ border: none;
283
+ background-color: #005c8a;
284
+ color: #ffffff;
285
+ cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
286
+ opacity: ${({ disabled }) => (disabled ? 0.6 : 1)};
287
+
288
+ div[data-lp-event] {
289
+ cursor: pointer;
290
+ font-family: 'Roboto';
291
+ font-weight: 500;
292
+ line-height: 1.5;
293
+ font-size: 1rem;
294
+ letter-spacing: 0em;
295
+ }
296
+
297
+ &:hover {
298
+ background-color: #00527a;
299
+ }
300
+
301
+ ${({ isApp }) =>
302
+ applyDarkMode(
303
+ `
304
+ background-color: #74bade !important;
305
+ color: #1d1d1b !important;
306
+
307
+ &:hover {
308
+ background-color: #93cbe8 !important;
309
+ }
310
+ `,
311
+ isApp
312
+ )};
313
+ `;
314
+
315
+ export const SecondaryButton = styled(BaseButton)<{ isApp?: boolean }>`
316
+ border: 1px solid #005c8a;
317
+ background-color: transparent;
318
+ color: #005c8a;
319
+
320
+ &:hover {
321
+ background-color: #f5f5f5;
322
+ }
323
+
324
+ ${({ isApp }) =>
325
+ applyDarkMode(
326
+ `
327
+ border-color: #74bade !important;
328
+ color: #74bade !important;
329
+
330
+ &:hover {
331
+ background-color: #01000d !important;
332
+ }
333
+ `,
334
+ isApp
335
+ )};
336
+ `;
@@ -0,0 +1,157 @@
1
+ import React from 'react';
2
+ import { TravelMiniCTA } from './index';
3
+ import { TravelMiniCTAProps } from './types';
4
+
5
+ const TravelMiniCTAStory = ({
6
+ description,
7
+ phoneLabel,
8
+ phoneNumber,
9
+ workingHours,
10
+ primaryButtonText,
11
+ secondaryButtonText,
12
+ secondaryButtonUrl
13
+ }: TravelMiniCTAProps) => {
14
+ return (
15
+ <div
16
+ style={{
17
+ padding: '16px'
18
+ }}
19
+ >
20
+ <TravelMiniCTA
21
+ description={description}
22
+ phoneLabel={phoneLabel}
23
+ phoneNumber={phoneNumber}
24
+ workingHours={workingHours}
25
+ primaryButtonText={primaryButtonText}
26
+ secondaryButtonText={secondaryButtonText}
27
+ secondaryButtonUrl={secondaryButtonUrl}
28
+ />
29
+ </div>
30
+ );
31
+ };
32
+
33
+ export default {
34
+ title: 'Typescript Component/Travel Mini CTA',
35
+ component: TravelMiniCTA,
36
+ parameters: {
37
+ docs: {
38
+ subtitle:
39
+ 'The `TravelMiniCTA` component displays a call-to-action for travel services with contact information and action buttons.',
40
+ description: {
41
+ component:
42
+ 'A responsive component that shows travel expert contact details, working hours, and primary/secondary action buttons. The layout adapts for mobile, tablet, and desktop viewports.'
43
+ }
44
+ }
45
+ }
46
+ };
47
+
48
+ export const Default = {
49
+ render: TravelMiniCTAStory,
50
+ name: 'Travel Mini CTA - Default',
51
+
52
+ args: {
53
+ description:
54
+ 'Begin your journey to Croatia with a holiday designed around you, guided by a dedicated travel expert.',
55
+ phoneLabel: 'Call us on',
56
+ phoneNumber: '08083049757',
57
+ workingHours: ['Mon - Fri: 9am - 6pm', 'Sat: 10am - 5pm'],
58
+ primaryButtonText: 'Chat with us',
59
+ secondaryButtonText: 'Enquire now',
60
+ secondaryButtonUrl: '/enquire'
61
+ },
62
+
63
+ argTypes: {
64
+ description: {
65
+ control: {
66
+ type: 'text'
67
+ },
68
+ description: 'Main description text for the CTA'
69
+ },
70
+ phoneLabel: {
71
+ control: {
72
+ type: 'text'
73
+ },
74
+ description: 'Label text before the phone number'
75
+ },
76
+ phoneNumber: {
77
+ control: {
78
+ type: 'text'
79
+ },
80
+ description: 'Phone number for contact (creates tel: link)'
81
+ },
82
+ workingHours: {
83
+ control: {
84
+ type: 'object'
85
+ },
86
+ description: 'Array of working hours strings'
87
+ },
88
+ primaryButtonText: {
89
+ control: {
90
+ type: 'text'
91
+ },
92
+ description: 'Text for the primary action button'
93
+ },
94
+ secondaryButtonText: {
95
+ control: {
96
+ type: 'text'
97
+ },
98
+ description: 'Text for the secondary action button'
99
+ },
100
+ secondaryButtonUrl: {
101
+ control: {
102
+ type: 'text'
103
+ },
104
+ description: 'URL for the secondary button link'
105
+ }
106
+ }
107
+ };
108
+
109
+ export const MinimalContent = {
110
+ render: TravelMiniCTAStory,
111
+ name: 'Travel Mini CTA - Minimal',
112
+
113
+ args: {
114
+ description: 'Discover your perfect holiday with expert guidance.',
115
+ phoneLabel: 'Call us',
116
+ phoneNumber: '0800 123 4567',
117
+ primaryButtonText: 'Get started',
118
+ secondaryButtonText: 'Learn more',
119
+ secondaryButtonUrl: '/learn-more'
120
+ }
121
+ };
122
+
123
+ export const ExtendedWorkingHours = {
124
+ render: TravelMiniCTAStory,
125
+ name: 'Travel Mini CTA - Extended Hours',
126
+
127
+ args: {
128
+ description:
129
+ 'Plan your dream vacation with our 24/7 travel concierge service.',
130
+ phoneLabel: 'Contact us on',
131
+ phoneNumber: '+44 20 1234 5678',
132
+ workingHours: [
133
+ 'Mon - Thu: 8am - 8pm',
134
+ 'Fri: 8am - 6pm',
135
+ 'Sat: 9am - 5pm',
136
+ 'Sun: 10am - 4pm'
137
+ ],
138
+ primaryButtonText: 'Start chatting',
139
+ secondaryButtonText: 'View packages',
140
+ secondaryButtonUrl: '/packages'
141
+ }
142
+ };
143
+
144
+ export const CustomDestination = {
145
+ render: TravelMiniCTAStory,
146
+ name: 'Travel Mini CTA - Custom Description',
147
+
148
+ args: {
149
+ description: 'This is a placeholder for description.',
150
+ phoneLabel: 'Ring us on',
151
+ phoneNumber: '0808 1234567',
152
+ workingHours: ['Mon - Sat: 9am - 7pm', 'Sun: Closed'],
153
+ primaryButtonText: 'Talk to an expert',
154
+ secondaryButtonText: 'Request callback',
155
+ secondaryButtonUrl: '/callback'
156
+ }
157
+ };
@@ -0,0 +1,10 @@
1
+ export interface TravelMiniCTAProps {
2
+ description?: string;
3
+ phoneLabel?: string;
4
+ phoneNumber?: string;
5
+ workingHours?: string;
6
+ primaryButtonText?: string;
7
+ secondaryButtonText?: string;
8
+ secondaryButtonUrl?: string;
9
+ isApp?: boolean;
10
+ }
package/src/index.ts CHANGED
@@ -32,6 +32,7 @@ export {
32
32
  } from './components/update-button/update-button-with-delay';
33
33
  export { Banner } from './components/banner/banner';
34
34
  export { JobTitle } from './components/job-title/job-title';
35
+ export { TravelMiniCTA } from './components/travel-mini-cta';
35
36
 
36
37
  // Newsletter Components
37
38
  export {
@@ -104,8 +105,6 @@ export {
104
105
  default as ArticleHeader
105
106
  } from './components/article-header/ArticleHeader';
106
107
 
107
- export { TripCards } from './components/trip-cards';
108
-
109
108
  export {
110
109
  UpdatedTimestamp
111
110
  } from './components/updated-timestamp/UpdatedTimestamp';
@@ -0,0 +1,12 @@
1
+ // Helper for dark mode styling
2
+ export const applyDarkMode = (styles: string, isApp?: boolean) => {
3
+ if (!isApp) {
4
+ return '';
5
+ }
6
+
7
+ return `
8
+ @media (prefers-color-scheme: dark) {
9
+ ${styles}
10
+ }
11
+ `;
12
+ };
@@ -0,0 +1,25 @@
1
+ export const breakpoints = {
2
+ xs: 0,
3
+ sm: 520,
4
+ md: 768,
5
+ lg: 1024,
6
+ xl: 1320,
7
+ all: 0
8
+ };
9
+
10
+ export type BreakPointKeys = keyof typeof breakpoints;
11
+ export type MQ = Partial<Record<BreakPointKeys, string>> | string;
12
+
13
+ export const getMediaQuery = (
14
+ minWidth?: keyof typeof breakpoints,
15
+ maxWidth?: keyof typeof breakpoints
16
+ ) => () => {
17
+ const queries = ['@media screen'];
18
+ if (minWidth && breakpoints[minWidth]) {
19
+ queries.push(` and (min-width: ${breakpoints[minWidth]}px)`);
20
+ }
21
+ if (maxWidth) {
22
+ queries.push(` and (max-width: ${breakpoints[maxWidth] - 1}px)`);
23
+ }
24
+ return queries.join('');
25
+ };