cozy-ui 111.6.0 → 111.8.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 (39) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +1 -1
  3. package/react/AppIcon/index.jsx +9 -0
  4. package/react/AppSections/Sections.jsx +48 -1
  5. package/react/AppSections/__snapshots__/index.spec.jsx.snap +10 -0
  6. package/react/AppSections/categories.js +35 -11
  7. package/react/AppSections/categories.spec.js +6 -0
  8. package/react/AppSections/components/__snapshots__/AppsSection.spec.jsx.snap +1 -1
  9. package/react/AppSections/constants.js +6 -1
  10. package/react/AppSections/generateI18nConfig.ts +23 -0
  11. package/react/AppSections/helpers.js +8 -0
  12. package/react/AppSections/locales/en.json +4 -2
  13. package/react/AppSections/locales/fr.json +4 -2
  14. package/react/AppTile/AppTile.spec.jsx +4 -3
  15. package/react/AppTile/index.jsx +32 -11
  16. package/react/AppTile/locales/en.json +2 -1
  17. package/react/AppTile/locales/fr.json +2 -1
  18. package/react/MobileStepper/Readme.md +43 -0
  19. package/react/MuiCozyTheme/overrides/makeLightNormalOverrides.js +18 -0
  20. package/react/ShortcutTile/index.tsx +63 -0
  21. package/react/types.d.ts +4 -0
  22. package/transpiled/react/AppIcon/index.js +11 -1
  23. package/transpiled/react/AppSections/Sections.js +39 -5
  24. package/transpiled/react/AppSections/categories.js +31 -3
  25. package/transpiled/react/AppSections/constants.js +5 -1
  26. package/transpiled/react/AppSections/generateI18nConfig.d.ts +6 -0
  27. package/transpiled/react/AppSections/generateI18nConfig.js +25 -0
  28. package/transpiled/react/AppSections/helpers.js +5 -0
  29. package/transpiled/react/AppTile/index.js +21 -6
  30. package/transpiled/react/MuiCozyTheme/overrides/makeDarkInvertedOverrides.d.ts +18 -0
  31. package/transpiled/react/MuiCozyTheme/overrides/makeDarkNormalOverrides.d.ts +18 -0
  32. package/transpiled/react/MuiCozyTheme/overrides/makeLightInvertedOverrides.d.ts +18 -0
  33. package/transpiled/react/MuiCozyTheme/overrides/makeLightNormalOverrides.d.ts +18 -0
  34. package/transpiled/react/MuiCozyTheme/overrides/makeLightNormalOverrides.js +18 -0
  35. package/transpiled/react/ShortcutTile/index.d.ts +15 -0
  36. package/transpiled/react/ShortcutTile/index.js +53 -0
  37. package/transpiled/react/Tile/index.d.ts +68 -0
  38. package/transpiled/react/Typography/index.d.ts +3 -0
  39. package/transpiled/react/types.d.js +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [111.8.0](https://github.com/cozy/cozy-ui/compare/v111.7.0...v111.8.0) (2024-08-19)
2
+
3
+
4
+ ### Features
5
+
6
+ * **MobileStepper:** Add cozy design to MUI export ([d6728f8](https://github.com/cozy/cozy-ui/commit/d6728f8))
7
+
8
+ # [111.7.0](https://github.com/cozy/cozy-ui/compare/v111.6.0...v111.7.0) (2024-08-14)
9
+
10
+
11
+ ### Features
12
+
13
+ * handle shortcuttiles ([e5ff800](https://github.com/cozy/cozy-ui/commit/e5ff800))
14
+
1
15
  # [111.6.0](https://github.com/cozy/cozy-ui/compare/v111.5.0...v111.6.0) (2024-08-14)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "111.6.0",
3
+ "version": "111.8.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -5,8 +5,10 @@ import React, { Component } from 'react'
5
5
  import { withClient } from 'cozy-client'
6
6
 
7
7
  import styles from './styles.styl'
8
+ import { isShortcutFile } from '../AppSections/helpers'
8
9
  import Icon, { iconPropType } from '../Icon'
9
10
  import CubeIcon from '../Icons/Cube'
11
+ import { ShortcutTile } from '../ShortcutTile'
10
12
  import palette from '../palette'
11
13
  import { AppDoctype } from '../proptypes'
12
14
 
@@ -45,6 +47,9 @@ export class AppIcon extends Component {
45
47
  fetchIcon() {
46
48
  const { app, type, priority, client } = this.props
47
49
 
50
+ // Shortcut files used in cozy-store have their own icon in their doctype metadata
51
+ if (isShortcutFile(app)) return
52
+
48
53
  return client.getStackClient().getIconURL({
49
54
  type,
50
55
  slug: app.slug || app,
@@ -93,6 +98,10 @@ export class AppIcon extends Component {
93
98
  const { alt, className, fallbackIcon } = this.props
94
99
  const { icon, status } = this.state
95
100
 
101
+ if (isShortcutFile(this.props.app)) {
102
+ return <ShortcutTile file={this.props.app} />
103
+ }
104
+
96
105
  switch (status) {
97
106
  case FETCHING:
98
107
  return (
@@ -2,11 +2,16 @@ import cx from 'classnames'
2
2
  import PropTypes from 'prop-types'
3
3
  import React, { Component } from 'react'
4
4
 
5
+ import flag from 'cozy-flags'
6
+ import { useExtendI18n } from 'cozy-ui/transpiled/react/providers/I18n'
7
+
5
8
  import styles from './Sections.styl'
6
9
  import * as catUtils from './categories'
7
10
  import AppsSection from './components/AppsSection'
8
11
  import DropdownFilter from './components/DropdownFilter'
9
12
  import { APP_TYPE } from './constants'
13
+ import { generateI18nConfig } from './generateI18nConfig'
14
+ import { isShortcutFile } from './helpers'
10
15
  import en from './locales/en.json'
11
16
  import fr from './locales/fr.json'
12
17
  import * as searchUtils from './search'
@@ -105,12 +110,19 @@ export class Sections extends Component {
105
110
  const webAppGroups = catUtils.groupApps(
106
111
  filteredApps.filter(a => a.type === APP_TYPE.WEBAPP)
107
112
  )
113
+ const shortcutsGroups = catUtils.groupApps(
114
+ filteredApps.filter(a => isShortcutFile(a))
115
+ )
116
+
108
117
  const webAppsCategories = Object.keys(webAppGroups)
109
118
  .map(cat => catUtils.addLabel({ value: cat }, t))
110
119
  .sort(catUtils.sorter)
111
120
  const konnectorsCategories = Object.keys(konnectorGroups)
112
121
  .map(cat => catUtils.addLabel({ value: cat }, t))
113
122
  .sort(catUtils.sorter)
123
+ const shortcutsCategories = Object.keys(shortcutsGroups)
124
+ .map(cat => catUtils.addLabel({ value: cat }, t))
125
+ .sort(catUtils.sorter)
114
126
 
115
127
  const dropdownDisplayed =
116
128
  hasNav && (isMobile || isTablet) && showFilterDropdown
@@ -154,6 +166,33 @@ export class Sections extends Component {
154
166
  })}
155
167
  </div>
156
168
  )}
169
+ {!!shortcutsCategories.length && (
170
+ <div>
171
+ {showSubTitles && (
172
+ <SectionSubtitle>{t('sections.shortcuts')}</SectionSubtitle>
173
+ )}
174
+
175
+ {shortcutsCategories.map(cat => {
176
+ return (
177
+ <AppsSection
178
+ key={cat.value}
179
+ {...componentsProps?.appsSection}
180
+ appsList={shortcutsGroups[cat.value]}
181
+ subtitle={
182
+ showSubSubTitles ? (
183
+ <SectionSubSubtitle>{cat.label}</SectionSubSubtitle>
184
+ ) : null
185
+ }
186
+ IconComponent={IconComponent}
187
+ onAppClick={onAppClick}
188
+ displaySpecificMaintenanceStyle={
189
+ displaySpecificMaintenanceStyle
190
+ }
191
+ />
192
+ )
193
+ })}
194
+ </div>
195
+ )}
157
196
  {!!konnectorsCategories.length && (
158
197
  <div>
159
198
  {showSubTitles && (
@@ -186,6 +225,14 @@ export class Sections extends Component {
186
225
  }
187
226
  }
188
227
 
228
+ const SectionsWrapper = props => {
229
+ const config = flag('store.alternative-source')
230
+ const i18nConfig = generateI18nConfig(config?.categories)
231
+ useExtendI18n(i18nConfig)
232
+
233
+ return <Sections {...props} />
234
+ }
235
+
189
236
  Sections.propTypes = {
190
237
  t: PropTypes.func.isRequired,
191
238
 
@@ -230,6 +277,6 @@ Sections.defaultProps = {
230
277
  })
231
278
  }
232
279
 
233
- export const Untranslated = withBreakpoints()(Sections)
280
+ export const Untranslated = withBreakpoints()(SectionsWrapper)
234
281
 
235
282
  export default withLocales(locales)(translate()(Untranslated))
@@ -1075,6 +1075,11 @@ exports[`AppsSection component should render dropdown filter on mobile if no nav
1075
1075
  "type": "webapp",
1076
1076
  "value": "partners",
1077
1077
  },
1078
+ Object {
1079
+ "label": "Shortcuts",
1080
+ "secondary": false,
1081
+ "value": "shortcuts",
1082
+ },
1078
1083
  Object {
1079
1084
  "label": "Services",
1080
1085
  "secondary": false,
@@ -1476,6 +1481,11 @@ exports[`AppsSection component should render dropdown filter on tablet if no nav
1476
1481
  "type": "webapp",
1477
1482
  "value": "partners",
1478
1483
  },
1484
+ Object {
1485
+ "label": "Shortcuts",
1486
+ "secondary": false,
1487
+ "value": "shortcuts",
1488
+ },
1479
1489
  Object {
1480
1490
  "label": "Services",
1481
1491
  "secondary": false,
@@ -38,21 +38,37 @@ export const groupApps = apps => multiGroupBy(apps, getAppCategory)
38
38
  * Alphabetical sort on label except for
39
39
  * - 'all' value always at the beginning
40
40
  * - 'others' value always at the end
41
+ * - 'cozy' value should be near the beginning, right after 'all'
42
+ * - items of type 'file' should appear alphabetically between 'webapp' and 'konnector'
41
43
  *
42
44
  * @param {CategoryOption} categoryA
43
45
  * @param {CategoryOption} categoryB
44
46
  * @return {Number}
45
47
  */
46
48
  export const sorter = (categoryA, categoryB) => {
47
- return (
48
- (categoryA.value === 'all' && -1) ||
49
- (categoryB.value === 'all' && 1) ||
50
- (categoryA.value === 'others' && 1) ||
51
- (categoryB.value === 'others' && -1) ||
52
- (categoryA.value === 'cozy' && -1) ||
53
- (categoryB.value === 'cozy' && 1) ||
54
- categoryA.label.localeCompare(categoryB.label)
55
- )
49
+ // Always keep 'all' at the beginning
50
+ if (categoryA.value === 'all') return -1
51
+ if (categoryB.value === 'all') return 1
52
+
53
+ // Always keep 'others' at the end
54
+ if (categoryA.value === 'others') return 1
55
+ if (categoryB.value === 'others') return -1
56
+
57
+ // Keep 'cozy' near the beginning, right after 'all'
58
+ if (categoryA.value === 'cozy') return -1
59
+ if (categoryB.value === 'cozy') return 1
60
+
61
+ // Sort by type order: webapp < file < konnector
62
+ const typeOrder = ['webapp', 'file', 'konnector']
63
+ const typeAIndex = typeOrder.indexOf(categoryA.type)
64
+ const typeBIndex = typeOrder.indexOf(categoryB.type)
65
+
66
+ if (typeAIndex !== typeBIndex) {
67
+ return typeAIndex - typeBIndex
68
+ }
69
+
70
+ // Alphabetical sort on label for the rest
71
+ return categoryA.label.localeCompare(categoryB.label)
56
72
  }
57
73
 
58
74
  export const addLabel = (cat, t) => ({
@@ -82,7 +98,7 @@ export const generateOptionsFromApps = (apps, options = {}) => {
82
98
  ]
83
99
  : []
84
100
 
85
- for (const type of [APP_TYPE.WEBAPP, APP_TYPE.KONNECTOR]) {
101
+ for (const type of [APP_TYPE.WEBAPP, APP_TYPE.FILE, APP_TYPE.KONNECTOR]) {
86
102
  const catApps = groupApps(apps.filter(a => a.type === type))
87
103
  // Add an entry to filter by all konnectors
88
104
  if (type === APP_TYPE.KONNECTOR) {
@@ -93,11 +109,19 @@ export const generateOptionsFromApps = (apps, options = {}) => {
93
109
  })
94
110
  )
95
111
  }
112
+ if (type === APP_TYPE.FILE) {
113
+ allCategoryOptions.push(
114
+ addLabel({
115
+ value: 'shortcuts',
116
+ secondary: false
117
+ })
118
+ )
119
+ }
96
120
  const categoryOptions = Object.keys(catApps).map(cat => {
97
121
  return addLabel({
98
122
  value: cat,
99
123
  type: type,
100
- secondary: type === APP_TYPE.KONNECTOR
124
+ secondary: type === APP_TYPE.KONNECTOR || type === APP_TYPE.FILE
101
125
  })
102
126
  })
103
127
 
@@ -104,6 +104,7 @@ describe('generateOptionsFromApps', () => {
104
104
  type: 'webapp',
105
105
  value: 'others'
106
106
  },
107
+ { label: 'Shortcuts', secondary: false, value: 'shortcuts' },
107
108
  {
108
109
  label: 'Services',
109
110
  secondary: false,
@@ -156,6 +157,11 @@ describe('generateOptionsFromApps', () => {
156
157
  type: 'webapp',
157
158
  value: 'others'
158
159
  },
160
+ {
161
+ label: 'Shortcuts',
162
+ secondary: false,
163
+ value: 'shortcuts'
164
+ },
159
165
  {
160
166
  label: 'Services',
161
167
  secondary: false,
@@ -28,7 +28,7 @@ Array [
28
28
  "title": "Cozy Photos",
29
29
  },
30
30
  Object {
31
- "developer": null,
31
+ "developer": "By undefined",
32
32
  "status": "Update available",
33
33
  "title": "Tasky",
34
34
  },
@@ -1,4 +1,9 @@
1
1
  export const APP_TYPE = {
2
2
  KONNECTOR: 'konnector',
3
- WEBAPP: 'webapp'
3
+ WEBAPP: 'webapp',
4
+ FILE: 'file'
5
+ }
6
+
7
+ export const APP_CLASS = {
8
+ SHORTCUT: 'shortcut'
4
9
  }
@@ -0,0 +1,23 @@
1
+ export const generateI18nConfig = (categories?: {
2
+ [key: string]: string
3
+ }): {
4
+ en: Record<string, string>
5
+ fr: Record<string, string>
6
+ } => {
7
+ if (!categories) return { en: {}, fr: {} }
8
+
9
+ const i18nConfig: Record<string, string> = {}
10
+
11
+ for (const [key, value] of Object.entries(categories)) {
12
+ // Extract the final part of the path as the display name
13
+ const displayName =
14
+ value?.split('/').pop() ?? ''.replace(/([A-Z])/g, ' $1').trim()
15
+
16
+ i18nConfig[`app_categories.${key}`] = displayName
17
+ }
18
+
19
+ return {
20
+ en: i18nConfig,
21
+ fr: i18nConfig
22
+ }
23
+ }
@@ -1,8 +1,16 @@
1
1
  import _get from 'lodash/get'
2
2
 
3
+ import { APP_CLASS, APP_TYPE } from './constants'
4
+
3
5
  export const getTranslatedManifestProperty = (app, path, t) => {
4
6
  if (!t || !app || !path) return _get(app, path, '')
5
7
  return t(`apps.${app.slug}.${path}`, {
6
8
  _: _get(app, path, '')
7
9
  })
8
10
  }
11
+
12
+ export const isShortcutFile = app => {
13
+ if (!app) return false
14
+
15
+ return app.type === APP_TYPE.FILE && app.class === APP_CLASS.SHORTCUT
16
+ }
@@ -26,10 +26,12 @@
26
26
  "tech": "Tech",
27
27
  "telecom": "Telecom",
28
28
  "transport": "Transportation",
29
- "pro": "Work"
29
+ "pro": "Work",
30
+ "shortcuts": "Shortcuts"
30
31
  },
31
32
  "sections": {
32
33
  "applications": "Applications",
33
- "konnectors": "Services"
34
+ "konnectors": "Services",
35
+ "shortcuts": "Shortcuts"
34
36
  }
35
37
  }
@@ -26,10 +26,12 @@
26
26
  "tech": "Tech",
27
27
  "telecom": "Mobile",
28
28
  "transport": "Voyage et transport",
29
- "pro": "Travail"
29
+ "pro": "Travail",
30
+ "shortcuts": "Raccourcis"
30
31
  },
31
32
  "sections": {
32
33
  "applications": "Applications",
33
- "konnectors": "Services"
34
+ "konnectors": "Services",
35
+ "shortcuts": "Raccourcis"
34
36
  }
35
37
  }
@@ -5,10 +5,11 @@
5
5
  import { render } from '@testing-library/react'
6
6
  import React from 'react'
7
7
 
8
- import CozyClient, { CozyProvider } from 'cozy-client'
8
+ import CozyClient from 'cozy-client'
9
9
 
10
10
  import AppTile from '.'
11
11
  import en from '../AppSections/locales/en.json'
12
+ import DemoProvider from '../providers/DemoProvider'
12
13
  import I18n from '../providers/I18n'
13
14
 
14
15
  const appMock = {
@@ -41,11 +42,11 @@ const appMock2 = {
41
42
  const client = new CozyClient({})
42
43
  const Wrapper = props => {
43
44
  return (
44
- <CozyProvider client={client}>
45
+ <DemoProvider client={client}>
45
46
  <I18n dictRequire={() => en} lang="en">
46
47
  <AppTile {...props} />
47
48
  </I18n>
48
- </CozyProvider>
49
+ </DemoProvider>
49
50
  )
50
51
  }
51
52
 
@@ -7,8 +7,10 @@ import en from './locales/en.json'
7
7
  import fr from './locales/fr.json'
8
8
  import styles from './styles.styl'
9
9
  import AppIcon from '../AppIcon'
10
+ import { isShortcutFile } from '../AppSections/helpers.js'
10
11
  import Icon from '../Icon'
11
12
  import WrenchCircleIcon from '../Icons/WrenchCircle'
13
+ import { ShortcutTile } from '../ShortcutTile'
12
14
  import Tile, {
13
15
  TileTitle,
14
16
  TileSubtitle,
@@ -18,6 +20,7 @@ import Tile, {
18
20
  } from '../Tile'
19
21
  import palette from '../palette'
20
22
  import { AppDoctype } from '../proptypes'
23
+ import useBreakpoints from '../providers/Breakpoints'
21
24
  import { createUseI18n } from '../providers/I18n'
22
25
 
23
26
  const locales = { en, fr }
@@ -47,16 +50,30 @@ export const AppTile = ({
47
50
  IconComponent: IconComponentProp,
48
51
  displaySpecificMaintenanceStyle
49
52
  }) => {
50
- const name = nameProp || app.name
51
53
  const { t } = useI18n()
52
54
  const { developer = {} } = app
55
+ const { isMobile } = useBreakpoints()
56
+
57
+ const name = nameProp || app.name
58
+
53
59
  const statusLabel = getCurrentStatusLabel(app)
54
- const statusToDisplay = Array.isArray(showStatus)
55
- ? showStatus.indexOf(statusLabel) > -1 && statusLabel
56
- : showStatus && statusLabel
60
+
61
+ const isStatusArray = Array.isArray(showStatus)
62
+
63
+ const statusToDisplay =
64
+ isShortcutFile(app) && statusLabel === APP_STATUS.installed && isMobile
65
+ ? 'favorite'
66
+ : isStatusArray
67
+ ? showStatus.indexOf(statusLabel) > -1 && statusLabel
68
+ : showStatus && statusLabel
69
+
57
70
  const IconComponent = IconComponentProp || AppIcon
71
+
58
72
  const isInMaintenanceWithSpecificDisplay =
59
73
  displaySpecificMaintenanceStyle && statusLabel === APP_STATUS.maintenance
74
+ const tileSubtitle = isShortcutFile(app)
75
+ ? app.metadata?.source
76
+ : developer.name
60
77
 
61
78
  return (
62
79
  <Tile
@@ -70,11 +87,15 @@ export const AppTile = ({
70
87
  isSecondary={statusLabel === APP_STATUS.installed}
71
88
  >
72
89
  <TileIcon>
73
- <IconComponent
74
- app={app}
75
- className={styles['AppTile-icon']}
76
- {...getAppIconProps()}
77
- />
90
+ {isShortcutFile(app) ? (
91
+ <ShortcutTile file={app} />
92
+ ) : (
93
+ <IconComponent
94
+ app={app}
95
+ className={styles['AppTile-icon']}
96
+ {...getAppIconProps()}
97
+ />
98
+ )}
78
99
  {isInMaintenanceWithSpecificDisplay && (
79
100
  <Icon
80
101
  data-testid="icon-maintenance"
@@ -88,8 +109,8 @@ export const AppTile = ({
88
109
  <TileTitle isMultiline={!statusLabel}>
89
110
  {namePrefix ? `${namePrefix} ${name}` : name}
90
111
  </TileTitle>
91
- {developer.name && showDeveloper && (
92
- <TileSubtitle>{`${t('app_item.by')} ${developer.name}`}</TileSubtitle>
112
+ {showDeveloper && (
113
+ <TileSubtitle>{`${t('app_item.by')} ${tileSubtitle}`}</TileSubtitle>
93
114
  )}
94
115
  {statusToDisplay && (
95
116
  <TileFooter isAccent={statusLabel === APP_STATUS.update}>
@@ -3,6 +3,7 @@
3
3
  "by": "By",
4
4
  "installed": "Installed",
5
5
  "maintenance": "In maintenance",
6
- "update": "Update available"
6
+ "update": "Update available",
7
+ "favorite": "Added to home page"
7
8
  }
8
9
  }
@@ -3,6 +3,7 @@
3
3
  "by": "Par",
4
4
  "installed": "Installée",
5
5
  "maintenance": "En maintenance",
6
- "update": "Mise à jour dispo."
6
+ "update": "Mise à jour dispo.",
7
+ "favorite": "Ajouté sur la page d'accueil"
7
8
  }
8
9
  }
@@ -0,0 +1,43 @@
1
+ ```jsx
2
+ import { useState } from 'react'
3
+ import MobileStepper from 'cozy-ui/transpiled/react/MobileStepper'
4
+ import IconButton from 'cozy-ui/transpiled/react/IconButton'
5
+ import Icon from 'cozy-ui/transpiled/react/Icon'
6
+ import LeftIcon from 'cozy-ui/transpiled/react/Icons/Left'
7
+ import RightIcon from 'cozy-ui/transpiled/react/Icons/Right'
8
+
9
+ const maxSteps = 5
10
+ const [activeStep, setActiveStep] = useState(0)
11
+
12
+ const handleNext = () => {
13
+ setActiveStep(activeStep + 1)
14
+ }
15
+
16
+ const handleBack = () => {
17
+ setActiveStep(activeStep - 1)
18
+ }
19
+
20
+ ;
21
+
22
+ <div class="u-flex">
23
+ <MobileStepper
24
+ className="u-mh-auto"
25
+ steps={maxSteps}
26
+ position="static"
27
+ activeStep={activeStep}
28
+ nextButton={
29
+ <IconButton
30
+ onClick={handleNext}
31
+ disabled={activeStep === maxSteps - 1}
32
+ >
33
+ <Icon icon={RightIcon} />
34
+ </IconButton>
35
+ }
36
+ backButton={
37
+ <IconButton onClick={handleBack} disabled={activeStep === 0}>
38
+ <Icon icon={LeftIcon} />
39
+ </IconButton>
40
+ }
41
+ />
42
+ </div>
43
+ ```
@@ -876,5 +876,23 @@ export const makeLightNormalOverrides = theme => ({
876
876
  padding: '0 16px'
877
877
  }
878
878
  }
879
+ },
880
+ MuiMobileStepper: {
881
+ root: {
882
+ background: 'transparent',
883
+ height: 40,
884
+ padding: 0
885
+ },
886
+ dot: {
887
+ backgroundColor: 'transparent',
888
+ width: '10px',
889
+ height: '10px',
890
+ margin: '0 3px',
891
+ border: `1px solid ${theme.palette.border.main}`,
892
+ boxSizing: 'border-box'
893
+ },
894
+ dotActive: {
895
+ border: 'none'
896
+ }
879
897
  }
880
898
  })
@@ -0,0 +1,63 @@
1
+ import React from 'react'
2
+
3
+ import { IOCozyFile } from 'cozy-client/types/types'
4
+ // @ts-expect-error - The following component is not typed
5
+ import { nameToColor } from 'cozy-ui/react/Avatar/helpers'
6
+ // @ts-expect-error - The following component is not typed
7
+ import Typography from 'cozy-ui/react/Typography'
8
+
9
+ import styles from '../AppTile/styles.styl'
10
+ import { TileIcon } from '../Tile'
11
+ import { makeStyles } from '../styles'
12
+
13
+ interface ShortcutTileProps {
14
+ file: Partial<IOCozyFile> & {
15
+ name: string
16
+ attributes?: { metadata?: { icon?: string; iconMimeType?: string } }
17
+ }
18
+ }
19
+
20
+ const useStyles = makeStyles({
21
+ letter: {
22
+ color: 'white',
23
+ margin: 'auto'
24
+ },
25
+ letterWrapper: {
26
+ backgroundColor: ({ name }: { name: string }) =>
27
+ (nameToColor as (name: string) => string)(name)
28
+ }
29
+ })
30
+
31
+ export const ShortcutTile = ({ file }: ShortcutTileProps): JSX.Element => {
32
+ const classes = useStyles({ name: file.name })
33
+ const icon = file.attributes?.metadata?.icon
34
+ const iconMimeType = file.attributes?.metadata?.iconMimeType
35
+
36
+ if (icon) {
37
+ return (
38
+ <TileIcon>
39
+ <img
40
+ className={styles['AppTile-icon']}
41
+ src={
42
+ iconMimeType
43
+ ? `data:${iconMimeType};base64,${icon}`
44
+ : `data:image/svg+xml;base64,${window.btoa(icon)}`
45
+ }
46
+ width={48}
47
+ height={48}
48
+ alt={file.name}
49
+ />
50
+ </TileIcon>
51
+ )
52
+ }
53
+
54
+ return (
55
+ <TileIcon>
56
+ <div className={classes.letterWrapper}>
57
+ <Typography className={classes.letter} variant="h2" align="center">
58
+ {file.name[0].toUpperCase()}
59
+ </Typography>
60
+ </div>
61
+ </TileIcon>
62
+ )
63
+ }
@@ -0,0 +1,4 @@
1
+ declare module '*.styl' {
2
+ const classes: Record<string, string>
3
+ export default classes
4
+ }
@@ -22,8 +22,10 @@ var styles = {
22
22
  "c-app-icon": "styles__c-app-icon___2_O40",
23
23
  "c-app-icon-default": "styles__c-app-icon-default___3CEmt"
24
24
  };
25
+ import { isShortcutFile } from "cozy-ui/transpiled/react/AppSections/helpers";
25
26
  import Icon, { iconPropType } from "cozy-ui/transpiled/react/Icon";
26
27
  import CubeIcon from "cozy-ui/transpiled/react/Icons/Cube";
28
+ import { ShortcutTile } from "cozy-ui/transpiled/react/ShortcutTile";
27
29
  import palette from "cozy-ui/transpiled/react/palette";
28
30
  import { AppDoctype } from "cozy-ui/transpiled/react/proptypes";
29
31
  var DONE = 'done';
@@ -78,7 +80,9 @@ export var AppIcon = /*#__PURE__*/function (_Component) {
78
80
  app = _this$props.app,
79
81
  type = _this$props.type,
80
82
  priority = _this$props.priority,
81
- client = _this$props.client;
83
+ client = _this$props.client; // Shortcut files used in cozy-store have their own icon in their doctype metadata
84
+
85
+ if (isShortcutFile(app)) return;
82
86
  return client.getStackClient().getIconURL({
83
87
  type: type,
84
88
  slug: app.slug || app,
@@ -164,6 +168,12 @@ export var AppIcon = /*#__PURE__*/function (_Component) {
164
168
  icon = _this$state.icon,
165
169
  status = _this$state.status;
166
170
 
171
+ if (isShortcutFile(this.props.app)) {
172
+ return /*#__PURE__*/React.createElement(ShortcutTile, {
173
+ file: this.props.app
174
+ });
175
+ }
176
+
167
177
  switch (status) {
168
178
  case FETCHING:
169
179
  return /*#__PURE__*/React.createElement("div", {
@@ -13,6 +13,8 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
13
13
  import cx from 'classnames';
14
14
  import PropTypes from 'prop-types';
15
15
  import React, { Component } from 'react';
16
+ import flag from 'cozy-flags';
17
+ import { useExtendI18n } from 'cozy-ui/transpiled/react/providers/I18n';
16
18
  var styles = {
17
19
  "Sections__section": "Sections__Sections__section___2onYy"
18
20
  };
@@ -20,6 +22,8 @@ import * as catUtils from "cozy-ui/transpiled/react/AppSections/categories";
20
22
  import AppsSection from "cozy-ui/transpiled/react/AppSections/components/AppsSection";
21
23
  import DropdownFilter from "cozy-ui/transpiled/react/AppSections/components/DropdownFilter";
22
24
  import { APP_TYPE } from "cozy-ui/transpiled/react/AppSections/constants";
25
+ import { generateI18nConfig } from "cozy-ui/transpiled/react/AppSections/generateI18nConfig";
26
+ import { isShortcutFile } from "cozy-ui/transpiled/react/AppSections/helpers";
23
27
  var en = {
24
28
  app_categories: {
25
29
  all: "All categories",
@@ -48,11 +52,13 @@ var en = {
48
52
  tech: "Tech",
49
53
  telecom: "Telecom",
50
54
  transport: "Transportation",
51
- pro: "Work"
55
+ pro: "Work",
56
+ shortcuts: "Shortcuts"
52
57
  },
53
58
  sections: {
54
59
  applications: "Applications",
55
- konnectors: "Services"
60
+ konnectors: "Services",
61
+ shortcuts: "Shortcuts"
56
62
  }
57
63
  };
58
64
  var fr = {
@@ -83,11 +89,13 @@ var fr = {
83
89
  tech: "Tech",
84
90
  telecom: "Mobile",
85
91
  transport: "Voyage et transport",
86
- pro: "Travail"
92
+ pro: "Travail",
93
+ shortcuts: "Raccourcis"
87
94
  },
88
95
  sections: {
89
96
  applications: "Applications",
90
- konnectors: "Services"
97
+ konnectors: "Services",
98
+ shortcuts: "Raccourcis"
91
99
  }
92
100
  };
93
101
  import * as searchUtils from "cozy-ui/transpiled/react/AppSections/search";
@@ -210,6 +218,9 @@ export var Sections = /*#__PURE__*/function (_Component) {
210
218
  var webAppGroups = catUtils.groupApps(filteredApps.filter(function (a) {
211
219
  return a.type === APP_TYPE.WEBAPP;
212
220
  }));
221
+ var shortcutsGroups = catUtils.groupApps(filteredApps.filter(function (a) {
222
+ return isShortcutFile(a);
223
+ }));
213
224
  var webAppsCategories = Object.keys(webAppGroups).map(function (cat) {
214
225
  return catUtils.addLabel({
215
226
  value: cat
@@ -220,6 +231,11 @@ export var Sections = /*#__PURE__*/function (_Component) {
220
231
  value: cat
221
232
  }, t);
222
233
  }).sort(catUtils.sorter);
234
+ var shortcutsCategories = Object.keys(shortcutsGroups).map(function (cat) {
235
+ return catUtils.addLabel({
236
+ value: cat
237
+ }, t);
238
+ }).sort(catUtils.sorter);
223
239
  var dropdownDisplayed = hasNav && (isMobile || isTablet) && showFilterDropdown;
224
240
  var rawSelectOptions = catUtils.generateOptionsFromApps(apps, {
225
241
  includeAll: true
@@ -244,6 +260,16 @@ export var Sections = /*#__PURE__*/function (_Component) {
244
260
  IconComponent: IconComponent,
245
261
  displaySpecificMaintenanceStyle: displaySpecificMaintenanceStyle
246
262
  });
263
+ })), !!shortcutsCategories.length && /*#__PURE__*/React.createElement("div", null, showSubTitles && /*#__PURE__*/React.createElement(SectionSubtitle, null, t('sections.shortcuts')), shortcutsCategories.map(function (cat) {
264
+ return /*#__PURE__*/React.createElement(AppsSection, _extends({
265
+ key: cat.value
266
+ }, componentsProps === null || componentsProps === void 0 ? void 0 : componentsProps.appsSection, {
267
+ appsList: shortcutsGroups[cat.value],
268
+ subtitle: showSubSubTitles ? /*#__PURE__*/React.createElement(SectionSubSubtitle, null, cat.label) : null,
269
+ IconComponent: IconComponent,
270
+ onAppClick: onAppClick,
271
+ displaySpecificMaintenanceStyle: displaySpecificMaintenanceStyle
272
+ }));
247
273
  })), !!konnectorsCategories.length && /*#__PURE__*/React.createElement("div", null, showSubTitles && /*#__PURE__*/React.createElement(SectionSubtitle, null, t('sections.konnectors')), konnectorsCategories.map(function (cat) {
248
274
  return /*#__PURE__*/React.createElement(AppsSection, _extends({
249
275
  key: cat.value
@@ -260,6 +286,14 @@ export var Sections = /*#__PURE__*/function (_Component) {
260
286
 
261
287
  return Sections;
262
288
  }(Component);
289
+
290
+ var SectionsWrapper = function SectionsWrapper(props) {
291
+ var config = flag('store.alternative-source');
292
+ var i18nConfig = generateI18nConfig(config === null || config === void 0 ? void 0 : config.categories);
293
+ useExtendI18n(i18nConfig);
294
+ return /*#__PURE__*/React.createElement(Sections, props);
295
+ };
296
+
263
297
  Sections.propTypes = {
264
298
  t: PropTypes.func.isRequired,
265
299
 
@@ -300,5 +334,5 @@ Sections.defaultProps = {
300
334
  })
301
335
  })
302
336
  };
303
- export var Untranslated = withBreakpoints()(Sections);
337
+ export var Untranslated = withBreakpoints()(SectionsWrapper);
304
338
  export default withLocales(locales)(translate()(Untranslated));
@@ -69,6 +69,8 @@ export var groupApps = function groupApps(apps) {
69
69
  * Alphabetical sort on label except for
70
70
  * - 'all' value always at the beginning
71
71
  * - 'others' value always at the end
72
+ * - 'cozy' value should be near the beginning, right after 'all'
73
+ * - items of type 'file' should appear alphabetically between 'webapp' and 'konnector'
72
74
  *
73
75
  * @param {CategoryOption} categoryA
74
76
  * @param {CategoryOption} categoryB
@@ -76,7 +78,26 @@ export var groupApps = function groupApps(apps) {
76
78
  */
77
79
 
78
80
  export var sorter = function sorter(categoryA, categoryB) {
79
- return categoryA.value === 'all' && -1 || categoryB.value === 'all' && 1 || categoryA.value === 'others' && 1 || categoryB.value === 'others' && -1 || categoryA.value === 'cozy' && -1 || categoryB.value === 'cozy' && 1 || categoryA.label.localeCompare(categoryB.label);
81
+ // Always keep 'all' at the beginning
82
+ if (categoryA.value === 'all') return -1;
83
+ if (categoryB.value === 'all') return 1; // Always keep 'others' at the end
84
+
85
+ if (categoryA.value === 'others') return 1;
86
+ if (categoryB.value === 'others') return -1; // Keep 'cozy' near the beginning, right after 'all'
87
+
88
+ if (categoryA.value === 'cozy') return -1;
89
+ if (categoryB.value === 'cozy') return 1; // Sort by type order: webapp < file < konnector
90
+
91
+ var typeOrder = ['webapp', 'file', 'konnector'];
92
+ var typeAIndex = typeOrder.indexOf(categoryA.type);
93
+ var typeBIndex = typeOrder.indexOf(categoryB.type);
94
+
95
+ if (typeAIndex !== typeBIndex) {
96
+ return typeAIndex - typeBIndex;
97
+ } // Alphabetical sort on label for the rest
98
+
99
+
100
+ return categoryA.label.localeCompare(categoryB.label);
80
101
  };
81
102
  export var addLabel = function addLabel(cat, t) {
82
103
  return _objectSpread(_objectSpread({}, cat), {}, {
@@ -120,11 +141,18 @@ export var generateOptionsFromApps = function generateOptionsFromApps(apps) {
120
141
  }));
121
142
  }
122
143
 
144
+ if (type === APP_TYPE.FILE) {
145
+ allCategoryOptions.push(addLabel({
146
+ value: 'shortcuts',
147
+ secondary: false
148
+ }));
149
+ }
150
+
123
151
  var categoryOptions = Object.keys(catApps).map(function (cat) {
124
152
  return addLabel({
125
153
  value: cat,
126
154
  type: type,
127
- secondary: type === APP_TYPE.KONNECTOR
155
+ secondary: type === APP_TYPE.KONNECTOR || type === APP_TYPE.FILE
128
156
  });
129
157
  }); // Since options have been labelled, it's possible to sort them
130
158
 
@@ -135,7 +163,7 @@ export var generateOptionsFromApps = function generateOptionsFromApps(apps) {
135
163
  allCategoryOptions = allCategoryOptions.concat(categoryOptions);
136
164
  };
137
165
 
138
- for (var _i = 0, _arr = [APP_TYPE.WEBAPP, APP_TYPE.KONNECTOR]; _i < _arr.length; _i++) {
166
+ for (var _i = 0, _arr = [APP_TYPE.WEBAPP, APP_TYPE.FILE, APP_TYPE.KONNECTOR]; _i < _arr.length; _i++) {
139
167
  _loop2();
140
168
  }
141
169
 
@@ -1,4 +1,8 @@
1
1
  export var APP_TYPE = {
2
2
  KONNECTOR: 'konnector',
3
- WEBAPP: 'webapp'
3
+ WEBAPP: 'webapp',
4
+ FILE: 'file'
5
+ };
6
+ export var APP_CLASS = {
7
+ SHORTCUT: 'shortcut'
4
8
  };
@@ -0,0 +1,6 @@
1
+ export declare const generateI18nConfig: (categories?: {
2
+ [key: string]: string;
3
+ } | undefined) => {
4
+ en: Record<string, string>;
5
+ fr: Record<string, string>;
6
+ };
@@ -0,0 +1,25 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ export var generateI18nConfig = function generateI18nConfig(categories) {
3
+ if (!categories) return {
4
+ en: {},
5
+ fr: {}
6
+ };
7
+ var i18nConfig = {};
8
+
9
+ for (var _i = 0, _Object$entries = Object.entries(categories); _i < _Object$entries.length; _i++) {
10
+ var _value$split$pop;
11
+
12
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
13
+ _key = _Object$entries$_i[0],
14
+ value = _Object$entries$_i[1];
15
+
16
+ // Extract the final part of the path as the display name
17
+ var displayName = (_value$split$pop = value === null || value === void 0 ? void 0 : value.split('/').pop()) !== null && _value$split$pop !== void 0 ? _value$split$pop : ''.replace(/([A-Z])/g, ' $1').trim();
18
+ i18nConfig["app_categories.".concat(_key)] = displayName;
19
+ }
20
+
21
+ return {
22
+ en: i18nConfig,
23
+ fr: i18nConfig
24
+ };
25
+ };
@@ -1,7 +1,12 @@
1
1
  import _get from 'lodash/get';
2
+ import { APP_CLASS, APP_TYPE } from "cozy-ui/transpiled/react/AppSections/constants";
2
3
  export var getTranslatedManifestProperty = function getTranslatedManifestProperty(app, path, t) {
3
4
  if (!t || !app || !path) return _get(app, path, '');
4
5
  return t("apps.".concat(app.slug, ".").concat(path), {
5
6
  _: _get(app, path, '')
6
7
  });
8
+ };
9
+ export var isShortcutFile = function isShortcutFile(app) {
10
+ if (!app) return false;
11
+ return app.type === APP_TYPE.FILE && app.class === APP_CLASS.SHORTCUT;
7
12
  };
@@ -9,7 +9,8 @@ var en = {
9
9
  by: "By",
10
10
  installed: "Installed",
11
11
  maintenance: "In maintenance",
12
- update: "Update available"
12
+ update: "Update available",
13
+ favorite: "Added to home page"
13
14
  }
14
15
  };
15
16
  var fr = {
@@ -17,7 +18,8 @@ var fr = {
17
18
  by: "Par",
18
19
  installed: "Install\xE9e",
19
20
  maintenance: "En maintenance",
20
- update: "Mise \xE0 jour dispo."
21
+ update: "Mise \xE0 jour dispo.",
22
+ favorite: "Ajout\xE9 sur la page d'accueil"
21
23
  }
22
24
  };
23
25
  var styles = {
@@ -27,11 +29,14 @@ var styles = {
27
29
  "AppTile-container-maintenance": "styles__AppTile-container-maintenance___u1a1M"
28
30
  };
29
31
  import AppIcon from "cozy-ui/transpiled/react/AppIcon";
32
+ import { isShortcutFile } from "cozy-ui/transpiled/react/AppSections/helpers.js";
30
33
  import Icon from "cozy-ui/transpiled/react/Icon";
31
34
  import WrenchCircleIcon from "cozy-ui/transpiled/react/Icons/WrenchCircle";
35
+ import { ShortcutTile } from "cozy-ui/transpiled/react/ShortcutTile";
32
36
  import Tile, { TileTitle, TileSubtitle, TileFooter, TileIcon, TileDescription } from "cozy-ui/transpiled/react/Tile";
33
37
  import palette from "cozy-ui/transpiled/react/palette";
34
38
  import { AppDoctype } from "cozy-ui/transpiled/react/proptypes";
39
+ import useBreakpoints from "cozy-ui/transpiled/react/providers/Breakpoints";
35
40
  import { createUseI18n } from "cozy-ui/transpiled/react/providers/I18n";
36
41
  var locales = {
37
42
  en: en,
@@ -55,6 +60,8 @@ var getAppIconProps = function getAppIconProps() {
55
60
 
56
61
  var useI18n = createUseI18n(locales);
57
62
  export var AppTile = function AppTile(_ref) {
63
+ var _app$metadata;
64
+
58
65
  var app = _ref.app,
59
66
  nameProp = _ref.name,
60
67
  namePrefix = _ref.namePrefix,
@@ -63,24 +70,32 @@ export var AppTile = function AppTile(_ref) {
63
70
  showStatus = _ref.showStatus,
64
71
  IconComponentProp = _ref.IconComponent,
65
72
  displaySpecificMaintenanceStyle = _ref.displaySpecificMaintenanceStyle;
66
- var name = nameProp || app.name;
67
73
 
68
74
  var _useI18n = useI18n(),
69
75
  t = _useI18n.t;
70
76
 
71
77
  var _app$developer = app.developer,
72
78
  developer = _app$developer === void 0 ? {} : _app$developer;
79
+
80
+ var _useBreakpoints = useBreakpoints(),
81
+ isMobile = _useBreakpoints.isMobile;
82
+
83
+ var name = nameProp || app.name;
73
84
  var statusLabel = getCurrentStatusLabel(app);
74
- var statusToDisplay = Array.isArray(showStatus) ? showStatus.indexOf(statusLabel) > -1 && statusLabel : showStatus && statusLabel;
85
+ var isStatusArray = Array.isArray(showStatus);
86
+ var statusToDisplay = isShortcutFile(app) && statusLabel === APP_STATUS.installed && isMobile ? 'favorite' : isStatusArray ? showStatus.indexOf(statusLabel) > -1 && statusLabel : showStatus && statusLabel;
75
87
  var IconComponent = IconComponentProp || AppIcon;
76
88
  var isInMaintenanceWithSpecificDisplay = displaySpecificMaintenanceStyle && statusLabel === APP_STATUS.maintenance;
89
+ var tileSubtitle = isShortcutFile(app) ? (_app$metadata = app.metadata) === null || _app$metadata === void 0 ? void 0 : _app$metadata.source : developer.name;
77
90
  return /*#__PURE__*/React.createElement(Tile, {
78
91
  tag: "button",
79
92
  type: "button",
80
93
  onClick: onClick,
81
94
  className: cx(_defineProperty({}, styles['AppTile-container-maintenance'], isInMaintenanceWithSpecificDisplay)),
82
95
  isSecondary: statusLabel === APP_STATUS.installed
83
- }, /*#__PURE__*/React.createElement(TileIcon, null, /*#__PURE__*/React.createElement(IconComponent, _extends({
96
+ }, /*#__PURE__*/React.createElement(TileIcon, null, isShortcutFile(app) ? /*#__PURE__*/React.createElement(ShortcutTile, {
97
+ file: app
98
+ }) : /*#__PURE__*/React.createElement(IconComponent, _extends({
84
99
  app: app,
85
100
  className: styles['AppTile-icon']
86
101
  }, getAppIconProps())), isInMaintenanceWithSpecificDisplay && /*#__PURE__*/React.createElement(Icon, {
@@ -92,7 +107,7 @@ export var AppTile = function AppTile(_ref) {
92
107
  className: styles["AppTile-description"]
93
108
  }, /*#__PURE__*/React.createElement(TileTitle, {
94
109
  isMultiline: !statusLabel
95
- }, namePrefix ? "".concat(namePrefix, " ").concat(name) : name), developer.name && showDeveloper && /*#__PURE__*/React.createElement(TileSubtitle, null, "".concat(t('app_item.by'), " ").concat(developer.name)), statusToDisplay && /*#__PURE__*/React.createElement(TileFooter, {
110
+ }, namePrefix ? "".concat(namePrefix, " ").concat(name) : name), showDeveloper && /*#__PURE__*/React.createElement(TileSubtitle, null, "".concat(t('app_item.by'), " ").concat(tileSubtitle)), statusToDisplay && /*#__PURE__*/React.createElement(TileFooter, {
96
111
  isAccent: statusLabel === APP_STATUS.update
97
112
  }, t("app_item.".concat(statusToDisplay)))));
98
113
  };
@@ -1376,6 +1376,24 @@ export function makeDarkInvertedOverrides(theme: any): {
1376
1376
  };
1377
1377
  };
1378
1378
  };
1379
+ MuiMobileStepper: {
1380
+ root: {
1381
+ background: string;
1382
+ height: number;
1383
+ padding: number;
1384
+ };
1385
+ dot: {
1386
+ backgroundColor: string;
1387
+ width: string;
1388
+ height: string;
1389
+ margin: string;
1390
+ border: string;
1391
+ boxSizing: string;
1392
+ };
1393
+ dotActive: {
1394
+ border: string;
1395
+ };
1396
+ };
1379
1397
  } & {
1380
1398
  MuiLinearProgress: {
1381
1399
  colorPrimary: {
@@ -1376,4 +1376,22 @@ export function makeDarkNormalOverrides(theme: any): {
1376
1376
  };
1377
1377
  };
1378
1378
  };
1379
+ MuiMobileStepper: {
1380
+ root: {
1381
+ background: string;
1382
+ height: number;
1383
+ padding: number;
1384
+ };
1385
+ dot: {
1386
+ backgroundColor: string;
1387
+ width: string;
1388
+ height: string;
1389
+ margin: string;
1390
+ border: string;
1391
+ boxSizing: string;
1392
+ };
1393
+ dotActive: {
1394
+ border: string;
1395
+ };
1396
+ };
1379
1397
  };
@@ -1376,6 +1376,24 @@ export function makeLightInvertedOverrides(theme: any): {
1376
1376
  };
1377
1377
  };
1378
1378
  };
1379
+ MuiMobileStepper: {
1380
+ root: {
1381
+ background: string;
1382
+ height: number;
1383
+ padding: number;
1384
+ };
1385
+ dot: {
1386
+ backgroundColor: string;
1387
+ width: string;
1388
+ height: string;
1389
+ margin: string;
1390
+ border: string;
1391
+ boxSizing: string;
1392
+ };
1393
+ dotActive: {
1394
+ border: string;
1395
+ };
1396
+ };
1379
1397
  } & {
1380
1398
  MuiLinearProgress: {
1381
1399
  colorPrimary: {
@@ -1376,4 +1376,22 @@ export function makeLightNormalOverrides(theme: any): {
1376
1376
  };
1377
1377
  };
1378
1378
  };
1379
+ MuiMobileStepper: {
1380
+ root: {
1381
+ background: string;
1382
+ height: number;
1383
+ padding: number;
1384
+ };
1385
+ dot: {
1386
+ backgroundColor: string;
1387
+ width: string;
1388
+ height: string;
1389
+ margin: string;
1390
+ border: string;
1391
+ boxSizing: string;
1392
+ };
1393
+ dotActive: {
1394
+ border: string;
1395
+ };
1396
+ };
1379
1397
  };
@@ -820,6 +820,24 @@ export var makeLightNormalOverrides = function makeLightNormalOverrides(theme) {
820
820
  padding: '0 16px'
821
821
  }
822
822
  }
823
+ },
824
+ MuiMobileStepper: {
825
+ root: {
826
+ background: 'transparent',
827
+ height: 40,
828
+ padding: 0
829
+ },
830
+ dot: {
831
+ backgroundColor: 'transparent',
832
+ width: '10px',
833
+ height: '10px',
834
+ margin: '0 3px',
835
+ border: "1px solid ".concat(theme.palette.border.main),
836
+ boxSizing: 'border-box'
837
+ },
838
+ dotActive: {
839
+ border: 'none'
840
+ }
823
841
  }
824
842
  };
825
843
  };
@@ -0,0 +1,15 @@
1
+ /// <reference types="react" />
2
+ import { IOCozyFile } from 'cozy-client/types/types';
3
+ interface ShortcutTileProps {
4
+ file: Partial<IOCozyFile> & {
5
+ name: string;
6
+ attributes?: {
7
+ metadata?: {
8
+ icon?: string;
9
+ iconMimeType?: string;
10
+ };
11
+ };
12
+ };
13
+ }
14
+ export declare const ShortcutTile: ({ file }: ShortcutTileProps) => JSX.Element;
15
+ export {};
@@ -0,0 +1,53 @@
1
+ import React from 'react';
2
+ // @ts-expect-error - The following component is not typed
3
+ import { nameToColor } from 'cozy-ui/react/Avatar/helpers'; // @ts-expect-error - The following component is not typed
4
+
5
+ import Typography from 'cozy-ui/react/Typography';
6
+ var styles = {
7
+ "AppTile-icon": "styles__AppTile-icon___1f0c0",
8
+ "AppTile-icon--default": "styles__AppTile-icon--default___1tjiF",
9
+ "AppTile-icon-maintenance": "styles__AppTile-icon-maintenance___2VOvO",
10
+ "AppTile-container-maintenance": "styles__AppTile-container-maintenance___u1a1M"
11
+ };
12
+ import { TileIcon } from "cozy-ui/transpiled/react/Tile";
13
+ import { makeStyles } from "cozy-ui/transpiled/react/styles";
14
+ var useStyles = makeStyles({
15
+ letter: {
16
+ color: 'white',
17
+ margin: 'auto'
18
+ },
19
+ letterWrapper: {
20
+ backgroundColor: function backgroundColor(_ref) {
21
+ var name = _ref.name;
22
+ return nameToColor(name);
23
+ }
24
+ }
25
+ });
26
+ export var ShortcutTile = function ShortcutTile(_ref2) {
27
+ var _file$attributes, _file$attributes$meta, _file$attributes2, _file$attributes2$met;
28
+
29
+ var file = _ref2.file;
30
+ var classes = useStyles({
31
+ name: file.name
32
+ });
33
+ var icon = (_file$attributes = file.attributes) === null || _file$attributes === void 0 ? void 0 : (_file$attributes$meta = _file$attributes.metadata) === null || _file$attributes$meta === void 0 ? void 0 : _file$attributes$meta.icon;
34
+ var iconMimeType = (_file$attributes2 = file.attributes) === null || _file$attributes2 === void 0 ? void 0 : (_file$attributes2$met = _file$attributes2.metadata) === null || _file$attributes2$met === void 0 ? void 0 : _file$attributes2$met.iconMimeType;
35
+
36
+ if (icon) {
37
+ return /*#__PURE__*/React.createElement(TileIcon, null, /*#__PURE__*/React.createElement("img", {
38
+ className: styles['AppTile-icon'],
39
+ src: iconMimeType ? "data:".concat(iconMimeType, ";base64,").concat(icon) : "data:image/svg+xml;base64,".concat(window.btoa(icon)),
40
+ width: 48,
41
+ height: 48,
42
+ alt: file.name
43
+ }));
44
+ }
45
+
46
+ return /*#__PURE__*/React.createElement(TileIcon, null, /*#__PURE__*/React.createElement("div", {
47
+ className: classes.letterWrapper
48
+ }, /*#__PURE__*/React.createElement(Typography, {
49
+ className: classes.letter,
50
+ variant: "h2",
51
+ align: "center"
52
+ }, file.name[0].toUpperCase())));
53
+ };
@@ -0,0 +1,68 @@
1
+ export function TileDescription({ children, className }: {
2
+ children: any;
3
+ className: any;
4
+ }): JSX.Element;
5
+ export function TileTitle({ children, className, isMultiline }: {
6
+ children: any;
7
+ className: any;
8
+ isMultiline: any;
9
+ }): JSX.Element;
10
+ export namespace TileTitle {
11
+ namespace propTypes {
12
+ const className: PropTypes.Requireable<string>;
13
+ const isMultiline: PropTypes.Requireable<boolean>;
14
+ }
15
+ namespace defaultProps {
16
+ const isMultiline_1: boolean;
17
+ export { isMultiline_1 as isMultiline };
18
+ }
19
+ }
20
+ export function TileSubtitle({ children }: {
21
+ children: any;
22
+ }): JSX.Element;
23
+ export function TileFooter({ children, className, isAccent }: {
24
+ children: any;
25
+ className: any;
26
+ isAccent: any;
27
+ }): JSX.Element;
28
+ export namespace TileFooter {
29
+ export namespace propTypes_1 {
30
+ const className_1: PropTypes.Requireable<string>;
31
+ export { className_1 as className };
32
+ export const isAccent: PropTypes.Requireable<boolean>;
33
+ }
34
+ export { propTypes_1 as propTypes };
35
+ export namespace defaultProps_1 {
36
+ const isAccent_1: boolean;
37
+ export { isAccent_1 as isAccent };
38
+ }
39
+ export { defaultProps_1 as defaultProps };
40
+ }
41
+ export function TileIcon({ children }: {
42
+ children: any;
43
+ }): JSX.Element;
44
+ export default Tile;
45
+ import PropTypes from "prop-types";
46
+ declare function Tile({ children, className, tag: Tag, isSecondary, ...props }: {
47
+ [x: string]: any;
48
+ children: any;
49
+ className: any;
50
+ tag: any;
51
+ isSecondary: any;
52
+ }): JSX.Element;
53
+ declare namespace Tile {
54
+ export namespace propTypes_2 {
55
+ const className_2: PropTypes.Requireable<string>;
56
+ export { className_2 as className };
57
+ export const isSecondary: PropTypes.Requireable<boolean>;
58
+ export const tag: PropTypes.Requireable<string>;
59
+ }
60
+ export { propTypes_2 as propTypes };
61
+ export namespace defaultProps_2 {
62
+ const isSecondary_1: boolean;
63
+ export { isSecondary_1 as isSecondary };
64
+ const tag_1: string;
65
+ export { tag_1 as tag };
66
+ }
67
+ export { defaultProps_2 as defaultProps };
68
+ }
@@ -0,0 +1,3 @@
1
+ export default Typography;
2
+ declare const Typography: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
3
+ import React from "react";
File without changes