cozy-ui 135.5.0 → 135.7.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 (43) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/assets/icons/ui/expand.svg +1 -0
  3. package/assets/icons/ui/export.svg +1 -0
  4. package/assets/icons/ui/narrow.svg +1 -0
  5. package/package.json +1 -1
  6. package/react/ActionsMenu/Actions/exportToText.js +54 -0
  7. package/react/ActionsMenu/Actions/helpers.js +20 -0
  8. package/react/ActionsMenu/Actions/index.js +1 -0
  9. package/react/ActionsMenu/Actions/locales/en.json +2 -1
  10. package/react/ActionsMenu/Actions/locales/fr.json +2 -1
  11. package/react/ActionsMenu/Actions/locales/ru.json +3 -2
  12. package/react/ActionsMenu/Actions/locales/vi.json +3 -2
  13. package/react/ActionsMenu/Actions/pdfHelpers.js +187 -0
  14. package/react/Icon/Readme.md +7 -1
  15. package/react/Icons/Expand.jsx +12 -0
  16. package/react/Icons/Export.jsx +13 -0
  17. package/react/Icons/Narrow.jsx +16 -0
  18. package/react/Table/Readme.md +2 -1
  19. package/react/Table/Virtualized/FixedHeaderContent.jsx +14 -12
  20. package/react/Table/Virtualized/RowContent.jsx +16 -14
  21. package/react/Table/Virtualized/TableRow.jsx +8 -0
  22. package/react/Table/Virtualized/index.jsx +9 -3
  23. package/transpiled/react/ActionsMenu/Actions/exportToText.d.ts +13 -0
  24. package/transpiled/react/ActionsMenu/Actions/exportToText.js +84 -0
  25. package/transpiled/react/ActionsMenu/Actions/helpers.d.ts +1 -0
  26. package/transpiled/react/ActionsMenu/Actions/helpers.js +20 -1
  27. package/transpiled/react/ActionsMenu/Actions/index.d.ts +1 -0
  28. package/transpiled/react/ActionsMenu/Actions/index.js +2 -1
  29. package/transpiled/react/ActionsMenu/Actions/locales/withActionsLocales.js +8 -4
  30. package/transpiled/react/ActionsMenu/Actions/pdfHelpers.d.ts +34 -0
  31. package/transpiled/react/ActionsMenu/Actions/pdfHelpers.js +242 -0
  32. package/transpiled/react/Icon/icons-sprite.d.ts +1 -1
  33. package/transpiled/react/Icon/icons-sprite.js +1 -1
  34. package/transpiled/react/Icons/Expand.d.ts +2 -0
  35. package/transpiled/react/Icons/Expand.js +14 -0
  36. package/transpiled/react/Icons/Export.d.ts +2 -0
  37. package/transpiled/react/Icons/Export.js +16 -0
  38. package/transpiled/react/Icons/Narrow.d.ts +2 -0
  39. package/transpiled/react/Icons/Narrow.js +16 -0
  40. package/transpiled/react/Table/Virtualized/FixedHeaderContent.js +1 -1
  41. package/transpiled/react/Table/Virtualized/RowContent.js +1 -1
  42. package/transpiled/react/Table/Virtualized/TableRow.js +12 -1
  43. package/transpiled/react/Table/Virtualized/index.js +11 -4
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [135.7.0](https://github.com/cozy/cozy-ui/compare/v135.6.0...v135.7.0) (2026-02-02)
2
+
3
+
4
+ ### Features
5
+
6
+ * Allow to hide checkboxes in VirtualizedTable ([fa375d7](https://github.com/cozy/cozy-ui/commit/fa375d7))
7
+
8
+ # [135.6.0](https://github.com/cozy/cozy-ui/compare/v135.5.0...v135.6.0) (2026-01-27)
9
+
10
+
11
+ ### Features
12
+
13
+ * Implement new actions ExportToText and new icons :sparkles: ([6714f4a](https://github.com/cozy/cozy-ui/commit/6714f4a))
14
+
1
15
  # [135.5.0](https://github.com/cozy/cozy-ui/compare/v135.4.0...v135.5.0) (2026-01-24)
2
16
 
3
17
 
@@ -0,0 +1 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14.8 15.2a.8.8 0 0 0-.8-.8H2.8a.8.8 0 0 0 0 1.6H14a.8.8 0 0 0 .8-.8ZM14.8.8A.8.8 0 0 0 14 0H2.8a.8.8 0 1 0 0 1.6H14a.8.8 0 0 0 .8-.8ZM6.893 9.833a.799.799 0 0 0-1.128 1.132l1.928 1.928a1 1 0 0 0 1.414 0l1.928-1.928a.799.799 0 0 0-1.128-1.132l-.707.703V5.464l.707.703a.799.799 0 0 0 1.128-1.132L9.107 3.107a1 1 0 0 0-1.414 0L5.765 5.035a.799.799 0 0 0 1.128 1.132l.707-.703v5.072l-.707-.703Z" fill="#2C3038"/></svg>
@@ -0,0 +1 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14.8 4v10.4l-.008.159A1.6 1.6 0 0 1 13.2 16H3.6a1.6 1.6 0 0 1-1.014-.362l-.117-.107a1.6 1.6 0 0 1-.461-.972L2 14.4V1.6c0-.372.13-.73.362-1.014L2.47.469A1.6 1.6 0 0 1 3.599 0h7.2l4 4ZM3.6 14.4h9.6V5.6h-1.598a2.4 2.4 0 0 1-2.4-2.4V1.6H3.6v12.8Zm7.202-11.2a.8.8 0 0 0 .8.8h.935l-1.736-1.736V3.2Z" fill="#2C3038"/><path d="M8.401 7.2a.8.8 0 0 1 .8.799v2.867l1.034-1.032a.8.8 0 1 1 1.131 1.13l-2.4 2.401a.794.794 0 0 1-.436.222.817.817 0 0 1-.13.013.793.793 0 0 1-.127-.013.794.794 0 0 1-.438-.222l-2.4-2.4a.8.8 0 1 1 1.131-1.131l1.035 1.034V8a.8.8 0 0 1 .8-.8Z" fill="#2C3038"/></svg>
@@ -0,0 +1 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15.736.264a.9.9 0 0 1 0 1.274L12.07 5.204h2.027a.9.9 0 1 1 0 1.802H9.896a.9.9 0 0 1-.901-.9V1.901a.9.9 0 1 1 1.802 0V3.93L14.462.264a.9.9 0 0 1 1.274 0ZM1 9.895a.9.9 0 0 1 .902-.901h4.203a.9.9 0 0 1 .901.9v4.204a.9.9 0 0 1-1.802 0V12.07l-3.666 3.667a.9.9 0 0 1-1.274-1.274l3.667-3.666H1.9a.9.9 0 0 1-.9-.901Z" fill="#2C3038"/></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "135.5.0",
3
+ "version": "135.7.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -0,0 +1,54 @@
1
+ import React, { forwardRef } from 'react'
2
+
3
+ import logger from 'cozy-logger'
4
+
5
+ import { downloadBlob } from './helpers'
6
+ import { getActionsI18n } from './locales/withActionsLocales'
7
+ import { makePdfBlobFromText } from './pdfHelpers'
8
+ import Icon from '../../Icon'
9
+ import ExportIcon from '../../Icons/Export'
10
+ import ListItemIcon from '../../ListItemIcon'
11
+ import ListItemText from '../../ListItemText'
12
+ import ActionsMenuItem from '../ActionsMenuItem'
13
+
14
+ const makeComponent = (label, icon) => {
15
+ const Component = forwardRef((props, ref) => {
16
+ return (
17
+ <ActionsMenuItem {...props} ref={ref}>
18
+ <ListItemIcon>
19
+ <Icon icon={icon} />
20
+ </ListItemIcon>
21
+ <ListItemText primary={label} />
22
+ </ActionsMenuItem>
23
+ )
24
+ })
25
+
26
+ Component.displayName = 'exportToText'
27
+
28
+ return Component
29
+ }
30
+
31
+ export const exportToText = ({ exportedText, file }) => {
32
+ const { t } = getActionsI18n()
33
+ const icon = ExportIcon
34
+ const label = t('exportToText')
35
+
36
+ return {
37
+ name: 'exportToText',
38
+ icon,
39
+ label,
40
+ displayCondition: () => !!exportedText,
41
+ Component: makeComponent(label, icon),
42
+ action: async () => {
43
+ try {
44
+ const blob = await makePdfBlobFromText(exportedText)
45
+ const baseName = file?.name
46
+ ? `${file.name.replace(/\.[^/.]+$/, '')}_export`
47
+ : 'export'
48
+ downloadBlob(blob, `${baseName}.pdf`)
49
+ } catch (error) {
50
+ logger.error(error)
51
+ }
52
+ }
53
+ }
54
+ }
@@ -238,3 +238,23 @@ export const makePdfBlob = async ({ client, docs, fetchBlobFileById }) => {
238
238
 
239
239
  return blob
240
240
  }
241
+
242
+ /**
243
+ * Trigger a browser download for a given blob.
244
+ *
245
+ * @param {Blob} blob - File content
246
+ * @param {string} filename - Desired filename
247
+ * @returns {void}
248
+ */
249
+ export const downloadBlob = (blob, filename) => {
250
+ if (!blob || !filename) return
251
+
252
+ const url = URL.createObjectURL(blob)
253
+ const a = document.createElement('a')
254
+ a.href = url
255
+ a.download = filename
256
+ a.style.display = 'none'
257
+ document.body.appendChild(a)
258
+ a.click()
259
+ a.remove()
260
+ }
@@ -13,3 +13,4 @@ export { viewInDrive } from './viewInDrive'
13
13
  export { copyToClipboard } from './copyToClipboard'
14
14
  export { editAttribute } from './editAttribute'
15
15
  export { others } from './others'
16
+ export { exportToText } from './exportToText'
@@ -25,5 +25,6 @@
25
25
  "success": "Copied to clipboard",
26
26
  "error": "Cannot copy to clipboard"
27
27
  },
28
- "call": "Call"
28
+ "call": "Call",
29
+ "exportToText": "Export as text"
29
30
  }
@@ -25,5 +25,6 @@
25
25
  "success": "Copié dans le presse-papier",
26
26
  "error": "Impossible de copier dans le presse-papier"
27
27
  },
28
- "call": "Appeler"
28
+ "call": "Appeler",
29
+ "exportToText": "Exporter en texte"
29
30
  }
@@ -25,5 +25,6 @@
25
25
  "success": "Скопировано в буфер обмена",
26
26
  "error": "Не удается скопировать в буфер обмена"
27
27
  },
