@times-components/ts-components 1.98.2 → 1.98.3-alpha.15
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.
- package/dist/components/article-flag/ArticleFlag.d.ts +1 -4
- package/dist/components/article-flag/ArticleFlag.js +1 -1
- package/dist/components/article-flag/getActiveFlags.d.ts +1 -1
- package/dist/components/article-flag/styles.d.ts +1 -1
- package/dist/components/article-flag/types.d.ts +4 -0
- package/dist/components/article-flag/types.js +2 -0
- package/dist/components/banner/__tests__/banner.test.d.ts +1 -0
- package/dist/components/banner/__tests__/banner.test.js +11 -0
- package/dist/components/banner/assets/CloseIconBlack.d.ts +3 -0
- package/dist/components/banner/assets/CloseIconBlack.js +5 -0
- package/dist/components/banner/assets/EmailIcon.d.ts +3 -0
- package/dist/components/banner/assets/EmailIcon.js +5 -0
- package/dist/components/banner/banner.d.ts +8 -0
- package/dist/components/banner/banner.js +17 -0
- package/dist/components/banner/styles.d.ts +8 -0
- package/dist/components/banner/styles.js +73 -0
- package/dist/components/breadcrumb/__tests__/index.test.d.ts +1 -0
- package/dist/components/breadcrumb/__tests__/index.test.js +40 -0
- package/dist/components/breadcrumb/assets/BreadcrumbIcon.d.ts +2 -0
- package/dist/components/breadcrumb/assets/BreadcrumbIcon.js +5 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts +9 -0
- package/dist/components/breadcrumb/breadcrumb.js +28 -0
- package/dist/components/breadcrumb/fixtures/breadcrumbs.json +27 -0
- package/dist/components/breadcrumb/styles.d.ts +13 -0
- package/dist/components/breadcrumb/styles.js +39 -0
- package/dist/components/delayed-component/__tests__/delayed-component.test.d.ts +1 -0
- package/dist/components/delayed-component/__tests__/delayed-component.test.js +23 -0
- package/dist/components/delayed-component/delayed-component.d.ts +6 -0
- package/dist/components/delayed-component/delayed-component.js +11 -0
- package/dist/components/in-article-info-card/Card.d.ts +1 -1
- package/dist/components/in-article-info-card/InfoCard.d.ts +0 -8
- package/dist/components/in-article-info-card/InfoCard.js +1 -1
- package/dist/components/in-article-info-card/types.d.ts +8 -0
- package/dist/components/in-article-info-card/types.js +2 -0
- package/dist/components/job-title/__tests__/index.test.d.ts +1 -0
- package/dist/components/job-title/__tests__/index.test.js +45 -0
- package/dist/components/job-title/assets/TooltipIcon.d.ts +2 -0
- package/dist/components/job-title/assets/TooltipIcon.js +11 -0
- package/dist/components/job-title/assets/close-icon.d.ts +2 -0
- package/dist/components/job-title/assets/close-icon.js +5 -0
- package/dist/components/job-title/job-title.d.ts +11 -0
- package/dist/components/job-title/job-title.js +31 -0
- package/dist/components/job-title/styles.d.ts +11 -0
- package/dist/components/job-title/styles.js +150 -0
- package/dist/components/save-star/ContentProvider.d.ts +0 -6
- package/dist/components/save-star/ContentProvider.js +1 -1
- package/dist/components/save-star/SaveStar.js +1 -1
- package/dist/components/save-star/SaveStarUI.d.ts +1 -4
- package/dist/components/save-star/SaveStarUI.js +1 -1
- package/dist/components/save-star/types.d.ts +8 -0
- package/dist/components/save-star/types.js +2 -0
- package/dist/components/update-button/__tests__/update-button-with-delay.test.d.ts +1 -0
- package/dist/components/update-button/__tests__/update-button-with-delay.test.js +24 -0
- package/dist/components/update-button/__tests__/update-button.test.d.ts +1 -0
- package/dist/components/update-button/__tests__/update-button.test.js +27 -0
- package/dist/components/update-button/assets/FilledArrowIcon.d.ts +3 -0
- package/dist/components/update-button/assets/FilledArrowIcon.js +5 -0
- package/dist/components/update-button/styles.d.ts +1 -0
- package/dist/components/update-button/styles.js +39 -0
- package/dist/components/update-button/update-button-with-delay.d.ts +11 -0
- package/dist/components/update-button/update-button-with-delay.js +27 -0
- package/dist/components/update-button/update-button.d.ts +6 -0
- package/dist/components/update-button/update-button.js +9 -0
- package/dist/fixtures/article-harness/__tests__/articleHarness.test.d.ts +1 -0
- package/dist/fixtures/article-harness/__tests__/articleHarness.test.js +11 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +8 -3
- package/jest.config.js +2 -1
- package/package.json +17 -16
- package/rnw.js +1 -1
- package/src/components/article-flag/ArticleFlag.tsx +1 -5
- package/src/components/article-flag/getActiveFlags.ts +1 -1
- package/src/components/article-flag/styles.ts +1 -1
- package/src/components/article-flag/types.ts +4 -0
- package/src/components/banner/__tests__/__snapshots__/banner.test.tsx.snap +66 -0
- package/src/components/banner/__tests__/banner.test.tsx +13 -0
- package/src/components/banner/assets/CloseIconBlack.tsx +24 -0
- package/src/components/banner/assets/EmailIcon.tsx +24 -0
- package/src/components/banner/banner.stories.mdx +30 -0
- package/src/components/banner/banner.tsx +40 -0
- package/src/components/banner/styles.ts +80 -0
- package/src/components/breadcrumb/__tests__/__snapshots__/index.test.tsx.snap +64 -0
- package/src/components/breadcrumb/__tests__/index.test.tsx +51 -0
- package/src/components/breadcrumb/assets/BreadcrumbIcon.tsx +16 -0
- package/src/components/breadcrumb/breadcrumb.stories.mdx +47 -0
- package/src/components/breadcrumb/breadcrumb.tsx +84 -0
- package/src/components/breadcrumb/fixtures/breadcrumbs.json +27 -0
- package/src/components/breadcrumb/styles.ts +43 -0
- package/src/components/delayed-component/__tests__/delayed-component.test.tsx +30 -0
- package/src/components/delayed-component/delayed-component.stories.mdx +38 -0
- package/src/components/delayed-component/delayed-component.tsx +16 -0
- package/src/components/in-article-info-card/Card.tsx +1 -1
- package/src/components/in-article-info-card/InfoCard.tsx +1 -8
- package/src/components/in-article-info-card/types.ts +8 -0
- package/src/components/job-title/__tests__/__snapshots__/index.test.tsx.snap +271 -0
- package/src/components/job-title/__tests__/index.test.tsx +71 -0
- package/src/components/job-title/assets/TooltipIcon.tsx +37 -0
- package/src/components/job-title/assets/close-icon.tsx +18 -0
- package/src/components/job-title/job-title.stories.mdx +38 -0
- package/src/components/job-title/job-title.tsx +85 -0
- package/src/components/job-title/styles.ts +154 -0
- package/src/components/save-star/ContentProvider.tsx +1 -7
- package/src/components/save-star/SaveStar.tsx +2 -1
- package/src/components/save-star/SaveStarUI.tsx +1 -5
- package/src/components/save-star/types.ts +9 -0
- package/src/components/update-button/__tests__/__snapshots__/update-button-with-delay.test.tsx.snap +23 -0
- package/src/components/update-button/__tests__/__snapshots__/update-button.test.tsx.snap +23 -0
- package/src/components/update-button/__tests__/update-button-with-delay.test.tsx +67 -0
- package/src/components/update-button/__tests__/update-button.test.tsx +31 -0
- package/src/components/update-button/assets/FilledArrowIcon.tsx +17 -0
- package/src/components/update-button/styles.ts +40 -0
- package/src/components/update-button/update-button-with-delay.stories.mdx +40 -0
- package/src/components/update-button/update-button-with-delay.tsx +53 -0
- package/src/components/update-button/update-button.stories.mdx +32 -0
- package/src/components/update-button/update-button.tsx +17 -0
- package/src/fixtures/article-harness/__tests__/__snapshots__/articleHarness.test.tsx.snap +34 -0
- package/src/fixtures/article-harness/__tests__/articleHarness.test.tsx +11 -0
- package/src/index.ts +15 -7
- package/tsconfig.json +6 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
export const IconButton = styled.button`
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
display: inline-grid;
|
|
7
|
+
column-gap: 8px;
|
|
8
|
+
grid-template-columns: repeat(1, auto);
|
|
9
|
+
width: 32px;
|
|
10
|
+
height: 32px;
|
|
11
|
+
margin-inline-start: 8px;
|
|
12
|
+
padding-inline: 8px;
|
|
13
|
+
padding-block: 8px;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
border: none;
|
|
17
|
+
appearance: none;
|
|
18
|
+
background-color: #00000000;
|
|
19
|
+
border-radius: 50%;
|
|
20
|
+
color: #333333;
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
export const Popover = styled.div`
|
|
25
|
+
position: relative;
|
|
26
|
+
display: inline-block;
|
|
27
|
+
`;
|
|
28
|
+
export const PopoverContext = styled.div<{ isOpen?: boolean }>`
|
|
29
|
+
display: ${({ isOpen }) => (isOpen ? 'grid' : 'none')};
|
|
30
|
+
position: absolute;
|
|
31
|
+
top: -55px;
|
|
32
|
+
left: 4px;
|
|
33
|
+
box-shadow: 0px 20px 32px 0px #11111114;
|
|
34
|
+
border-radius: 0px;
|
|
35
|
+
border-style: none;
|
|
36
|
+
z-index: 80;
|
|
37
|
+
|
|
38
|
+
div {
|
|
39
|
+
margin: 0;
|
|
40
|
+
color: #333333;
|
|
41
|
+
border-radius: 0px;
|
|
42
|
+
background-color: #ffffff;
|
|
43
|
+
white-space: nowrap;
|
|
44
|
+
|
|
45
|
+
display: grid;
|
|
46
|
+
grid-template-areas:
|
|
47
|
+
'header close'
|
|
48
|
+
'content content';
|
|
49
|
+
grid-template-columns: 1fr auto;
|
|
50
|
+
grid-template-rows: auto 1fr;
|
|
51
|
+
|
|
52
|
+
/* Pointer Arrow */
|
|
53
|
+
&::after {
|
|
54
|
+
content: '';
|
|
55
|
+
position: absolute;
|
|
56
|
+
-webkit-transform: rotate(45deg);
|
|
57
|
+
-moz-transform: rotate(45deg);
|
|
58
|
+
-ms-transform: rotate(45deg);
|
|
59
|
+
transform: rotate(45deg);
|
|
60
|
+
box-sizing: border-box;
|
|
61
|
+
background-color: #ffffff;
|
|
62
|
+
width: 16px;
|
|
63
|
+
height: 16px;
|
|
64
|
+
left: 12px;
|
|
65
|
+
bottom: calc(-16px / 2);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
export const PopoverHeader = styled.div`
|
|
71
|
+
div {
|
|
72
|
+
display: flex;
|
|
73
|
+
grid-area: header;
|
|
74
|
+
align-items: center;
|
|
75
|
+
box-sizing: border-box;
|
|
76
|
+
box-shadow: 0px 20px 32px 0px #11111114;
|
|
77
|
+
border-radius: 0px;
|
|
78
|
+
border-style: none;
|
|
79
|
+
font-family: Roboto;
|
|
80
|
+
font-size: 1.4000000000000001rem;
|
|
81
|
+
line-height: 1.5;
|
|
82
|
+
font-weight: 500;
|
|
83
|
+
letter-spacing: 0em;
|
|
84
|
+
padding-inline: 24px;
|
|
85
|
+
padding-block: 16px;
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
88
|
+
|
|
89
|
+
export const CloseButton = styled.button`
|
|
90
|
+
height: 48px;
|
|
91
|
+
width: 48px;
|
|
92
|
+
border-radius: 50%;
|
|
93
|
+
padding: 16px;
|
|
94
|
+
background-color: transparent;
|
|
95
|
+
border: none;
|
|
96
|
+
outline: none;
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
display: flex;
|
|
99
|
+
justify-content: center;
|
|
100
|
+
align-items: center;
|
|
101
|
+
transition: background-color 0.2s;
|
|
102
|
+
&:focus-visible {
|
|
103
|
+
background-color: #eeeeee;
|
|
104
|
+
border: 1px solid #000;
|
|
105
|
+
}
|
|
106
|
+
&:hover {
|
|
107
|
+
background-color: #eeeeee;
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
export const Tooltip = styled.div`
|
|
112
|
+
position: relative;
|
|
113
|
+
display: inline-block;
|
|
114
|
+
z-index: 80;
|
|
115
|
+
`;
|
|
116
|
+
export const TooltipContext = styled.div<{ isOpen?: boolean }>`
|
|
117
|
+
display: ${({ isOpen }) => (isOpen ? 'grid' : 'none')};
|
|
118
|
+
position: absolute;
|
|
119
|
+
top: -34px;
|
|
120
|
+
left: 8px;
|
|
121
|
+
grid-template-areas:
|
|
122
|
+
'header close'
|
|
123
|
+
'content content';
|
|
124
|
+
grid-template-columns: 1fr auto;
|
|
125
|
+
grid-template-rows: auto 1fr;
|
|
126
|
+
|
|
127
|
+
color: rgb(255, 255, 255);
|
|
128
|
+
background-color: rgb(17, 17, 17);
|
|
129
|
+
font-family: 'Roboto';
|
|
130
|
+
font-size: 14px;
|
|
131
|
+
line-height: 21px;
|
|
132
|
+
font-weight: 500;
|
|
133
|
+
letter-spacing: 0em;
|
|
134
|
+
padding-inline: 8px;
|
|
135
|
+
padding-block: 8px;
|
|
136
|
+
white-space: nowrap;
|
|
137
|
+
|
|
138
|
+
/* Pointer Arrow */
|
|
139
|
+
&::after {
|
|
140
|
+
content: '';
|
|
141
|
+
position: absolute;
|
|
142
|
+
-webkit-transform: rotate(45deg);
|
|
143
|
+
-moz-transform: rotate(45deg);
|
|
144
|
+
-ms-transform: rotate(45deg);
|
|
145
|
+
box-sizing: border-box;
|
|
146
|
+
background-color: #ffffff;
|
|
147
|
+
width: 4px;
|
|
148
|
+
height: 4px;
|
|
149
|
+
left: 14px;
|
|
150
|
+
bottom: calc(-4px / 2);
|
|
151
|
+
box-sizing: border-box;
|
|
152
|
+
background-color: rgb(17, 17, 17);
|
|
153
|
+
}
|
|
154
|
+
`;
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useFetch } from '../../helpers/fetch/FetchProvider';
|
|
3
|
-
import { ArticleBookmark } from './
|
|
4
|
-
|
|
5
|
-
export interface ContentProps {
|
|
6
|
-
loading?: boolean;
|
|
7
|
-
error?: string;
|
|
8
|
-
data?: ArticleBookmark;
|
|
9
|
-
}
|
|
3
|
+
import { ArticleBookmark, ContentProps } from './types';
|
|
10
4
|
|
|
11
5
|
export const ContentProvider: React.FC = React.memo(({ children }) => {
|
|
12
6
|
const fetchResponse = useFetch<ArticleBookmark>();
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { cloneElement, useCallback, useMemo, useState } from 'react';
|
|
2
2
|
import { FetchProvider } from '../../helpers/fetch/FetchProvider';
|
|
3
|
-
import { SaveStarUI
|
|
3
|
+
import { SaveStarUI } from './SaveStarUI';
|
|
4
4
|
import { ContentProvider } from './ContentProvider';
|
|
5
|
+
import { ArticleBookmark } from './types';
|
|
5
6
|
|
|
6
7
|
export const SaveStar: React.FC<{
|
|
7
8
|
articleId: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { colours } from '@times-components/ts-styleguide';
|
|
3
3
|
import { IconStar } from '@times-components/icons';
|
|
4
|
-
import { ContentProps } from './
|
|
4
|
+
import { ContentProps } from './types';
|
|
5
5
|
import {
|
|
6
6
|
IconContainer,
|
|
7
7
|
LoadingIcon,
|
|
@@ -9,10 +9,6 @@ import {
|
|
|
9
9
|
SaveStarButton
|
|
10
10
|
} from './styles';
|
|
11
11
|
|
|
12
|
-
export type ArticleBookmark = {
|
|
13
|
-
isBookmarked: boolean;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
12
|
const getText = (isSaved: boolean) => (isSaved ? 'Saved' : 'Save');
|
|
17
13
|
|
|
18
14
|
const getIconTitle = (isSaved: boolean) =>
|
package/src/components/update-button/__tests__/__snapshots__/update-button-with-delay.test.tsx.snap
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Render UpdateButtonWithDelay should render the Update button component and the DelayComponent as expected when it has an update 1`] = `
|
|
4
|
+
<DocumentFragment>
|
|
5
|
+
<button
|
|
6
|
+
class="sc-bdVaJa kaAiuV"
|
|
7
|
+
>
|
|
8
|
+
<svg
|
|
9
|
+
data-testid="upward-arrow"
|
|
10
|
+
fill="none"
|
|
11
|
+
height="16"
|
|
12
|
+
width="16"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
>
|
|
15
|
+
<path
|
|
16
|
+
d="m3.166 8 .94.94 3.727-3.72v8.113h1.333V5.22l3.72 3.727.947-.947-5.334-5.333L3.166 8Z"
|
|
17
|
+
fill="currentcolor"
|
|
18
|
+
/>
|
|
19
|
+
</svg>
|
|
20
|
+
New Updates
|
|
21
|
+
</button>
|
|
22
|
+
</DocumentFragment>
|
|
23
|
+
`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Render UpdateButton should render the component 1`] = `
|
|
4
|
+
<DocumentFragment>
|
|
5
|
+
<button
|
|
6
|
+
class="sc-bdVaJa kaAiuV"
|
|
7
|
+
>
|
|
8
|
+
<svg
|
|
9
|
+
data-testid="upward-arrow"
|
|
10
|
+
fill="none"
|
|
11
|
+
height="16"
|
|
12
|
+
width="16"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
>
|
|
15
|
+
<path
|
|
16
|
+
d="m3.166 8 .94.94 3.727-3.72v8.113h1.333V5.22l3.72 3.727.947-.947-5.334-5.333L3.166 8Z"
|
|
17
|
+
fill="currentcolor"
|
|
18
|
+
/>
|
|
19
|
+
</svg>
|
|
20
|
+
New Updates
|
|
21
|
+
</button>
|
|
22
|
+
</DocumentFragment>
|
|
23
|
+
`;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { render, waitFor } from '@testing-library/react';
|
|
4
|
+
import { UpdateButtonWithDelay } from '../update-button-with-delay';
|
|
5
|
+
|
|
6
|
+
const handleClickMock = jest.fn();
|
|
7
|
+
|
|
8
|
+
const renderComponent = (
|
|
9
|
+
delay: number,
|
|
10
|
+
display: boolean,
|
|
11
|
+
label: string,
|
|
12
|
+
handleClick: any,
|
|
13
|
+
updatedTime: string,
|
|
14
|
+
articleId: string,
|
|
15
|
+
update: boolean
|
|
16
|
+
) =>
|
|
17
|
+
render(
|
|
18
|
+
<UpdateButtonWithDelay
|
|
19
|
+
delay={delay}
|
|
20
|
+
display={display}
|
|
21
|
+
label={label}
|
|
22
|
+
handleClick={handleClick}
|
|
23
|
+
updatedTime={updatedTime}
|
|
24
|
+
articleId={articleId}
|
|
25
|
+
update={update}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
describe('Render UpdateButtonWithDelay', () => {
|
|
30
|
+
it('should render the Update button component and the DelayComponent as expected when it has an update', async () => {
|
|
31
|
+
const { asFragment, getByRole, queryByTestId } = renderComponent(
|
|
32
|
+
800,
|
|
33
|
+
true,
|
|
34
|
+
'New Updates',
|
|
35
|
+
handleClickMock,
|
|
36
|
+
'2023-10-12T00:00:00.000Z',
|
|
37
|
+
'12345',
|
|
38
|
+
true
|
|
39
|
+
);
|
|
40
|
+
expect(asFragment()).toMatchSnapshot();
|
|
41
|
+
expect(getByRole('button')).toBeVisible();
|
|
42
|
+
await waitFor(() => {
|
|
43
|
+
expect(queryByTestId('button')).toBeFalsy();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should not render the Update button component and the DelayComponent as expected when it has an update', async () => {
|
|
48
|
+
const { unmount, queryByTestId } = renderComponent(
|
|
49
|
+
500,
|
|
50
|
+
true,
|
|
51
|
+
'Update Now',
|
|
52
|
+
handleClickMock,
|
|
53
|
+
'2023-10-12T00:00:00.000Z',
|
|
54
|
+
'12345',
|
|
55
|
+
false
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
await waitFor(
|
|
59
|
+
() => {
|
|
60
|
+
expect(queryByTestId('button')).toBeNull();
|
|
61
|
+
},
|
|
62
|
+
{ timeout: 500 }
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
unmount();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { render, fireEvent } from '@testing-library/react';
|
|
4
|
+
|
|
5
|
+
import { UpdateButton } from '../update-button';
|
|
6
|
+
|
|
7
|
+
const handleClickMock = jest.fn();
|
|
8
|
+
|
|
9
|
+
const renderComponent = (label: string, handleClick: any) =>
|
|
10
|
+
render(<UpdateButton label={label} handleClick={handleClick} />);
|
|
11
|
+
|
|
12
|
+
describe('Render UpdateButton', () => {
|
|
13
|
+
it('should render the component', () => {
|
|
14
|
+
const { asFragment } = renderComponent('New Updates', handleClickMock);
|
|
15
|
+
expect(asFragment()).toMatchSnapshot();
|
|
16
|
+
});
|
|
17
|
+
it('should render the label text you pass through', () => {
|
|
18
|
+
const { getByText } = renderComponent('Test New Updates', handleClickMock);
|
|
19
|
+
expect(getByText('Test New Updates')).toBeVisible();
|
|
20
|
+
});
|
|
21
|
+
it('should trigger an event on click', () => {
|
|
22
|
+
const { getByRole } = renderComponent('New Update', handleClickMock);
|
|
23
|
+
const Button = getByRole('button');
|
|
24
|
+
fireEvent.click(Button);
|
|
25
|
+
expect(handleClickMock).toHaveBeenCalled();
|
|
26
|
+
});
|
|
27
|
+
it('should render the upward facing arrow icon', () => {
|
|
28
|
+
const { getByTestId } = renderComponent('New Updates', handleClickMock);
|
|
29
|
+
expect(getByTestId('upward-arrow')).toBeVisible();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const FilledArrowIcon: React.FC = (props: any) => (
|
|
4
|
+
<svg
|
|
5
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
6
|
+
width={16}
|
|
7
|
+
height={16}
|
|
8
|
+
fill="none"
|
|
9
|
+
{...props}
|
|
10
|
+
>
|
|
11
|
+
<path
|
|
12
|
+
fill="currentcolor"
|
|
13
|
+
d="m3.166 8 .94.94 3.727-3.72v8.113h1.333V5.22l3.72 3.727.947-.947-5.334-5.333L3.166 8Z"
|
|
14
|
+
/>
|
|
15
|
+
</svg>
|
|
16
|
+
);
|
|
17
|
+
export default FilledArrowIcon;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
const styleMap = {
|
|
4
|
+
colors: {
|
|
5
|
+
interactiveNegative040: '#9f0000',
|
|
6
|
+
interactiveNegative050: '#800000',
|
|
7
|
+
inkInverse: '#FFFFFF'
|
|
8
|
+
},
|
|
9
|
+
spacing: {
|
|
10
|
+
space030: '12px',
|
|
11
|
+
space020: '8px'
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const StyledButton = styled.button`
|
|
16
|
+
border: none;
|
|
17
|
+
background-color: ${styleMap.colors.interactiveNegative040};
|
|
18
|
+
padding-block: ${styleMap.spacing.space020};
|
|
19
|
+
padding-inline: ${styleMap.spacing.space030};
|
|
20
|
+
font-family: Roboto;
|
|
21
|
+
font-size: 1.4000000000000001rem;
|
|
22
|
+
font-weight: 500;
|
|
23
|
+
letter-spacing: 0em;
|
|
24
|
+
color: ${styleMap.colors.inkInverse};
|
|
25
|
+
display: inline-grid;
|
|
26
|
+
grid-template-columns: repeat(2, auto);
|
|
27
|
+
column-gap: 8px;
|
|
28
|
+
place-content: center;
|
|
29
|
+
place-items: center;
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
transition-property: background-color;
|
|
32
|
+
transition-duration: 200ms;
|
|
33
|
+
transition-timing-function: cubic-bezier(0, 0, 0.5, 1);
|
|
34
|
+
&:hover {
|
|
35
|
+
background-color: ${styleMap.colors.interactiveNegative050};
|
|
36
|
+
}
|
|
37
|
+
&:active {
|
|
38
|
+
background-color: ${styleMap.colors.interactiveNegative050};
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Meta, Story, Props } from '@storybook/addon-docs'
|
|
2
|
+
|
|
3
|
+
import { UpdateButtonWithDelay } from './update-button-with-delay.tsx';
|
|
4
|
+
|
|
5
|
+
<Meta
|
|
6
|
+
title="Components/Misc/UpdateButtonWithDelay"
|
|
7
|
+
component={UpdateButtonWithDelay}
|
|
8
|
+
/>
|
|
9
|
+
|
|
10
|
+
# UpdateButtonWithDelay component
|
|
11
|
+
The `UpdateButtonWithDelay` component is used to highlight when there is an update in an article.
|
|
12
|
+
|
|
13
|
+
The `UpdateButtonWithDelay` component makes use of the `DelayedComponent` which will set the component to mount or unmount given a delay and intial state.
|
|
14
|
+
|
|
15
|
+
This component takes in a six props:
|
|
16
|
+
- `loading` to display the loading spinner.
|
|
17
|
+
- `delay` to determine the delay in milliseconds for mounting or unmounting the component.
|
|
18
|
+
- `display` which will determine if the component initially displays, or is rendered after the delay has passed.
|
|
19
|
+
- `label` this is for the text label in the button.
|
|
20
|
+
- `handleClick` determines the function called on interaction.
|
|
21
|
+
- `arrowUp` this is to render either the upward arrow icon or the downward icon (depending on where in the article the user is vs where the update is).
|
|
22
|
+
|
|
23
|
+
## Props
|
|
24
|
+
<Props of={UpdateButtonWithDelay} />
|
|
25
|
+
|
|
26
|
+
## Code Example
|
|
27
|
+
`<UpdateButtonWithDelay display={true} delay={8000} label='New updates', arrowUp={true} updatedTime="2023-12-12T12:00:00.000Z" articleId="12345"/>`
|
|
28
|
+
|
|
29
|
+
## View Component
|
|
30
|
+
Please click the 'Canvas' tab for a better viewing experience, where you can update the props and review at the different breakpoints by clicking the preview icon and selecting from our list of pre-defined breakpoints (XS, SM, MD, LG and XL).
|
|
31
|
+
|
|
32
|
+
export const UpdateButtonWithDelayStory = ({ display, delay, label, arrowUp, updatedTime, articleId }) => (
|
|
33
|
+
<UpdateButtonWithDelay display={display} delay={delay} label={label} arrowUp={arrowUp} updatedTime={updatedTime} articleId={articleId} update={true}/>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
<Story name="UpdateButtonWithDelay"
|
|
37
|
+
args={{ display: true, delay: 8000, label: 'New Updates', arrowUp: true, updatedTime: '2023-07-13T12:00:00.000Z', articleId: '12345'} }
|
|
38
|
+
>
|
|
39
|
+
{UpdateButtonWithDelayStory.bind({})}
|
|
40
|
+
</Story>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { DelayedComponent } from '../delayed-component/delayed-component';
|
|
3
|
+
import { UpdateButton } from './update-button';
|
|
4
|
+
import fetch from 'isomorphic-unfetch';
|
|
5
|
+
|
|
6
|
+
type UpdateWithDelayProps = {
|
|
7
|
+
display: boolean;
|
|
8
|
+
delay: number;
|
|
9
|
+
label: string;
|
|
10
|
+
handleClick: () => void;
|
|
11
|
+
updatedTime: string;
|
|
12
|
+
articleId: string;
|
|
13
|
+
update: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const UpdateButtonWithDelay = ({
|
|
17
|
+
delay,
|
|
18
|
+
display,
|
|
19
|
+
label,
|
|
20
|
+
handleClick,
|
|
21
|
+
updatedTime,
|
|
22
|
+
articleId,
|
|
23
|
+
update = false
|
|
24
|
+
}: UpdateWithDelayProps) => {
|
|
25
|
+
const [hasUpdate, setUpdate] = useState(update);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
const fetchData = async () => {
|
|
28
|
+
try {
|
|
29
|
+
const response = await fetch(`/api/article-update-time/${articleId}`);
|
|
30
|
+
const json = await response.json();
|
|
31
|
+
return json.article.publishedTime;
|
|
32
|
+
} catch (err) {
|
|
33
|
+
// tslint:disable-next-line:no-console
|
|
34
|
+
console.log(err);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const interval = setInterval(async () => {
|
|
38
|
+
(await fetchData()) > updatedTime && setUpdate(true);
|
|
39
|
+
}, 120000);
|
|
40
|
+
|
|
41
|
+
return () => clearInterval(interval);
|
|
42
|
+
}, []);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<>
|
|
46
|
+
{hasUpdate ? (
|
|
47
|
+
<DelayedComponent delay={delay} initialState={display}>
|
|
48
|
+
<UpdateButton label={label} handleClick={handleClick} />
|
|
49
|
+
</DelayedComponent>
|
|
50
|
+
) : null}
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Meta, Story, Props } from '@storybook/addon-docs'
|
|
2
|
+
|
|
3
|
+
import { UpdateButton } from './update-button.tsx';
|
|
4
|
+
|
|
5
|
+
<Meta
|
|
6
|
+
title="Components/Misc/UpdateButton"
|
|
7
|
+
component={UpdateButton}
|
|
8
|
+
/>
|
|
9
|
+
|
|
10
|
+
# UpdateButton component
|
|
11
|
+
The `UpdateButton` component is used to highlight when there is an update.
|
|
12
|
+
|
|
13
|
+
This component takes in a two props, loading to display the loading spinner, arrowUp - determines the position of the arrow Icon, label - which determines the text content of the button, and handleClick which is the function called upon clicking the button.
|
|
14
|
+
|
|
15
|
+
## Props
|
|
16
|
+
<Props of={UpdateButton} />
|
|
17
|
+
|
|
18
|
+
## Code Example
|
|
19
|
+
`<UpdateButton loading={loading} label='New updates', arrowUp={true}/>`
|
|
20
|
+
|
|
21
|
+
## View Component
|
|
22
|
+
Please click the 'Canvas' tab for a better viewing experience, where you can update the props and review at the different breakpoints by clicking the preview icon and selecting from our list of pre-defined breakpoints (XS, SM, MD, LG and XL).
|
|
23
|
+
|
|
24
|
+
export const UpdateButtonStory = ({ loading, label, arrowUp }) => (
|
|
25
|
+
<UpdateButton loading={loading} label={label} arrowUp={arrowUp} />
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
<Story name="UpdateButton"
|
|
29
|
+
args={{ loading: false, label: 'New Updates', arrowUp: true} }
|
|
30
|
+
>
|
|
31
|
+
{UpdateButtonStory.bind({})}
|
|
32
|
+
</Story>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import FilledArrowIcon from './assets/FilledArrowIcon';
|
|
3
|
+
import { StyledButton } from './styles';
|
|
4
|
+
|
|
5
|
+
type UpdateButtonProps = {
|
|
6
|
+
label: string;
|
|
7
|
+
handleClick: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const UpdateButton = ({ label, handleClick }: UpdateButtonProps) => {
|
|
11
|
+
return (
|
|
12
|
+
<StyledButton onClick={() => handleClick()}>
|
|
13
|
+
<FilledArrowIcon data-testid="upward-arrow" />
|
|
14
|
+
{label}
|
|
15
|
+
</StyledButton>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Render ArticleHarness renders the ArticleHarness 1`] = `
|
|
4
|
+
<DocumentFragment>
|
|
5
|
+
<div
|
|
6
|
+
class="sc-bdVaJa glDQbs"
|
|
7
|
+
>
|
|
8
|
+
<div
|
|
9
|
+
class="sc-bwzfXH fBhOFq"
|
|
10
|
+
>
|
|
11
|
+
<div
|
|
12
|
+
class="sc-htpNat sc-bxivhb gakSZq"
|
|
13
|
+
>
|
|
14
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eleifend quis purus eget consequat. Maecenas pellentesque lorem at ipsum egestas sagittis. Quisque eget nisi sed diam auctor luctus. Pellentesque rutrum sem nibh, at placerat elit iaculis in. Curabitur nec turpis nec nisi pulvinar pharetra.
|
|
15
|
+
</div>
|
|
16
|
+
<div
|
|
17
|
+
class="sc-htpNat sc-bxivhb gakSZq"
|
|
18
|
+
>
|
|
19
|
+
Aenean hendrerit erat non augue sagittis rhoncus. Praesent diam lacus, vehicula ut ante et, cursus finibus justo. Curabitur sollicitudin turpis nec diam ullamcorper, sed fermentum diam tempor. Integer maximus ultrices sem, eu facilisis magna condimentum ut. Curabitur orci odio, ornare in ipsum quis, cursus scelerisque sem.
|
|
20
|
+
</div>
|
|
21
|
+
<div
|
|
22
|
+
class="sc-htpNat sc-bxivhb gakSZq"
|
|
23
|
+
>
|
|
24
|
+
Maecenas ultricies risus at libero vulputate, non accumsan ex iaculis. In vel facilisis sapien. Nam imperdiet, elit a mattis consectetur, ex purus efficitur eros, nec condimentum mi tortor facilisis orci. Donec sodales felis tortor, ut dignissim turpis rhoncus ut. Quisque lacinia ornare tortor at convallis.
|
|
25
|
+
</div>
|
|
26
|
+
<div
|
|
27
|
+
class="sc-htpNat sc-bxivhb gakSZq"
|
|
28
|
+
>
|
|
29
|
+
Praesent ac elit quis metus vulputate facilisis. Quisque ac dolor eu felis pharetra dignissim. Sed tristique egestas sollicitudin. Nulla varius, risus ornare tristique lobortis, est libero vestibulum diam, nec mollis turpis ligula eget nibh. Praesent facilisis sem lectus, et consectetur sem fringilla non. Pellentesque condimentum est sed nisl porttitor ultricies.
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</DocumentFragment>
|
|
34
|
+
`;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { ArticleHarness } from '../ArticleHarness';
|
|
5
|
+
|
|
6
|
+
describe('Render ArticleHarness', () => {
|
|
7
|
+
it('renders the ArticleHarness', () => {
|
|
8
|
+
const { asFragment } = render(<ArticleHarness />);
|
|
9
|
+
expect(asFragment()).toMatchSnapshot();
|
|
10
|
+
});
|
|
11
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
// General Components
|
|
2
|
+
export {
|
|
3
|
+
BreakingArticleFlag,
|
|
4
|
+
LiveArticleFlag
|
|
5
|
+
} from './components/article-flag/LiveArticleFlag';
|
|
6
|
+
export {
|
|
7
|
+
TrackingContext,
|
|
8
|
+
TrackingContextProvider
|
|
9
|
+
} from './helpers/tracking/TrackingContextProvider';
|
|
2
10
|
export { InArticlePuff } from './components/in-article-puff/InArticlePuff';
|
|
3
11
|
export { InfoCard } from './components/in-article-info-card/InfoCard';
|
|
4
12
|
export { GalleryCarousel } from './components/carousel/GalleryCarousel';
|
|
@@ -6,10 +14,6 @@ export {
|
|
|
6
14
|
InfoCardBulletPoints
|
|
7
15
|
} from './components/in-article-info-card-bulletpoints/InfoCardBulletPoints';
|
|
8
16
|
export { BigNumbers } from './components/in-article-big-numbers/BigNumbers';
|
|
9
|
-
export {
|
|
10
|
-
BreakingArticleFlag,
|
|
11
|
-
LiveArticleFlag
|
|
12
|
-
} from './components/article-flag/LiveArticleFlag';
|
|
13
17
|
export {
|
|
14
18
|
ArticleFlag,
|
|
15
19
|
ArticleFlags,
|
|
@@ -21,6 +25,13 @@ export {
|
|
|
21
25
|
} from './components/article-flag/ArticleFlag';
|
|
22
26
|
export { Timelines } from './components/in-article-timelines/Timelines';
|
|
23
27
|
export { SaveStar } from './components/save-star/SaveStar';
|
|
28
|
+
export { Breadcrumb } from './components/breadcrumb/breadcrumb';
|
|
29
|
+
export { UpdateButton } from './components/update-button/update-button';
|
|
30
|
+
export {
|
|
31
|
+
UpdateButtonWithDelay
|
|
32
|
+
} from './components/update-button/update-button-with-delay';
|
|
33
|
+
export { Banner } from './components/banner/banner';
|
|
34
|
+
export { JobTitle } from './components/job-title/job-title';
|
|
24
35
|
|
|
25
36
|
// Newsletter Components
|
|
26
37
|
export {
|
|
@@ -83,9 +94,6 @@ export { FetchProvider } from './helpers/fetch/FetchProvider';
|
|
|
83
94
|
export {
|
|
84
95
|
ViewCountWrapper
|
|
85
96
|
} from './helpers/view-count-wrapper/ViewCountWrapper';
|
|
86
|
-
export {
|
|
87
|
-
TrackingContextProvider
|
|
88
|
-
} from './helpers/tracking/TrackingContextProvider';
|
|
89
97
|
|
|
90
98
|
export { HiddenDiv } from './components/common-styles';
|
|
91
99
|
export { InlineMessage } from './components/inline-message/InlineMessage';
|
package/tsconfig.json
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"declaration": true,
|
|
10
10
|
"inlineSourceMap": true,
|
|
11
11
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
|
12
|
+
"resolveJsonModule": true,
|
|
12
13
|
|
|
13
14
|
"strict": true /* Enable all strict type-checking options. */,
|
|
14
15
|
|
|
@@ -40,7 +41,11 @@
|
|
|
40
41
|
|
|
41
42
|
"lib": ["es6", "dom", "es2017", "dom.iterable"],
|
|
42
43
|
"types": ["jest"],
|
|
43
|
-
"typeRoots": [
|
|
44
|
+
"typeRoots": [
|
|
45
|
+
"node_modules/@types",
|
|
46
|
+
"src/types",
|
|
47
|
+
"../../node_modules/@types"
|
|
48
|
+
]
|
|
44
49
|
},
|
|
45
50
|
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
|
46
51
|
"exclude": ["node_modules/**"],
|