@automattic/vip-design-system 0.8.1 → 0.9.0

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 (90) hide show
  1. package/.eslines.json +10 -0
  2. package/.eslintignore +7 -0
  3. package/.eslintrc.json +23 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  5. package/.github/workflows/codeql-analysis.yml +71 -0
  6. package/.github/workflows/nodejs.yaml +29 -0
  7. package/.prettierrc +9 -0
  8. package/.storybook/preview.js +5 -0
  9. package/README.md +38 -1
  10. package/babel.config.js +10 -10
  11. package/build/system/Avatar/Avatar.js +1 -1
  12. package/build/system/Avatar/Avatar.test.js +54 -0
  13. package/build/system/Card/Card.js +8 -5
  14. package/build/system/Dialog/DialogButton.js +0 -2
  15. package/build/system/Dialog/DialogContent.js +1 -1
  16. package/build/system/Form/InlineSelect.js +2 -2
  17. package/build/system/Form/Input.js +8 -5
  18. package/build/system/Form/RadioBoxGroup.js +0 -2
  19. package/build/system/Form/SearchSelect.js +1 -1
  20. package/build/system/Form/Select.js +3 -3
  21. package/build/system/Form/Textarea.js +9 -6
  22. package/build/system/Form/ToggleGroup.js +0 -4
  23. package/build/system/Notice/Notice.js +50 -29
  24. package/build/system/ResourceList/ResourceItem.js +89 -0
  25. package/build/system/ResourceList/ResourceList.js +121 -0
  26. package/build/system/ResourceList/index.js +11 -0
  27. package/build/system/Time/index.js +91 -0
  28. package/build/system/Tooltip/Tooltip.js +4 -3
  29. package/build/system/index.js +7 -2
  30. package/package.json +47 -7
  31. package/src/system/Avatar/Avatar.js +1 -1
  32. package/src/system/Avatar/Avatar.stories.js +0 -5
  33. package/src/system/Avatar/Avatar.test.js +31 -0
  34. package/src/system/Badge/Badge.js +1 -1
  35. package/src/system/Badge/Badge.stories.js +0 -5
  36. package/src/system/BlankState/BlankState.js +2 -2
  37. package/src/system/BlankState/BlankState.stories.js +0 -5
  38. package/src/system/Box/Box.stories.js +0 -5
  39. package/src/system/Button/Button.js +1 -1
  40. package/src/system/Card/Card.js +6 -4
  41. package/src/system/Card/Card.stories.js +0 -5
  42. package/src/system/Code/Code.stories.js +4 -1
  43. package/src/system/ConfirmationDialog/ConfirmationDialog.stories.js +0 -5
  44. package/src/system/Dialog/Dialog.stories.js +0 -5
  45. package/src/system/Dialog/DialogButton.js +0 -1
  46. package/src/system/Dialog/DialogContent.js +14 -1
  47. package/src/system/Flex/Flex.stories.js +0 -5
  48. package/src/system/Form/InlineSelect.js +6 -6
  49. package/src/system/Form/Input.js +5 -3
  50. package/src/system/Form/Input.stories.js +0 -5
  51. package/src/system/Form/RadioBoxGroup.js +1 -2
  52. package/src/system/Form/RadioBoxGroup.stories.js +4 -5
  53. package/src/system/Form/SearchSelect.js +4 -4
  54. package/src/system/Form/Select.js +18 -18
  55. package/src/system/Form/Select.stories.js +1 -1
  56. package/src/system/Form/Textarea.js +6 -4
  57. package/src/system/Form/ToggleGroup.js +34 -37
  58. package/src/system/Form/ToggleGroup.stories.js +30 -32
  59. package/src/system/Form/ToggleRow.js +1 -1
  60. package/src/system/Grid/Grid.stories.js +0 -5
  61. package/src/system/Heading/Heading.stories.js +0 -5
  62. package/src/system/Link/Link.stories.js +0 -5
  63. package/src/system/Notice/Notice.js +30 -11
  64. package/src/system/Notification/Notification.js +2 -2
  65. package/src/system/Notification/Notification.stories.js +0 -5
  66. package/src/system/OptionRow/OptionRow.js +23 -23
  67. package/src/system/OptionRow/OptionRow.stories.js +0 -5
  68. package/src/system/Progress/Progress.stories.js +0 -5
  69. package/src/system/ResourceList/ResourceItem.js +66 -0
  70. package/src/system/ResourceList/ResourceList.js +96 -0
  71. package/src/system/ResourceList/ResourceList.stories.js +300 -0
  72. package/src/system/ResourceList/index.js +7 -0
  73. package/src/system/Spinner/Spinner.stories.js +0 -5
  74. package/src/system/Table/Table.stories.js +0 -5
  75. package/src/system/Table/TableRow.js +1 -1
  76. package/src/system/Tabs/Tabs.stories.js +0 -5
  77. package/src/system/Text/Text.stories.js +0 -5
  78. package/src/system/{Timeline/Timeline.stories.js → Time/Time.stories.js} +5 -5
  79. package/src/system/Time/index.js +62 -0
  80. package/src/system/Tooltip/Tooltip.js +5 -4
  81. package/src/system/Tooltip/Tooltip.stories.js +0 -5
  82. package/src/system/Wizard/Wizard.js +7 -7
  83. package/src/system/Wizard/WizardStep.js +5 -5
  84. package/src/system/Wizard/WizardStepHorizontal.js +1 -1
  85. package/src/system/index.js +27 -4
  86. package/src/system/theme/colors.js +1 -1
  87. package/src/system/theme/index.js +247 -247
  88. package/test/setupAfterEnv.js +13 -0
  89. package/test/setupTests.js +4 -0
  90. package/src/system/Timeline/index.js +0 -40