28
- "call": "Звонить"
29
- }
28
+ "call": "Звонить",
29
+ "exportToText": "Экспортировать как текст"
30
+ }
@@ -25,5 +25,6 @@
25
25
  "success": "Đã sao chép vào clipboard",
26
26
  "error": "Không thể sao chép vào clipboard"
27
27
  },
28
- "call": "Gọi"
29
- }
28
+ "call": "Gọi",
29
+ "exportToText": "Xuất dưới dạng văn bản"
30
+ }
@@ -0,0 +1,187 @@
1
+ import { PDFDocument, StandardFonts } from 'pdf-lib'
2
+
3
+ /**
4
+ * Wrap a string into multiple lines based on available width.
5
+ *
6
+ * @param {object} opts
7
+ * @param {import('pdf-lib').PDFFont} opts.font - Embedded pdf-lib font
8
+ * @param {number} opts.fontSize - Font size
9
+ * @param {number} opts.maxLineWidth - Max line width in PDF units
10
+ * @param {string} opts.line - Text to wrap
11
+ * @returns {string[]} Wrapped lines
12
+ */
13
+ export const wrapTextToLines = ({ font, fontSize, maxLineWidth, line }) => {
14
+ if (!line) return []
15
+ if (fontSize <= 0 || maxLineWidth <= 0) return [line]
16
+
17
+ const words = line.split(' ')
18
+
19
+ return words.reduce((lines, word) => {
20
+ const currentLine = lines[lines.length - 1]
21
+
22
+ if (!currentLine) {
23
+ return [word]
24
+ }
25
+
26
+ const testLine = `${currentLine} ${word}`
27
+ const testWidth = font.widthOfTextAtSize(testLine, fontSize)
28
+
29
+ if (testWidth <= maxLineWidth) {
30
+ lines[lines.length - 1] = testLine
31
+ } else {
32
+ lines.push(word)
33
+ }
34
+
35
+ return lines
36
+ }, [])
37
+ }
38
+
39
+ /**
40
+ * Add a new page if there is not enough space to draw a new line.
41
+ *
42
+ * @param {object} opts
43
+ * @param {PDFDocument} opts.pdfDoc - pdf-lib document
44
+ * @param {import('pdf-lib').PDFPage} opts.page - Current page
45
+ * @param {number} opts.y - Current y cursor position
46
+ * @param {number} opts.requiredHeight - Height required before adding a new page
47
+ * @param {number} opts.marginTop - Top margin
48
+ * @param {number} opts.marginBottom - Bottom margin
49
+ * @returns {{ page: import('pdf-lib').PDFPage, y: number }} Updated page and y
50
+ */
51
+ export const pushNewPageIfNeeded = ({
52
+ pdfDoc,
53
+ page,
54
+ y,
55
+ requiredHeight,
56
+ marginTop,
57
+ marginBottom
58
+ }) => {
59
+ if (!pdfDoc || !page) {
60
+ throw new Error('pdfDoc and page are required')
61
+ }
62
+
63
+ const { width, height } = page.getSize()
64
+
65
+ if (y - requiredHeight < marginBottom) {
66
+ const newPage = pdfDoc.addPage([width, height])
67
+ return {
68
+ page: newPage,
69
+ y: height - marginTop
70
+ }
71
+ }
72
+
73
+ return { page, y }
74
+ }
75
+
76
+ /**
77
+ * Draws a plain text string onto a PDF, wrapping lines to max width and handling page breaks.
78
+ *
79
+ * @param {object} opts
80
+ * @param {PDFDocument} opts.pdfDoc - pdf-lib document
81
+ * @param {import('pdf-lib').PDFPage} opts.page - Current page
82
+ * @param {number} opts.y - Current y cursor position
83
+ * @param {string} opts.text - Text to draw
84
+ * @param {import('pdf-lib').PDFFont} opts.font - Embedded pdf-lib font
85
+ * @param {number} opts.fontSize - Font size
86
+ * @param {number} opts.lineHeight - Line height
87
+ * @param {number} opts.marginX - Left margin
88
+ * @param {number} opts.marginY - Top/bottom margin
89
+ * @param {number} opts.maxLineWidth - Max line width in PDF units
90
+ * @returns {{ page: import('pdf-lib').PDFPage, y: number }} Updated page and y
91
+ */
92
+ export const drawWrappedText = ({
93
+ pdfDoc,
94
+ page,
95
+ y,
96
+ text,
97
+ font,
98
+ fontSize,
99
+ lineHeight,
100
+ marginX,
101
+ marginY,
102
+ maxLineWidth
103
+ }) => {
104
+ let currentPage = page
105
+ let currentY = y
106
+
107
+ const paragraphs = String(text ?? '').split(/\r?\n/)
108
+
109
+ const renderItems = paragraphs.flatMap(paragraph => {
110
+ const wrappedLines = wrapTextToLines({
111
+ font,
112
+ fontSize,
113
+ maxLineWidth,
114
+ line: paragraph
115
+ })
116
+
117
+ return [...wrappedLines, { type: 'paragraphGap' }]
118
+ })
119
+
120
+ for (const item of renderItems) {
121
+ if (typeof item === 'object' && item.type === 'paragraphGap') {
122
+ currentY -= lineHeight / 2
123
+ continue
124
+ }
125
+
126
+ const nextState = pushNewPageIfNeeded({
127
+ pdfDoc,
128
+ page: currentPage,
129
+ y: currentY,
130
+ requiredHeight: lineHeight,
131
+ marginTop: marginY,
132
+ marginBottom: marginY
133
+ })
134
+
135
+ currentPage = nextState.page
136
+ currentY = nextState.y
137
+
138
+ currentPage.drawText(item, {
139
+ x: marginX,
140
+ y: currentY - fontSize,
141
+ size: fontSize,
142
+ font
143
+ })
144
+
145
+ currentY -= lineHeight
146
+ }
147
+
148
+ return { page: currentPage, y: currentY }
149
+ }
150
+
151
+ /**
152
+ * Creates a PDF Blob from a plain text string.
153
+ *
154
+ * @param {string} text - Text content to put into the PDF
155
+ * @returns {Promise<Blob>} PDF file as a Blob
156
+ */
157
+ export const makePdfBlobFromText = async text => {
158
+ const pdfDoc = await PDFDocument.create()
159
+ const font = await pdfDoc.embedFont(StandardFonts.Helvetica)
160
+
161
+ const CONFIG = {
162
+ fontSize: 12,
163
+ lineHeight: 16,
164
+ marginX: 40,
165
+ marginY: 40,
166
+ pageSize: [595.28, 841.89] // A4
167
+ }
168
+
169
+ const maxLineWidth = CONFIG.pageSize[0] - CONFIG.marginX * 2
170
+ const initialPage = pdfDoc.addPage(CONFIG.pageSize)
171
+
172
+ drawWrappedText({
173
+ pdfDoc,
174
+ page: initialPage,
175
+ y: CONFIG.pageSize[1] - CONFIG.marginY,
176
+ text,
177
+ font,
178
+ fontSize: CONFIG.fontSize,
179
+ lineHeight: CONFIG.lineHeight,
180
+ marginX: CONFIG.marginX,
181
+ marginY: CONFIG.marginY,
182
+ maxLineWidth
183
+ })
184
+
185
+ const pdfBytes = await pdfDoc.save()
186
+ return new Blob([pdfBytes], { type: 'application/pdf' })
187
+ }
@@ -170,7 +170,9 @@ import EmailOpen from 'cozy-ui/transpiled/react/Icons/EmailOpen'
170
170
  import Eu from 'cozy-ui/transpiled/react/Icons/Eu'
