@times-components/ts-components 1.146.2-0f9388fe36c532b90db3f35d17847fc17a611f1e.44 → 1.146.2-9d94da839cee591620d598d11e637971d7109888.26

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 (138) hide show
  1. package/dist/components/travel-mini-cta/__tests__/index.test.js +262 -0
  2. package/dist/components/travel-mini-cta/index.d.ts +10 -0
  3. package/dist/components/travel-mini-cta/index.js +93 -0
  4. package/dist/components/travel-mini-cta/styles.d.ts +44 -0
  5. package/dist/components/travel-mini-cta/styles.js +269 -0
  6. package/dist/components/travel-mini-cta/travel-mini-cta.stories.js +8 -0
  7. package/dist/components/travel-mini-cta/types.d.ts +11 -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/__tests__/__snapshots__/index.test.tsx.snap +211 -0
  20. package/src/components/travel-mini-cta/__tests__/index.test.tsx +330 -0
  21. package/src/components/travel-mini-cta/index.tsx +191 -0
  22. package/src/components/travel-mini-cta/styles.ts +333 -0
  23. package/src/components/travel-mini-cta/travel-mini-cta.stories.tsx +23 -0
  24. package/src/components/travel-mini-cta/types.ts +11 -0
  25. package/src/index.ts +1 -2
  26. package/src/utils/applyDarkMode.ts +12 -0
  27. package/src/utils/getMediaQuery.ts +25 -0
  28. package/src/utils/index.ts +2 -0
  29. package/dist/components/carousel-component/CarouselComponent.stories.js +0 -146
  30. package/dist/components/carousel-component/CarouselItem.d.ts +0 -3
  31. package/dist/components/carousel-component/CarouselItem.js +0 -12
  32. package/dist/components/carousel-component/DefaultNavigationArrow.d.ts +0 -8
  33. package/dist/components/carousel-component/DefaultNavigationArrow.js +0 -6
  34. package/dist/components/carousel-component/DefaultPageDot.d.ts +0 -8
  35. package/dist/components/carousel-component/DefaultPageDot.js +0 -4
  36. package/dist/components/carousel-component/__tests__/CarouselComponent.test.d.ts +0 -1
  37. package/dist/components/carousel-component/__tests__/CarouselComponent.test.js +0 -163
  38. package/dist/components/carousel-component/__tests__/CarouselItem.test.d.ts +0 -1
  39. package/dist/components/carousel-component/__tests__/CarouselItem.test.js +0 -80
  40. package/dist/components/carousel-component/__tests__/DefaultNavigationArrow.test.d.ts +0 -1
  41. package/dist/components/carousel-component/__tests__/DefaultNavigationArrow.test.js +0 -62
  42. package/dist/components/carousel-component/__tests__/DefaultPageDot.test.d.ts +0 -1
  43. package/dist/components/carousel-component/__tests__/DefaultPageDot.test.js +0 -68
  44. package/dist/components/carousel-component/hooks/__tests__/useCarousel.test.d.ts +0 -1
  45. package/dist/components/carousel-component/hooks/__tests__/useCarousel.test.js +0 -459
  46. package/dist/components/carousel-component/hooks/useCarousel.d.ts +0 -2
  47. package/dist/components/carousel-component/hooks/useCarousel.js +0 -167
  48. package/dist/components/carousel-component/index.d.ts +0 -4
  49. package/dist/components/carousel-component/index.js +0 -20
  50. package/dist/components/carousel-component/styles.d.ts +0 -28
  51. package/dist/components/carousel-component/styles.js +0 -172
  52. package/dist/components/carousel-component/types.d.ts +0 -53
  53. package/dist/components/carousel-component/types.js +0 -2
  54. package/dist/components/trip-cards/SkeletonCard.d.ts +0 -7
  55. package/dist/components/trip-cards/SkeletonCard.js +0 -22
  56. package/dist/components/trip-cards/TripCard.d.ts +0 -3
  57. package/dist/components/trip-cards/TripCard.js +0 -49
  58. package/dist/components/trip-cards/TripCards.stories.d.ts +0 -1
  59. package/dist/components/trip-cards/TripCards.stories.js +0 -159
  60. package/dist/components/trip-cards/TripCardsLayout.d.ts +0 -3
  61. package/dist/components/trip-cards/TripCardsLayout.js +0 -56
  62. package/dist/components/trip-cards/__tests__/SkeletonCard.test.d.ts +0 -1
  63. package/dist/components/trip-cards/__tests__/SkeletonCard.test.js +0 -139
  64. package/dist/components/trip-cards/__tests__/TripCard.test.d.ts +0 -1
  65. package/dist/components/trip-cards/__tests__/TripCard.test.js +0 -95
  66. package/dist/components/trip-cards/__tests__/TripCardsLayout.test.d.ts +0 -1
  67. package/dist/components/trip-cards/__tests__/TripCardsLayout.test.js +0 -314
  68. package/dist/components/trip-cards/__tests__/assets.test.d.ts +0 -1
  69. package/dist/components/trip-cards/__tests__/assets.test.js +0 -165
  70. package/dist/components/trip-cards/__tests__/helpers.test.d.ts +0 -1
  71. package/dist/components/trip-cards/__tests__/helpers.test.js +0 -220
  72. package/dist/components/trip-cards/__tests__/index.test.js +0 -478
  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 -11
  90. package/dist/components/trip-cards/helpers.js +0 -138
  91. package/dist/components/trip-cards/index.d.ts +0 -4
  92. package/dist/components/trip-cards/index.js +0 -68
  93. package/dist/components/trip-cards/mockData.d.ts +0 -3
  94. package/dist/components/trip-cards/mockData.js +0 -317
  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 -43
  98. package/dist/components/trip-cards/styles.js +0 -404
  99. package/dist/components/trip-cards/types.d.ts +0 -119
  100. package/src/components/carousel-component/CarouselComponent.stories.tsx +0 -220
  101. package/src/components/carousel-component/CarouselItem.tsx +0 -26
  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 -625
  109. package/src/components/carousel-component/hooks/useCarousel.ts +0 -229
  110. package/src/components/carousel-component/index.tsx +0 -92
  111. package/src/components/carousel-component/styles.ts +0 -188
  112. package/src/components/carousel-component/types.ts +0 -62
  113. package/src/components/trip-cards/SkeletonCard.tsx +0 -64
  114. package/src/components/trip-cards/TripCard.tsx +0 -140
  115. package/src/components/trip-cards/TripCards.stories.tsx +0 -224
  116. package/src/components/trip-cards/TripCardsLayout.tsx +0 -145
  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 -583
  120. package/src/components/trip-cards/__tests__/assets.test.tsx +0 -206
  121. package/src/components/trip-cards/__tests__/helpers.test.ts +0 -272
  122. package/src/components/trip-cards/__tests__/index.test.tsx +0 -550
  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 -176
  132. package/src/components/trip-cards/index.tsx +0 -119
  133. package/src/components/trip-cards/mockData.ts +0 -345
  134. package/src/components/trip-cards/skeletonStyles.ts +0 -46
  135. package/src/components/trip-cards/styles.ts +0 -450
  136. package/src/components/trip-cards/types.ts +0 -128
  137. /package/dist/components/{trip-cards → travel-mini-cta}/__tests__/index.test.d.ts +0 -0
  138. /package/dist/components/{carousel-component/CarouselComponent.stories.d.ts → travel-mini-cta/travel-mini-cta.stories.d.ts} +0 -0