@@ -0,0 +1,66 @@
1
+ /** @jsxImportSource theme-ui */
2
+
3
+ /**
4
+ * External dependencies
5
+ */
6
+ import PropTypes from 'prop-types';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { Box, Flex, Time } from '..';
12
+
13
+ const ResourceItem = ( {
14
+ children,
15
+ item,
16
+ renderActions,
17
+ relativeTime = false,
18
+ timeOnly = false,
19
+ dateKey,
20
+ icon = null,
21
+ } ) => {
22
+ return (
23
+ <Flex
24
+ sx={{
25
+ alignItems: 'center',
26
+ gap: 3,
27
+ }}
28
+ >
29
+ {icon}
30
+ <Box sx={{ flex: '1 1 auto' }}>{children}</Box>
31
+ <Flex
32
+ sx={{
33
+ flex: '0 0 auto',
34
+ alignItems: 'center',
35
+ gap: 3,
36
+ }}
37
+ >
38
+ <Time
39
+ className="time"
40
+ relativeTime={relativeTime}
41
+ timeOnly={timeOnly}
42
+ time={item[ dateKey ]}
43
+ sx={{ color: 'muted', mb: 0, textAlign: 'right', flex: '0 0 auto' }}
44
+ />
45
+ {renderActions && (
46
+ <Flex className="actions" sx={{ alignItems: 'center', gap: 3 }}>
47
+ <Box sx={{ width: 4, height: 4, borderRadius: 4, bg: 'border' }} />
48
+ {renderActions( item )}
49
+ </Flex>
50
+ )}
51
+ </Flex>
52
+ </Flex>
53
+ );
54
+ };
55
+
56
+ ResourceItem.propTypes = {
57
+ children: PropTypes.node,
58
+ item: PropTypes.object,
59
+ icon: PropTypes.node,
60
+ relativeTime: PropTypes.bool,
61
+ timeOnly: PropTypes.bool,
62
+ dateKey: PropTypes.string,
63
+ renderActions: PropTypes.func,
64
+ };
65
+
66
+ export { ResourceItem };
@@ -0,0 +1,96 @@
1
+ /** @jsxImportSource theme-ui */
2
+
3
+ /**
4
+ * External dependencies
5
+ */
6
+ import PropTypes from 'prop-types';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { Box, Heading } from '..';
12
+
13
+ const formatterOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
14
+
15
+ const formatDate = date => {
16
+ const today = new Date();
17
+ if ( date.getFullYear() !== today.getFullYear() ) {
18
+ return date.toLocaleDateString( formatterOptions );
19
+ } else if ( date.getMonth() !== today.getMonth() ) {
20
+ return date.toLocaleDateString( formatterOptions );
21
+ } else if ( date.getDate() < today.getDate() - 1 ) {
22
+ return date.toLocaleDateString( formatterOptions );
23
+ } else if ( date.getDate() === today.getDate() - 1 ) {
24
+ return 'Yesterday';
25
+ }
26
+ return 'Today';
27
+ };
28
+
29
+ const StyledListItem = props => (
30
+ <Box
31
+ as="li"
32
+ sx={{
33
+ py: 2,
34
+ borderBottom: '1px solid',
35
+ borderColor: 'border',
36
+ listStyleType: 'none',
37
+ margin: 0,
38
+ px: 0,
39
+ }}
40
+ {...props}
41
+ />
42
+ );
43
+
44
+ const ResourceList = ( { groupedByDay = false, items, renderItem, dateKey } ) => {
45
+ let groupedItems = {};
46
+ if ( groupedByDay ) {
47
+ groupedItems = items?.reduce( ( itemGroups, item ) => {
48
+ const formattedDate = formatDate( item[ dateKey ] );
49
+ const itemsAtDate = itemGroups[ formattedDate ];
50
+
51
+ return {
52
+ ...itemGroups,
53
+ [ formattedDate ]: itemsAtDate ? [ ...itemsAtDate, item ] : [ item ],
54
+ };
55
+ }, {} );
56
+ }
57
+
58
+ const renderItemList = itemsList =>
59
+ itemsList.map( ( item, index ) => <StyledListItem key={index}>{renderItem( item )}</StyledListItem> );
60
+
61
+ return (
62
+ <Box as="ul" sx={{ listStyleType: 'none', m: 0, p: 0 }}>
63
+ {groupedByDay
64
+ ? Object.keys( groupedItems ).map( ( groupName, index ) => (
65
+ <Box sx={{ mb: 4 }} key={index}>
66
+ <Heading variant="h4" as="h4" sx={{ mb: 3 }}>
67
+ {groupName}
68
+ </Heading>
69
+ <Box
70
+ as="ul"
71
+ sx={{
72
+ listStyleType: 'none',
73
+ m: 0,
74
+ p: 0,
75
+ borderTop: '1px solid',
76
+ borderColor: 'border',
77
+ }}
78
+ >
79
+ {renderItemList( groupedItems[ groupName ] )}
80
+ </Box>
81
+ </Box>
82
+ ) )
83
+ : renderItemList( items )}
84
+ </Box>
85
+ );
86
+ };
87
+
88
+ ResourceList.propTypes = {
89
+ groupedByDay: PropTypes.bool,
90
+ items: PropTypes.array,
91
+ renderItem: PropTypes.func,
92
+ relativeTime: PropTypes.bool,
93
+ dateKey: PropTypes.string,
94
+ };
95
+
96
+ export { ResourceList };
@@ -0,0 +1,300 @@
1
+ /** @jsxImportSource theme-ui */
2
+
3
+ /**
4
+ * External dependencies
5
+ */
6
+ import React from 'react';
7
+ import { BiGlobe, BiCheckCircle, BiRevision } from 'react-icons/bi';
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ import {
13
+ Avatar,
14
+ Badge,
15
+ Box,
16
+ Card,
17
+ Flex,
18
+ Button,
19
+ ResourceList,
20
+ ResourceItem,
21
+ Text,
22
+ Heading,
23
+ } from '..';
24
+
25
+ export default {
26
+ title: 'ResourceList',
27
+ component: ResourceList,
28
+ };
29
+
30
+ const logs = [
31
+ {
32
+ actor: 'Saxon Fletcher',
33
+ action: 'switched primary domain to',
34
+ object: 'mydomain.com',
35
+ date: new Date(),
36
+ },
37
+ {
38
+ actor: 'Saxon Fletcher',
39
+ action: 'switched primary domain to',
40
+ object: 'mydomain.com',
41
+ date: new Date( new Date().setHours( 11 ) ),
42
+ },
43
+ {
44
+ actor: 'Simon Wheatley',
45
+ action: 'deployed to',
46
+ object: 'Production',
47
+ showObject: true,
48
+ date: new Date( new Date().setDate( 15 ) ),
49
+ },
50
+ {
51
+ actor: 'Saxon Fletcher',
52
+ action: 'created a backup on',
53
+ object: 'Production',
54
+ date: new Date( new Date().setDate( 13 ) ),
55
+ },
56
+ ];
57
+
58
+ export const Grouped = () => (
59
+ <Box sx={{ p: 5, pt: 2 }}>
60
+ <Heading sx={{ mb: 2 }}>Audit Log</Heading>
61
+ <Text sx={{ mb: 4 }}>A live trail of system and human events.</Text>
62
+ <ResourceList
63
+ items={logs}
64
+ dateKey="date"
65
+ groupedByDay={true}
66
+ renderItem={item => (
67
+ <ResourceItem
68
+ item={item}
69
+ icon={<BiGlobe sx={{ color: 'red' }} />}
70
+ dateKey={'date'}
71
+ relativeTime={true}
72
+ timeOnly={true}
73
+ >
74
+ <Flex sx={{ alignItems: 'center', gap: 3 }}>
75
+ <Avatar
76
+ name={item.actor}
77
+ src="https://uifaces.co/our-content/donated/1H_7AxP0.jpg"
78
+ size={16}
79
+ />
80
+ <Heading variant="h4" as="p" sx={{ mb: 0, fontWeight: 'normal' }}>
81
+ {item.actor}{' '}
82
+ <Text as="span" sx={{ color: 'muted', mb: 0 }}>
83
+ {item.action}
84
+ </Text>{' '}
85
+ {item.object}
86
+ </Heading>
87
+ </Flex>
88
+ {item.showObject && (
89
+ <Box
90
+ variant="indent"
91
+ sx={{ mt: 2, display: 'flex', flexWrap: 'wrap', gap: 3, alignItems: 'center' }}
92
+ >
93
+ <Heading variant="h5" as="div" sx={{ mb: 0 }}>
94
+ Merge pull request{' '}
95
+ <Text as="span" sx={{ color: 'muted' }}>
96
+ #443
97
+ </Text>
98
+ </Heading>
99
+ <Text sx={{ mb: 0, fontSize: 1, display: 'flex', alignItems: 'center', gap: 1 }}>
100
+ <Avatar
101
+ name={item.actor}
102
+ src="https://uifaces.co/our-content/donated/n4Ngwvi7.jpg"
103
+ size={16}
104
+ />
105
+ {item.actor}
106
+ </Text>
107
+ <Text sx={{ mb: 0, fontSize: 1, display: 'flex', alignItems: 'center', gap: 1 }}>
108
+ <BiCheckCircle size={16} />
109
+ Deployed in 31s
110
+ </Text>
111
+ </Box>
112
+ )}
113
+ </ResourceItem>
114
+ )}
115
+ />
116
+ </Box>
117
+ );
118
+
119
+ const deploys = [
120
+ {
121
+ title: 'Merge pull request',
122
+ id: '#773',
123
+ author: 'Saxon Fletcher',
124
+ date: new Date( new Date().setHours( 11 ) ),
125
+ status: 'running',
126
+ },
127
+ {
128
+ title: 'Update homepage',
129
+ id: '#772',
130
+ author: 'Saxon Fletcher',
131
+ date: new Date( new Date().setHours( 9 ) ),
132
+ },
133
+ {
134
+ title: 'Improve overall performance',
135
+ id: '#771',
136
+ author: 'Saxon Fletcher',
137
+ date: new Date( new Date().setHours( 8 ) ),
138
+ },
139
+ {
140
+ title: 'Merge pull request',
141
+ id: '#770',
142
+ author: 'Saxon Fletcher',
143
+ date: new Date( new Date().setHours( 5 ) ),
144
+ status: 'failed',
145
+ },
146
+ {
147
+ title: 'Merge pull request',
148
+ id: '#773',
149
+ author: 'Saxon Fletcher',
150
+ date: new Date( new Date().setHours( 11 ) ),
151
+ },
152
+ {
153
+ title: 'Update homepage',
154
+ id: '#772',
155
+ author: 'Saxon Fletcher',
156
+ date: new Date( new Date().setHours( 9 ) ),
157
+ },
158
+ {
159
+ title: 'Improve overall performance',
160
+ id: '#771',
161
+ author: 'Saxon Fletcher',
162
+ date: new Date( new Date().setHours( 8 ) ),
163
+ },
164
+ {
165
+ title: 'Merge pull request',
166
+ id: '#770',
167
+ author: 'Saxon Fletcher',
168
+ date: new Date( new Date().setHours( 5 ) ),
169
+ },
170
+ {
171
+ title: 'Merge pull request',
172
+ id: '#773',
173
+ author: 'Saxon Fletcher',
174
+ date: new Date( new Date().setHours( 11 ) ),
175
+ },
176
+ {
177
+ title: 'Update homepage',
178
+ id: '#772',
179
+ author: 'Saxon Fletcher',
180
+ date: new Date( new Date().setHours( 9 ) ),
181
+ },
182
+ {
183
+ title: 'Improve overall performance',
184
+ id: '#771',
185
+ author: 'Saxon Fletcher',
186
+ date: new Date( new Date().setHours( 8 ) ),
187
+ },
188
+ {
189
+ title: 'Merge pull request',
190
+ id: '#770',
191
+ author: 'Saxon Fletcher',
192
+ date: new Date( new Date().setHours( 5 ) ),
193
+ },
194
+ {
195
+ title: 'Merge pull request',
196
+ id: '#773',
197
+ author: 'Saxon Fletcher',
198
+ date: new Date( new Date().setHours( 11 ) ),
199
+ },
200
+ {
201
+ title: 'Update homepage',
202
+ id: '#772',
203
+ author: 'Saxon Fletcher',
204
+ date: new Date( new Date().setHours( 9 ) ),
205
+ },
206
+ {
207
+ title: 'Improve overall performance',
208
+ id: '#771',
209
+ author: 'Saxon Fletcher',
210
+ date: new Date( new Date().setHours( 8 ) ),
211
+ },
212
+ {
213
+ title: 'Merge pull request',
214
+ id: '#770',
215
+ author: 'Saxon Fletcher',
216
+ date: new Date( new Date().setHours( 5 ) ),
217
+ },
218
+ ];
219
+
220
+ export const Relative = () => (
221
+ <Box sx={{ p: 5, pt: 2 }}>
222
+ <Heading sx={{ mb: 2 }}>Deploys</Heading>
223
+ <Text sx={{ mb: 4 }}>View and manage application deployments.</Text>
224
+ <Card variant="indent" sx={{ mb: 4, display: 'flex', flexDirection: 'row-reverse', gap: 1 }}>
225
+ {deploys.map( ( deploy, index ) => (
226
+ <Box
227
+ key={index}
228
+ sx={{
229
+ flex: '1 1 auto',
230
+ width: 10,
231
+ height: 4,
232
+ backgroundColor: deploy.status === 'running' ? 'blue.50' : 'green.50',
233
+ borderRadius: 1,
234
+ }}
235
+ ></Box>
236
+ ) )}
237
+ </Card>
238
+ <ResourceList
239
+ items={deploys}
240
+ dateKey="date"
241
+ groupedByDay={false}
242
+ renderItem={item => (
243
+ <ResourceItem
244
+ item={item}
245
+ dateKey={'date'}
246
+ relativeTime={true}
247
+ timeOnly={true}
248
+ renderActions={() => (
249
+ <Flex sx={{ alignItems: 'center' }}>
250
+ <Button variant="secondary" sx={{ fontSize: 1 }}>
251
+ Rollback
252
+ </Button>
253
+ </Flex>
254
+ )}
255
+ >
256
+ <Flex sx={{ alignItems: 'center', gap: 4 }}>
257
+ <Flex sx={{ alignItems: 'center', gap: 3, minWidth: 300 }}>
258
+ <Heading variant="h4" as="p" sx={{ mb: 0, fontWeight: 'normal' }}>
259
+ {item.title}{' '}
260
+ <Text as="span" sx={{ color: 'muted', mb: 0 }}>
261
+ {item.id}
262
+ </Text>
263
+ </Heading>
264
+ {item.status === 'running' && <Badge sx={{ mb: 0 }}>Running</Badge>}
265
+ </Flex>
266
+ <Text sx={{ mb: 0, color: 'muted', display: 'flex', alignItems: 'center', gap: 2 }}>
267
+ <Avatar
268
+ name={item.author}
269
+ size={16}
270
+ src="https://randomuser.me/api/portraits/men/46.jpg"
271
+ />
272
+ {item.author}
273
+ </Text>
274
+ <Text
275
+ sx={{
276
+ mb: 0,
277
+ color: item.status === 'running' ? 'blue.60' : 'muted',
278
+ display: 'flex',
279
+ alignItems: 'center',
280
+ gap: 1,
281
+ }}
282
+ >
283
+ {item.status === 'running' ? (
284
+ <React.Fragment>
285
+ <BiRevision size={16} />
286
+ Running for 31s
287
+ </React.Fragment>
288
+ ) : (
289
+ <React.Fragment>
290
+ <BiCheckCircle size={16} />
291
+ Deployed in 31s
292
+ </React.Fragment>
293
+ )}
294
+ </Text>
295
+ </Flex>
296
+ </ResourceItem>
297
+ )}
298
+ />
299
+ </Box>
300
+ );
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import { ResourceList } from './ResourceList';
5
+ import { ResourceItem } from './ResourceItem';
6
+
7
+ export { ResourceList, ResourceItem };
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */
@@ -84,4 +84,4 @@ TableRow.propTypes = {
84
84
  rowHead: PropTypes.bool,
85
85
  };