171
171
  import Euro from 'cozy-ui/transpiled/react/Icons/Euro'
172
172
  import Exchange from 'cozy-ui/transpiled/react/Icons/Exchange'
173
+ import Expand from 'cozy-ui/transpiled/react/Icons/Expand'
173
174
  import Expert from 'cozy-ui/transpiled/react/Icons/Expert'
175
+ import Export from 'cozy-ui/transpiled/react/Icons/Export'
174
176
  import Eye from 'cozy-ui/transpiled/react/Icons/Eye'
175
177
  import EyeClosed from 'cozy-ui/transpiled/react/Icons/EyeClosed'
176
178
  import FaceId from 'cozy-ui/transpiled/react/Icons/FaceId'
@@ -245,6 +247,7 @@ import MovementOut from 'cozy-ui/transpiled/react/Icons/MovementOut'
245
247
  import Moveto from 'cozy-ui/transpiled/react/Icons/Moveto'
246
248
  import MultiFiles from 'cozy-ui/transpiled/react/Icons/MultiFiles'
247
249
  import Music from 'cozy-ui/transpiled/react/Icons/Music'
250
+ import Narrow from 'cozy-ui/transpiled/react/Icons/Narrow'
248
251
  import New from 'cozy-ui/transpiled/react/Icons/New'
