@iobroker/json-config 7.4.13 → 7.4.15

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/README.md CHANGED
@@ -1434,5 +1434,8 @@ The following variables are available in JS function in custom settings:
1434
1434
 
1435
1435
  You can find examples in [`telegram`](https://github.com/iobroker-community-adapters/ioBroker.telegram/tree/master/src-admin) or in [`pushbullet`](https://github.com/Jens1809/ioBroker.pushbullet/tree/master/src-admin) adapter.
1436
1436
 
1437
+ ## Report a schema error
1438
+ Create an issue here: https://github.com/ioBroker/adapter-react-v5/issues
1439
+
1437
1440
  ## For maintainer
1438
1441
  To update location of JsonConfig schema, create pull request to this file: https://github.com/SchemaStore/schemastore/blob/master/src/api/json/catalog.json
@@ -1,5 +1,5 @@
1
1
  import React, { type JSX } from 'react';
2
- import type { ConfigItemTable } from '#JC/types';
2
+ import type { ConfigItemTableIndexed, ConfigItemTable } from '#JC/types';
3
3
  import ConfigGeneric, { type ConfigGenericProps, type ConfigGenericState } from './ConfigGeneric';
4
4
  interface ConfigTableProps extends ConfigGenericProps {
5
5
  schema: ConfigItemTable;
@@ -18,11 +18,14 @@ interface ConfigTableState extends ConfigGenericState {
18
18
  customObj: Record<string, any>;
19
19
  uploadFile: boolean | 'dragging';
20
20
  icon: boolean;
21
+ width: number;
21
22
  }
22
23
  declare class ConfigTable extends ConfigGeneric<ConfigTableProps, ConfigTableState> {
23
24
  private readonly filterRefs;
24
25
  private typingTimer;
26
+ private resizeTimeout;
25
27
  private secret;
28
+ private readonly refDiv;
26
29
  constructor(props: ConfigTableProps);
27
30
  /**
28
31
  * React lifecycle hook, called once as component is mounted
@@ -40,6 +43,9 @@ declare class ConfigTable extends ConfigGeneric<ConfigTableProps, ConfigTableSta
40
43
  static setFilterValue(el: React.RefObject<HTMLInputElement>, filterValue: string): string;
41
44
  handleRequestSort: (property: string, orderCheck?: boolean) => void;
42
45
  stableSort: (order: 'desc' | 'asc', orderBy: string) => Record<string, any>[];
46
+ renderShowHideFilter(headCell: ConfigItemTableIndexed): React.JSX.Element | null;
47
+ renderImportExportButtons(schema: ConfigItemTable): React.JSX.Element;
48
+ renderAddButton(doAnyFilterSet: boolean): React.JSX.Element;
43
49
  enhancedTableHead(buttonsWidth: number, doAnyFilterSet: boolean): JSX.Element;
44
50
  onDelete: (index: number) => () => void;
45
51
  onExport(): void;
@@ -54,6 +60,22 @@ declare class ConfigTable extends ConfigGeneric<ConfigTableProps, ConfigTableSta
54
60
  onDrop(acceptedFiles: File[]): void;
55
61
  showTypeOfImportDialog(): JSX.Element | null;
56
62
  showImportDialog(): JSX.Element | null;
63
+ renderOneFilter(props: {
64
+ schema: ConfigItemTable;
65
+ doAnyFilterSet: boolean;
66
+ headCell: ConfigItemTableIndexed;
67
+ index: number;
68
+ orderBy: string;
69
+ order: 'asc' | 'desc';
70
+ showAddButton: boolean;
71
+ style: React.CSSProperties;
72
+ }): React.JSX.Element;
73
+ enhancedFilterCard(): JSX.Element;
74
+ enhancedBottomCard(): JSX.Element;
75
+ renderCards(): JSX.Element | null;
76
+ renderTable(): JSX.Element | null;
77
+ componentDidUpdate(): void;
78
+ getCurrentBreakpoint(): 'xs' | 'sm' | 'md' | 'lg' | 'xl';
57
79
  renderItem(): JSX.Element | null;
58
80
  }
59
81
  export default ConfigTable;
@@ -1,7 +1,7 @@
1
1
  import React, { createRef } from 'react';
2
2
  import Dropzone from 'react-dropzone';
3
- import { Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, InputAdornment, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TableSortLabel, TextField, Toolbar, Tooltip, Typography, FormHelperText, } from '@mui/material';
4
- import { Add as AddIcon, Delete as DeleteIcon, Close as CloseIcon, ArrowUpward as UpIcon, ArrowDownward as DownIcon, FilterAlt as IconFilterOn, FilterAltOff as IconFilterOff, ContentCopy as CopyContentIcon, Download as ExportIcon, Warning as ErrorIcon, UploadFile as ImportIcon, Close as IconClose, } from '@mui/icons-material';
3
+ import { Accordion, AccordionDetails, AccordionSummary, Button, Card, Dialog, DialogActions, DialogContent, DialogTitle, Grid2, IconButton, InputAdornment, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TableSortLabel, TextField, Toolbar, Tooltip, Typography, FormHelperText, } from '@mui/material';
4
+ import { Add as AddIcon, Delete as DeleteIcon, Close as CloseIcon, ArrowUpward as UpIcon, ArrowDownward as DownIcon, FilterAlt as IconFilterOn, FilterAltOff as IconFilterOff, ContentCopy as CopyContentIcon, Download as ExportIcon, Warning as ErrorIcon, UploadFile as ImportIcon, Close as IconClose, ExpandMore as ExpandMoreIcon, } from '@mui/icons-material';
5
5
  import { I18n } from '@iobroker/adapter-react-v5';
6
6
  import ConfigGeneric from './ConfigGeneric';
7
7
  import ConfigPanel from './ConfigPanel';
@@ -194,7 +194,9 @@ function decrypt(secret, value) {
194
194
  class ConfigTable extends ConfigGeneric {
195
195
  filterRefs;
196
196
  typingTimer = null;
197
+ resizeTimeout = null;
197
198
  secret = 'Zgfr56gFe87jJOM';
199
+ refDiv;
198
200
  constructor(props) {
199
201
  super(props);
200
202
  this.filterRefs = {};
@@ -204,6 +206,7 @@ class ConfigTable extends ConfigGeneric {
204
206
  this.filterRefs[el.attr] = createRef();
205
207
  }
206
208
  });
209
+ this.refDiv = React.createRef();
207
210
  }
208
211
  /**
209
212
  * React lifecycle hook, called once as component is mounted
@@ -240,6 +243,7 @@ class ConfigTable extends ConfigGeneric {
240
243
  order: 'asc',
241
244
  iteration: 0,
242
245
  filterOn: [],
246
+ width: 0,
243
247
  }, () => this.validateUniqueProps());
244
248
  }
245
249
  componentWillUnmount() {
@@ -247,6 +251,10 @@ class ConfigTable extends ConfigGeneric {
247
251
  clearTimeout(this.typingTimer);
248
252
  this.typingTimer = null;
249
253
  }
254
+ if (this.resizeTimeout) {
255
+ clearTimeout(this.resizeTimeout);
256
+ this.resizeTimeout = null;
257
+ }
250
258
  super.componentWillUnmount();
251
259
  }
252
260
  itemTable(attrItem, data, idx) {
@@ -318,12 +326,12 @@ class ConfigTable extends ConfigGeneric {
318
326
  }
319
327
  handleRequestSort = (property, orderCheck = false) => {
320
328
  const { order, orderBy } = this.state;
321
- if (orderBy) {
322
- const isAsc = orderBy === property && order === 'asc';
323
- const newOrder = orderCheck ? order : isAsc ? 'desc' : 'asc';
324
- const newValue = this.stableSort(newOrder, property);
325
- this.setState({ order: newOrder, orderBy: property, iteration: this.state.iteration + 10000 }, () => this.applyFilter(false, newValue));
326
- }
329
+ //if (orderBy || 'asc') {
330
+ const isAsc = orderBy === property && order === 'asc';
331
+ const newOrder = orderCheck ? order : isAsc ? 'desc' : 'asc';
332
+ const newValue = this.stableSort(newOrder, property);
333
+ this.setState({ value: newValue, order: newOrder, orderBy: property, iteration: this.state.iteration + 10000 }, () => this.applyFilter(false, newValue));
334
+ //}
327
335
  };
328
336
  stableSort = (order, orderBy) => {
329
337
  const { value } = this.state;
@@ -338,67 +346,65 @@ class ConfigTable extends ConfigGeneric {
338
346
  });
339
347
  return stabilizedThis.map(el => el.el);
340
348
  };
349
+ renderShowHideFilter(headCell) {
350
+ if (!headCell.filter) {
351
+ return null;
352
+ }
353
+ return (React.createElement(IconButton, { title: I18n.t('ra_Show/hide filter input'), size: "small", onClick: () => {
354
+ const filterOn = [...this.state.filterOn];
355
+ const pos = this.state.filterOn.indexOf(headCell.attr);
356
+ if (pos === -1) {
357
+ filterOn.push(headCell.attr);
358
+ }
359
+ else {
360
+ filterOn.splice(pos, 1);
361
+ }
362
+ this.setState({ filterOn }, () => {
363
+ if (pos && ConfigTable.getFilterValue(this.filterRefs[headCell.attr])) {
364
+ ConfigTable.setFilterValue(this.filterRefs[headCell.attr], '');
365
+ this.applyFilter();
366
+ }
367
+ });
368
+ } }, this.state.filterOn.includes(headCell.attr) ? React.createElement(IconFilterOff, null) : React.createElement(IconFilterOn, null)));
369
+ }
370
+ renderImportExportButtons(schema) {
371
+ return (React.createElement(React.Fragment, null,
372
+ !schema.noDelete && schema.import ? (React.createElement(Tooltip, { title: I18n.t('ra_Import data from %s file', 'CSV'), slotProps: { popper: { sx: styles.tooltip } } },
373
+ React.createElement(IconButton, { size: "small", onClick: () => this.setState({ showImportDialog: true }) },
374
+ React.createElement(ImportIcon, null)))) : null,
375
+ schema.export ? (React.createElement(Tooltip, { title: I18n.t('ra_Export data to %s file', 'CSV'), slotProps: { popper: { sx: styles.tooltip } } },
376
+ React.createElement(IconButton, { size: "small", onClick: () => this.onExport() },
377
+ React.createElement(ExportIcon, null)))) : null,
378
+ React.createElement(IconButton, { disabled: true, size: "small" },
379
+ React.createElement(DeleteIcon, null))));
380
+ }
381
+ renderAddButton(doAnyFilterSet) {
382
+ return (React.createElement(Tooltip, { title: doAnyFilterSet ? I18n.t('ra_Cannot add items with set filter') : I18n.t('ra_Add row'), slotProps: { popper: { sx: styles.tooltip } } },
383
+ React.createElement("span", null,
384
+ React.createElement(IconButton, { size: "small", color: "primary", disabled: !!doAnyFilterSet && !this.props.schema.allowAddByFilter, onClick: this.onAdd },
385
+ React.createElement(AddIcon, null)))));
386
+ }
341
387
  enhancedTableHead(buttonsWidth, doAnyFilterSet) {
342
388
  const { schema } = this.props;
343
389
  const { order, orderBy } = this.state;
344
390
  return (React.createElement(TableHead, null,
345
391
  React.createElement(TableRow, null,
346
- schema.items &&
347
- schema.items.map((headCell, i) => (React.createElement(TableCell, { style: {
348
- width: typeof headCell.width === 'string' && headCell.width.endsWith('%')
349
- ? headCell.width
350
- : headCell.width,
351
- }, key: `${headCell.attr}_${i}`, align: "left", sortDirection: orderBy === headCell.attr ? order : false },
352
- React.createElement("div", { style: {
353
- ...styles.flex,
354
- ...(schema.showFirstAddOnTop ? { flexDirection: 'column' } : undefined),
355
- } },
356
- !i && !schema.noDelete ? (React.createElement(Tooltip, { title: doAnyFilterSet
357
- ? I18n.t('ra_Cannot add items with set filter')
358
- : I18n.t('ra_Add row'), slotProps: { popper: { sx: styles.tooltip } } },
359
- React.createElement("span", null,
360
- React.createElement(IconButton, { size: "small", color: "primary", disabled: !!doAnyFilterSet && !this.props.schema.allowAddByFilter, onClick: this.onAdd },
361
- React.createElement(AddIcon, null))))) : null,
362
- headCell.sort && (React.createElement(TableSortLabel, { active: true, style: orderBy !== headCell.attr ? styles.silver : undefined, direction: orderBy === headCell.attr ? order : 'asc', onClick: () => this.handleRequestSort(headCell.attr) })),
363
- headCell.filter && this.state.filterOn.includes(headCell.attr) ? (React.createElement(TextField, { variant: "standard", ref: this.filterRefs[headCell.attr], onChange: () => this.applyFilter(), title: I18n.t('ra_You can filter entries by entering here some text'), slotProps: {
364
- input: {
365
- endAdornment: ConfigTable.getFilterValue(this.filterRefs[headCell.attr]) && (React.createElement(InputAdornment, { position: "end" },
366
- React.createElement(IconButton, { size: "small", onClick: () => {
367
- ConfigTable.setFilterValue(this.filterRefs[headCell.attr], '');
368
- this.applyFilter();
369
- } },
370
- React.createElement(CloseIcon, null)))),
371
- },
372
- }, fullWidth: true, placeholder: this.getText(headCell.title) })) : (React.createElement("span", { style: styles.headerText }, this.getText(headCell.title))),
373
- headCell.filter ? (React.createElement(IconButton, { title: I18n.t('ra_Show/hide filter input'), size: "small", onClick: () => {
374
- const filterOn = [...this.state.filterOn];
375
- const pos = this.state.filterOn.indexOf(headCell.attr);
376
- if (pos === -1) {
377
- filterOn.push(headCell.attr);
378
- }
379
- else {
380
- filterOn.splice(pos, 1);
381
- }
382
- this.setState({ filterOn }, () => {
383
- if (pos &&
384
- ConfigTable.getFilterValue(this.filterRefs[headCell.attr])) {
385
- ConfigTable.setFilterValue(this.filterRefs[headCell.attr], '');
386
- this.applyFilter();
387
- }
388
- });
389
- } }, this.state.filterOn.includes(headCell.attr) ? (React.createElement(IconFilterOff, null)) : (React.createElement(IconFilterOn, null)))) : null)))),
392
+ schema.items?.map((headCell, i) => this.renderOneFilter({
393
+ schema,
394
+ style: { width: headCell.width },
395
+ showAddButton: !i && !schema.noDelete,
396
+ headCell,
397
+ order,
398
+ orderBy,
399
+ index: i,
400
+ doAnyFilterSet,
401
+ })),
390
402
  !schema.noDelete && (React.createElement(TableCell, { style: {
391
403
  paddingLeft: 20,
392
404
  paddingRight: 20,
393
405
  width: buttonsWidth,
394
406
  textAlign: 'right',
395
- }, padding: "checkbox" },
396
- schema.import ? (React.createElement(IconButton, { style: { marginRight: 10 }, size: "small", onClick: () => this.setState({ showImportDialog: true }), title: I18n.t('ra_import data from %s file', 'CSV') },
397
- React.createElement(ImportIcon, null))) : null,
398
- schema.export ? (React.createElement(IconButton, { style: { marginRight: 10 }, size: "small", onClick: () => this.onExport(), title: I18n.t('ra_Export data to %s file', 'CSV') },
399
- React.createElement(ExportIcon, null))) : null,
400
- React.createElement(IconButton, { disabled: true, size: "small" },
401
- React.createElement(DeleteIcon, null)))))));
407
+ }, padding: "checkbox" }, this.renderImportExportButtons(schema))))));
402
408
  }
403
409
  onDelete = (index) => () => {
404
410
  const newValue = JSON.parse(JSON.stringify(this.state.value));
@@ -703,14 +709,137 @@ class ConfigTable extends ConfigGeneric {
703
709
  React.createElement(DialogActions, null,
704
710
  React.createElement(Button, { variant: "contained", onClick: () => this.setState({ showImportDialog: false }), color: "primary", startIcon: React.createElement(IconClose, null) }, I18n.t('Cancel')))));
705
711
  }
706
- renderItem( /* error, disabled, defaultValue */) {
712
+ renderOneFilter(props) {
713
+ return (React.createElement(TableCell, { key: `${props.headCell.attr}_${props.index}`, style: props.style, align: "left", sortDirection: props.orderBy === props.headCell.attr ? props.order : false },
714
+ React.createElement("div", { style: {
715
+ ...styles.flex,
716
+ ...(props.schema.showFirstAddOnTop ? { flexDirection: 'column' } : undefined),
717
+ } },
718
+ props.showAddButton ? this.renderAddButton(props.doAnyFilterSet) : null,
719
+ props.headCell.sort && (React.createElement(TableSortLabel, { active: true, style: props.orderBy !== props.headCell.attr ? styles.silver : undefined, direction: props.orderBy === props.headCell.attr ? props.order : 'asc', onClick: () => this.handleRequestSort(props.headCell.attr) })),
720
+ props.headCell.filter && this.state.filterOn.includes(props.headCell.attr) ? (React.createElement(TextField, { variant: "standard", ref: this.filterRefs[props.headCell.attr], onChange: () => this.applyFilter(), title: I18n.t('ra_You can filter entries by entering here some text'), slotProps: {
721
+ input: {
722
+ endAdornment: ConfigTable.getFilterValue(this.filterRefs[props.headCell.attr]) && (React.createElement(InputAdornment, { position: "end" },
723
+ React.createElement(IconButton, { size: "small", onClick: () => {
724
+ ConfigTable.setFilterValue(this.filterRefs[props.headCell.attr], '');
725
+ this.applyFilter();
726
+ } },
727
+ React.createElement(CloseIcon, null)))),
728
+ },
729
+ }, fullWidth: true, placeholder: this.getText(props.headCell.title) })) : (React.createElement("span", { style: styles.headerText }, this.getText(props.headCell.title))),
730
+ this.renderShowHideFilter(props.headCell))));
731
+ }
732
+ enhancedFilterCard() {
733
+ const { schema } = this.props;
734
+ const { order, orderBy } = this.state;
735
+ let tdStyle;
736
+ if (this.props.schema.compact) {
737
+ tdStyle = { paddingTop: 1, paddingBottom: 1 };
738
+ }
739
+ return (React.createElement(Grid2, { size: {
740
+ xs: schema.xs || 12,
741
+ sm: schema.sm || undefined,
742
+ md: schema.md || undefined,
743
+ lg: schema.lg || undefined,
744
+ xl: schema.xl || undefined,
745
+ } },
746
+ React.createElement(Card, null,
747
+ React.createElement(Paper, { style: styles.paper },
748
+ React.createElement(Accordion, { style: styles.paper },
749
+ React.createElement(AccordionSummary, { expandIcon: React.createElement(ExpandMoreIcon, null) },
750
+ React.createElement(Typography, null, I18n.t('ra_Filter and Data Actions'))),
751
+ React.createElement(AccordionDetails, null,
752
+ React.createElement(Table, null,
753
+ React.createElement(TableBody, null,
754
+ schema.items?.map((headCell, i) => (React.createElement(TableRow, { key: `${headCell.attr}_${i}` }, this.renderOneFilter({
755
+ schema,
756
+ style: tdStyle,
757
+ showAddButton: false,
758
+ headCell,
759
+ order,
760
+ orderBy,
761
+ index: i,
762
+ doAnyFilterSet: false,
763
+ })))),
764
+ React.createElement(TableRow, null,
765
+ React.createElement(TableCell, { align: "left", style: tdStyle },
766
+ React.createElement("span", { style: styles.headerText }, I18n.t('ra_Actions'))),
767
+ React.createElement(TableCell, { style: tdStyle }, this.renderImportExportButtons(schema)))))))))));
768
+ }
769
+ enhancedBottomCard() {
770
+ const { schema } = this.props;
771
+ let tdStyle;
772
+ if (this.props.schema.compact) {
773
+ tdStyle = { paddingTop: 1, paddingBottom: 1 };
774
+ }
775
+ const doAnyFilterSet = this.isAnyFilterSet();
776
+ return (React.createElement(Grid2, { size: {
777
+ xs: schema.xs || 12,
778
+ sm: schema.sm || undefined,
779
+ md: schema.md || undefined,
780
+ lg: schema.lg || undefined,
781
+ xl: schema.xl || undefined,
782
+ } },
783
+ React.createElement(Card, null,
784
+ React.createElement(Paper, { style: styles.paper },
785
+ React.createElement(Table, null,
786
+ React.createElement(TableBody, null,
787
+ React.createElement(TableRow, null,
788
+ React.createElement(TableCell, { colSpan: schema.items.length + 1, style: tdStyle }, this.renderAddButton(doAnyFilterSet)))))))));
789
+ }
790
+ renderCards() {
707
791
  const { schema } = this.props;
708
792
  let { visibleValue } = this.state;
709
- if (!this.state.value || !Array.isArray(this.state.value)) {
710
- return null;
793
+ let tdStyle;
794
+ if (this.props.schema.compact) {
795
+ tdStyle = { paddingTop: 1, paddingBottom: 1 };
711
796
  }
712
797
  visibleValue = visibleValue || this.state.value.map((_, i) => i);
713
798
  const doAnyFilterSet = this.isAnyFilterSet();
799
+ return (React.createElement(Grid2, { container: true },
800
+ this.showImportDialog(),
801
+ this.showTypeOfImportDialog(),
802
+ this.enhancedFilterCard(),
803
+ visibleValue.map((idx, i) => (React.createElement(Grid2, { key: `${idx}_${i}`, size: {
804
+ xs: schema.xs || 12,
805
+ sm: schema.sm || undefined,
806
+ md: schema.md || undefined,
807
+ lg: schema.lg || undefined,
808
+ xl: schema.xl || undefined,
809
+ } },
810
+ React.createElement(Card, null,
811
+ React.createElement(Paper, { style: styles.paper },
812
+ React.createElement(Table, null,
813
+ React.createElement(TableBody, null,
814
+ schema.items?.map((headCell) => (React.createElement(TableRow, { key: `${headCell.attr}_${idx}` },
815
+ React.createElement(TableCell, { align: "left", style: tdStyle },
816
+ React.createElement("span", { style: styles.headerText }, this.getText(headCell.title))),
817
+ React.createElement(TableCell, { align: "left", style: tdStyle }, this.itemTable(headCell.attr, this.state.value[idx], idx))))),
818
+ React.createElement(TableRow, null,
819
+ React.createElement(TableCell, { align: "left", style: tdStyle },
820
+ React.createElement("span", { style: styles.headerText }, this.getText('Actions'))),
821
+ React.createElement(TableCell, { align: "left", style: tdStyle },
822
+ !doAnyFilterSet && !this.state.orderBy ? (React.createElement(Tooltip, { title: I18n.t('ra_Move up'), slotProps: { popper: { sx: styles.tooltip } } },
823
+ React.createElement("span", null,
824
+ React.createElement(IconButton, { size: "small", onClick: () => this.onMoveUp(idx), disabled: i === 0 },
825
+ React.createElement(UpIcon, null))))) : null,
826
+ !doAnyFilterSet && !this.state.orderBy ? (React.createElement(Tooltip, { title: I18n.t('ra_Move down'), slotProps: { popper: { sx: styles.tooltip } } },
827
+ React.createElement("span", null,
828
+ React.createElement(IconButton, { size: "small", onClick: () => this.onMoveDown(idx), disabled: i === visibleValue.length - 1 },
829
+ React.createElement(DownIcon, null))))) : null,
830
+ React.createElement(Tooltip, { title: I18n.t('ra_Delete current row'), slotProps: { popper: { sx: styles.tooltip } } },
831
+ React.createElement(IconButton, { size: "small", onClick: this.onDelete(idx) },
832
+ React.createElement(DeleteIcon, null))),
833
+ this.props.schema.clone ? (React.createElement(Tooltip, { title: I18n.t('ra_Clone current row'), slotProps: { popper: { sx: styles.tooltip } } },
834
+ React.createElement(IconButton, { size: "small", onClick: this.onClone(idx) },
835
+ React.createElement(CopyContentIcon, null)))) : null))))))))),
836
+ this.enhancedBottomCard()));
837
+ }
838
+ renderTable() {
839
+ const { schema } = this.props;
840
+ let { visibleValue } = this.state;
841
+ visibleValue = visibleValue || this.state.value.map((_, i) => i);
842
+ const doAnyFilterSet = this.isAnyFilterSet();
714
843
  let tdStyle;
715
844
  if (this.props.schema.compact) {
716
845
  tdStyle = { paddingTop: 1, paddingBottom: 1 };
@@ -726,8 +855,7 @@ class ConfigTable extends ConfigGeneric {
726
855
  this.enhancedTableHead(!doAnyFilterSet && !this.state.orderBy ? 120 : 64, doAnyFilterSet),
727
856
  React.createElement(TableBody, null,
728
857
  visibleValue.map((idx, i) => (React.createElement(TableRow, { hover: true, key: `${idx}_${i}` },
729
- schema.items &&
730
- schema.items.map((headCell) => (React.createElement(TableCell, { key: `${headCell.attr}_${idx}`, align: "left", style: tdStyle }, this.itemTable(headCell.attr, this.state.value[idx], idx)))),
858
+ schema.items?.map((headCell) => (React.createElement(TableCell, { key: `${headCell.attr}_${idx}`, align: "left", style: tdStyle }, this.itemTable(headCell.attr, this.state.value[idx], idx)))),
731
859
  !schema.noDelete && (React.createElement(TableCell, { align: "left", style: { ...tdStyle, ...styles.buttonCell } },
732
860
  !doAnyFilterSet && !this.state.orderBy ? (i ? (React.createElement(Tooltip, { title: I18n.t('ra_Move up'), slotProps: { popper: { sx: styles.tooltip } } },
733
861
  React.createElement(IconButton, { size: "small", onClick: () => this.onMoveUp(idx) },
@@ -742,13 +870,7 @@ class ConfigTable extends ConfigGeneric {
742
870
  React.createElement(IconButton, { size: "small", onClick: this.onClone(idx) },
743
871
  React.createElement(CopyContentIcon, null)))) : null))))),
744
872
  !schema.noDelete && visibleValue.length >= (schema.showSecondAddAt || 5) ? (React.createElement(TableRow, null,
745
- React.createElement(TableCell, { colSpan: schema.items.length + 1, style: { ...tdStyle } },
746
- React.createElement(Tooltip, { title: doAnyFilterSet
747
- ? I18n.t('ra_Cannot add items with set filter')
748
- : I18n.t('ra_Add row'), slotProps: { popper: { sx: styles.tooltip } } },
749
- React.createElement("span", null,
750
- React.createElement(IconButton, { size: "small", color: "primary", disabled: !!doAnyFilterSet && !this.props.schema.allowAddByFilter, onClick: this.onAdd },
751
- React.createElement(AddIcon, null))))))) : null)),
873
+ React.createElement(TableCell, { colSpan: schema.items.length + 1, style: { ...tdStyle } }, this.renderAddButton(doAnyFilterSet)))) : null)),
752
874
  !visibleValue.length && this.state.value.length ? (React.createElement("div", { style: styles.filteredOut },
753
875
  React.createElement(Typography, { style: styles.title, variant: "h6", id: "tableTitle", component: "div" },
754
876
  I18n.t('ra_All items are filtered out'),
@@ -759,6 +881,50 @@ class ConfigTable extends ConfigGeneric {
759
881
  React.createElement(ErrorIcon, { color: "error" }),
760
882
  React.createElement("span", { style: { color: 'red', alignSelf: 'center' } }, this.state.errorMessage))) : null));
761
883
  }
884
+ componentDidUpdate() {
885
+ if (this.refDiv.current?.clientWidth && this.refDiv.current.clientWidth !== this.state.width) {
886
+ if (this.resizeTimeout) {
887
+ clearTimeout(this.resizeTimeout);
888
+ }
889
+ this.resizeTimeout = setTimeout(() => {
890
+ this.resizeTimeout = null;
891
+ this.setState({ width: this.refDiv.current?.clientWidth });
892
+ }, 50);
893
+ }
894
+ }
895
+ getCurrentBreakpoint() {
896
+ if (!this.state.width) {
897
+ return 'md';
898
+ }
899
+ if (this.state.width < 600) {
900
+ return 'xs';
901
+ }
902
+ if (this.state.width < 900) {
903
+ return 'sm';
904
+ }
905
+ if (this.state.width < 1200) {
906
+ return 'md';
907
+ }
908
+ if (this.state.width < 1536) {
909
+ return 'lg';
910
+ }
911
+ return 'xl';
912
+ }
913
+ renderItem( /* error, disabled, defaultValue */) {
914
+ const { schema } = this.props;
915
+ if (!this.state.value || !Array.isArray(this.state.value)) {
916
+ return null;
917
+ }
918
+ const currentBreakpoint = this.getCurrentBreakpoint();
919
+ let content;
920
+ if (currentBreakpoint && (schema.useCardFor || ['xs']).includes(currentBreakpoint)) {
921
+ content = this.renderCards();
922
+ }
923
+ else {
924
+ content = this.renderTable();
925
+ }
926
+ return (React.createElement("div", { ref: this.refDiv, style: { width: '100%' } }, content));
927
+ }
762
928
  }
763
929
  export default ConfigTable;
764
930
  //# sourceMappingURL=ConfigTable.js.map