@@ -0,0 +1,191 @@
1
+ import React, { useEffect, useState, useRef, MouseEvent, FC } 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
+ // Extend Window interface for LivePerson
26
+ declare global {
27
+ interface Window {
28
+ lpTag?: {
29
+ [key: string]: any;
30
+ };
31
+ }
32
+ }
33
+
34
+ export const TravelMiniCTA: FC<TravelMiniCTAProps> = ({
35
+ description,
36
+ phoneLabel,
37
+ phoneNumber,
38
+ workingHours,
39
+ primaryButtonText,
40
+ secondaryButtonText,
41
+ secondaryButtonUrl,
42
+ isApp,
43
+ isOnChannelPage = false
44
+ }) => {
45
+ const [chatReady, setChatReady] = useState(false);
46
+ const [chatFailed, setChatFailed] = useState(false);
47
+ const [buttonText, setButtonText] = useState('Loading chat...');
48
+ const chatDivRef = useRef<HTMLDivElement>(null);
49
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null);
50
+ const observerRef = useRef<MutationObserver | null>(null);
51
+
52
+ const handlePrimaryButtonClick = (
53
+ e: MouseEvent<HTMLButtonElement | HTMLAnchorElement>
54
+ ) => {
55
+ e.preventDefault();
56
+
57
+ const chatDiv = chatDivRef.current;
58
+ if (chatDiv) {
59
+ const lpEventElement = chatDiv.querySelector(
60
+ '[data-lp-event]'
61
+ ) as HTMLElement;
62
+ if (lpEventElement) {
63
+ lpEventElement.click();
64
+ }
65
+ }
66
+ };
67
+
68
+ useEffect(
69
+ () => {
70
+ if (typeof window === 'undefined') {
71
+ return;
72
+ }
73
+
74
+ const cleanup = () => {
75
+ if (timeoutRef.current) {
76
+ clearTimeout(timeoutRef.current);
77
+ timeoutRef.current = null;
78
+ }
79
+ if (observerRef.current) {
80
+ observerRef.current.disconnect();
81
+ observerRef.current = null;
82
+ }
83
+ };
84
+
85
+ const handleChatReady = () => {
86
+ cleanup();
87
+ setChatReady(true);
88
+ setChatFailed(false);
89
+ setButtonText(primaryButtonText || 'Chat with us');
90
+ };
91
+
92
+ const handleChatFailed = () => {
93
+ cleanup();
94
+ setChatReady(false);
95
+ setChatFailed(true);
96
+ setButtonText('Call us');
97
+ };
98
+
99
+ // Check if LivePerson is already loaded
100
+ if (window.lpTag && window.lpTag.loaded) {
101
+ handleChatReady();
102
+ return cleanup;
103
+ }
104
+
105
+ // Set up MutationObserver to detect when LivePerson loads
106
+ const chatDiv = chatDivRef.current;
107
+ if (!chatDiv) {
108
+ return cleanup;
109
+ }
110
+
111
+ observerRef.current = new MutationObserver(() => {
112
+ const lpEventElement = chatDiv.querySelector('[data-lp-event]');
113
+ if (lpEventElement) {
114
+ handleChatReady();
115
+ }
116
+ });
117
+
118
+ observerRef.current.observe(chatDiv, {
119
+ childList: true,
120
+ subtree: true
121
+ });
122
+
123
+ // Fallback: If LivePerson doesn't load in 15s, show "Call us"
124
+ timeoutRef.current = setTimeout(handleChatFailed, 15000);
125
+
126
+ return cleanup;
127
+ },
128
+ [primaryButtonText]
129
+ );
130
+
131
+ return (
132
+ <Container data-testid="travel-mini-cta" isApp={isApp}>
133
+ <ContentWrapper>
134
+ <LeftSection>
135
+ <LogoContainer>
136
+ <LogoBox isApp={isApp}>
137
+ <LogoText isApp={isApp}>T</LogoText>
138
+ </LogoBox>
139
+ <MobileLabel isApp={isApp}>TIMES HOLIDAYS</MobileLabel>
140
+ </LogoContainer>
141
+ <TextContainer>
142
+ <Label isApp={isApp}>TIMES HOLIDAYS</Label>
143
+ <Description isApp={isApp}>{description}</Description>
144
+ </TextContainer>
145
+ </LeftSection>
146
+
147
+ <RightSection>
148
+ <ContactInfo>
149
+ <PhoneLabel href={`tel:${phoneNumber}`} isApp={isApp}>
150
+ {phoneLabel}{' '}
151
+ <PhoneNumber isApp={isApp}>{phoneNumber}</PhoneNumber>
152
+ </PhoneLabel>
153
+ <WorkingHoursContainer>
154
+ {workingHours &&
155
+ workingHours.map((hours, index) => (
156
+ <WorkingHoursText key={index} isApp={isApp}>
157
+ {hours}
158
+ </WorkingHoursText>
159
+ ))}
160
+ </WorkingHoursContainer>
161
+ </ContactInfo>
162
+ <ButtonsContainer $isOnChannelPage={isOnChannelPage}>
163
+ {chatFailed ? (
164
+ <PrimaryButton as="a" href={`tel:${phoneNumber}`} isApp={isApp}>
165
+ {buttonText}
166
+ </PrimaryButton>
167
+ ) : (
168
+ <PrimaryButton
169
+ as="button"
170
+ type="button"
171
+ onClick={handlePrimaryButtonClick}
172
+ isApp={isApp}
173
+ disabled={!chatReady}
174
+ >
175
+ {buttonText}
176
+ </PrimaryButton>
177
+ )}
178
+ <div
179
+ id="LP_DIV_TRAVEL_1239001"
180
+ ref={chatDivRef}
181
+ style={{ display: 'none' }}
182
+ />
183
+ <SecondaryButton href={secondaryButtonUrl} isApp={isApp}>
184
+ {secondaryButtonText}
185
+ </SecondaryButton>
186
+ </ButtonsContainer>
187
+ </RightSection>
188
+ </ContentWrapper>
189
+ </Container>
190
+ );
191
+ };
@@ -0,0 +1,333 @@
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: 14px;
9
+ letter-spacing: 0em;
10
+ color: #236fa3;
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 0;
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
+ justify-content: space-between;
42
+ align-items: flex-start;
43
+ gap: 20px;
44
+
45
+ ${getMediaQuery('xs', 'md')} {
46
+ flex-direction: column;
47
+ gap: 24px;
48
+ }
49
+ `;
50
+
51
+ export const LeftSection = styled.div`
52
+ display: flex;
53
+ align-items: flex-start;
54
+ width: 50%;
55
+ gap: 24px;
56
+
57
+ ${getMediaQuery('xs', 'md')} {
58
+ width: 100%;
59
+ flex-direction: column;
60
+ gap: 16px;
61
+ }
62
+ `;
63
+
64
+ export const LogoContainer = styled.div`
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ flex-shrink: 0;
69
+
70
+ ${getMediaQuery('xs', 'md')} {
71
+ flex-direction: row-reverse;
72
+ justify-content: flex-start;
73
+ justify-content: space-between;
74
+ width: 100%;
75
+ }
76
+ `;
77
+
78
+ export const LogoBox = styled.div<{ isApp?: boolean }>`
79
+ width: 40px;
80
+ height: 40px;
81
+ position: relative;
82
+ display: flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ background-color: #236fa3;
86
+
87
+ ${({ isApp }) =>
88
+ applyDarkMode(
89
+ `
90
+ background-color: #c2c2c2 !important;
91
+ `,
92
+ isApp
93
+ )};
94
+ `;
95
+
96
+ export const LogoText = styled.span<{ isApp?: boolean }>`
97
+ font-family: 'Times Modern', serif;
98
+ font-weight: 700;
99
+ font-size: 40px;
100
+ line-height: 1.125;
101
+ letter-spacing: 0.02em;
102
+ color: #ffffff;
103
+ padding-top: 4px;
104
+
105
+ ${({ isApp }) =>
106
+ applyDarkMode(
107
+ `
108
+ color: #1d1d1b !important;
109
+ `,
110
+ isApp
111
+ )};
112
+ `;
113
+
114
+ export const TextContainer = styled.div`
115
+ display: flex;
116
+ flex-direction: column;
117
+ gap: 16px;
118
+ max-width: 375px;
119
+
120
+ ${getMediaQuery('xs', 'md')} {
121
+ gap: 24px;
122
+ }
123
+ `;
124
+
125
+ export const Label = styled(BaseLabel)`
126
+ ${getMediaQuery('xs', 'md')} {
127
+ display: none;
128
+ }
129
+ `;
130
+
131
+ export const MobileLabel = styled(BaseLabel)`
132
+ display: none;
133
+
134
+ ${getMediaQuery('xs', 'md')} {
135
+ display: block;
136
+ }
137
+ `;
138
+
139
+ export const Description = styled.div<{ isApp?: boolean }>`
140
+ font-family: 'Times Modern';
141
+ font-weight: 700;
142
+ line-height: 1.125;
143
+ font-size: 24px;
144
+ letter-spacing: 0em;
145
+ color: #333333;
146
+
147
+ ${({ isApp }) =>
148
+ applyDarkMode(
149
+ `
150
+ color: #cccccc !important;
151
+ `,
152
+ isApp
153
+ )};
154
+
155
+ ${getMediaQuery('xs', 'md')} {
156
+ margin-right: 64px;
157
+ }
158
+ `;
159
+
160
+ export const RightSection = styled.div`
161
+ display: flex;
162
+ flex-direction: column;
163
+ gap: 24px;
164
+ width: 50%;
165
+
166
+ ${getMediaQuery('xs', 'md')} {
167
+ gap: 32px;
168
+ width: 100%;
169
+ }
170
+ `;
171
+
172
+ export const ContactInfo = styled.div`
173
+ display: flex;
174
+ flex-direction: column;
175
+ gap: 16px;
176
+ `;
177
+
178
+ export const PhoneLabel = styled.a<{ isApp?: boolean }>`
179
+ text-decoration: none;
180
+ display: inline;
181
+ font-family: 'Times Digital W04 Regular';
182
+ font-weight: 400;
183
+ line-height: 1.5;
184
+ font-size: 18px;
185
+ letter-spacing: 0em;
186
+ color: #333333;
187
+ cursor: pointer;
188
+
189
+ ${({ isApp }) =>
190
+ applyDarkMode(
191
+ `
192
+ color: #c2c2c2 !important;
193
+ `,
194
+ isApp
195
+ )};
196
+
197
+ &:hover {
198
+ text-decoration: underline;
199
+ }
200
+ `;
201
+
202
+ export const PhoneNumber = styled.span<{ isApp?: boolean }>`
203
+ font-family: 'Times Modern';
204
+ font-weight: 700;
205
+ line-height: 1.125;
206
+ font-size: 22px;
207
+ letter-spacing: 0em;
208
+ color: #333333;
209
+
210
+ ${({ isApp }) =>
211
+ applyDarkMode(
212
+ `
213
+ color: #c2c2c2 !important;
214
+ `,
215
+ isApp
216
+ )};
217
+ `;
218
+
219
+ export const WorkingHoursContainer = styled.div`
220
+ display: flex;
221
+ flex-wrap: wrap;
222
+ gap: 8px;
223
+
224
+ ${getMediaQuery('xs', 'md')} {
225
+ flex-direction: column;
226
+ }
227
+ `;
228
+
229
+ export const WorkingHoursText = styled.div<{ isApp?: boolean }>`
230
+ font-family: 'Times Digital W04 Regular';
231
+ font-weight: 400;
232
+ line-height: 1.5;
233
+ font-size: 18px;
234
+ letter-spacing: 0em;
235
+ color: #333333;
236
+
237
+ ${({ isApp }) =>
238
+ applyDarkMode(
239
+ `
240
+ color: #cccccc !important;
241
+ `,
242
+ isApp
243
+ )};
244
+ `;
245
+
246
+ export const ButtonsContainer = styled.div<{ $isOnChannelPage?: boolean }>`
247
+ display: flex;
248
+ flex-direction: column;
249
+ gap: 16px;
250
+
251
+ ${getMediaQuery('lg')} {
252
+ flex-direction: ${({ $isOnChannelPage }) =>
253
+ $isOnChannelPage ? 'row' : 'column'};
254
+ }
255
+ `;
256
+
257
+ const BaseButton = styled.a`
258
+ text-decoration: none;
259
+ border-radius: 0px;
260
+ width: 100%;
261
+ min-height: 44px;
262
+ font-family: 'Roboto';
263
+ font-weight: 500;
264
+ line-height: 1.5;
265
+ font-size: 16px;
266
+ letter-spacing: 0em;
267
+ display: flex;
268
+ align-items: center;
269
+ justify-content: center;
270
+ padding: 12px;
271
+ cursor: pointer;
272
+ transition: all 0.2s ease;
273
+ `;
274
+
275
+ export const PrimaryButton = styled(BaseButton)<{
276
+ disabled?: boolean;
277
+ isApp?: boolean;
278
+ }>`
279
+ border: none;
280
+ background-color: #005c8a;
281
+ color: #ffffff;
282
+ cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
283
+ opacity: ${({ disabled }) => (disabled ? 0.6 : 1)};
284
+
285
+ div[data-lp-event] {
286
+ cursor: pointer;
287
+ font-family: 'Roboto';
288
+ font-weight: 500;
289
+ line-height: 1.5;
290
+ font-size: 16px;
291
+ letter-spacing: 0em;
292
+ }
293
+
294
+ &:hover {
295
+ background-color: #00527a;
296
+ }
297
+
298
+ ${({ isApp }) =>
299
+ applyDarkMode(
300
+ `
301
+ background-color: #74bade !important;
302
+ color: #1d1d1b !important;
303
+
304
+ &:hover {
305
+ background-color: #93cbe8 !important;
306
+ }
307
+ `,
308
+ isApp
309
+ )};
310
+ `;
311
+
312
+ export const SecondaryButton = styled(BaseButton)<{ isApp?: boolean }>`
313
+ border: 1px solid #005c8a;
314
+ background-color: transparent;
315
+ color: #005c8a;
316
+
317
+ &:hover {
318
+ background-color: #f5f5f5;
319
+ }
320
+
321
+ ${({ isApp }) =>
322
+ applyDarkMode(
323
+ `
324
+ border-color: #74bade !important;
325
+ color: #74bade !important;
326
+
327
+ &:hover {
328
+ background-color: #01000d !important;
329
+ }
330
+ `,
331
+ isApp
332
+ )};
333
+ `;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { storiesOf } from '@storybook/react';
3
+ import { TravelMiniCTA } from './index';
4
+ import { ArticleHarness } from '../../fixtures/article-harness/ArticleHarness';
5
+
6
+ storiesOf('Typescript Component/In Article/Travel Mini CTA', module).add(
7
+ 'Travel Mini CTA',
8
+ () => (
9
+ <ArticleHarness>
10
+ <div style={{ padding: '16px' }}>
11
+ <TravelMiniCTA
12
+ description="Begin your journey to Croatia with a holiday designed around you, guided by a dedicated travel expert."
13
+ phoneLabel="Call us on"
14
+ phoneNumber="08083049757"
15
+ workingHours={['Mon - Fri: 9am - 6pm', 'Sat: 10am - 5pm']}
16
+ primaryButtonText="Chat to a consultant"
17
+ secondaryButtonText="Enquire now"
18
+ secondaryButtonUrl="/enquire"
19
+ />
20
+ </div>
21
+ </ArticleHarness>
22
+ )
23
+ );
@@ -0,0 +1,11 @@
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
+ isOnChannelPage?: boolean;
11
+ }
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
+ };
@@ -0,0 +1,2 @@
1
+ export { applyDarkMode } from './applyDarkMode';
2
+ export { getMediaQuery } from './getMediaQuery';