cozy-ui 61.1.1 → 62.0.3

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 CHANGED
@@ -1,3 +1,42 @@
1
+ ## [62.0.3](https://github.com/cozy/cozy-ui/compare/v62.0.2...v62.0.3) (2022-02-22)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **Grid:** Use justifyContent props inside Grid component ([d5eb807](https://github.com/cozy/cozy-ui/commit/d5eb807))
7
+
8
+ ## [62.0.2](https://github.com/cozy/cozy-ui/compare/v62.0.1...v62.0.2) (2022-02-21)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Inverted palette opacity values ([c90b554](https://github.com/cozy/cozy-ui/commit/c90b554))
14
+
15
+ ## [62.0.1](https://github.com/cozy/cozy-ui/compare/v62.0.0...v62.0.1) (2022-02-18)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **deps:** bump url-parse from 1.4.3 to 1.5.7 in /examples/webpack-app ([af9429c](https://github.com/cozy/cozy-ui/commit/af9429c))
21
+
22
+ # [62.0.0](https://github.com/cozy/cozy-ui/compare/v61.1.1...v62.0.0) (2022-02-11)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * Use correct color for checkbox in inverted theme ([878c8ad](https://github.com/cozy/cozy-ui/commit/878c8ad))
28
+ * **UploadQueue:** UploadQueue manage internationalized progress message ([ecb00e1](https://github.com/cozy/cozy-ui/commit/ecb00e1))
29
+
30
+
31
+ ### Features
32
+
33
+ * Remove useless IconButton stylus ([7749774](https://github.com/cozy/cozy-ui/commit/7749774))
34
+
35
+
36
+ ### BREAKING CHANGES
37
+
38
+ * The .IconButton css class is no longer available in the stylesheet
39
+
1
40
  ## [61.1.1](https://github.com/cozy/cozy-ui/compare/v61.1.0...v61.1.1) (2022-02-10)
2
41
 
3
42
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "61.1.1",
3
+ "version": "62.0.3",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -34,7 +34,7 @@ const Banner = ({
34
34
  className={cx(styles['c-banner-wrapper'], className)}
35
35
  style={bgcolor && { backgroundColor: bgcolor }}
36
36
  >
37
- <Grid container justify="space-between">
37
+ <Grid container justifyContent="space-between">
38
38
  <Grid
39
39
  container
40
40
  item
@@ -0,0 +1,19 @@
1
+ import React from 'react'
2
+ import { render } from '@testing-library/react'
3
+ import Banner from './index'
4
+
5
+ describe('Grid', () => {
6
+ it('should render correctly justify content', () => {
7
+ // Given
8
+ console.error = jest.fn()
9
+
10
+ // When
11
+ const { container } = render(<Banner />)
12
+
13
+ // Then
14
+ expect(console.error).not.toHaveBeenCalled()
15
+ expect(
16
+ container.querySelector('.MuiGrid-justify-content-xs-space-between')
17
+ ).toBeInTheDocument()
18
+ })
19
+ })
@@ -4,91 +4,37 @@
4
4
  import Checkbox from 'cozy-ui/transpiled/react/Checkbox'
5
5
  import Grid from 'cozy-ui/transpiled/react/MuiCozyTheme/Grid'
6
6
  import Paper from 'cozy-ui/transpiled/react/Paper'
7
- import CozyTheme from 'cozy-ui/transpiled/react/CozyTheme';
7
+ import CozyTheme from 'cozy-ui/transpiled/react/CozyTheme'
8
+
9
+ ;
8
10
 
9
11
  <>
10
12
  <Grid container>
11
- <Grid item xs={6}>
12
- <div><Checkbox label="This is a checkbox" /></div>
13
- <div><Checkbox label="This is a checked checkbox" checked /></div>
14
- <div><Checkbox label="This is a mixed checkbox" mixed /></div>
15
- <div><Checkbox label="This is a mixed checked checkbox" checked mixed /></div>
13
+ <Grid item xs={6} sm={3}>
14
+ <div><Checkbox label="Checkbox" /></div>
15
+ <div><Checkbox label="Checked checkbox" checked /></div>
16
+ <div><Checkbox label="Mixed checkbox" mixed /></div>
17
+ <div><Checkbox label="Mixed checked checkbox" checked mixed /></div>
16
18
  </Grid>
17
- <Grid item xs={6}>
18
- <div><Checkbox label="This is a disabled checkbox" disabled /></div>
19
- <div><Checkbox label="This is a disabled checked checkbox" checked disabled /></div>
20
- <div><Checkbox label="This is a disabled mixed checkbox" mixed disabled /></div>
21
- <div><Checkbox label="This is a disabled mixed checked checkbox" checked mixed disabled /></div>
19
+ <Grid item xs={6} sm={3}>
20
+ <div><Checkbox label="Disabled checkbox" disabled /></div>
21
+ <div><Checkbox label="Disabled checked checkbox" checked disabled /></div>
22
+ <div><Checkbox label="Disabled mixed checkbox" mixed disabled /></div>
23
+ <div><Checkbox label="Disabled mixed checked checkbox" checked mixed disabled /></div>
22
24
  </Grid>
23
- </Grid>
24
-
25
- {isTesting() &&
26
- <CozyTheme variant='inverted'>
27
- <Paper className='u-p-1'>
28
- <Grid container>
29
- <Grid item xs={6}>
30
- <div><Checkbox label="This is a checkbox" /></div>
31
- <div><Checkbox label="This is a checked checkbox" checked /></div>
32
- <div><Checkbox label="This is a mixed checkbox" mixed /></div>
33
- <div><Checkbox label="This is a mixed checked checkbox" checked mixed /></div>
34
- </Grid>
35
- <Grid item xs={6}>
36
- <div><Checkbox label="This is a disabled checkbox" disabled /></div>
37
- <div><Checkbox label="This is a disabled checked checkbox" checked disabled /></div>
38
- <div><Checkbox label="This is a disabled mixed checkbox" mixed disabled /></div>
39
- <div><Checkbox label="This is a disabled mixed checked checkbox" checked mixed disabled /></div>
40
- </Grid>
41
- </Grid>
42
- </Paper>
43
- </CozyTheme>
44
- }
45
- </>
46
- ```
47
-
48
- ### Error Checkbox
49
-
50
- ```jsx
51
- import Checkbox from 'cozy-ui/transpiled/react/Checkbox'
52
- import Grid from 'cozy-ui/transpiled/react/MuiCozyTheme/Grid'
53
- import Paper from 'cozy-ui/transpiled/react/Paper'
54
- import CozyTheme from 'cozy-ui/transpiled/react/CozyTheme';
55
-
56
- <>
57
- <Grid container>
58
- <Grid item xs={6}>
59
- <div><Checkbox label="This is a checkbox with an error" error /></div>
60
- <div><Checkbox label="This is a checked checkbox with an error" error checked /></div>
61
- <div><Checkbox label="This is a mixed checkbox with an error" error mixed /></div>
62
- <div><Checkbox label="This is a mixed checked checkbox with an error" error checked mixed /></div>
25
+ <Grid item xs={6} sm={3}>
26
+ <div><Checkbox label="Error checkbox" error /></div>
27
+ <div><Checkbox label="Error checked checkbox" error checked /></div>
28
+ <div><Checkbox label="Error mixed checkbox" error mixed /></div>
29
+ <div><Checkbox label="Error mixed checked checkbox" error checked mixed /></div>
63
30
  </Grid>
64
- <Grid item xs={6}>
65
- <div><Checkbox label="This is a disabled checkbox with an error" error disabled /></div>
66
- <div><Checkbox label="This is a disabled checked checkbox with an error" error checked disabled /></div>
67
- <div><Checkbox label="This is a disabled mixed checkbox with an error" error mixed disabled /></div>
68
- <div><Checkbox label="This is a disabled mixed checked checkbox with an error" error checked mixed disabled /></div>
31
+ <Grid item xs={6} sm={3}>
32
+ <div><Checkbox label="Error disabled checkbox" error disabled /></div>
33
+ <div><Checkbox label="Error disabled checked checkbox" error checked disabled /></div>
34
+ <div><Checkbox label="Error disabled mixed checkbox" error mixed disabled /></div>
35
+ <div><Checkbox label="Error disabled mixed checked checkbox" error checked mixed disabled /></div>
69
36
  </Grid>
70
37
  </Grid>
71
-
72
- {isTesting() &&
73
- <CozyTheme variant='inverted'>
74
- <Paper className='u-p-1'>
75
- <Grid container>
76
- <Grid item xs={6}>
77
- <div><Checkbox label="This is a checkbox with an error" error /></div>
78
- <div><Checkbox label="This is a checked checkbox with an error" error checked /></div>
79
- <div><Checkbox label="This is a mixed checkbox with an error" error mixed /></div>
80
- <div><Checkbox label="This is a mixed checked checkbox with an error" error checked mixed /></div>
81
- </Grid>
82
- <Grid item xs={6}>
83
- <div><Checkbox label="This is a disabled checkbox with an error" error disabled /></div>
84
- <div><Checkbox label="This is a disabled checked checkbox with an error" error checked disabled /></div>
85
- <div><Checkbox label="This is a disabled mixed checkbox with an error" error mixed disabled /></div>
86
- <div><Checkbox label="This is a disabled mixed checked checkbox with an error" error checked mixed disabled /></div>
87
- </Grid>
88
- </Grid>
89
- </Paper>
90
- </CozyTheme>
91
- }
92
38
  </>
93
39
  ```
94
40
 
@@ -96,6 +42,7 @@ import CozyTheme from 'cozy-ui/transpiled/react/CozyTheme';
96
42
 
97
43
  ```jsx
98
44
  import Checkbox from 'cozy-ui/transpiled/react/Checkbox';
45
+
99
46
  <div>
100
47
  <Checkbox label={(<>This is a <strong>complex</strong> text</>)} />
101
48
  </div>
@@ -1,12 +1,15 @@
1
1
  import format from 'date-fns/format'
2
2
  import { DEFAULT_LANG } from '.'
3
+ import formatDistanceToNow from 'date-fns/distance_in_words_to_now'
4
+
5
+ const locales = {}
6
+ let lang = DEFAULT_LANG
3
7
 
4
8
  const getWarningMessage = lang =>
5
9
  `The "${lang}" locale isn't supported by date-fns. or has not been included in the build. Check if you have configured a ContextReplacementPlugin that is too restrictive.`
6
10
 
7
- export const initFormat = (lang, defaultLang = DEFAULT_LANG) => {
8
- const locales = {}
9
-
11
+ export const provideDateFnsLocale = (userLang, defaultLang = DEFAULT_LANG) => {
12
+ lang = userLang
10
13
  try {
11
14
  locales[defaultLang] = require(`date-fns/locale/${defaultLang}/index.js`)
12
15
  } catch (err) {
@@ -20,5 +23,16 @@ export const initFormat = (lang, defaultLang = DEFAULT_LANG) => {
20
23
  console.warn(getWarningMessage(lang))
21
24
  }
22
25
  }
23
- return (date, formatStr) => format(date, formatStr, { locale: locales[lang] })
26
+ return locales[lang]
24
27
  }
28
+
29
+ export const initFormat = (userLang, defaultLang = DEFAULT_LANG) => (
30
+ date,
31
+ formatStr
32
+ ) => {
33
+ const locale = provideDateFnsLocale(userLang, defaultLang)
34
+ return format(date, formatStr, { locale })
35
+ }
36
+
37
+ export const formatLocallyDistanceToNow = date =>
38
+ formatDistanceToNow(date, { locale: locales[lang] })
@@ -1,4 +1,4 @@
1
- import { initFormat } from './format'
1
+ import { initFormat, formatLocallyDistanceToNow } from './format'
2
2
 
3
3
  describe('initFormat', () => {
4
4
  beforeEach(() => {
@@ -11,3 +11,37 @@ describe('initFormat', () => {
11
11
  expect(() => initFormat('unknown-lang', 'unknown-default')).not.toThrow()
12
12
  })
13
13
  })
14
+
15
+ describe('formatLocallyDistanceToNow', () => {
16
+ it('should formatDistanceToNow with small value', () => {
17
+ const date = Date.now() + 29 * 1000
18
+
19
+ const result = formatLocallyDistanceToNow(date)
20
+
21
+ expect(result).toEqual('less than a minute')
22
+ })
23
+
24
+ it('should formatDistanceToNow with medium value', () => {
25
+ const date = Date.now() + 2671 * 1000
26
+
27
+ const result = formatLocallyDistanceToNow(date)
28
+
29
+ expect(result).toEqual('about 1 hour')
30
+ })
31
+
32
+ it('should formatDistanceToNow with high value', () => {
33
+ const date = Date.now() + 5371 * 1000
34
+
35
+ const result = formatLocallyDistanceToNow(date)
36
+
37
+ expect(result).toEqual('about 2 hours')
38
+ })
39
+
40
+ it('should not throw if a date-fns locale can not be found', () => {
41
+ jest.spyOn(console, 'warn').mockImplementation()
42
+
43
+ expect(() => formatLocallyDistanceToNow('unknown-lang')).not.toThrow()
44
+
45
+ console.warn.mockRestore()
46
+ })
47
+ })
@@ -4,64 +4,27 @@ Provides hover, active styles + accessible size (48px).
4
4
  ```jsx
5
5
  import IconButton from 'cozy-ui/transpiled/react/IconButton'
6
6
  import Icon from 'cozy-ui/transpiled/react/Icon'
7
- import Stack from 'cozy-ui/transpiled/react/Stack'
8
- import Typography from 'cozy-ui/transpiled/react/Typography'
7
+
8
+ import TrashIcon from 'cozy-ui/transpiled/react/Icons/Trash'
9
9
  import LeftIcon from 'cozy-ui/transpiled/react/Icons/Left'
10
10
  import RestoreIcon from 'cozy-ui/transpiled/react/Icons/Restore'
11
11
  import RightIcon from 'cozy-ui/transpiled/react/Icons/Right'
12
-
13
- const StateRadio = ({ name, ...props }) => {
14
- return <input
15
- type='radio'
16
- name={name}
17
- checked={state[name] == props.value}
18
- onChange={() => setState({ [name]: props.value })}
19
- {...props}
20
- />
21
- }
22
-
23
- const Example = ({ color }) => {
24
- return <>
25
- <IconButton color={color}>
26
- <Icon icon={LeftIcon} />
27
- </IconButton>
28
- <IconButton color={color}>
29
- <Icon icon={RestoreIcon} />
30
- </IconButton>
31
- <IconButton color={color}>
32
- <Icon icon={RightIcon} />
33
- </IconButton>
34
- </>
35
- }
36
-
37
- initialState = {
38
- color: 'default'
39
- }
40
-
41
- const colors = ['default', 'primary', 'secondary']
12
+ import CrossIcon from 'cozy-ui/transpiled/react/Icons/Cross'
42
13
 
43
14
  ;
44
15
 
45
16
  <>
46
- { isTesting ()
47
- ? <Stack spacing='l'>
48
- {colors.map((color, index) => (
49
- <div key={index}>
50
- <Typography variant='h3' gutterBottom>color: {color}</Typography>
51
- <Example color={color} key={color} />
52
- </div>
53
- ))}
54
- </Stack>
55
- : <div>
56
- <Stack spacing='l'>
57
- <div>
58
- <StateRadio value='default' name='color' /> default{' '}
59
- <StateRadio value='primary' name='color' /> primary{' '}
60
- <StateRadio value='secondary' name='color' /> secondary
61
- </div>
62
- <Example color={state.color} />
63
- </Stack>
64
- </div>
65
- }
17
+ <IconButton>
18
+ <Icon icon={TrashIcon} />
19
+ </IconButton>
20
+ <IconButton disabled>
21
+ <Icon icon={TrashIcon} />
22
+ </IconButton>
23
+ <IconButton color="primary">
24
+ <Icon icon={RestoreIcon} />
25
+ </IconButton>
26
+ <IconButton color="secondary">
27
+ <Icon icon={CrossIcon} />
28
+ </IconButton>
66
29
  </>
67
30
  ```
@@ -711,7 +711,7 @@ const makeInvertedOverrides = invertedTheme => {
711
711
  MuiCheckbox: {
712
712
  colorPrimary: {
713
713
  '&$checked:not($disabled)': {
714
- color: invertedTheme.palette.success.main
714
+ color: invertedTheme.palette.primary.light
715
715
  }
716
716
  },
717
717
  colorSecondary: {
@@ -1,13 +1,48 @@
1
+ import merge from 'lodash/merge'
2
+
1
3
  import {
2
4
  getCssVariableValue,
3
5
  getInvertedCssVariableValue
4
6
  } from '../utils/color'
5
7
 
8
+ const opacityByTheme = {
9
+ light: {
10
+ action: {
11
+ hoverOpacity: 0.04,
12
+ selectedOpacity: 0.08,
13
+ disabledOpacity: 0.32,
14
+ focusOpacity: 0.12,
15
+ activatedOpacity: 0.12,
16
+ ghostOpacity: 0.08,
17
+ hoverGhostOpacity: 0.16
18
+ },
19
+ border: {
20
+ opacity: 0.16,
21
+ ghostOpacity: 0.48
22
+ }
23
+ },
24
+ dark: {
25
+ action: {
26
+ hoverOpacity: 0.08,
27
+ selectedOpacity: 0.16,
28
+ disabledOpacity: 0.32,
29
+ focusOpacity: 0.25,
30
+ activatedOpacity: 0.24,
31
+ ghostOpacity: 0.08,
32
+ hoverGhostOpacity: 0.16
33
+ },
34
+ border: {
35
+ opacity: 0.24,
36
+ ghostOpacity: 0.48
37
+ }
38
+ }
39
+ }
40
+
6
41
  export const makePalette = type => {
7
42
  const getCssValue =
8
43
  type === 'dark' ? getInvertedCssVariableValue : getCssVariableValue
9
44
 
10
- return {
45
+ const paletteByTheme = {
11
46
  type,
12
47
  primary: {
13
48
  light: getCssValue('primaryColorLight'),
@@ -73,27 +108,18 @@ export const makePalette = type => {
73
108
  action: {
74
109
  active: getCssValue('actionColorActive'),
75
110
  hover: getCssValue('actionColorHover'),
76
- hoverOpacity: 0.04,
77
111
  selected: getCssValue('actionColorSelected'),
78
- selectedOpacity: 0.08,
79
112
  disabled: getCssValue('actionColorDisabled'),
80
113
  disabledBackground: getCssValue('actionColorDisabledBackground'),
81
- disabledOpacity: 0.32,
82
114
  focus: getCssValue('actionColorFocus'),
83
- focusOpacity: 0.12,
84
115
  ghost: getCssValue('actionColorGhost'),
85
- ghostOpacity: 0.08,
86
- hoverGhost: getCssValue('actionColorHoverGhost'),
87
- hoverGhostOpacity: 0.16,
88
- activatedOpacity: 0.12
116
+ hoverGhost: getCssValue('actionColorHoverGhost')
89
117
  },
90
118
  border: {
91
119
  main: getCssValue('borderMainColor'),
92
- opacity: 0.16,
93
120
  disabled: getCssValue('borderDisabledColor'),
94
121
  ghost: getCssValue('borderGhostColor'),
95
- ghostDisabled: getCssValue('borderGhostDisabledColor'),
96
- ghostOpacity: 0.48
122
+ ghostDisabled: getCssValue('borderGhostDisabledColor')
97
123
  },
98
124
  background: {
99
125
  default: getCssValue('defaultBackgroundColor'),
@@ -101,4 +127,6 @@ export const makePalette = type => {
101
127
  selected: '#F5FAFF' // deprecated, should be removed. Use action.selected instead
102
128
  }
103
129
  }
130
+
131
+ return merge(paletteByTheme, opacityByTheme[type])
104
132
  }
@@ -1,45 +1,57 @@
1
- On desktop show a vertical menu on the left. On mobile, shows a
2
- horizontal bottom nav.
1
+ On desktop shows a vertical menu on the left. On mobile, shows a horizontal bottom nav.
3
2
 
4
- ⚠️ `NavLink` would be imported normally from `react-router-dom` and
5
- used as follows.
3
+ ⚠️ `NavLink` must be imported normally from `react-router-dom` and used as follows.
6
4
 
7
5
  ```jsx static
8
- import { NavLink as RRNavLink } from 'react-router'
6
+ import { NavLink as RouterLink } from 'react-router'
9
7
  import { genNavLink } from 'cozy-ui/transpiled/react/Nav'
10
8
 
11
- const NavLink = genNavLink(RRNavLink)
9
+ const NavLink = genNavLink(RouterLink)
12
10
  ```
13
11
 
14
12
  In action :
15
13
 
16
14
  ```jsx
17
- import Sidebar from 'cozy-ui/transpiled/react/Sidebar';
18
- import Nav, { NavItem, NavIcon, NavText, genNavLink } from 'cozy-ui/transpiled/react/Nav';
19
- import cx from 'classnames';
15
+ import Sidebar from 'cozy-ui/transpiled/react/Sidebar'
16
+ import Nav, { NavItem, NavIcon, NavText, genNavLink } from 'cozy-ui/transpiled/react/Nav'
20
17
  import WarnIcon from 'cozy-ui/transpiled/react/Icons/Warn'
21
18
  import CheckIcon from 'cozy-ui/transpiled/react/Icons/Check'
22
19
  import DownloadIcon from 'cozy-ui/transpiled/react/Icons/Download'
23
20
 
24
- const NavLink = genNavLink(({ children, className, active, activeClassName }) =>
25
- <a className={cx(className, active ? activeClassName : null)}>{ children }</a>);
21
+ // <-- only usefull for the documentation,
22
+ // should be `const NavLink = genNavLink(RouterLink)`
23
+ import cx from 'classnames'
24
+
25
+ const NavLink = genNavLink(
26
+ ({ children, className, active, activeClassName }) => (
27
+ <a className={cx(className, active ? activeClassName : null)}>{children}</a>
28
+ )
29
+ )
30
+ // -->
31
+
32
+ ;
26
33
 
27
34
  <Sidebar id='sidebar'>
28
35
  <Nav>
29
36
  <NavItem id='nav-item'>
30
- <NavLink active>
37
+ <NavLink to="/warn" active>
31
38
  <NavIcon icon={WarnIcon} />
32
39
  <NavText>Warn</NavText>
33
40
  </NavLink>
34
41
  </NavItem>
35
42
  <NavItem>
36
- <NavLink>
43
+ <NavLink to="/check">
37
44
  <NavIcon icon={CheckIcon} />
38
45
  <NavText>Check</NavText>
39
46
  </NavLink>
40
47
  </NavItem>
48
+ <NavItem secondary>
49
+ <NavLink to="/secondary">
50
+ <NavText>Secondary link</NavText>
51
+ </NavLink>
52
+ </NavItem>
41
53
  <NavItem>
42
- <NavLink>
54
+ <NavLink to="/download">
43
55
  <NavIcon icon={DownloadIcon} />
44
56
  <NavText>Download</NavText>
45
57
  </NavLink>
@@ -12,6 +12,7 @@ the upload queue:
12
12
  ```jsx
13
13
  import isTesting from '../helpers/isTesting'
14
14
  import FileIcon from 'cozy-ui/transpiled/react/Icons/File'
15
+ import UploadQueue from 'cozy-ui/transpiled/react/UploadQueue';
15
16
 
16
17
  const initialState = {
17
18
  popover: false
@@ -51,7 +52,7 @@ const data = {
51
52
  };
52
53
 
53
54
  <>
54
- popover: <input type="checkbox" value={state.popover} onChange={() => setState({ popover: !state.popover })} />
55
+ popover: <input type="checkbox" value={state.popover} onChange={() => setState({ popover: !state.popover })}/>
55
56
  <UploadQueue
56
57
  lang='fr'
57
58
  app='Cozy Drive'
@@ -2,7 +2,6 @@ import React, { Component } from 'react'
2
2
  import cx from 'classnames'
3
3
  import { withStyles } from '@material-ui/core/styles'
4
4
  import LinearProgress from '@material-ui/core/LinearProgress'
5
- import formatDistanceToNow from 'date-fns/distance_in_words_to_now'
6
5
 
7
6
  import { splitFilename } from 'cozy-client/dist/models/file'
8
7
 
@@ -25,6 +24,7 @@ import styles from './styles.styl'
25
24
  import localeEn from './locales/en.json'
26
25
  import localeEs from './locales/es.json'
27
26
  import localeFr from './locales/fr.json'
27
+ import { formatLocallyDistanceToNow } from '../I18n/format'
28
28
 
29
29
  const locales = {
30
30
  en: localeEn,
@@ -64,20 +64,26 @@ const Pending = translate()(props => (
64
64
  </Typography>
65
65
  ))
66
66
 
67
- const formatRemainingTime = durationInSec => {
67
+ export const formatRemainingTime = durationInSec => {
68
68
  const later = Date.now() + durationInSec * 1000
69
- return formatDistanceToNow(later)
69
+ return formatLocallyDistanceToNow(later)
70
70
  }
71
71
 
72
+ // https://date-fns.org/v2.28.0/docs/formatDistanceToNow
73
+ const numberOfReferencesForPluralForm = durationInSec =>
74
+ durationInSec < 90 || (durationInSec > 2670 && durationInSec < 5370) ? 1 : 2
75
+
72
76
  const RemainingTime = ({ durationInSec }) => {
73
77
  const { t } = useI18n()
78
+
74
79
  return (
75
80
  <Typography
76
81
  variant="caption"
77
82
  className={cx(styles['upload-queue__progress-caption'], 'u-ellipsis')}
78
83
  >
79
84
  {t('item.remainingTime', {
80
- time: formatRemainingTime(durationInSec)
85
+ time: formatRemainingTime(durationInSec),
86
+ smart_count: numberOfReferencesForPluralForm(durationInSec)
81
87
  })}
82
88
  </Typography>
83
89
  )
@@ -127,7 +133,7 @@ const Item = translate()(
127
133
  let done = false
128
134
  let error = false
129
135
  /**
130
- * Status cames from the Upload Queue, but sometimes we're using
136
+ * Status came from the Upload Queue, but sometimes we're using
131
137
  * manual upload without using the Upload Queue system but we're still
132
138
  * using the UI component. When this is the case, the file handles on
133
139
  * his own its status.
@@ -210,7 +216,7 @@ const Item = translate()(
210
216
  }
211
217
  )
212
218
 
213
- class UploadQueue extends Component {
219
+ export class UploadQueue extends Component {
214
220
  state = {
215
221
  collapsed: false
216
222
  }
@@ -256,7 +262,7 @@ class UploadQueue extends Component {
256
262
  >
257
263
  {t('header_mobile', {
258
264
  done: doneCount,
259
- total: queue.length
265
+ smart_count: queue.length
260
266
  })}
261
267
  </Typography>
262
268
  </div>
@@ -269,7 +275,7 @@ class UploadQueue extends Component {
269
275
  <Typography variant="h6">
270
276
  {t('header_done', {
271
277
  done: successCount,
272
- total: queue.length
278
+ smart_count: queue.length
273
279
  })}
274
280
  </Typography>
275
281
  <Button