@etsoo/react 1.5.74 → 1.5.77

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.
@@ -1,5 +1,4 @@
1
- import { IdLabelDto } from '@etsoo/appscript';
2
- import { Keyboard } from '@etsoo/shared';
1
+ import { DataTypes, Keyboard } from '@etsoo/shared';
3
2
  import { Autocomplete, AutocompleteRenderInputParams } from '@mui/material';
4
3
  import React from 'react';
5
4
  import { Utils as SharedUtils } from '@etsoo/shared';
@@ -11,8 +10,10 @@ import { ReactUtils } from '../app/ReactUtils';
11
10
  /**
12
11
  * ComboBox props
13
12
  */
14
- export interface ComboBoxProps<T extends {}>
15
- extends AutocompleteExtendedProps<T> {
13
+ export interface ComboBoxProps<
14
+ T extends {},
15
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
16
+ > extends AutocompleteExtendedProps<T, D> {
16
17
  /**
17
18
  * Auto add blank item
18
19
  */
@@ -26,7 +27,7 @@ export interface ComboBoxProps<T extends {}>
26
27
  /**
27
28
  * Label field
28
29
  */
29
- labelField?: string & keyof T;
30
+ labelField: T extends DataTypes.IdLabelItem ? D | undefined : D;
30
31
 
31
32
  /**
32
33
  * Load data callback
@@ -49,12 +50,15 @@ export interface ComboBoxProps<T extends {}>
49
50
  * @param props Props
50
51
  * @returns Component
51
52
  */
52
- export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
53
+ export function ComboBox<
54
+ T extends {} = DataTypes.IdLabelItem,
55
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
56
+ >(props: ComboBoxProps<T, D>) {
53
57
  // Destruct
54
58
  const {
55
59
  search = false,
56
60
  autoAddBlankItem = search,
57
- idField = 'id',
61
+ idField = 'id' as D,
58
62
  idValue,
59
63
  inputError,
60
64
  inputHelperText,
@@ -64,7 +68,7 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
64
68
  inputVariant,
65
69
  defaultValue,
66
70
  label,
67
- labelField = 'label',
71
+ labelField = 'label' as D,
68
72
  loadData,
69
73
  onLoadData,
70
74
  name,
@@ -75,7 +79,7 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
75
79
  onChange,
76
80
  openOnFocus = true,
77
81
  value,
78
- getOptionLabel = (option: T) => String(Reflect.get(option, labelField)),
82
+ getOptionLabel = (option: T) => `${option[labelField]}`,
79
83
  sx = { minWidth: '150px' },
80
84
  ...rest
81
85
  } = props;
@@ -97,7 +101,7 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
97
101
  // Local default value
98
102
  let localValue =
99
103
  idValue != null
100
- ? localOptions.find((o) => Reflect.get(o, idField) === idValue)
104
+ ? localOptions.find((o) => o[idField] === idValue)
101
105
  : defaultValue ?? value;
102
106
 
103
107
  if (localValue === undefined) localValue = null;
@@ -108,7 +112,7 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
108
112
 
109
113
  // Current id value
110
114
  // One time calculation for input's default value (uncontrolled)
111
- const localIdValue = stateValue && Reflect.get(stateValue, idField);
115
+ const localIdValue = stateValue && stateValue[idField];
112
116
 
113
117
  React.useEffect(() => {
114
118
  if (localValue != null) setStateValue(localValue);
@@ -147,8 +151,7 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
147
151
  const input = inputRef.current;
148
152
  if (input) {
149
153
  // Update value
150
- const newValue =
151
- value != null ? `${Reflect.get(value, idField)}` : '';
154
+ const newValue = value != null ? `${value[idField]}` : '';
152
155
 
153
156
  if (newValue !== input.value) {
154
157
  // Different value, trigger change event
@@ -186,7 +189,7 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
186
189
  type="text"
187
190
  style={{ display: 'none' }}
188
191
  name={name}
189
- value={localIdValue ?? ''}
192
+ value={`${localIdValue ?? ''}`}
190
193
  readOnly
191
194
  onChange={inputOnChange}
192
195
  />
@@ -195,7 +198,7 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
195
198
  value={stateValue}
196
199
  getOptionLabel={getOptionLabel}
197
200
  isOptionEqualToValue={(option: T, value: T) =>
198
- Reflect.get(option, idField) === Reflect.get(value, idField)
201
+ option[idField] === value[idField]
199
202
  }
200
203
  onChange={(event, value, reason, details) => {
201
204
  // Set value
@@ -1,5 +1,5 @@
1
1
  import { css } from '@emotion/css';
2
- import { Utils } from '@etsoo/shared';
2
+ import { DataTypes, Utils } from '@etsoo/shared';
3
3
  import {
4
4
  Box,
5
5
  BoxProps,
@@ -30,9 +30,7 @@ import { MouseEventWithDataHandler } from './MUGlobal';
30
30
  /**
31
31
  * Footer item renderer props
32
32
  */
33
- export interface DataGridExFooterItemRendererProps<
34
- T extends Record<string, any>
35
- > {
33
+ export interface DataGridExFooterItemRendererProps<T extends {}> {
36
34
  column: GridColumn<T>;
37
35
  index: number;
38
36
  states: GridLoaderStates<T>;
@@ -43,9 +41,11 @@ export interface DataGridExFooterItemRendererProps<
43
41
  /**
44
42
  * Extended DataGrid with VariableSizeGrid props
45
43
  */
46
- export interface DataGridExProps<T extends Record<string, any>>
47
- extends Omit<
48
- ScrollerGridProps<T>,
44
+ export interface DataGridExProps<
45
+ T extends {},
46
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
47
+ > extends Omit<
48
+ ScrollerGridProps<T, D>,
49
49
  'itemRenderer' | 'columnCount' | 'columnWidth' | 'width'
50
50
  > {
51
51
  /**
@@ -210,9 +210,10 @@ export function DataGridExCalColumns<T>(columns: GridColumn<T>[]) {
210
210
  * @param props Props
211
211
  * @returns Component
212
212
  */
213
- export function DataGridEx<T extends Record<string, any>>(
214
- props: DataGridExProps<T>
215
- ) {
213
+ export function DataGridEx<
214
+ T extends {},
215
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
216
+ >(props: DataGridExProps<T, D>) {
216
217
  // Theme
217
218
  const theme = useTheme();
218
219
 
@@ -360,7 +361,7 @@ export function DataGridEx<T extends Record<string, any>>(
360
361
  footerItemRenderer = DataGridRenderers.defaultFooterItemRenderer,
361
362
  hideFooter = false,
362
363
  hoverColor = '#f6f9fb',
363
- idField = 'id',
364
+ idField = 'id' as D,
364
365
  mRef = React.createRef(),
365
366
  onClick,
366
367
  onDoubleClick,
@@ -372,7 +373,7 @@ export function DataGridEx<T extends Record<string, any>>(
372
373
 
373
374
  if (checkable) {
374
375
  const cbColumn: GridColumn<T> = {
375
- field: 'selected',
376
+ field: 'selected' as any, // Avoid validation from data model
376
377
  header: '',
377
378
  sortable: false,
378
379
  width: 50,
@@ -1,10 +1,5 @@
1
1
  import { NumberUtils } from '@etsoo/shared';
2
- import {
3
- Breakpoint,
4
- ListItemButtonProps,
5
- ListItemProps,
6
- Theme
7
- } from '@mui/material';
2
+ import { Breakpoint, ListItemButtonProps, Theme } from '@mui/material';
8
3
  import { RLink } from './RLink';
9
4
 
10
5
  /**
@@ -1,4 +1,3 @@
1
- import { IdLabelDto } from '@etsoo/appscript';
2
1
  import { DataTypes, Utils } from '@etsoo/shared';
3
2
  import {
4
3
  Checkbox,
@@ -16,13 +15,13 @@ import React from 'react';
16
15
  * OptionGroup props
17
16
  */
18
17
  export interface OptionGroupProps<
19
- T extends Record<string, any> = IdLabelDto,
20
- D extends DataTypes.IdType = string
18
+ T extends {} = DataTypes.IdLabelItem,
19
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
21
20
  > extends Omit<FormControlProps<'fieldset'>, 'defaultValue'> {
22
21
  /**
23
22
  * Default value
24
23
  */
25
- defaultValue?: D | D[];
24
+ defaultValue?: T[D] | T[D][];
26
25
 
27
26
  /**
28
27
  * Get option label function
@@ -32,7 +31,7 @@ export interface OptionGroupProps<
32
31
  /**
33
32
  * Id field, default is id
34
33
  */
35
- idField?: string & keyof T;
34
+ idField: T extends DataTypes.IdLabelItem ? D | undefined : D;
36
35
 
37
36
  /**
38
37
  * Label
@@ -42,7 +41,7 @@ export interface OptionGroupProps<
42
41
  /**
43
42
  * Label field, default is label
44
43
  */
45
- labelField?: string & keyof T;
44
+ labelField: T extends DataTypes.IdLabelItem ? D | undefined : D;
46
45
 
47
46
  /**
48
47
  * Multiple choose item
@@ -57,7 +56,7 @@ export interface OptionGroupProps<
57
56
  /**
58
57
  * On value change handler
59
58
  */
60
- onValueChange?: (value: D | D[] | undefined) => void;
59
+ onValueChange?: (value: T[D] | T[D][] | undefined) => void;
61
60
 
62
61
  /**
63
62
  * Array of options.
@@ -81,16 +80,16 @@ export interface OptionGroupProps<
81
80
  * @returns Component
82
81
  */
83
82
  export function OptionGroup<
84
- T extends Record<string, unknown> = IdLabelDto,
85
- D extends DataTypes.IdType = string
83
+ T extends {} = DataTypes.IdLabelItem,
84
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
86
85
  >(props: OptionGroupProps<T, D>) {
87
86
  // Destruct
88
87
  const {
89
88
  getOptionLabel,
90
89
  defaultValue,
91
- idField = 'id',
90
+ idField = 'id' as D,
92
91
  label,
93
- labelField = 'label',
92
+ labelField = 'label' as D,
94
93
  multiple = false,
95
94
  name,
96
95
  onValueChange,
@@ -103,10 +102,10 @@ export function OptionGroup<
103
102
 
104
103
  // Get option value
105
104
  // D type should be the source id type
106
- const getOptionValue = (option: T): D | null => {
105
+ const getOptionValue = (option: T): T[D] | null => {
107
106
  const value = DataTypes.getValue(option, idField);
108
107
  if (value == null) return null;
109
- return value as D;
108
+ return value as T[D];
110
109
  };
111
110
 
112
111
  // Checkbox values
@@ -142,7 +141,7 @@ export function OptionGroup<
142
141
  onChange={(event) => {
143
142
  if (firstOptionValue == null) return;
144
143
 
145
- const typeValue = Utils.parseString<D>(
144
+ const typeValue = Utils.parseString(
146
145
  event.target.value,
147
146
  firstOptionValue
148
147
  );
@@ -175,7 +174,7 @@ export function OptionGroup<
175
174
 
176
175
  // Value, convert to string
177
176
  // Will fail when type is number
178
- const value = getOptionValue(option);
177
+ const value = getOptionValue(option) as unknown as React.Key;
179
178
 
180
179
  return (
181
180
  <FormControlLabel
@@ -197,7 +196,7 @@ export function OptionGroup<
197
196
  value={values[0]}
198
197
  onChange={(_event, value) => {
199
198
  if (firstOptionValue == null) return;
200
- const typeValue = Utils.parseString<D>(value, firstOptionValue);
199
+ const typeValue = Utils.parseString(value, firstOptionValue);
201
200
  if (onValueChange) onValueChange(typeValue);
202
201
  setValues([typeValue]);
203
202
  }}
@@ -32,9 +32,10 @@ import { SearchBar } from './SearchBar';
32
32
  */
33
33
  export interface ResponsibleContainerProps<
34
34
  T extends {},
35
- F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate
35
+ F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
36
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
36
37
  > extends Omit<
37
- DataGridExProps<T>,
38
+ DataGridExProps<T, D>,
38
39
  | 'height'
39
40
  | 'itemKey'
40
41
  | 'loadData'
@@ -163,8 +164,9 @@ function defaultContainerBoxSx(
163
164
  */
164
165
  export function ResponsibleContainer<
165
166
  T extends {},
166
- F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate
167
- >(props: ResponsibleContainerProps<T, F>) {
167
+ F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
168
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
169
+ >(props: ResponsibleContainerProps<T, F, D>) {
168
170
  // Destruct
169
171
  const {
170
172
  adjustHeight,
@@ -319,7 +321,7 @@ export function ResponsibleContainer<
319
321
 
320
322
  return [
321
323
  <Box className="ListBox" sx={{ height: heightLocal }}>
322
- <ScrollerListEx<T>
324
+ <ScrollerListEx<T, D>
323
325
  autoLoad={!hasFields}
324
326
  height={heightLocal}
325
327
  loadData={localLoadData}
@@ -117,8 +117,10 @@ export type ScrollerListExItemSize =
117
117
  /**
118
118
  * Extended ScrollerList Props
119
119
  */
120
- export interface ScrollerListExProps<T>
121
- extends Omit<ScrollerListProps<T>, 'itemRenderer' | 'itemSize'> {
120
+ export interface ScrollerListExProps<
121
+ T extends {},
122
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
123
+ > extends Omit<ScrollerListProps<T>, 'itemRenderer' | 'itemSize'> {
122
124
  /**
123
125
  * Alternating colors for odd/even rows
124
126
  */
@@ -127,7 +129,7 @@ export interface ScrollerListExProps<T>
127
129
  /**
128
130
  * Id field
129
131
  */
130
- idField?: string & keyof T;
132
+ idField?: D;
131
133
 
132
134
  /**
133
135
  * Inner item renderer
@@ -260,9 +262,10 @@ function defaultItemRenderer<T>({
260
262
  * @param props Props
261
263
  * @returns Component
262
264
  */
263
- export function ScrollerListEx<T extends Record<string, unknown>>(
264
- props: ScrollerListExProps<T>
265
- ) {
265
+ export function ScrollerListEx<
266
+ T extends {},
267
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
268
+ >(props: ScrollerListExProps<T, D>) {
266
269
  // Selected item ref
267
270
  const selectedItem = React.useRef<[HTMLDivElement, T]>();
268
271
 
@@ -295,11 +298,11 @@ export function ScrollerListEx<T extends Record<string, unknown>>(
295
298
  const {
296
299
  alternatingColors = [undefined, undefined],
297
300
  className,
298
- idField = 'id',
301
+ idField = 'id' as D,
299
302
  innerItemRenderer,
300
303
  itemSize,
301
304
  itemKey = (index: number, data: T) =>
302
- DataTypes.getValue(data, idField) ?? index,
305
+ DataTypes.getIdValue1(data, idField) ?? index,
303
306
  itemRenderer = (itemProps) => {
304
307
  const [itemHeight, space, margins] = calculateItemSize(
305
308
  itemProps.index
@@ -1,4 +1,3 @@
1
- import { IdLabelDto } from '@etsoo/appscript';
2
1
  import { DataTypes } from '@etsoo/shared';
3
2
  import React from 'react';
4
3
  import { MUGlobal } from './MUGlobal';
@@ -10,8 +9,8 @@ import { OptionGroup, OptionGroupProps } from './OptionGroup';
10
9
  * @returns Component
11
10
  */
12
11
  export function SearchOptionGroup<
13
- T extends Record<string, any> = IdLabelDto,
14
- D extends DataTypes.IdType = string
12
+ T extends {} = DataTypes.IdLabelItem,
13
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
15
14
  >(props: OptionGroupProps<T, D>) {
16
15
  // Destruct
17
16
  const {
@@ -1,5 +1,4 @@
1
- import { IdLabelDto } from '@etsoo/appscript';
2
- import { Utils } from '@etsoo/shared';
1
+ import { DataTypes, Utils } from '@etsoo/shared';
3
2
  import React from 'react';
4
3
  import { globalApp } from '..';
5
4
  import { SelectEx, SelectExProps } from './SelectEx';
@@ -8,7 +7,10 @@ import { SelectEx, SelectExProps } from './SelectEx';
8
7
  * SelectBool props
9
8
  */
10
9
  export interface SelectBoolProps
11
- extends Omit<SelectExProps<IdLabelDto<string>>, 'options' | 'loadData'> {}
10
+ extends Omit<
11
+ SelectExProps<DataTypes.IdLabelItem<string>>,
12
+ 'options' | 'loadData'
13
+ > {}
12
14
 
13
15
  /**
14
16
  * SelectBool (yes/no)
@@ -20,7 +22,7 @@ export function SelectBool(props: SelectBoolProps) {
20
22
  const { search = true, autoAddBlankItem = search, ...rest } = props;
21
23
 
22
24
  // Options
23
- const options: IdLabelDto<string>[] = [
25
+ const options: DataTypes.IdLabelItem<string>[] = [
24
26
  { id: 'false', label: globalApp.get('no')! },
25
27
  { id: 'true', label: globalApp.get('yes')! }
26
28
  ];
@@ -28,5 +30,11 @@ export function SelectBool(props: SelectBoolProps) {
28
30
  if (autoAddBlankItem) Utils.addBlankItem(options);
29
31
 
30
32
  // Layout
31
- return <SelectEx options={options} search={search} {...rest} />;
33
+ return (
34
+ <SelectEx<DataTypes.IdLabelItem<string>>
35
+ options={options}
36
+ search={search}
37
+ {...rest}
38
+ />
39
+ );
32
40
  }
@@ -11,25 +11,26 @@ import {
11
11
  } from '@mui/material';
12
12
  import React from 'react';
13
13
  import { MUGlobal } from './MUGlobal';
14
- import { IdLabelDto } from '@etsoo/appscript';
15
14
  import { ListItemRightIcon } from './ListItemRightIcon';
16
- import { Utils } from '@etsoo/shared';
15
+ import { DataTypes, Utils } from '@etsoo/shared';
17
16
  import { ReactUtils } from '../app/ReactUtils';
18
17
 
19
18
  /**
20
19
  * Extended select component props
21
20
  */
22
- export interface SelectExProps<T extends {}>
23
- extends Omit<SelectProps, 'labelId' | 'input' | 'native'> {
21
+ export interface SelectExProps<
22
+ T extends {},
23
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
24
+ > extends Omit<SelectProps, 'labelId' | 'input' | 'native'> {
24
25
  /**
25
26
  * Auto add blank item
26
27
  */
27
28
  autoAddBlankItem?: boolean;
28
29
 
29
30
  /**
30
- * Id field, default is id
31
+ * Id field
31
32
  */
32
- idField?: string & keyof T;
33
+ idField: T extends DataTypes.IdLabelItem ? D | undefined : D;
33
34
 
34
35
  /**
35
36
  * Item icon renderer
@@ -37,9 +38,11 @@ export interface SelectExProps<T extends {}>
37
38
  itemIconRenderer?: (id: unknown) => React.ReactNode;
38
39
 
39
40
  /**
40
- * Label field, default is label
41
+ * Label field
41
42
  */
42
- labelField?: ((option: T) => string) | (string & keyof T);
43
+ labelField:
44
+ | ((option: T) => string)
45
+ | (T extends DataTypes.IdLabelItem ? D | undefined : D);
43
46
 
44
47
  /**
45
48
  * Load data callback
@@ -72,14 +75,17 @@ export interface SelectExProps<T extends {}>
72
75
  * @param props Props
73
76
  * @returns Component
74
77
  */
75
- export function SelectEx<T extends {} = IdLabelDto>(props: SelectExProps<T>) {
78
+ export function SelectEx<
79
+ T extends {} = DataTypes.IdLabelItem,
80
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
81
+ >(props: SelectExProps<T, D>) {
76
82
  // Destruct
77
83
  const {
78
84
  defaultValue,
79
- idField = 'id',
85
+ idField = 'id' as D,
80
86
  itemIconRenderer,
81
87
  label,
82
- labelField = 'label',
88
+ labelField = 'label' as D,
83
89
  loadData,
84
90
  onItemClick,
85
91
  onLoadData,
@@ -153,14 +159,14 @@ export function SelectEx<T extends {} = IdLabelDto>(props: SelectExProps<T>) {
153
159
 
154
160
  // Get option id
155
161
  const getId = (option: T) => {
156
- return Reflect.get(option, idField);
162
+ return option[idField] as unknown as React.Key;
157
163
  };
158
164
 
159
165
  // Get option label
160
166
  const getLabel = (option: T) => {
161
167
  return typeof labelField === 'function'
162
168
  ? labelField(option)
163
- : Reflect.get(option, labelField);
169
+ : new String(option[labelField]);
164
170
  };
165
171
 
166
172
  // Refs
@@ -47,8 +47,10 @@ export interface TableExMethodRef extends GridMethodRef {
47
47
  /**
48
48
  * Extended table props
49
49
  */
50
- export interface TableExProps<T extends Record<string, any>>
51
- extends TableProps,
50
+ export interface TableExProps<
51
+ T extends {},
52
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
53
+ > extends TableProps,
52
54
  GridLoader<T> {
53
55
  /**
54
56
  * Alternating colors for odd/even rows
@@ -68,7 +70,7 @@ export interface TableExProps<T extends Record<string, any>>
68
70
  /**
69
71
  * Id field
70
72
  */
71
- idField?: string & keyof T;
73
+ idField?: D;
72
74
 
73
75
  /**
74
76
  * Max height
@@ -101,14 +103,13 @@ export interface TableExProps<T extends Record<string, any>>
101
103
  * @param props Props
102
104
  * @returns Component
103
105
  */
104
- export function TableEx<T extends Record<string, unknown>>(
105
- props: TableExProps<T>
106
- ) {
106
+ export function TableEx<
107
+ T extends {},
108
+ D extends DataTypes.Keys<T> = DataTypes.Keys<T>
109
+ >(props: TableExProps<T, D>) {
107
110
  // Theme
108
111
  const theme = useTheme();
109
112
 
110
- type keyType = string & keyof T;
111
-
112
113
  // Destruct
113
114
  const {
114
115
  alternatingColors = [theme.palette.action.hover, undefined],
@@ -116,7 +117,7 @@ export function TableEx<T extends Record<string, unknown>>(
116
117
  columns,
117
118
  defaultOrderBy,
118
119
  headerColors = [undefined, undefined],
119
- idField = 'id' as keyType,
120
+ idField = 'id' as D,
120
121
  loadBatchSize,
121
122
  loadData,
122
123
  maxHeight,
@@ -451,7 +452,10 @@ export function TableEx<T extends Record<string, unknown>>(
451
452
  : false;
452
453
 
453
454
  return (
454
- <TableRow key={rowId} selected={isItemSelected}>
455
+ <TableRow
456
+ key={rowId as unknown as React.Key}
457
+ selected={isItemSelected}
458
+ >
455
459
  {selectable && (
456
460
  <TableCell padding="checkbox">
457
461
  {row && (
@@ -522,10 +526,7 @@ export function TableEx<T extends Record<string, unknown>>(
522
526
 
523
527
  return (
524
528
  <TableCell
525
- key={
526
- rowId.toString() +
527
- columnIndex
528
- }
529
+ key={`${rowId}${columnIndex}`}
529
530
  {...cellProps}
530
531
  >
531
532
  {child}