@times-components/ts-components 1.146.2-52fb3513ac253011b85740aa1f70a12f27281c4e.28 → 1.146.2-63663ce01bc48c5c40f3f9affcb75ec88314b196.4

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 (48) hide show
  1. package/dist/components/social-embed/SocialMediaEmbed.js +97 -15
  2. package/dist/components/social-embed/SocialVendor.d.ts +1 -16
  3. package/dist/components/social-embed/SocialVendor.js +41 -2
  4. package/dist/components/social-embed/__tests__/SocialVendor.test.js +8 -1
  5. package/dist/components/social-embed/components/FacebookComponent.d.ts +6 -0
  6. package/dist/components/social-embed/components/FacebookComponent.js +74 -0
  7. package/dist/components/social-embed/constants.d.ts +1 -0
  8. package/dist/components/social-embed/constants.js +3 -2
  9. package/dist/components/social-embed/helpers/socialMediaVendors.js +6 -1
  10. package/dist/components/social-embed/styles.d.ts +1 -0
  11. package/dist/components/social-embed/styles.js +28 -1
  12. package/dist/index.d.ts +0 -1
  13. package/dist/index.js +1 -2
  14. package/package.json +3 -3
  15. package/rnw.js +1 -1
  16. package/src/components/social-embed/SocialMediaEmbed.tsx +84 -1
  17. package/src/components/social-embed/SocialVendor.tsx +46 -1
  18. package/src/components/social-embed/__tests__/SocialVendor.test.tsx +11 -0
  19. package/src/components/social-embed/components/FacebookComponent.tsx +93 -0
  20. package/src/components/social-embed/constants.ts +2 -1
  21. package/src/components/social-embed/helpers/socialMediaVendors.ts +5 -0
  22. package/src/components/social-embed/styles.ts +30 -0
  23. package/src/index.ts +0 -1
  24. package/dist/components/travel-mini-cta/__tests__/index.test.d.ts +0 -1
  25. package/dist/components/travel-mini-cta/__tests__/index.test.js +0 -262
  26. package/dist/components/travel-mini-cta/index.d.ts +0 -10
  27. package/dist/components/travel-mini-cta/index.js +0 -93
  28. package/dist/components/travel-mini-cta/styles.d.ts +0 -45
  29. package/dist/components/travel-mini-cta/styles.js +0 -293
  30. package/dist/components/travel-mini-cta/travel-mini-cta.stories.d.ts +0 -1
  31. package/dist/components/travel-mini-cta/travel-mini-cta.stories.js +0 -9
  32. package/dist/components/travel-mini-cta/types.d.ts +0 -11
  33. package/dist/components/travel-mini-cta/types.js +0 -2
  34. package/dist/utils/applyDarkMode.d.ts +0 -1
  35. package/dist/utils/applyDarkMode.js +0 -12
  36. package/dist/utils/getMediaQuery.d.ts +0 -11
  37. package/dist/utils/getMediaQuery.js +0 -19
  38. package/dist/utils/index.d.ts +0 -2
  39. package/dist/utils/index.js +0 -3
  40. package/src/components/travel-mini-cta/__tests__/__snapshots__/index.test.tsx.snap +0 -211
  41. package/src/components/travel-mini-cta/__tests__/index.test.tsx +0 -330
  42. package/src/components/travel-mini-cta/index.tsx +0 -191
  43. package/src/components/travel-mini-cta/styles.ts +0 -359
  44. package/src/components/travel-mini-cta/travel-mini-cta.stories.tsx +0 -24
  45. package/src/components/travel-mini-cta/types.ts +0 -11
  46. package/src/utils/applyDarkMode.ts +0 -12
  47. package/src/utils/getMediaQuery.ts +0 -25
  48. package/src/utils/index.ts +0 -2
