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.
- package/CHANGELOG.md +14 -0
- package/assets/icons/ui/expand.svg +1 -0
- package/assets/icons/ui/export.svg +1 -0
- package/assets/icons/ui/narrow.svg +1 -0
- package/package.json +1 -1
- package/react/ActionsMenu/Actions/exportToText.js +54 -0
- package/react/ActionsMenu/Actions/helpers.js +20 -0
- package/react/ActionsMenu/Actions/index.js +1 -0
- package/react/ActionsMenu/Actions/locales/en.json +2 -1
- package/react/ActionsMenu/Actions/locales/fr.json +2 -1
- package/react/ActionsMenu/Actions/locales/ru.json +3 -2
- package/react/ActionsMenu/Actions/locales/vi.json +3 -2
- package/react/ActionsMenu/Actions/pdfHelpers.js +187 -0
- package/react/Icon/Readme.md +7 -1
- package/react/Icons/Expand.jsx +12 -0
- package/react/Icons/Export.jsx +13 -0
- package/react/Icons/Narrow.jsx +16 -0
- package/react/Table/Readme.md +2 -1
- package/react/Table/Virtualized/FixedHeaderContent.jsx +14 -12
- package/react/Table/Virtualized/RowContent.jsx +16 -14
- package/react/Table/Virtualized/TableRow.jsx +8 -0
- package/react/Table/Virtualized/index.jsx +9 -3
- package/transpiled/react/ActionsMenu/Actions/exportToText.d.ts +13 -0
- package/transpiled/react/ActionsMenu/Actions/exportToText.js +84 -0
- package/transpiled/react/ActionsMenu/Actions/helpers.d.ts +1 -0
- package/transpiled/react/ActionsMenu/Actions/helpers.js +20 -1
- package/transpiled/react/ActionsMenu/Actions/index.d.ts +1 -0
- package/transpiled/react/ActionsMenu/Actions/index.js +2 -1
- package/transpiled/react/ActionsMenu/Actions/locales/withActionsLocales.js +8 -4
- package/transpiled/react/ActionsMenu/Actions/pdfHelpers.d.ts +34 -0
- package/transpiled/react/ActionsMenu/Actions/pdfHelpers.js +242 -0
- package/transpiled/react/Icon/icons-sprite.d.ts +1 -1
- package/transpiled/react/Icon/icons-sprite.js +1 -1
- package/transpiled/react/Icons/Expand.d.ts +2 -0
- package/transpiled/react/Icons/Expand.js +14 -0
- package/transpiled/react/Icons/Export.d.ts +2 -0
- package/transpiled/react/Icons/Export.js +16 -0
- package/transpiled/react/Icons/Narrow.d.ts +2 -0
- package/transpiled/react/Icons/Narrow.js +16 -0
- package/transpiled/react/Table/Virtualized/FixedHeaderContent.js +1 -1
- package/transpiled/react/Table/Virtualized/RowContent.js +1 -1
- package/transpiled/react/Table/Virtualized/TableRow.js +12 -1
- 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
|
@@ -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
|
+
}
|
|
@@ -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
|
+
}
|
package/react/Icon/Readme.md
CHANGED
|
@@ -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
|
package/react/Table/Readme.md
CHANGED
|
@@ -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
|
-
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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";
|