86
86
 
87
- export { TableRow };
87
+ export { TableRow };
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */
@@ -6,24 +6,24 @@ import React from 'react';
6
6
  /**
7
7
  * Internal dependencies
8
8
  */
9
- import { Timeline, Grid, Box } from '..';
9
+ import { Time, Grid, Box } from '..';
10
10
 
11
11
  export default {
12
- title: 'Timeline',
13
- component: Timeline,
12
+ title: 'Time',
13
+ component: Time,
14
14
  };
15
15
 
16
16
  export const Default = () => (
17
17
  <React.Fragment>
18
18
  <Grid gap={ 2 } columns={ [ 2, '100px 300px' ] } sx={ { mb: '20px' } }>
19
- <Timeline time="7pm" />
19
+ <Time time="7pm" />
20
20
  <Box>
21
21
  It looks like everything is recovered now. You can forget about the last event.
22
22
  </Box>
23
23
  </Grid>
24
24
 
25
25
  <Grid gap={ 2 } columns={ [ 2, '100px 200px' ] }>
26
- <Timeline time="6pm" />
26
+ <Time time="6pm" />
27
27
  <Box>
28
28
  At this particular moment in the day, something happened with your environment.
29
29
  </Box>
@@ -0,0 +1,62 @@
1
+ /** @jsxImportSource theme-ui */
2
+
3
+ /**
4
+ * External dependencies
5
+ */
6
+ import { Text } from 'theme-ui';
7
+ import PropTypes from 'prop-types';
8
+
9
+ const formatter = new Intl.RelativeTimeFormat( undefined, {
10
+ numeric: 'auto',
11
+ } );
12
+
13
+ const DIVISIONS = [
14
+ { amount: 60, name: 'seconds' },
15
+ { amount: 60, name: 'minutes' },
16
+ { amount: 24, name: 'hours' },
17
+ { amount: 7, name: 'days' },
18
+ { amount: 12, name: 'months' },
19
+ { amount: Number.POSITIVE_INFINITY, name: 'years' },
20
+ ];
21
+
22
+ function formatTimeAgo( date ) {
23
+ let duration = ( date - new Date() ) / 1000;
24
+
25
+ for ( let i = 0; i <= DIVISIONS.length; i++ ) {
26
+ const division = DIVISIONS[ i ];
27
+ if ( Math.abs( duration ) < division.amount ) {
28
+ return formatter.format( Math.round( duration ), division.name );
29
+ }
30
+ duration /= division.amount;
31
+ }
32
+ }
33
+
34
+ const Time = ( { time, relativeTime = false, timeOnly = false, ...props } ) => {
35
+ let formattedTime;
36
+ if ( relativeTime ) {
37
+ formattedTime = formatTimeAgo( time );
38
+ } else if ( timeOnly ) {
39
+ formattedTime = time.toLocaleTimeString();
40
+ } else {
41
+ formattedTime = time.toLocaleString();
42
+ }
43
+
44
+ return (
45
+ <Text
46
+ title={time.toLocaleString( 'sv', { timeZoneName: 'short' } )}
47
+ datetime={time}
48
+ as="time"
49
+ {...props}
50
+ >
51
+ {formattedTime}
52
+ </Text>
53
+ );
54
+ };
55
+
56
+ Time.propTypes = {
57
+ time: PropTypes.string,
58
+ timeOnly: PropTypes.bool,
59
+ relativeTime: PropTypes.bool,
60
+ };
61
+
62
+ export { Time };
@@ -5,14 +5,14 @@
5
5
  */
6
6
  import PropTypes from 'prop-types';
7
7
  import { MdHelp } from 'react-icons/md';
8
- import * as TTip from "@radix-ui/react-tooltip";
8
+ import * as TTip from '@radix-ui/react-tooltip';
9
9
 
10
10
  /**
11
11
  * Internal dependencies
12
12
  */
13
13
  import { Card, Text } from '..';
14
14
 
15
- const StyledArrow = props => <TTip.Arrow sx={{ fill: 'white' }} { ...props } />
15
+ const StyledArrow = props => <TTip.Arrow sx={{ fill: 'white' }} { ...props } />;
16
16
 
17
17
  const Tooltip = ( {
18
18
  trigger = <MdHelp />,
@@ -70,10 +70,11 @@ const Tooltip = ( {
70
70
  };
71
71
 
72
72
  Tooltip.propTypes = {
73
+ children: PropTypes.object,
74
+ text: PropTypes.string,
75
+ tooltipProps: PropTypes.object,
73
76
  trigger: PropTypes.string,
74
77
  width: PropTypes.number,
75
- text: PropTypes.string,
76
- children: PropTypes.object,
77
78
  };
78
79
 
79
80
  export { Tooltip };
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */
@@ -12,7 +12,7 @@ import { MdArrowForward } from 'react-icons/md';
12
12
  */
13
13
  import { Box, WizardStep, Flex, WizardStepHorizontal } from '..';
14
14
 
15
- const Wizard = ({ steps, activeStep, variant, completed = [], ...props }) => {
15
+ const Wizard = ( { steps, activeStep, variant, completed = [], ...props } ) => {
16
16
  return (
17
17
  <Box>
18
18
  {variant === 'horizontal' ? (
@@ -23,7 +23,7 @@ const Wizard = ({ steps, activeStep, variant, completed = [], ...props }) => {
23
23
  }}
24
24
  {...props}
25
25
  >
26
- {steps.map(({ title, subTitle }, index) => (
26
+ {steps.map( ( { title, subTitle }, index ) => (
27
27
  <React.Fragment key={index}>
28
28
  <WizardStepHorizontal
29
29
  active={index === activeStep}
@@ -32,22 +32,22 @@ const Wizard = ({ steps, activeStep, variant, completed = [], ...props }) => {
32
32
  />
33
33
  {index < steps.length - 1 && <MdArrowForward sx={{ mx: 2, color: 'grey.80' }} />}
34
34
  </React.Fragment>
35
- ))}
35
+ ) )}
36
36
  </Flex>
37
- {steps[activeStep].children}
37
+ {steps[ activeStep ].children}
38
38
  </Box>
39
39
  ) : (
40
- steps.map(({ title, subTitle, children }, index) => (
40
+ steps.map( ( { title, subTitle, children }, index ) => (
41
41
  <WizardStep
42
42
  active={index === activeStep}
43
43
  title={title}
44
44
  subTitle={subTitle}
45
- complete={completed.includes(index)}
45
+ complete={completed.includes( index )}
46
46
  key={index}
47
47
  >
48
48
  {children}
49
49
  </WizardStep>
50
- ))
50
+ ) )
51
51
  )}
52
52
  </Box>
53
53
  );