@@ -1,191 +0,0 @@
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
- };
@@ -1,359 +0,0 @@
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('sm')} {
252
- flex-direction: ${({ $isOnChannelPage }) =>
253
- $isOnChannelPage ? 'row' : 'column'};
254
- }
255
-
256
- ${getMediaQuery('md')} {
257
- flex-direction: column;
258
- }
259
-
260
- ${getMediaQuery('lg')} {
261
- flex-direction: ${({ $isOnChannelPage }) =>
262
- $isOnChannelPage ? 'row' : 'column'};
263
- }
264
- `;
265
-
266
- const BaseButton = styled.a`
267
- text-decoration: none;
268
- border-radius: 0px;
269
- width: 100%;
270
- min-height: 44px;
271
- font-family: 'Roboto';
272
- font-weight: 500;
273
- line-height: 1.5;
274
- font-size: 16px;
275
- letter-spacing: 0em;
276
- display: flex;
277
- align-items: center;
278
- justify-content: center;
279
- padding: 12px;
280
- cursor: pointer;
281
- transition: all 0.2s ease;
282
- `;
283
-
284
- export const PrimaryButton = styled(BaseButton)<{
285
- disabled?: boolean;
286
- isApp?: boolean;
287
- }>`
288
- border: none;
289
- background-color: #005c8a;
290
- color: #ffffff;
291
- cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
292
- opacity: ${({ disabled }) => (disabled ? 0.6 : 1)};
293
-
294
- div[data-lp-event] {
295
- cursor: pointer;
296
- font-family: 'Roboto';
297
- font-weight: 500;
298
- line-height: 1.5;
299
- font-size: 16px;
300
- letter-spacing: 0em;
301
- }
302
-
303
- &:hover {
304
- background-color: #00527a;
305
- }
306
-
307
- ${({ isApp }) =>
308
- applyDarkMode(
309
- `
310
- background-color: #74bade !important;
311
- color: #1d1d1b !important;
312
-
313
- &:hover {
314
- background-color: #93cbe8 !important;
315
- }
316
- `,
317
- isApp
318
- )};
319
- `;
320
-
321
- export const SecondaryButton = styled(BaseButton)<{ isApp?: boolean }>`
322
- border: 1px solid #005c8a;
323
- background-color: transparent;
324
- color: #005c8a;
325
-
326
- &:hover {
327
- background-color: #f5f5f5;
328
- }
329
-
330
- ${({ isApp }) =>
331
- applyDarkMode(
332
- `
333
- border-color: #74bade !important;
334
- color: #74bade !important;
335
-
336
- &:hover {
337
- background-color: #01000d !important;
338
- }
339
- `,
340
- isApp
341
- )};
342
- `;
343
-
344
- export const ArticleBlockContainer = styled.div`
345
- padding-inline: 10px;
346
- margin-block-end: 25px;
347
-
348
- ${getMediaQuery('md')} {
349
- max-width: 80.8%;
350
- padding-inline: 0;
351
- margin-inline: auto;
352
- }
353
-
354
- ${getMediaQuery('lg')} {
355
- max-width: 56.2%;
356
- padding-inline: 0;
357
- margin-inline: auto;
358
- }
359
- `;
@@ -1,24 +0,0 @@
1
- import React from 'react';
2
- import { storiesOf } from '@storybook/react';
3
- import { TravelMiniCTA } from './index';
4
- import { ArticleBlockContainer } from './styles';
5
- import { ArticleHarness } from '../../fixtures/article-harness/ArticleHarness';
6
-
7
- storiesOf('Typescript Component/In Article/Travel Mini CTA', module).add(
8
- 'Travel Mini CTA',
9
- () => (
10
- <ArticleHarness>
11
- <ArticleBlockContainer>
12
- <TravelMiniCTA
13
- description="Begin your journey to Croatia with a holiday designed around you, guided by a dedicated travel expert."
14
- phoneLabel="Call us on"
15
- phoneNumber="08083049757"
16
- workingHours={['Mon - Fri: 9am - 6pm', 'Sat: 10am - 5pm']}
17
- primaryButtonText="Chat to a consultant"
18
- secondaryButtonText="Enquire now"
19
- secondaryButtonUrl="/enquire"
20
- />
21
- </ArticleBlockContainer>
22
- </ArticleHarness>
23
- )
24
- );
@@ -1,11 +0,0 @@
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
- }
@@ -1,12 +0,0 @@
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
- };
@@ -1,25 +0,0 @@
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
- };
@@ -1,2 +0,0 @@
1
- export { applyDarkMode } from './applyDarkMode';
2
- export { getMediaQuery } from './getMediaQuery';