249
252
  import Next from 'cozy-ui/transpiled/react/Icons/Next'
250
253
  import Note from 'cozy-ui/transpiled/react/Icons/Note'
@@ -461,7 +464,9 @@ const icons = [
461
464
  Eu,
462
465
  Euro,
463
466
  Exchange,
467
+ Expand,
464
468
  Expert,
469
+ Export,
465
470
  Eye,
466
471
  EyeClosed,
467
472
  FaceId,
@@ -536,6 +541,7 @@ const icons = [
536
541
  Moveto,
537
542
  MultiFiles,
538
543
  Music,
544
+ Narrow,
539
545
  New,
540
546
  Next,
541
547
  Note,
@@ -1014,7 +1020,7 @@ import Typography from 'cozy-ui/transpiled/react/Typography'
1014
1020
 
1015
1021
  const colors = ['#297EF2', '#08b442', '#B449E7', '#F52D2D', '#FF962F']
1016
1022
  let i = 0
1017
- const availableIcons = ['album-add','album-remove','album','answer','apple','archive','arrowUp', 'article', 'assign-admin','assign-moderator','attachment','attention','bank-check','bank','banking-add','banking','bell','benefit','bike','bill','bottom','browser-brave','browser-chrome','browser-duckduckgo','browser-edge','browser-edge-chromium','browser-firefox','browser-ie','browser-opera','browser-safari','burger','bus','calendar','camera','car','carbonCopy','carpooling','categories','certified','check-circle','check-list','check-square','check','checkbox','chess','child','circle-filled','clock','clock-outline','cloud-happy','cloud-rainbow','cloud-plus-outlined','cloud','cloud2','collect','cocktail','comment','company','compare','compass','connector','contract','contrast','copy','cozy-circle','cozy-laugh', 'cozy-lock', 'cozy-text', 'cozy-release', 'credit-card-add','credit-card','credit','crop','cross-circle-outline','cross-circle','cross-medium','cross-small','cross','cube','dash','dashboard','data-control','database','debit','desktop-download','devices','discuss','dots','down','download','drawing-arrow-up','dropdown-close','dropdown-open','dropdown','dropup','electric-bike','electric-car','electric-scooter','email-notification','email-open','email','eu','euro','exchange','expert','eye-closed','eye','face-id','file-add','file-duotone','file-new','file-none','file-outline','file','filter','fingerprint','fitness','flag-outlined','flag','flash-auto','flashlight','folder-add','folder-moveto','folder-open','folder','forbidden','from-user','gear','globe','gouv','graph-circle','grid','group-list','groups','growth','hand','heart','help','help-outlined','history','home','hourglass','image','info-outlined','info','justice','key','key2','label-outlined','laudry','laptop','left','library','lightbulb','lightning','link-out','link','list','list-min','location','lock', 'lock-screen', 'logout','magic-trick','magnet','magnifier','matrix','merge','moped','mosaic','mosaic-min','motorcycle','mountain','movement-in','movement-out','mouvement','moveto','multi-files','music','new','next','note','notification-email','number','offline','online', 'openapp', 'openwith','palette','paper','paperplane','password','pen','people','peoples','percent-circle','percent','person-add','personal-data','phone-download','phone-upload','phone','pie-chart','pin','plane','planet','plus-small','plus', 'pop-inside', 'previous','printer','qualify','radio-checked','radio-unchecked','refresh','relationship','remboursement','rename','repare','reply','restaurant','restore-straight','restore','right','rise','rotate-left','rotate-right','sad-cozy','safe','school','scooter','secutiry','select-all','send','server','setting','share-circle','share','shield','shield-infected','shield-clean','shop','sound','spinner','sport-bag','stack','star','star-outline','stats','stop', 'subway', 'support', 'swap', 'sync-cozy','sync','tab','tag','target','task','team','telecom','telephone','text','text-info','to-the-cloud','top','train','tram','trash','trophy', 'uncloud', 'unknow','unlink','unlock','up','upload','videos','walk','wallet-add','wallet-new','wallet','warn','warning-circle','warning','water','wrench-circle','work']
1023
+ const availableIcons = ['album-add','album-remove','album','answer','apple','archive','arrowUp', 'article', 'assign-admin','assign-moderator','attachment','attention','bank-check','bank','banking-add','banking','bell','benefit','bike','bill','bottom','browser-brave','browser-chrome','browser-duckduckgo','browser-edge','browser-edge-chromium','browser-firefox','browser-ie','browser-opera','browser-safari','burger','bus','calendar','camera','car','carbonCopy','carpooling','categories','certified','check-circle','check-list','check-square','check','checkbox','chess','child','circle-filled','clock','clock-outline','cloud-happy','cloud-rainbow','cloud-plus-outlined','cloud','cloud2','collect','cocktail','comment','company','compare','compass','connector','contract','contrast','copy','cozy-circle','cozy-laugh', 'cozy-lock', 'cozy-text', 'cozy-release', 'credit-card-add','credit-card','credit','crop','cross-circle-outline','cross-circle','cross-medium','cross-small','cross','cube','dash','dashboard','data-control','database','debit','desktop-download','devices','discuss','dots','down','download','drawing-arrow-up','dropdown-close','dropdown-open','dropdown','dropup','electric-bike','electric-car','electric-scooter','email-notification','email-open','email','eu','euro','exchange','expand','expert','export','eye-closed','eye','face-id','file-add','file-duotone','file-new','file-none','file-outline','file','filter','fingerprint','fitness','flag-outlined','flag','flash-auto','flashlight','folder-add','folder-moveto','folder-open','folder','forbidden','from-user','gear','globe','gouv','graph-circle','grid','group-list','groups','growth','hand','heart','help','help-outlined','history','home','hourglass','image','info-outlined','info','justice','key','key2','label-outlined','laudry','laptop','left','library','lightbulb','lightning','link-out','link','list','list-min','location','lock', 'lock-screen', 'logout','magic-trick','magnet','magnifier','matrix','merge','moped','mosaic','mosaic-min','motorcycle','mountain','movement-in','movement-out','mouvement','moveto','multi-files','music','narrow','new','next','note','notification-email','number','offline','online', 'openapp', 'openwith','palette','paper','paperplane','password','pen','people','peoples','percent-circle','percent','person-add','personal-data','phone-download','phone-upload','phone','pie-chart','pin','plane','planet','plus-small','plus', 'pop-inside', 'previous','printer','qualify','radio-checked','radio-unchecked','refresh','relationship','remboursement','rename','repare','reply','restaurant','restore-straight','restore','right','rise','rotate-left','rotate-right','sad-cozy','safe','school','scooter','secutiry','select-all','send','server','setting','share-circle','share','shield','shield-infected','shield-clean','shop','sound','spinner','sport-bag','stack','star','star-outline','stats','stop', 'subway', 'support', 'swap', 'sync-cozy','sync','tab','tag','target','task','team','telecom','telephone','text','text-info','to-the-cloud','top','train','tram','trash','trophy', 'uncloud', 'unknow','unlink','unlock','up','upload','videos','walk','wallet-add','wallet-new','wallet','warn','warning-circle','warning','water','wrench-circle','work']
1018
1024
  ;
1019
1025
 
1020
1026
  <Grid container spacing={2}>
@@ -0,0 +1,12 @@
1
+ // Automatically created, please run `scripts/generate-svgr-icon.sh assets/icons/ui/expand.svg` to regenerate;
2
+ import React from 'react'
3
+
4
+ function SvgExpand(props) {
5
+ return (
6
+ <svg viewBox="0 0 16 16" fill="none" {...props}>
7
+ <path d="M14.8 15.2a.8.8 0 00-.8-.8H2.8a.8.8 0 000 1.6H14a.8.8 0 00.8-.8zm0-14.4A.8.8 0 0014 0H2.8a.8.8 0 100 1.6H14a.8.8 0 00.8-.8zM6.893 9.833a.799.799 0 00-1.128 1.132l1.928 1.928a1 1 0 001.414 0l1.928-1.928a.799.799 0 00-1.128-1.132l-.707.703V5.464l.707.703a.799.799 0 001.128-1.132L9.107 3.107a1 1 0 00-1.414 0L5.765 5.035a.799.799 0 001.128 1.132l.707-.703v5.072l-.707-.703z" />
8
+ </svg>
9
+ )
10
+ }
11
+
12
+ export default SvgExpand
@@ -0,0 +1,13 @@
1
+ // Automatically created, please run `scripts/generate-svgr-icon.sh assets/icons/ui/export.svg` to regenerate;
2
+ import React from 'react'
3
+
4
+ function SvgExport(props) {
5
+ return (
6
+ <svg viewBox="0 0 16 16" fill="none" {...props}>
7
+ <path d="M14.8 4v10.4l-.008.159A1.6 1.6 0 0113.2 16H3.6a1.6 1.6 0 01-1.014-.362l-.117-.107a1.6 1.6 0 01-.461-.972L2 14.4V1.6c0-.372.13-.73.362-1.014L2.47.469A1.6 1.6 0 013.599 0h7.2l4 4zM3.6 14.4h9.6V5.6h-1.598a2.4 2.4 0 01-2.4-2.4V1.6H3.6v12.8zm7.202-11.2a.8.8 0 00.8.8h.935l-1.736-1.736V3.2z" />
8
+ <path d="M8.401 7.2a.8.8 0 01.8.799v2.867l1.034-1.032a.8.8 0 111.131 1.13l-2.4 2.401a.794.794 0 01-.436.222.817.817 0 01-.13.013.793.793 0 01-.127-.013.794.794 0 01-.438-.222l-2.4-2.4a.8.8 0 111.131-1.131l1.035 1.034V8a.8.8 0 01.8-.8z" />
9
+ </svg>
10
+ )
11
+ }
12
+
13
+ export default SvgExport
@@ -0,0 +1,16 @@
1
+ // Automatically created, please run `scripts/generate-svgr-icon.sh assets/icons/ui/narrow.svg` to regenerate;
2
+ import React from 'react'
3
+
4
+ function SvgNarrow(props) {
5
+ return (
6
+ <svg viewBox="0 0 16 16" fill="none" {...props}>
7
+ <path
8
+ fillRule="evenodd"
9
+ clipRule="evenodd"
10
+ d="M15.736.264a.9.9 0 010 1.274L12.07 5.204h2.027a.9.9 0 110 1.802H9.896a.9.9 0 01-.901-.9V1.901a.9.9 0 111.802 0V3.93L14.462.264a.9.9 0 011.274 0zM1 9.895a.9.9 0 01.902-.901h4.203a.9.9 0 01.901.9v4.204a.9.9 0 01-1.802 0V12.07l-3.666 3.667a.9.9 0 01-1.274-1.274l3.667-3.666H1.9a.9.9 0 01-.9-.901z"
11
+ />
12
+ </svg>
13
+ )
14
+ }
15
+
16
+ export default SvgNarrow
@@ -73,7 +73,7 @@ const columns = [
73
73
  }
74
74
  ]
75
75
 
76
- const initialVariants = [{ grouped: false }]
76
+ const initialVariants = [{ grouped: false, withCheckbox: true }, { grouped: false, withCheckbox: false }]
77
77
 
78
78
  // Very basic usage only works when Dessert is sorted "asc"
79
79
  // Ideally you have to create a logic to create groups with sorted data
@@ -98,6 +98,7 @@ const ExampleTable = ({ variant, ...props }) => {
98
98
  onSelect={(row, event, index) => toggleSelectedItem(row.id)}
99
99
  onSelectAll={rows => toggleSelectAllItems(rows.map(item => item.id))}
100
100
  onSortChange={onSortChange}
101
+ withCheckbox={variant.withCheckbox}
101
102
  componentsProps={{
102
103
  rowContent: {
103
104
  onClick: (row, column) => { console.info(`click on cell. Row ${row['id']}, Column ${column['id']}`) },
@@ -35,18 +35,20 @@ const FixedHeaderContent = ({
35
35
 
36
36
  return (
37
37
  <TableRow>
38
- <TableCell align="center" padding="checkbox">
39
- <Checkbox
40
- className={cx('virtualizedCheckbox', {
41
- checked: selectedCount > 0
42
- })}
43
- indeterminate={selectedCount > 0 && selectedCount < rowCount}
44
- checked={rowCount > 0 && selectedCount === rowCount}
45
- inputProps={{ 'aria-label': 'select all' }}
46
- size="small"
47
- onChange={onSelectAllClick}
48
- />
49
- </TableCell>
38
+ {context.withCheckbox && (
39
+ <TableCell align="center" padding="checkbox">
40
+ <Checkbox
41
+ className={cx('virtualizedCheckbox', {
42
+ checked: selectedCount > 0
43
+ })}
44
+ indeterminate={selectedCount > 0 && selectedCount < rowCount}
45
+ checked={rowCount > 0 && selectedCount === rowCount}
46
+ inputProps={{ 'aria-label': 'select all' }}
47
+ size="small"
48
+ onChange={onSelectAllClick}
49
+ />
50
+ </TableCell>
51
+ )}
50
52
  {columns.map(column => (
51
53
  <TableHeadCell
52
54
  key={column.id}
@@ -19,20 +19,22 @@ const RowContent = ({
19
19
 
20
20
  return (
21
21
  <>
22
- <TableCell align="center" padding="checkbox">
23
- <Checkbox
24
- className={cx('virtualizedCheckbox', {
25
- visible: selectedCount > 0,
26
- checked: context.isSelectedItem(row)
27
- })}
28
- checked={context.isSelectedItem(row)}
29
- inputProps={{
30
- 'aria-labelledby': `enhanced-table-checkbox-${index}`
31
- }}
32
- size="small"
33
- onClick={event => onSelectClick(row, event, index)}
34
- />
35
- </TableCell>
22
+ {context.withCheckbox && (
23
+ <TableCell align="center" padding="checkbox">
24
+ <Checkbox
25
+ className={cx('virtualizedCheckbox', {
26
+ visible: selectedCount > 0,
27
+ checked: context.isSelectedItem(row)
28
+ })}
29
+ checked={context.isSelectedItem(row)}
30
+ inputProps={{
31
+ 'aria-labelledby': `enhanced-table-checkbox-${index}`
32
+ }}
33
+ size="small"
34
+ onClick={event => onSelectClick(row, event, index)}
35
+ />
36
+ </TableCell>
37
+ )}
36
38
  {columns.map(column => (
37
39
  <Cell
38
40
  key={column.id}
@@ -7,12 +7,20 @@ const TableRow = ({ item, context, className, ...props }) => {
7
7
  const _item = item || context.data[props['data-item-index']]
8
8
  const isSelected = context.isSelectedItem(_item)
9
9
 
10
+ const handleClick = () => {
11
+ if (!context.withCheckbox && _item) {
12
+ const index = props['data-item-index']
13
+ context.onSelect?.(_item, null, index)
14
+ }
15
+ }
16
+
10
17
  return (
11
18
  <TableRowClassic
12
19
  {...props}
13
20
  className={cx(className, 'virtualized')}
14
21
  selected={isSelected}
15
22
  hover
23
+ onClick={!context.withCheckbox ? handleClick : props.onClick}
16
24
  />
17
25
  )
18
26
  }
@@ -25,6 +25,7 @@ const VirtualizedTable = forwardRef(
25
25
  components,
26
26
  onSortChange,
27
27
  isNewItem,
28
+ withCheckbox,
28
29
  ...props
29
30
  },
30
31
  ref
@@ -45,7 +46,9 @@ const VirtualizedTable = forwardRef(
45
46
  ...(isGroupedTable && { data }), // we use directly `data` prop if no groupCounts
46
47
  isSelectedItem,
47
48
  selectedItems,
48
- isNewItem
49
+ isNewItem,
50
+ withCheckbox,
51
+ onSelect
49
52
  }
50
53
 
51
54
  const handleSort = property => {
@@ -117,7 +120,8 @@ VirtualizedTable.defaultProps = {
117
120
  selectedItems: [],
118
121
  isSelectedItem: () => {},
119
122
  onSelect: () => {},
120
- onSelectAll: () => {}
123
+ onSelectAll: () => {},
124
+ withCheckbox: true
121
125
  }
122
126
 
123
127
  VirtualizedTable.propTypes = {
@@ -145,7 +149,9 @@ VirtualizedTable.propTypes = {
145
149
  /** Callback called after the sort */
146
150
  onSortChange: PropTypes.func,
147
151
  /** Function to determine if a row is new */
148
- isNewItem: PropTypes.func
152
+ isNewItem: PropTypes.func,
153
+ /** Whether to show checkboxes. When false, rows become clickable for selection */
154
+ withCheckbox: PropTypes.bool
149
155
  }
150
156
 
151
157
  export default VirtualizedTable
@@ -0,0 +1,13 @@
1
+ export function exportToText({ exportedText, file }: {
2
+ exportedText: any;
3
+ file: any;
4
+ }): {
5
+ name: string;
6
+ icon: typeof ExportIcon;
7
+ label: any;
8
+ displayCondition: () => boolean;
9
+ Component: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
10
+ action: () => Promise<void>;
11
+ };
12
+ import ExportIcon from "../../Icons/Export";
13
+ import React from "react";