@sproutsocial/seeds-react-duration 1.0.30 → 1.0.32

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/CHANGELOG.md DELETED
@@ -1,254 +0,0 @@
1
- # @sproutsocial/seeds-react-duration
2
-
3
- ## 1.0.30
4
-
5
- ### Patch Changes
6
-
7
- - Updated dependencies [d8509a3]
8
- - @sproutsocial/seeds-react-theme@4.3.1
9
- - @sproutsocial/seeds-react-visually-hidden@1.0.28
10
-
11
- ## 1.0.29
12
-
13
- ### Patch Changes
14
-
15
- - Updated dependencies [b77aca0]
16
- - Updated dependencies [2e72599]
17
- - @sproutsocial/seeds-react-system-props@3.1.3
18
- - @sproutsocial/seeds-react-theme@4.3.0
19
- - @sproutsocial/seeds-react-text@1.5.2
20
- - @sproutsocial/seeds-react-visually-hidden@1.0.27
21
-
22
- ## 1.0.28
23
-
24
- ### Patch Changes
25
-
26
- - Updated dependencies [d21ae54]
27
- - @sproutsocial/seeds-react-theme@4.2.1
28
- - @sproutsocial/seeds-react-visually-hidden@1.0.26
29
-
30
- ## 1.0.27
31
-
32
- ### Patch Changes
33
-
34
- - Updated dependencies [6611f6a]
35
- - @sproutsocial/seeds-react-system-props@3.1.2
36
- - @sproutsocial/seeds-react-text@1.5.1
37
- - @sproutsocial/seeds-react-visually-hidden@1.0.25
38
-
39
- ## 1.0.26
40
-
41
- ### Patch Changes
42
-
43
- - Updated dependencies [85f9728]
44
- - Updated dependencies [fa7d859]
45
- - @sproutsocial/seeds-react-theme@4.2.0
46
- - @sproutsocial/seeds-react-visually-hidden@1.0.24
47
-
48
- ## 1.0.25
49
-
50
- ### Patch Changes
51
-
52
- - Updated dependencies [65b5879]
53
- - @sproutsocial/seeds-react-text@1.5.0
54
-
55
- ## 1.0.24
56
-
57
- ### Patch Changes
58
-
59
- - Updated dependencies [a13a571]
60
- - @sproutsocial/seeds-react-theme@4.1.1
61
- - @sproutsocial/seeds-react-visually-hidden@1.0.23
62
-
63
- ## 1.0.23
64
-
65
- ### Patch Changes
66
-
67
- - Updated dependencies [edc1819]
68
- - @sproutsocial/seeds-react-text@1.4.3
69
-
70
- ## 1.0.22
71
-
72
- ### Patch Changes
73
-
74
- - Updated dependencies [5892f44]
75
- - @sproutsocial/seeds-react-system-props@3.1.1
76
- - @sproutsocial/seeds-react-text@1.4.2
77
- - @sproutsocial/seeds-react-visually-hidden@1.0.22
78
-
79
- ## 1.0.21
80
-
81
- ### Patch Changes
82
-
83
- - Updated dependencies [5114a32]
84
- - @sproutsocial/seeds-react-theme@4.1.0
85
- - @sproutsocial/seeds-react-visually-hidden@1.0.21
86
-
87
- ## 1.0.20
88
-
89
- ### Patch Changes
90
-
91
- - Updated dependencies [132ef9d]
92
- - Updated dependencies [132ef9d]
93
- - @sproutsocial/seeds-react-theme@4.0.0
94
- - @sproutsocial/seeds-react-system-props@3.1.0
95
- - @sproutsocial/seeds-react-visually-hidden@1.0.20
96
- - @sproutsocial/seeds-react-text@1.4.1
97
-
98
- ## 1.0.19
99
-
100
- ### Patch Changes
101
-
102
- - Updated dependencies [47c62b3]
103
- - @sproutsocial/seeds-react-theme@3.7.1
104
- - @sproutsocial/seeds-react-visually-hidden@1.0.19
105
-
106
- ## 1.0.18
107
-
108
- ### Patch Changes
109
-
110
- - Updated dependencies [06da9c2]
111
- - @sproutsocial/seeds-react-theme@3.7.0
112
- - @sproutsocial/seeds-react-visually-hidden@1.0.18
113
-
114
- ## 1.0.17
115
-
116
- ### Patch Changes
117
-
118
- - Updated dependencies [4ba8720]
119
- - @sproutsocial/seeds-react-theme@3.6.2
120
- - @sproutsocial/seeds-react-visually-hidden@1.0.17
121
-
122
- ## 1.0.16
123
-
124
- ### Patch Changes
125
-
126
- - Updated dependencies [1f9a473]
127
- - @sproutsocial/seeds-react-theme@3.6.1
128
- - @sproutsocial/seeds-react-visually-hidden@1.0.16
129
-
130
- ## 1.0.15
131
-
132
- ### Patch Changes
133
-
134
- - Updated dependencies [17d4f12]
135
- - @sproutsocial/seeds-react-theme@3.6.0
136
- - @sproutsocial/seeds-react-visually-hidden@1.0.15
137
-
138
- ## 1.0.14
139
-
140
- ### Patch Changes
141
-
142
- - @sproutsocial/seeds-react-visually-hidden@1.0.14
143
-
144
- ## 1.0.13
145
-
146
- ### Patch Changes
147
-
148
- - Updated dependencies [118e300]
149
- - @sproutsocial/seeds-react-theme@3.5.1
150
- - @sproutsocial/seeds-react-visually-hidden@1.0.13
151
-
152
- ## 1.0.12
153
-
154
- ### Patch Changes
155
-
156
- - Updated dependencies [db6ce39]
157
- - Updated dependencies [20bb01b]
158
- - @sproutsocial/seeds-react-theme@3.5.0
159
- - @sproutsocial/seeds-react-visually-hidden@1.0.12
160
-
161
- ## 1.0.11
162
-
163
- ### Patch Changes
164
-
165
- - Updated dependencies [29ced53]
166
- - @sproutsocial/seeds-react-text@1.4.0
167
-
168
- ## 1.0.10
169
-
170
- ### Patch Changes
171
-
172
- - Updated dependencies [7716e16]
173
- - @sproutsocial/seeds-react-theme@3.4.0
174
- - @sproutsocial/seeds-react-visually-hidden@1.0.11
175
-
176
- ## 1.0.9
177
-
178
- ### Patch Changes
179
-
180
- - @sproutsocial/seeds-react-theme@3.3.2
181
- - @sproutsocial/seeds-react-visually-hidden@1.0.10
182
-
183
- ## 1.0.8
184
-
185
- ### Patch Changes
186
-
187
- - @sproutsocial/seeds-react-theme@3.3.1
188
- - @sproutsocial/seeds-react-visually-hidden@1.0.9
189
-
190
- ## 1.0.7
191
-
192
- ### Patch Changes
193
-
194
- - Updated dependencies [750d1ea]
195
- - @sproutsocial/seeds-react-theme@3.3.0
196
- - @sproutsocial/seeds-react-visually-hidden@1.0.8
197
-
198
- ## 1.0.6
199
-
200
- ### Patch Changes
201
-
202
- - Updated dependencies [fa7579a]
203
- - @sproutsocial/seeds-react-theme@3.2.1
204
- - @sproutsocial/seeds-react-visually-hidden@1.0.7
205
-
206
- ## 1.0.5
207
-
208
- ### Patch Changes
209
-
210
- - Updated dependencies [8f6ba8d]
211
- - @sproutsocial/seeds-react-theme@3.2.0
212
- - @sproutsocial/seeds-react-visually-hidden@1.0.6
213
-
214
- ## 1.0.4
215
-
216
- ### Patch Changes
217
-
218
- - Updated dependencies [b1c3b44]
219
- - @sproutsocial/seeds-react-theme@3.1.1
220
- - @sproutsocial/seeds-react-visually-hidden@1.0.5
221
-
222
- ## 1.0.3
223
-
224
- ### Patch Changes
225
-
226
- - Updated dependencies [47580c4]
227
- - @sproutsocial/seeds-react-theme@3.1.0
228
- - @sproutsocial/seeds-react-visually-hidden@1.0.4
229
-
230
- ## 1.0.2
231
-
232
- ### Patch Changes
233
-
234
- - Updated dependencies [22e1111]
235
- - @sproutsocial/seeds-react-text@1.3.2
236
- - @sproutsocial/seeds-react-theme@3.0.1
237
- - @sproutsocial/seeds-react-visually-hidden@1.0.3
238
-
239
- ## 1.0.1
240
-
241
- ### Patch Changes
242
-
243
- - 9fd8bac: Update dependencies to use semantic package version instead of wildcards
244
- - Updated dependencies [9fd8bac]
245
- - @sproutsocial/seeds-react-visually-hidden@1.0.2
246
- - @sproutsocial/seeds-react-system-props@3.0.2
247
- - @sproutsocial/seeds-react-theme@2.2.1
248
- - @sproutsocial/seeds-react-text@1.3.1
249
-
250
- ## 1.0.0
251
-
252
- ### Major Changes
253
-
254
- - b812940: Migrated Duration from Racine to seeds-react-duration
package/jest.config.js DELETED
@@ -1,13 +0,0 @@
1
- const baseConfig = require("@sproutsocial/seeds-testing");
2
-
3
- /** * @type {import('jest').Config} */
4
- const config = {
5
- ...baseConfig,
6
- displayName: "seeds-react-duration",
7
- testPathIgnorePatterns: [
8
- ...baseConfig.testPathIgnorePatterns,
9
- "testDuration.tsx",
10
- ],
11
- };
12
-
13
- module.exports = config;
@@ -1,82 +0,0 @@
1
- import React from "react";
2
- import type { Meta, StoryObj } from "@storybook/react";
3
- import Duration from "./Duration";
4
-
5
- const localeOptions = [
6
- "English (en-US)",
7
- "Spanish (es-LA)",
8
- "French (fr-FR)",
9
- "Italian (it-IT)",
10
- "Portuguese (pt-BR)",
11
- ];
12
-
13
- const localeMapping = {
14
- "English (en-US)": "en-US",
15
- "Spanish (es-LA)": "es-LA",
16
- "French (fr-FR)": "fr-FR",
17
- "Italian (it-IT)": "it-IT",
18
- "Portuguese (pt-BR)": "pt-BR",
19
- };
20
-
21
- const displayOptions = ["Long", "Narrow"];
22
-
23
- const displayMapping = {
24
- Long: "long",
25
- Narrow: "narrow",
26
- };
27
-
28
- const meta: Meta<typeof Duration> = {
29
- title: "Components/Duration",
30
- component: Duration,
31
- argTypes: {
32
- locale: {
33
- control: "select",
34
- options: localeOptions,
35
- mapping: localeMapping,
36
- },
37
- display: {
38
- control: "select",
39
- options: displayOptions,
40
- mapping: displayMapping,
41
- },
42
- },
43
- args: {
44
- milliseconds: 123456789,
45
- },
46
- };
47
- export default meta;
48
-
49
- type Story = StoryObj<typeof Duration>;
50
-
51
- export const Default: Story = {
52
- args: {
53
- milliseconds: 123456789,
54
- },
55
- };
56
-
57
- export const Invalid: Story = {
58
- args: {
59
- milliseconds: null,
60
- },
61
- };
62
-
63
- export const DisplayLong: Story = {
64
- args: {
65
- display: "long",
66
- },
67
- };
68
-
69
- export const Negative: Story = {
70
- args: {
71
- milliseconds: -123456789,
72
- },
73
- };
74
-
75
- export const DisplayUnits: Story = {
76
- args: {
77
- displayUnits: {
78
- hours: true,
79
- minutes: true,
80
- },
81
- },
82
- };
package/src/Duration.tsx DELETED
@@ -1,151 +0,0 @@
1
- import * as React from "react";
2
- // @ts-expect-error lru-memoize is not typed
3
- import memoize from "lru-memoize";
4
- import { EM_DASH } from "./constants";
5
- import { VisuallyHidden } from "@sproutsocial/seeds-react-visually-hidden";
6
-
7
- import {
8
- COMPARE_OBJECTS,
9
- DEFAULT_DISPLAY,
10
- DEFAULT_DISPLAY_UNITS,
11
- DEFAULT_LOCALE,
12
- DEFAULT_MILLISECONDS,
13
- MEMO_CACHE_SIZE,
14
- ORDERED_UNITS,
15
- UNITS,
16
- } from "./constants";
17
- import { Container } from "./styles";
18
- import type {
19
- TypeDurationProps,
20
- TypeDurationLocale,
21
- TypeDurationDisplay,
22
- TypeDurationDisplayUnits,
23
- } from "./DurationTypes";
24
- import {
25
- isValidNumber,
26
- getLowestUnit,
27
- splitMillisecondsIntoUnits,
28
- } from "./utils";
29
-
30
- const _createDurationFormatter = (
31
- locale: TypeDurationLocale,
32
- unitDisplay: TypeDurationDisplay,
33
- displayUnits: TypeDurationDisplayUnits
34
- ) => {
35
- const timeUnitFormatter = (
36
- locale: TypeDurationProps["locale"],
37
- unit: string,
38
- unitDisplay: TypeDurationProps["display"]
39
- ) => Intl.NumberFormat(locale, { style: "unit", unit, unitDisplay }).format;
40
-
41
- const formatterByUnit = {
42
- [UNITS.days]: timeUnitFormatter(locale, "day", unitDisplay),
43
- [UNITS.hours]: timeUnitFormatter(locale, "hour", unitDisplay),
44
- [UNITS.minutes]: timeUnitFormatter(locale, "minute", unitDisplay),
45
- [UNITS.seconds]: timeUnitFormatter(locale, "second", unitDisplay),
46
- [UNITS.milliseconds]: timeUnitFormatter(locale, "millisecond", unitDisplay),
47
- };
48
-
49
- const formatList = new Intl.ListFormat(locale, {
50
- style: "narrow",
51
- type: "unit",
52
- });
53
-
54
- return (value: number) => {
55
- const lowestUnit = getLowestUnit(displayUnits);
56
-
57
- // if the value is zero or negative, we just want to return 0 for the lowest unit (ex "0 minutes")
58
- if (value <= 0) {
59
- // @ts-ignore TS error later
60
- return formatterByUnit[lowestUnit](0);
61
- }
62
-
63
- const millisecondsByUnit = splitMillisecondsIntoUnits(value, displayUnits);
64
- const list: string[] = [];
65
-
66
- ORDERED_UNITS.forEach((unit) => {
67
- if (unit in millisecondsByUnit) {
68
- // @ts-ignore TS error later
69
- const unitValue = millisecondsByUnit[unit];
70
-
71
- // we want to add to the list if one of two conditions are met:
72
- // 1) the unit has a value greater than 0 OR
73
- // 2) the unit has value 0 AND the unit is the lowest unit AND the list is already empty
74
- if (
75
- unitValue !== 0 ||
76
- (unitValue === 0 && unit === lowestUnit && list.length === 0)
77
- ) {
78
- // @ts-ignore TS error later
79
- list.push(formatterByUnit[unit](millisecondsByUnit[unit]));
80
- }
81
- }
82
- });
83
-
84
- return formatList.format(list);
85
- };
86
- };
87
-
88
- // Memoize to reduce the energy of creating new instances of Intl.NumberFormat
89
- const memoizer = memoize(MEMO_CACHE_SIZE, COMPARE_OBJECTS);
90
- const createDurationFormatter = memoizer(_createDurationFormatter);
91
-
92
- const getDuration = ({
93
- returnType,
94
- props,
95
- }: {
96
- returnType: "string" | "component";
97
- props: TypeDurationProps;
98
- }): string | React.ReactNode => {
99
- const {
100
- display = DEFAULT_DISPLAY,
101
- displayUnits = DEFAULT_DISPLAY_UNITS,
102
- invalidMillisecondsLabel,
103
- locale = DEFAULT_LOCALE,
104
- milliseconds = DEFAULT_MILLISECONDS,
105
- qa,
106
- } = props;
107
- const isReturnTypeString = returnType === "string";
108
-
109
- if (!isValidNumber(milliseconds)) {
110
- return isReturnTypeString ? (
111
- EM_DASH
112
- ) : (
113
- <>
114
- {invalidMillisecondsLabel ? (
115
- // Give screen readers something useful to read off + hide the em dash
116
- <VisuallyHidden>{invalidMillisecondsLabel}</VisuallyHidden>
117
- ) : null}
118
- <Container aria-hidden {...qa}>
119
- {EM_DASH}
120
- </Container>
121
- </>
122
- );
123
- }
124
-
125
- const validatedDisplayUnits =
126
- Object.keys(displayUnits).length === 0
127
- ? DEFAULT_DISPLAY_UNITS
128
- : displayUnits;
129
-
130
- const fullText = createDurationFormatter(
131
- locale,
132
- display,
133
- validatedDisplayUnits
134
- )(milliseconds);
135
-
136
- return isReturnTypeString ? (
137
- fullText
138
- ) : (
139
- <Container {...qa}>{fullText}</Container>
140
- );
141
- };
142
-
143
- export const formatDuration = (props: TypeDurationProps): string => {
144
- return getDuration({ returnType: "string", props }) as string;
145
- };
146
-
147
- const Duration = (props: TypeDurationProps) => {
148
- return getDuration({ returnType: "component", props });
149
- };
150
-
151
- export default Duration;
@@ -1,34 +0,0 @@
1
- import type { TypeTextProps } from "@sproutsocial/seeds-react-text";
2
-
3
- export type TypeDurationMilliseconds = number | null;
4
-
5
- export type TypeDurationLocale = Intl.LocalesArgument;
6
-
7
- export type TypeDurationDisplay = "long" | "narrow";
8
-
9
- export interface TypeDurationDisplayUnits {
10
- days?: boolean;
11
- hours?: boolean;
12
- minutes?: boolean;
13
- seconds?: boolean;
14
- milliseconds?: boolean;
15
- }
16
-
17
- export interface TypeDurationProps extends Omit<TypeTextProps, "children"> {
18
- /** The milliseconds to be formatted */
19
- milliseconds: TypeDurationMilliseconds;
20
-
21
- /** Locale to format. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument */
22
- locale?: TypeDurationLocale;
23
-
24
- /** The style of the formatted duration */
25
- display?: TypeDurationDisplay;
26
-
27
- /** The units of the duration to render */
28
- displayUnits?: TypeDurationDisplayUnits;
29
-
30
- /** Text to be read off by screen readers for invalid values (i.e., any value rendered as '—' (em dash)) */
31
- invalidMillisecondsLabel?: string;
32
-
33
- qa?: object;
34
- }
@@ -1,29 +0,0 @@
1
- import * as React from "react";
2
- import Duration from "../Duration";
3
-
4
- const defaultProps = {
5
- color: "text.headline",
6
- milliseconds: 12345,
7
- };
8
-
9
- export const DurationTypeTest = () => (
10
- <>
11
- <Duration {...defaultProps} />
12
- <Duration
13
- {...defaultProps}
14
- milliseconds={100}
15
- fontWeight="semibold"
16
- fontSize={500}
17
- />
18
- <Duration {...defaultProps} milliseconds={100} color="teal.500" />
19
- <Duration {...defaultProps} milliseconds={100} locale="it-IT" />
20
- <Duration {...defaultProps} milliseconds={123.4} display="narrow" />
21
- <Duration
22
- {...defaultProps}
23
- milliseconds={null}
24
- invalidMillisecondsLabel="Not available"
25
- />
26
- {/* @ts-expect-error - test that invalid display is rejected */}
27
- <Duration {...defaultProps} display="short" />
28
- </>
29
- );
@@ -1,11 +0,0 @@
1
- import React from "react";
2
- import { render } from "@sproutsocial/seeds-react-testing-library";
3
- import Duration from "../../Duration";
4
-
5
- describe("When rendering...", () => {
6
- it("should handle A11y", async () => {
7
- const { container, runA11yCheck } = render(<Duration milliseconds={0} />);
8
- expect(container).toBeTruthy();
9
- await runA11yCheck();
10
- });
11
- });
@@ -1,116 +0,0 @@
1
- import testDuration from "./testDuration";
2
-
3
- describe("When using the default props...", () => {
4
- describe("... it renders properly", () => {
5
- testDuration(1, {}, { text: "0s" });
6
- testDuration(2, {}, { text: "0s" });
7
- testDuration(1000, {}, { text: "1s" });
8
- testDuration(2000, {}, { text: "2s" });
9
- testDuration(1001, {}, { text: "1s" });
10
- testDuration(2002, {}, { text: "2s" });
11
- testDuration(60000, {}, { text: "1m" });
12
- testDuration(120000, {}, { text: "2m" });
13
- testDuration(61000, {}, { text: "1m 1s" });
14
- testDuration(122000, {}, { text: "2m 2s" });
15
- testDuration(60001, {}, { text: "1m" });
16
- testDuration(120002, {}, { text: "2m" });
17
- testDuration(61001, {}, { text: "1m 1s" });
18
- testDuration(
19
- 122002,
20
- {},
21
- {
22
- text: "2m 2s",
23
- }
24
- );
25
- testDuration(3600000, {}, { text: "1h" });
26
- testDuration(7200000, {}, { text: "2h" });
27
- testDuration(3660000, {}, { text: "1h 1m" });
28
- testDuration(7320000, {}, { text: "2h 2m" });
29
- testDuration(3601000, {}, { text: "1h 1s" });
30
- testDuration(7202000, {}, { text: "2h 2s" });
31
- testDuration(3600001, {}, { text: "1h" });
32
- testDuration(7200002, {}, { text: "2h" });
33
- testDuration(3661000, {}, { text: "1h 1m 1s" });
34
- testDuration(7322000, {}, { text: "2h 2m 2s" });
35
- testDuration(3601001, {}, { text: "1h 1s" });
36
- testDuration(
37
- 7202002,
38
- {},
39
- {
40
- text: "2h 2s",
41
- }
42
- );
43
- testDuration(3660001, {}, { text: "1h 1m" });
44
- testDuration(
45
- 7320002,
46
- {},
47
- {
48
- text: "2h 2m",
49
- }
50
- );
51
- testDuration(3661001, {}, { text: "1h 1m 1s" });
52
- testDuration(7322002, {}, { text: "2h 2m 2s" });
53
- testDuration(86400000, {}, { text: "1d" });
54
- testDuration(172800000, {}, { text: "2d" });
55
- testDuration(90000000, {}, { text: "1d 1h" });
56
- testDuration(180000000, {}, { text: "2d 2h" });
57
- testDuration(86460000, {}, { text: "1d 1m" });
58
- testDuration(172920000, {}, { text: "2d 2m" });
59
- testDuration(86401000, {}, { text: "1d 1s" });
60
- testDuration(172802000, {}, { text: "2d 2s" });
61
- testDuration(86400001, {}, { text: "1d" });
62
- testDuration(172800002, {}, { text: "2d" });
63
- testDuration(90060000, {}, { text: "1d 1h 1m" });
64
- testDuration(180120000, {}, { text: "2d 2h 2m" });
65
- testDuration(90001000, {}, { text: "1d 1h 1s" });
66
- testDuration(180002000, {}, { text: "2d 2h 2s" });
67
- testDuration(90000001, {}, { text: "1d 1h" });
68
- testDuration(180000002, {}, { text: "2d 2h" });
69
- testDuration(86461000, {}, { text: "1d 1m 1s" });
70
- testDuration(172922000, {}, { text: "2d 2m 2s" });
71
- testDuration(86460001, {}, { text: "1d 1m" });
72
- testDuration(
73
- 172920002,
74
- {},
75
- {
76
- text: "2d 2m",
77
- }
78
- );
79
- testDuration(86401001, {}, { text: "1d 1s" });
80
- testDuration(
81
- 172802002,
82
- {},
83
- {
84
- text: "2d 2s",
85
- }
86
- );
87
- testDuration(90061000, {}, { text: "1d 1h 1m 1s" });
88
- testDuration(
89
- 180122000,
90
- {},
91
- {
92
- text: "2d 2h 2m 2s",
93
- }
94
- );
95
- testDuration(86461001, {}, { text: "1d 1m 1s" });
96
- testDuration(172922002, {}, { text: "2d 2m 2s" });
97
- testDuration(
98
- 90001001,
99
- {},
100
- {
101
- text: "1d 1h 1s",
102
- }
103
- );
104
- testDuration(180002002, {}, { text: "2d 2h 2s" });
105
- testDuration(
106
- 90060001,
107
- {},
108
- {
109
- text: "1d 1h 1m",
110
- }
111
- );
112
- testDuration(180120002, {}, { text: "2d 2h 2m" });
113
- testDuration(90061001, {}, { text: "1d 1h 1m 1s" });
114
- testDuration(180122002, {}, { text: "2d 2h 2m 2s" });
115
- });
116
- });