cozy-ui 142.3.0 → 143.0.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 CHANGED
@@ -1,3 +1,32 @@
1
+ # [143.0.0](https://github.com/cozy/cozy-ui/compare/v142.3.1...v143.0.0) (2026-10-15)
2
+
3
+
4
+ ### Code Refactoring
5
+
6
+ * **Table:** Remove secondarySort from VirtualizedTable ([772c5f7](https://github.com/cozy/cozy-ui/commit/772c5f7))
7
+
8
+
9
+ ### Features
10
+
11
+ * **Table:** Add sortingMode to VirtualizedTable ([2413bd5](https://github.com/cozy/cozy-ui/commit/2413bd5))
12
+
13
+
14
+ ### BREAKING CHANGES
15
+
16
+ * **Table:** VirtualizedTable no longer takes secondarySort. Sort
17
+ the rows, secondary order included, before passing them (stableSort
18
+ and getComparator are in cozy-ui/transpiled/react/Table/Virtualized/helpers),
19
+ and set sortingMode="server" so that the table keeps their order.
20
+
21
+ Assisted-by: LLM
22
+
23
+ ## [142.3.1](https://github.com/cozy/cozy-ui/compare/v142.3.0...v142.3.1) (2026-10-13)
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * **Badge:** Draw counts as a pill ([5e0875c](https://github.com/cozy/cozy-ui/commit/5e0875c))
29
+
1
30
  # [142.3.0](https://github.com/cozy/cozy-ui/compare/v142.2.3...v142.3.0) (2026-10-06)
2
31
 
3
32
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "142.3.0",
3
+ "version": "143.0.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "engines": {
6
6
  "node": "24.x"
@@ -56,6 +56,32 @@ const DemoBadge = ({ variant, ...props }) => {
56
56
  </Variants>
57
57
  ```
58
58
 
59
+ ### Counts
60
+
61
+ One or two digits sit in a circle, longer counts in a pill.
62
+
63
+ ```jsx
64
+ import Badge from 'cozy-ui/transpiled/react/Badge'
65
+ import { CircleFilled, Icon } from '@linagora/twake-icons'
66
+
67
+ ;
68
+
69
+ <>
70
+ {[1, 12, 44, 99, 120].map(count => (
71
+ <Badge
72
+ key={count}
73
+ className="u-m-1"
74
+ badgeContent={count}
75
+ max={99}
76
+ color="primary"
77
+ size="medium"
78
+ >
79
+ <Icon icon={CircleFilled} size="24" color="var(--iconTextColor)" />
80
+ </Badge>
81
+ ))}
82
+ </>
83
+ ```
84
+
59
85
  ### Double badges
60
86
 
61
87
  Badges can be combined — in this example, we have an item with a new qualification.
@@ -1047,7 +1047,9 @@ export const makeLightOverrides = theme => ({
1047
1047
  badge: {
1048
1048
  boxSizing: 'content-box',
1049
1049
  padding: 0,
1050
- borderRadius: '100%',
1050
+ borderRadius: 100,
1051
+ // Every two-digit count fits the circle, longer counts grow into a pill
1052
+ fontVariantNumeric: 'tabular-nums',
1051
1053
  '&.badgeBorder': {
1052
1054
  border: `2px solid ${theme.palette.background.paper}`
1053
1055
  },
@@ -252,3 +252,51 @@ const DndExample = () => {
252
252
  </SelectionProvider>
253
253
  </DemoProvider>
254
254
  ```
255
+
256
+ ### With rows sorted by the caller
257
+
258
+ With `sortingMode="server"`, the table keeps the rows in the given order, e.g. paged from a server: the headers still change the sort and call `onSortChange`, for the caller to sort the rows. With `sortingMode="client"`, the default, the table sorts them.
259
+
260
+ ```jsx
261
+ import { useState } from 'react'
262
+ import VirtualizedTable from 'cozy-ui/transpiled/react/Table/Virtualized'
263
+ import { getComparator, stableSort } from 'cozy-ui/transpiled/react/Table/Virtualized/helpers'
264
+ import DemoProvider from 'cozy-ui/docs/components/DemoProvider'
265
+
266
+ const rows = [
267
+ { id: 0, name: 'Cupcake', calories: 305 },
268
+ { id: 1, name: 'Donut', calories: 452 },
269
+ { id: 2, name: 'Eclair', calories: 262 },
270
+ { id: 3, name: 'Gingerbread', calories: 356 },
271
+ { id: 4, name: 'Honeycomb', calories: 408 }
272
+ ]
273
+
274
+ const columns = [
275
+ { id: 'name', label: 'Dessert', width: 300 },
276
+ { id: 'calories', label: 'Calories', width: 80, textAlign: 'right' }
277
+ ]
278
+
279
+ // The caller sorts the rows, as a server would, and the table keeps their order
280
+ const SortedByCallerTable = () => {
281
+ const [sortedRows, setSortedRows] = useState(rows)
282
+
283
+ return (
284
+ <VirtualizedTable
285
+ rows={sortedRows}
286
+ columns={columns}
287
+ sortingMode="server"
288
+ onSortChange={({ order, orderBy }) =>
289
+ setSortedRows(stableSort(rows, getComparator(order, orderBy)))
290
+ }
291
+ />
292
+ )
293
+ }
294
+
295
+ ;
296
+
297
+ <DemoProvider>
298
+ <div style={{ border: "1px solid var(--borderMainColor)", height: 300, width: "100%" }}>
299
+ <SortedByCallerTable />
300
+ </div>
301
+ </DemoProvider>
302
+ ```
@@ -17,7 +17,7 @@ const VirtualizedTable = forwardRef(
17
17
  columns,
18
18
  groups,
19
19
  defaultOrder,
20
- secondarySort,
20
+ sortingMode,
21
21
  selectedItems,
22
22
  isSelectedItem,
23
23
  componentsProps,
@@ -34,12 +34,13 @@ const VirtualizedTable = forwardRef(
34
34
  )
35
35
  const [orderBy, setOrderBy] = useState(defaultOrder?.by ?? undefined)
36
36
 
37
- const data = useMemo(() => {
38
- const sortedData = orderBy
39
- ? stableSort(rows, getComparator(orderDirection, orderBy))
40
- : rows
41
- return secondarySort ? secondarySort(sortedData) : sortedData
42
- }, [rows, orderBy, orderDirection, secondarySort])
37
+ const data = useMemo(
38
+ () =>
39
+ orderBy && sortingMode === 'client'
40
+ ? stableSort(rows, getComparator(orderDirection, orderBy))
41
+ : rows,
42
+ [rows, orderBy, orderDirection, sortingMode]
43
+ )
43
44
  const { groupLabels, groupCounts } = groups?.(data) || {}
44
45
  const isGroupedTable = !!groupCounts
45
46
  const _context = {
@@ -105,6 +106,7 @@ const VirtualizedTable = forwardRef(
105
106
  VirtualizedTable.displayName = 'VirtualizedTable'
106
107
 
107
108
  VirtualizedTable.defaultProps = {
109
+ sortingMode: 'client',
108
110
  selectedItems: [],
109
111
  isSelectedItem: () => {}
110
112
  }
@@ -116,19 +118,19 @@ VirtualizedTable.propTypes = {
116
118
  columns: PropTypes.array,
117
119
  /** Returned object is: PropTypes.shape({ groupLabels: PropTypes.array, groupCounts: PropTypes.array }) */
118
120
  groups: PropTypes.func,
119
- /** Default sorting configuration */
121
+ /** Column sorted at first: without it, no column is sorted until one is clicked */
120
122
  defaultOrder: PropTypes.shape({
121
123
  direction: PropTypes.oneOf(['asc', 'desc']),
122
124
  by: PropTypes.string
123
125
  }),
126
+ /** Who sorts the rows. 'server': the table keeps the given order, its headers changing the sort and calling onSortChange for the caller to sort them, e.g. on its server. 'client': the table sorts them by the sorted column */
127
+ sortingMode: PropTypes.oneOf(['client', 'server']),
124
128
  /** Context object passed down to children and virtuoso */
125
129
  context: PropTypes.object,
126
130
  /** Props passed to child components */
127
131
  componentsProps: PropTypes.object,
128
132
  /** Custom components used by react-virtuoso */
129
133
  components: PropTypes.object,
130
- /** Sort files by type to put directory and trash before files */
131
- secondarySort: PropTypes.func,
132
134
  /** Array of selected items */
133
135
  selectedItems: PropTypes.array,
134
136
  /** Function to determine if a row is selected */
@@ -1065,7 +1065,8 @@ export function makeDarkOverrides(theme: any): {
1065
1065
  badge: {
1066
1066
  boxSizing: string;
1067
1067
  padding: number;
1068
- borderRadius: string;
1068
+ borderRadius: number;
1069
+ fontVariantNumeric: string;
1069
1070
  '&.badgeBorder': {
1070
1071
  border: string;
1071
1072
  };
@@ -1065,7 +1065,8 @@ export function makeLightOverrides(theme: any): {
1065
1065
  badge: {
1066
1066
  boxSizing: string;
1067
1067
  padding: number;
1068
- borderRadius: string;
1068
+ borderRadius: number;
1069
+ fontVariantNumeric: string;
1069
1070
  '&.badgeBorder': {
1070
1071
  border: string;
1071
1072
  };
@@ -990,7 +990,9 @@ export var makeLightOverrides = function makeLightOverrides(theme) {
990
990
  badge: {
991
991
  boxSizing: 'content-box',
992
992
  padding: 0,
993
- borderRadius: '100%',
993
+ borderRadius: 100,
994
+ // Every two-digit count fits the circle, longer counts grow into a pill
995
+ fontVariantNumeric: 'tabular-nums',
994
996
  '&.badgeBorder': {
995
997
  border: "2px solid ".concat(theme.palette.background.paper)
996
998
  },
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/extends";
2
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
3
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
4
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
5
- var _excluded = ["rows", "columns", "groups", "defaultOrder", "secondarySort", "selectedItems", "isSelectedItem", "componentsProps", "context", "components", "onSortChange", "isNewItem"];
5
+ var _excluded = ["rows", "columns", "groups", "defaultOrder", "sortingMode", "selectedItems", "isSelectedItem", "componentsProps", "context", "components", "onSortChange", "isNewItem"];
6
6
 
7
7
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
8
8
 
@@ -24,7 +24,7 @@ var VirtualizedTable = /*#__PURE__*/forwardRef(function (_ref, ref) {
24
24
  columns = _ref.columns,
25
25
  groups = _ref.groups,
26
26
  defaultOrder = _ref.defaultOrder,
27
- secondarySort = _ref.secondarySort,
27
+ sortingMode = _ref.sortingMode,
28
28
  selectedItems = _ref.selectedItems,
29
29
  isSelectedItem = _ref.isSelectedItem,
30
30
  componentsProps = _ref.componentsProps,
@@ -45,9 +45,8 @@ var VirtualizedTable = /*#__PURE__*/forwardRef(function (_ref, ref) {
45
45
  setOrderBy = _useState4[1];
46
46
 
47
47
  var data = useMemo(function () {
48
- var sortedData = orderBy ? stableSort(rows, getComparator(orderDirection, orderBy)) : rows;
49
- return secondarySort ? secondarySort(sortedData) : sortedData;
50
- }, [rows, orderBy, orderDirection, secondarySort]);
48
+ return orderBy && sortingMode === 'client' ? stableSort(rows, getComparator(orderDirection, orderBy)) : rows;
49
+ }, [rows, orderBy, orderDirection, sortingMode]);
51
50
 
52
51
  var _ref2 = (groups === null || groups === void 0 ? void 0 : groups(data)) || {},
53
52
  groupLabels = _ref2.groupLabels,
@@ -114,6 +113,7 @@ var VirtualizedTable = /*#__PURE__*/forwardRef(function (_ref, ref) {
114
113
  });
115
114
  VirtualizedTable.displayName = 'VirtualizedTable';
116
115
  VirtualizedTable.defaultProps = {
116
+ sortingMode: 'client',
117
117
  selectedItems: [],
118
118
  isSelectedItem: function isSelectedItem() {}
119
119
  };
@@ -127,12 +127,15 @@ VirtualizedTable.propTypes = {
127
127
  /** Returned object is: PropTypes.shape({ groupLabels: PropTypes.array, groupCounts: PropTypes.array }) */
128
128
  groups: PropTypes.func,
129
129
 
130
- /** Default sorting configuration */
130
+ /** Column sorted at first: without it, no column is sorted until one is clicked */
131
131
  defaultOrder: PropTypes.shape({
132
132
  direction: PropTypes.oneOf(['asc', 'desc']),
133
133
  by: PropTypes.string
134
134
  }),
135
135
 
136
+ /** Who sorts the rows. 'server': the table keeps the given order, its headers changing the sort and calling onSortChange for the caller to sort them, e.g. on its server. 'client': the table sorts them by the sorted column */
137
+ sortingMode: PropTypes.oneOf(['client', 'server']),
138
+
136
139
  /** Context object passed down to children and virtuoso */
137
140
  context: PropTypes.object,
138
141
 
@@ -142,9 +145,6 @@ VirtualizedTable.propTypes = {
142
145
  /** Custom components used by react-virtuoso */
143
146
  components: PropTypes.object,
144
147
 
145
- /** Sort files by type to put directory and trash before files */
146
- secondarySort: PropTypes.func,
147
-
148
148
  /** Array of selected items */
149
149
  selectedItems: PropTypes.array,
150
150