@deviceinsight/ng-ui-components 6.24.0 → 6.26.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 (30) hide show
  1. package/lib/cjs/assets/style.css +1 -1
  2. package/lib/cjs/components/input/__tests__/DateTimeInput.spec.js +2 -2
  3. package/lib/cjs/components/reactable/helpers/ReactableTableFilterRow.d.ts.map +1 -1
  4. package/lib/cjs/components/reactable/helpers/ReactableTableFilterRow.js +17 -8
  5. package/lib/cjs/components/upload/FileUpload.d.ts +23 -9
  6. package/lib/cjs/components/upload/FileUpload.d.ts.map +1 -1
  7. package/lib/cjs/components/upload/FileUpload.js +32 -24
  8. package/lib/cjs/components/upload/ImageUpload.d.ts +3 -2
  9. package/lib/cjs/components/upload/ImageUpload.d.ts.map +1 -1
  10. package/lib/cjs/components/upload/ImageUpload.js +13 -6
  11. package/lib/esm/assets/style.css +1 -1
  12. package/lib/esm/components/input/__tests__/DateTimeInput.spec.js +2 -2
  13. package/lib/esm/components/reactable/helpers/ReactableTableFilterRow.d.ts.map +1 -1
  14. package/lib/esm/components/reactable/helpers/ReactableTableFilterRow.js +17 -8
  15. package/lib/esm/components/upload/FileUpload.d.ts +23 -9
  16. package/lib/esm/components/upload/FileUpload.d.ts.map +1 -1
  17. package/lib/esm/components/upload/FileUpload.js +32 -24
  18. package/lib/esm/components/upload/ImageUpload.d.ts +3 -2
  19. package/lib/esm/components/upload/ImageUpload.d.ts.map +1 -1
  20. package/lib/esm/components/upload/ImageUpload.js +13 -6
  21. package/lib/esm/src/components/input/__tests__/DateTimeInput.spec.js +2 -2
  22. package/lib/esm/src/components/reactable/helpers/ReactableTableFilterRow.d.ts.map +1 -1
  23. package/lib/esm/src/components/reactable/helpers/ReactableTableFilterRow.js +17 -8
  24. package/lib/esm/src/components/upload/FileUpload.d.ts +23 -9
  25. package/lib/esm/src/components/upload/FileUpload.d.ts.map +1 -1
  26. package/lib/esm/src/components/upload/FileUpload.js +32 -24
  27. package/lib/esm/src/components/upload/ImageUpload.d.ts +3 -2
  28. package/lib/esm/src/components/upload/ImageUpload.d.ts.map +1 -1
  29. package/lib/esm/src/components/upload/ImageUpload.js +13 -6
  30. package/package.json +24 -24
@@ -74,7 +74,7 @@
74
74
  .di.upload,
75
75
  .di.upload * {transition:all .1s ease;}
76
76
  .di.upload {margin:0; padding:0; width:100%; height:100%; min-height:80px; font-size:16px; border:1px dashed #888; border-radius:4px; overflow:hidden; user-select:none;}
77
- .di.upload {display:flex; align-items:center;}
77
+ .di.upload {display:flex; flex-direction:column; align-items:center;}
78
78
  .di.upload:hover {border-color:#666; background:#f9f9f9;}
79
79
  .di.upload:active {background:#eee;}
80
80
  .di.upload > div {width:100%; height:100%;}
@@ -17,14 +17,14 @@ const testing_library_1 = require("@storybook/testing-library");
17
17
  (0, vitest_1.expect)(timeElement).toHaveDisplayValue('03:24');
18
18
  });
19
19
  (0, vitest_1.it)('should display the time and date as timezone date', async () => {
20
- const { rerender } = (0, react_2.render)(react_1.default.createElement(DateTimeInput_1.default, { timestamp: new Date('2019-02-01T11:11:00').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
20
+ const { rerender } = (0, react_2.render)(react_1.default.createElement(DateTimeInput_1.default, { timestamp: new Date('2019-02-01T11:11:00Z').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
21
21
  const timeElementUtm = react_2.screen.queryByDisplayValue('11:11');
22
22
  (0, vitest_1.expect)(timeElementUtm).not.toBeInTheDocument();
23
23
  const timeElement = react_2.screen.queryByDisplayValue('03:11');
24
24
  (0, vitest_1.expect)(timeElement).toBeInTheDocument();
25
25
  const dateElement = react_2.screen.queryByDisplayValue('01.02.2019');
26
26
  (0, vitest_1.expect)(dateElement).toBeInTheDocument();
27
- rerender(react_1.default.createElement(DateTimeInput_1.default, { timestamp: new Date('2019-02-02T03:24:00').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
27
+ rerender(react_1.default.createElement(DateTimeInput_1.default, { timestamp: new Date('2019-02-02T03:24:00Z').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
28
28
  (0, vitest_1.expect)(timeElement).toHaveDisplayValue('19:24');
29
29
  (0, vitest_1.expect)(dateElement).toHaveDisplayValue('01.02.2019');
30
30
  await (0, react_2.act)(async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAuF5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA+F5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -34,14 +34,23 @@ const ReactableTableFilterRow = ({ columnDefs, onFilter, tableName }) => {
34
34
  const { t } = (0, i18n_1.useTranslation)();
35
35
  const [state, setState] = (0, react_1.useState)({});
36
36
  (0, react_1.useEffect)(() => {
37
- const initialFilters = columnDefs.reduce((acc, columnDef) => ({
38
- ...acc,
39
- [columnDef.name]: columnDef.filterable?.initialValue ?? ''
40
- }), {});
41
- setState(initialFilters);
42
- if (Object.values(initialFilters).some((value) => value)) {
43
- onFilter(initialFilters);
44
- }
37
+ setState((prev) => {
38
+ const merged = {};
39
+ for (const cd of columnDefs) {
40
+ merged[cd.name] = prev[cd.name] !== undefined ? prev[cd.name] : cd.filterable?.initialValue ?? '';
41
+ }
42
+ const prevKeys = Object.keys(prev);
43
+ const mergedKeys = Object.keys(merged);
44
+ const sameKeys = mergedKeys.length === prevKeys.length && mergedKeys.every((k) => prevKeys.includes(k));
45
+ const sameValues = sameKeys && mergedKeys.every((k) => merged[k] === prev[k]);
46
+ if (sameKeys && sameValues) {
47
+ return prev; // no change
48
+ }
49
+ if (Object.values(merged).some((v) => v)) {
50
+ onFilter(merged);
51
+ }
52
+ return merged;
53
+ });
45
54
  }, [columnDefs, onFilter]);
46
55
  const changeFilter = (columnName, value) => {
47
56
  const newState = { ...state, [columnName]: value };
@@ -10,12 +10,8 @@ export declare type PreviewComponentProps = {
10
10
  export declare type Props = {
11
11
  /** (Optional) string for accepting files */
12
12
  accept?: string;
13
- /** Function, executed when a file gets removed */
14
- onRemoveFile: () => void;
15
13
  /** Optional Function, executed to download the file */
16
- onDownloadFile?: () => void;
17
- /** Function, executed when a file gets selected */
18
- onSelectFile: (file: DropzoneFile) => void;
14
+ onDownloadFile?: (file: DropzoneFile) => void;
19
15
  /** (Optional) function, executed when a file gets dragged into the upload field and accepted */
20
16
  onDropAccepted?: () => void;
21
17
  /** (Optional) function, executed when a file gets dragged into the upload field and rejected */
@@ -32,9 +28,27 @@ export declare type Props = {
32
28
  previewComponent?: React.ComponentType<PreviewComponentProps>;
33
29
  /** (Optional) Maximum upload size */
34
30
  maxSize?: number;
35
- };
31
+ } & ({
32
+ /** (Optional) accept multiple files */
33
+ multiple?: false;
34
+ /** Function, executed when files get added or removed */
35
+ onChange?: (files: DropzoneFile[]) => void;
36
+ /** Function, executed when a file gets removed */
37
+ onRemoveFile: (file: DropzoneFile) => void;
38
+ /** Function, executed when a file gets selected */
39
+ onSelectFile: (file: DropzoneFile) => void;
40
+ } | {
41
+ /** (Optional) accept multiple files */
42
+ multiple: true;
43
+ /** Function, executed when files get added or removed */
44
+ onChange: (files: DropzoneFile[]) => void;
45
+ /** Function, executed when a file gets removed */
46
+ onRemoveFile?: (file: DropzoneFile) => void;
47
+ /** Function, executed when a file gets selected */
48
+ onSelectFile?: (file: DropzoneFile) => void;
49
+ });
36
50
  export declare type State = {
37
- file: DropzoneFile | null | undefined;
51
+ files: DropzoneFile[];
38
52
  };
39
53
  /**
40
54
  * FileUpload enables the possibility to upload files conveniently
@@ -60,8 +74,8 @@ export default class FileUpload extends React.Component<Props, State> {
60
74
  };
61
75
  state: State;
62
76
  handleDrop: (accepted: Array<DropzoneFile>, rejected: Array<DropzoneFile>) => void;
63
- selectFile: (arg0: DropzoneFile) => void;
64
- handleRemoveFile: () => void;
77
+ selectFile: (files: DropzoneFile[]) => void;
78
+ handleRemoveFile: (file: DropzoneFile) => void;
65
79
  render(): React.JSX.Element;
66
80
  }
67
81
  //# sourceMappingURL=FileUpload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileUpload.d.ts","sourceRoot":"","sources":["../../../../src/components/upload/FileUpload.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,oBAAY,YAAY,GAAG,IAAI,GAAG;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,oBAAY,qBAAqB,GAAG;IACnC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,oBAAY,KAAK,GAAG;IACnB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,kDAAkD;IAClD,YAAY,EAAE,MAAM,IAAI,CAAC;IAEzB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,mDAAmD;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAE3C,gGAAgG;IAChG,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,gGAAgG;IAChG,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAEjD,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IAEjC,qDAAqD;IACrD,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAElC,wDAAwD;IACxD,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAEnC,wDAAwD;IACxD,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAEnC,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAE9D,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,oBAAY,KAAK,GAAG;IACnB,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;IACpE,MAAM,CAAC,YAAY,EAAE;QACpB,UAAU,EAAE;YACX,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,QAAQ,EAAE;YACT,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,SAAS,EAAE;YACV,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,UAAU,EAAE;YACX,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;KACF,CAiBC;IAEF,KAAK,EAAE,KAAK,CAEV;IAEF,UAAU,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,KAAK,IAAI,CAgBhF;IAEF,UAAU,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAMtC;IAEF,gBAAgB,EAAE,MAAM,IAAI,CAW1B;IAEF,MAAM;CAqEN"}
1
+ {"version":3,"file":"FileUpload.d.ts","sourceRoot":"","sources":["../../../../src/components/upload/FileUpload.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,oBAAY,YAAY,GAAG,IAAI,GAAG;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,oBAAY,qBAAqB,GAAG;IACnC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,oBAAY,KAAK,GAAG;IACnB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,uDAAuD;IACvD,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAE9C,gGAAgG;IAChG,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,gGAAgG;IAChG,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAEjD,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IAEjC,qDAAqD;IACrD,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAElC,wDAAwD;IACxD,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAEnC,wDAAwD;IACxD,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAEnC,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAE9D,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,CACD;IACA,uCAAuC;IACvC,QAAQ,CAAC,EAAE,KAAK,CAAC;IAEjB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAE3C,kDAAkD;IAClD,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAE3C,mDAAmD;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;CAC1C,GACD;IACA,uCAAuC;IACvC,QAAQ,EAAE,IAAI,CAAC;IAEf,yDAAyD;IACzD,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAE1C,kDAAkD;IAClD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAE5C,mDAAmD;IACnD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;CAC3C,CACH,CAAC;AAEF,oBAAY,KAAK,GAAG;IACnB,KAAK,EAAE,YAAY,EAAE,CAAC;CACtB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;IACpE,MAAM,CAAC,YAAY,EAAE;QACpB,UAAU,EAAE;YACX,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,QAAQ,EAAE;YACT,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,SAAS,EAAE;YACV,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,UAAU,EAAE;YACX,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;KACF,CAiBC;IAEF,KAAK,EAAE,KAAK,CAEV;IAEF,UAAU,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,KAAK,IAAI,CAchF;IAEF,UAAU,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAazC;IAEF,gBAAgB,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAU5C;IAEF,MAAM;CA8EN"}
@@ -38,58 +38,66 @@ class FileUpload extends React.Component {
38
38
  constructor() {
39
39
  super(...arguments);
40
40
  this.state = {
41
- file: null
41
+ files: []
42
42
  };
43
43
  this.handleDrop = (accepted, rejected) => {
44
- if (accepted.length > 1) {
44
+ if (!this.props.multiple && accepted.length > 1) {
45
45
  return;
46
46
  }
47
47
  if (rejected.length > 0) {
48
48
  return;
49
49
  }
50
- const file = accepted[0];
51
50
  /** Prevent console error on <Dropzone /> component */
52
- setTimeout(() => this.selectFile(file), 100);
51
+ setTimeout(() => this.selectFile(accepted), 100);
53
52
  };
54
- this.selectFile = (file) => {
55
- file.preview = URL.createObjectURL(file);
56
- this.setState({
57
- file
53
+ this.selectFile = (files) => {
54
+ const { onSelectFile, onChange } = this.props;
55
+ files.forEach((file) => {
56
+ file.preview = URL.createObjectURL(file);
58
57
  });
59
- this.props.onSelectFile(file);
58
+ const newFiles = [...this.state.files, ...files];
59
+ this.setState({ files: newFiles });
60
+ onChange?.(newFiles);
61
+ if (onSelectFile) {
62
+ files.forEach((file) => {
63
+ onSelectFile(file);
64
+ });
65
+ }
60
66
  };
61
- this.handleRemoveFile = () => {
62
- const { file } = this.state;
63
- const { onRemoveFile } = this.props;
67
+ this.handleRemoveFile = (file) => {
68
+ const { files } = this.state;
64
69
  if (file) {
65
70
  if (file.preview)
66
71
  window.URL.revokeObjectURL(file.preview);
67
- onRemoveFile();
68
- this.setState({
69
- file: null
70
- });
72
+ const newFiles = files.filter((f) => f !== file);
73
+ this.setState({ files: newFiles });
74
+ this.props.onChange?.(newFiles);
75
+ this.props.onRemoveFile?.(file);
71
76
  }
72
77
  };
73
78
  }
74
79
  render() {
75
- const { file } = this.state;
80
+ const { files } = this.state;
76
81
  const { accept, previewComponent: Preview, dropHint, hoverHint, acceptHint, rejectHint,
77
82
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
83
+ onChange,
84
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
78
85
  onRemoveFile, onDownloadFile,
79
86
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
80
- onSelectFile, onDropRejected, onDropAccepted, maxSize, ...otherProps } = this.props;
87
+ onSelectFile, onDropRejected, onDropAccepted, maxSize, multiple, ...otherProps } = this.props;
81
88
  const dropHintOrDefault = dropHint || FileUpload.defaultProps.dropHint;
82
89
  const hoverHintOrDefault = hoverHint || FileUpload.defaultProps.hoverHint;
83
90
  const acceptHintOrDefault = acceptHint || FileUpload.defaultProps.acceptHint;
84
91
  const rejectHintOrDefault = rejectHint || FileUpload.defaultProps.rejectHint;
85
92
  return (React.createElement("div", { ...otherProps, className: (0, classnames_1.default)('di upload', {
86
- clickable: !file,
87
- hasContent: !!file
93
+ clickable: !files.length,
94
+ hasContent: !!files.length
88
95
  }) },
89
- !!file && !!Preview && (
90
- // @ts-ignore
91
- React.createElement(Preview, { file: file, onRemoveFile: this.handleRemoveFile, onDownloadFile: onDownloadFile })),
92
- !file && (React.createElement(react_dropzone_1.default, { accept: accept, multiple: false, style: {
96
+ !!Preview &&
97
+ files.map((file, i) => (React.createElement(Preview, { key: i, file: file, onRemoveFile: () => this.handleRemoveFile(file),
98
+ // @ts-ignore
99
+ onDownloadFile: onDownloadFile && (() => onDownloadFile(file)) }))),
100
+ (multiple || !files.length) && (React.createElement(react_dropzone_1.default, { accept: accept, multiple: multiple ?? false, style: {
93
101
  border: 'none'
94
102
  }, onDrop: this.handleDrop, onDropRejected: onDropRejected, onDropAccepted: onDropAccepted, activeClassName: "active", acceptClassName: "accept", rejectClassName: "reject", maxSize: maxSize || Infinity },
95
103
  React.createElement("div", { className: "drag-drop-text-container" },
@@ -1,12 +1,13 @@
1
1
  import * as React from 'react';
2
- import { Props as FileUploadProps } from './FileUpload';
3
- export declare type Props = FileUploadProps & {
2
+ import { DropzoneFile, Props as FileUploadProps } from './FileUpload';
3
+ export declare type Props = Omit<FileUploadProps, 'multiple'> & {
4
4
  /** (Optional) Url for the image preview */
5
5
  imageUrl: string | null | undefined;
6
6
  imageSize?: 'contain' | 'cover';
7
7
  };
8
8
  declare type ImageUploadState = {
9
9
  dragOverPreview: boolean;
10
+ file: DropzoneFile | null;
10
11
  };
11
12
  /**
12
13
  * ImageUpload enables the possibility to upload images conveniently
@@ -1 +1 @@
1
- {"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../../src/components/upload/ImageUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAmB,EAAC,KAAK,IAAI,eAAe,EAAC,MAAM,cAAc,CAAC;AA+BlE,oBAAY,KAAK,GAAG,eAAe,GAAG;IACrC,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAChC,CAAC;AAEF,aAAK,gBAAgB,GAAG;IACvB,eAAe,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAChF,KAAK,EAAE,gBAAgB,CAErB;IAEF,kBAAkB,CAAC,SAAS,EAAE,KAAK,GAAG,IAAI;IAQ1C,cAAc,EAAE,MAAM,IAAI,CAIxB;IAEF,MAAM;CAkBN"}
1
+ {"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../../src/components/upload/ImageUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAmB,EAAC,YAAY,EAAE,KAAK,IAAI,eAAe,EAAC,MAAM,cAAc,CAAC;AA+BhF,oBAAY,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,GAAG;IACvD,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAChC,CAAC;AAEF,aAAK,gBAAgB,GAAG;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAChF,KAAK,EAAE,gBAAgB,CAGrB;IAEF,kBAAkB,CAAC,SAAS,EAAE,KAAK,GAAG,IAAI;IAQ1C,cAAc,EAAE,MAAM,IAAI,CAIxB;IAEF,MAAM;CA+BN"}
@@ -45,7 +45,8 @@ class ImageUpload extends React.Component {
45
45
  constructor() {
46
46
  super(...arguments);
47
47
  this.state = {
48
- dragOverPreview: false
48
+ dragOverPreview: false,
49
+ file: null
49
50
  };
50
51
  this.handleDragOver = () => {
51
52
  this.setState({
@@ -61,13 +62,19 @@ class ImageUpload extends React.Component {
61
62
  }
62
63
  }
63
64
  render() {
64
- const { accept, imageUrl, imageSize, ...otherProps } = this.props;
65
- const { dragOverPreview } = this.state;
66
- if (imageUrl && !dragOverPreview) {
67
- return (React.createElement(PreviewImage, { url: imageUrl, imageSize: imageSize, onRemoveFile: otherProps.onRemoveFile, onDownloadFile: otherProps.onDownloadFile, onDragOver: this.handleDragOver }));
65
+ const { accept, imageUrl, imageSize, onSelectFile, onRemoveFile, ...otherProps } = this.props;
66
+ const { dragOverPreview, file } = this.state;
67
+ if (imageUrl && !dragOverPreview && file) {
68
+ return (React.createElement(PreviewImage, { url: imageUrl, imageSize: imageSize, onRemoveFile: () => onRemoveFile?.(file), onDownloadFile: () => otherProps.onDownloadFile?.(file), onDragOver: this.handleDragOver }));
68
69
  }
69
70
  else {
70
- return React.createElement(FileUpload_1.default, { ...otherProps, accept: accept || 'image/jpeg, image/png' });
71
+ return (React.createElement(FileUpload_1.default, { ...otherProps, onRemoveFile: (file) => {
72
+ this.setState({ file: null });
73
+ onRemoveFile?.(file);
74
+ }, onSelectFile: (file) => {
75
+ this.setState({ file });
76
+ onSelectFile?.(file);
77
+ }, accept: accept || 'image/jpeg, image/png' }));
71
78
  }
72
79
  }
73
80
  }
@@ -74,7 +74,7 @@
74
74
  .di.upload,
75
75
  .di.upload * {transition:all .1s ease;}
76
76
  .di.upload {margin:0; padding:0; width:100%; height:100%; min-height:80px; font-size:16px; border:1px dashed #888; border-radius:4px; overflow:hidden; user-select:none;}
77
- .di.upload {display:flex; align-items:center;}
77
+ .di.upload {display:flex; flex-direction:column; align-items:center;}
78
78
  .di.upload:hover {border-color:#666; background:#f9f9f9;}
79
79
  .di.upload:active {background:#eee;}
80
80
  .di.upload > div {width:100%; height:100%;}
@@ -12,14 +12,14 @@ describe('DateTimeInput.js', () => {
12
12
  expect(timeElement).toHaveDisplayValue('03:24');
13
13
  });
14
14
  it('should display the time and date as timezone date', async () => {
15
- const { rerender } = render(React.createElement(DateTimeInput, { timestamp: new Date('2019-02-01T11:11:00').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
15
+ const { rerender } = render(React.createElement(DateTimeInput, { timestamp: new Date('2019-02-01T11:11:00Z').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
16
16
  const timeElementUtm = screen.queryByDisplayValue('11:11');
17
17
  expect(timeElementUtm).not.toBeInTheDocument();
18
18
  const timeElement = screen.queryByDisplayValue('03:11');
19
19
  expect(timeElement).toBeInTheDocument();
20
20
  const dateElement = screen.queryByDisplayValue('01.02.2019');
21
21
  expect(dateElement).toBeInTheDocument();
22
- rerender(React.createElement(DateTimeInput, { timestamp: new Date('2019-02-02T03:24:00').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
22
+ rerender(React.createElement(DateTimeInput, { timestamp: new Date('2019-02-02T03:24:00Z').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
23
23
  expect(timeElement).toHaveDisplayValue('19:24');
24
24
  expect(dateElement).toHaveDisplayValue('01.02.2019');
25
25
  await act(async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAuF5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA+F5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -6,14 +6,23 @@ const ReactableTableFilterRow = ({ columnDefs, onFilter, tableName }) => {
6
6
  const { t } = useTranslation();
7
7
  const [state, setState] = useState({});
8
8
  useEffect(() => {
9
- const initialFilters = columnDefs.reduce((acc, columnDef) => ({
10
- ...acc,
11
- [columnDef.name]: columnDef.filterable?.initialValue ?? ''
12
- }), {});
13
- setState(initialFilters);
14
- if (Object.values(initialFilters).some((value) => value)) {
15
- onFilter(initialFilters);
16
- }
9
+ setState((prev) => {
10
+ const merged = {};
11
+ for (const cd of columnDefs) {
12
+ merged[cd.name] = prev[cd.name] !== undefined ? prev[cd.name] : cd.filterable?.initialValue ?? '';
13
+ }
14
+ const prevKeys = Object.keys(prev);
15
+ const mergedKeys = Object.keys(merged);
16
+ const sameKeys = mergedKeys.length === prevKeys.length && mergedKeys.every((k) => prevKeys.includes(k));
17
+ const sameValues = sameKeys && mergedKeys.every((k) => merged[k] === prev[k]);
18
+ if (sameKeys && sameValues) {
19
+ return prev; // no change
20
+ }
21
+ if (Object.values(merged).some((v) => v)) {
22
+ onFilter(merged);
23
+ }
24
+ return merged;
25
+ });
17
26
  }, [columnDefs, onFilter]);
18
27
  const changeFilter = (columnName, value) => {
19
28
  const newState = { ...state, [columnName]: value };
@@ -10,12 +10,8 @@ export declare type PreviewComponentProps = {
10
10
  export declare type Props = {
11
11
  /** (Optional) string for accepting files */
12
12
  accept?: string;
13
- /** Function, executed when a file gets removed */
14
- onRemoveFile: () => void;
15
13
  /** Optional Function, executed to download the file */
16
- onDownloadFile?: () => void;
17
- /** Function, executed when a file gets selected */
18
- onSelectFile: (file: DropzoneFile) => void;
14
+ onDownloadFile?: (file: DropzoneFile) => void;
19
15
  /** (Optional) function, executed when a file gets dragged into the upload field and accepted */
20
16
  onDropAccepted?: () => void;
21
17
  /** (Optional) function, executed when a file gets dragged into the upload field and rejected */
@@ -32,9 +28,27 @@ export declare type Props = {
32
28
  previewComponent?: React.ComponentType<PreviewComponentProps>;
33
29
  /** (Optional) Maximum upload size */
34
30
  maxSize?: number;
35
- };
31
+ } & ({
32
+ /** (Optional) accept multiple files */
33
+ multiple?: false;
34
+ /** Function, executed when files get added or removed */
35
+ onChange?: (files: DropzoneFile[]) => void;
36
+ /** Function, executed when a file gets removed */
37
+ onRemoveFile: (file: DropzoneFile) => void;
38
+ /** Function, executed when a file gets selected */
39
+ onSelectFile: (file: DropzoneFile) => void;
40
+ } | {
41
+ /** (Optional) accept multiple files */
42
+ multiple: true;
43
+ /** Function, executed when files get added or removed */
44
+ onChange: (files: DropzoneFile[]) => void;
45
+ /** Function, executed when a file gets removed */
46
+ onRemoveFile?: (file: DropzoneFile) => void;
47
+ /** Function, executed when a file gets selected */
48
+ onSelectFile?: (file: DropzoneFile) => void;
49
+ });
36
50
  export declare type State = {
37
- file: DropzoneFile | null | undefined;
51
+ files: DropzoneFile[];
38
52
  };
39
53
  /**
40
54
  * FileUpload enables the possibility to upload files conveniently
@@ -60,8 +74,8 @@ export default class FileUpload extends React.Component<Props, State> {
60
74
  };
61
75
  state: State;
62
76
  handleDrop: (accepted: Array<DropzoneFile>, rejected: Array<DropzoneFile>) => void;
63
- selectFile: (arg0: DropzoneFile) => void;
64
- handleRemoveFile: () => void;
77
+ selectFile: (files: DropzoneFile[]) => void;
78
+ handleRemoveFile: (file: DropzoneFile) => void;
65
79
  render(): React.JSX.Element;
66
80
  }
67
81
  //# sourceMappingURL=FileUpload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileUpload.d.ts","sourceRoot":"","sources":["../../../../src/components/upload/FileUpload.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,oBAAY,YAAY,GAAG,IAAI,GAAG;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,oBAAY,qBAAqB,GAAG;IACnC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,oBAAY,KAAK,GAAG;IACnB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,kDAAkD;IAClD,YAAY,EAAE,MAAM,IAAI,CAAC;IAEzB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,mDAAmD;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAE3C,gGAAgG;IAChG,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,gGAAgG;IAChG,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAEjD,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IAEjC,qDAAqD;IACrD,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAElC,wDAAwD;IACxD,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAEnC,wDAAwD;IACxD,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAEnC,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAE9D,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,oBAAY,KAAK,GAAG;IACnB,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;IACpE,MAAM,CAAC,YAAY,EAAE;QACpB,UAAU,EAAE;YACX,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,QAAQ,EAAE;YACT,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,SAAS,EAAE;YACV,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,UAAU,EAAE;YACX,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;KACF,CAiBC;IAEF,KAAK,EAAE,KAAK,CAEV;IAEF,UAAU,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,KAAK,IAAI,CAgBhF;IAEF,UAAU,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAMtC;IAEF,gBAAgB,EAAE,MAAM,IAAI,CAW1B;IAEF,MAAM;CAqEN"}
1
+ {"version":3,"file":"FileUpload.d.ts","sourceRoot":"","sources":["../../../../src/components/upload/FileUpload.tsx"],"names":[],"mappings":"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"}
@@ -10,58 +10,66 @@ export default class FileUpload extends React.Component {
10
10
  constructor() {
11
11
  super(...arguments);
12
12
  this.state = {
13
- file: null
13
+ files: []
14
14
  };
15
15
  this.handleDrop = (accepted, rejected) => {
16
- if (accepted.length > 1) {
16
+ if (!this.props.multiple && accepted.length > 1) {
17
17
  return;
18
18
  }
19
19
  if (rejected.length > 0) {
20
20
  return;
21
21
  }
22
- const file = accepted[0];
23
22
  /** Prevent console error on <Dropzone /> component */
24
- setTimeout(() => this.selectFile(file), 100);
23
+ setTimeout(() => this.selectFile(accepted), 100);
25
24
  };
26
- this.selectFile = (file) => {
27
- file.preview = URL.createObjectURL(file);
28
- this.setState({
29
- file
25
+ this.selectFile = (files) => {
26
+ const { onSelectFile, onChange } = this.props;
27
+ files.forEach((file) => {
28
+ file.preview = URL.createObjectURL(file);
30
29
  });
31
- this.props.onSelectFile(file);
30
+ const newFiles = [...this.state.files, ...files];
31
+ this.setState({ files: newFiles });
32
+ onChange?.(newFiles);
33
+ if (onSelectFile) {
34
+ files.forEach((file) => {
35
+ onSelectFile(file);
36
+ });
37
+ }
32
38
  };
33
- this.handleRemoveFile = () => {
34
- const { file } = this.state;
35
- const { onRemoveFile } = this.props;
39
+ this.handleRemoveFile = (file) => {
40
+ const { files } = this.state;
36
41
  if (file) {
37
42
  if (file.preview)
38
43
  window.URL.revokeObjectURL(file.preview);
39
- onRemoveFile();
40
- this.setState({
41
- file: null
42
- });
44
+ const newFiles = files.filter((f) => f !== file);
45
+ this.setState({ files: newFiles });
46
+ this.props.onChange?.(newFiles);
47
+ this.props.onRemoveFile?.(file);
43
48
  }
44
49
  };
45
50
  }
46
51
  render() {
47
- const { file } = this.state;
52
+ const { files } = this.state;
48
53
  const { accept, previewComponent: Preview, dropHint, hoverHint, acceptHint, rejectHint,
49
54
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
55
+ onChange,
56
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
50
57
  onRemoveFile, onDownloadFile,
51
58
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
52
- onSelectFile, onDropRejected, onDropAccepted, maxSize, ...otherProps } = this.props;
59
+ onSelectFile, onDropRejected, onDropAccepted, maxSize, multiple, ...otherProps } = this.props;
53
60
  const dropHintOrDefault = dropHint || FileUpload.defaultProps.dropHint;
54
61
  const hoverHintOrDefault = hoverHint || FileUpload.defaultProps.hoverHint;
55
62
  const acceptHintOrDefault = acceptHint || FileUpload.defaultProps.acceptHint;
56
63
  const rejectHintOrDefault = rejectHint || FileUpload.defaultProps.rejectHint;
57
64
  return (React.createElement("div", { ...otherProps, className: classNames('di upload', {
58
- clickable: !file,
59
- hasContent: !!file
65
+ clickable: !files.length,
66
+ hasContent: !!files.length
60
67
  }) },
61
- !!file && !!Preview && (
62
- // @ts-ignore
63
- React.createElement(Preview, { file: file, onRemoveFile: this.handleRemoveFile, onDownloadFile: onDownloadFile })),
64
- !file && (React.createElement(Dropzone, { accept: accept, multiple: false, style: {
68
+ !!Preview &&
69
+ files.map((file, i) => (React.createElement(Preview, { key: i, file: file, onRemoveFile: () => this.handleRemoveFile(file),
70
+ // @ts-ignore
71
+ onDownloadFile: onDownloadFile && (() => onDownloadFile(file)) }))),
72
+ (multiple || !files.length) && (React.createElement(Dropzone, { accept: accept, multiple: multiple ?? false, style: {
65
73
  border: 'none'
66
74
  }, onDrop: this.handleDrop, onDropRejected: onDropRejected, onDropAccepted: onDropAccepted, activeClassName: "active", acceptClassName: "accept", rejectClassName: "reject", maxSize: maxSize || Infinity },
67
75
  React.createElement("div", { className: "drag-drop-text-container" },
@@ -1,12 +1,13 @@
1
1
  import * as React from 'react';
2
- import { Props as FileUploadProps } from './FileUpload';
3
- export declare type Props = FileUploadProps & {
2
+ import { DropzoneFile, Props as FileUploadProps } from './FileUpload';
3
+ export declare type Props = Omit<FileUploadProps, 'multiple'> & {
4
4
  /** (Optional) Url for the image preview */
5
5
  imageUrl: string | null | undefined;
6
6
  imageSize?: 'contain' | 'cover';
7
7
  };
8
8
  declare type ImageUploadState = {
9
9
  dragOverPreview: boolean;
10
+ file: DropzoneFile | null;
10
11
  };
11
12
  /**
12
13
  * ImageUpload enables the possibility to upload images conveniently
@@ -1 +1 @@
1
- {"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../../src/components/upload/ImageUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAmB,EAAC,KAAK,IAAI,eAAe,EAAC,MAAM,cAAc,CAAC;AA+BlE,oBAAY,KAAK,GAAG,eAAe,GAAG;IACrC,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAChC,CAAC;AAEF,aAAK,gBAAgB,GAAG;IACvB,eAAe,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAChF,KAAK,EAAE,gBAAgB,CAErB;IAEF,kBAAkB,CAAC,SAAS,EAAE,KAAK,GAAG,IAAI;IAQ1C,cAAc,EAAE,MAAM,IAAI,CAIxB;IAEF,MAAM;CAkBN"}
1
+ {"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../../src/components/upload/ImageUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAmB,EAAC,YAAY,EAAE,KAAK,IAAI,eAAe,EAAC,MAAM,cAAc,CAAC;AA+BhF,oBAAY,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,GAAG;IACvD,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAChC,CAAC;AAEF,aAAK,gBAAgB,GAAG;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAChF,KAAK,EAAE,gBAAgB,CAGrB;IAEF,kBAAkB,CAAC,SAAS,EAAE,KAAK,GAAG,IAAI;IAQ1C,cAAc,EAAE,MAAM,IAAI,CAIxB;IAEF,MAAM;CA+BN"}
@@ -17,7 +17,8 @@ export default class ImageUpload extends React.Component {
17
17
  constructor() {
18
18
  super(...arguments);
19
19
  this.state = {
20
- dragOverPreview: false
20
+ dragOverPreview: false,
21
+ file: null
21
22
  };
22
23
  this.handleDragOver = () => {
23
24
  this.setState({
@@ -33,13 +34,19 @@ export default class ImageUpload extends React.Component {
33
34
  }
34
35
  }
35
36
  render() {
36
- const { accept, imageUrl, imageSize, ...otherProps } = this.props;
37
- const { dragOverPreview } = this.state;
38
- if (imageUrl && !dragOverPreview) {
39
- return (React.createElement(PreviewImage, { url: imageUrl, imageSize: imageSize, onRemoveFile: otherProps.onRemoveFile, onDownloadFile: otherProps.onDownloadFile, onDragOver: this.handleDragOver }));
37
+ const { accept, imageUrl, imageSize, onSelectFile, onRemoveFile, ...otherProps } = this.props;
38
+ const { dragOverPreview, file } = this.state;
39
+ if (imageUrl && !dragOverPreview && file) {
40
+ return (React.createElement(PreviewImage, { url: imageUrl, imageSize: imageSize, onRemoveFile: () => onRemoveFile?.(file), onDownloadFile: () => otherProps.onDownloadFile?.(file), onDragOver: this.handleDragOver }));
40
41
  }
41
42
  else {
42
- return React.createElement(FileUpload, { ...otherProps, accept: accept || 'image/jpeg, image/png' });
43
+ return (React.createElement(FileUpload, { ...otherProps, onRemoveFile: (file) => {
44
+ this.setState({ file: null });
45
+ onRemoveFile?.(file);
46
+ }, onSelectFile: (file) => {
47
+ this.setState({ file });
48
+ onSelectFile?.(file);
49
+ }, accept: accept || 'image/jpeg, image/png' }));
43
50
  }
44
51
  }
45
52
  }
@@ -12,14 +12,14 @@ describe('DateTimeInput.js', () => {
12
12
  expect(timeElement).toHaveDisplayValue('03:24');
13
13
  });
14
14
  it('should display the time and date as timezone date', async () => {
15
- const { rerender } = render(React.createElement(DateTimeInput, { timestamp: new Date('2019-02-01T11:11:00').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
15
+ const { rerender } = render(React.createElement(DateTimeInput, { timestamp: new Date('2019-02-01T11:11:00Z').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
16
16
  const timeElementUtm = screen.queryByDisplayValue('11:11');
17
17
  expect(timeElementUtm).not.toBeInTheDocument();
18
18
  const timeElement = screen.queryByDisplayValue('03:11');
19
19
  expect(timeElement).toBeInTheDocument();
20
20
  const dateElement = screen.queryByDisplayValue('01.02.2019');
21
21
  expect(dateElement).toBeInTheDocument();
22
- rerender(React.createElement(DateTimeInput, { timestamp: new Date('2019-02-02T03:24:00').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
22
+ rerender(React.createElement(DateTimeInput, { timestamp: new Date('2019-02-02T03:24:00Z').getTime(), onChange: () => { }, timezone: "America/Vancouver" }));
23
23
  expect(timeElement).toHaveDisplayValue('19:24');
24
24
  expect(dateElement).toHaveDisplayValue('01.02.2019');
25
25
  await act(async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAuF5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ReactableTableFilterRow.d.ts","sourceRoot":"","sources":["../../../../../../src/components/reactable/helpers/ReactableTableFilterRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAIrE,aAAK,KAAK,GAAG;IACZ,UAAU,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,aAAa,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,QAAA,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA+F5C,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -6,14 +6,23 @@ const ReactableTableFilterRow = ({ columnDefs, onFilter, tableName }) => {
6
6
  const { t } = useTranslation();
7
7
  const [state, setState] = useState({});
8
8
  useEffect(() => {
9
- const initialFilters = columnDefs.reduce((acc, columnDef) => ({
10
- ...acc,
11
- [columnDef.name]: columnDef.filterable?.initialValue ?? ''
12
- }), {});
13
- setState(initialFilters);
14
- if (Object.values(initialFilters).some((value) => value)) {
15
- onFilter(initialFilters);
16
- }
9
+ setState((prev) => {
10
+ const merged = {};
11
+ for (const cd of columnDefs) {
12
+ merged[cd.name] = prev[cd.name] !== undefined ? prev[cd.name] : cd.filterable?.initialValue ?? '';
13
+ }
14
+ const prevKeys = Object.keys(prev);
15
+ const mergedKeys = Object.keys(merged);
16
+ const sameKeys = mergedKeys.length === prevKeys.length && mergedKeys.every((k) => prevKeys.includes(k));
17
+ const sameValues = sameKeys && mergedKeys.every((k) => merged[k] === prev[k]);
18
+ if (sameKeys && sameValues) {
19
+ return prev; // no change
20
+ }
21
+ if (Object.values(merged).some((v) => v)) {
22
+ onFilter(merged);
23
+ }
24
+ return merged;
25
+ });
17
26
  }, [columnDefs, onFilter]);
18
27
  const changeFilter = (columnName, value) => {
19
28
  const newState = { ...state, [columnName]: value };
@@ -10,12 +10,8 @@ export declare type PreviewComponentProps = {
10
10
  export declare type Props = {
11
11
  /** (Optional) string for accepting files */
12
12
  accept?: string;
13
- /** Function, executed when a file gets removed */
14
- onRemoveFile: () => void;
15
13
  /** Optional Function, executed to download the file */
16
- onDownloadFile?: () => void;
17
- /** Function, executed when a file gets selected */
18
- onSelectFile: (file: DropzoneFile) => void;
14
+ onDownloadFile?: (file: DropzoneFile) => void;
19
15
  /** (Optional) function, executed when a file gets dragged into the upload field and accepted */
20
16
  onDropAccepted?: () => void;
21
17
  /** (Optional) function, executed when a file gets dragged into the upload field and rejected */
@@ -32,9 +28,27 @@ export declare type Props = {
32
28
  previewComponent?: React.ComponentType<PreviewComponentProps>;
33
29
  /** (Optional) Maximum upload size */
34
30
  maxSize?: number;
35
- };
31
+ } & ({
32
+ /** (Optional) accept multiple files */
33
+ multiple?: false;
34
+ /** Function, executed when files get added or removed */
35
+ onChange?: (files: DropzoneFile[]) => void;
36
+ /** Function, executed when a file gets removed */
37
+ onRemoveFile: (file: DropzoneFile) => void;
38
+ /** Function, executed when a file gets selected */
39
+ onSelectFile: (file: DropzoneFile) => void;
40
+ } | {
41
+ /** (Optional) accept multiple files */
42
+ multiple: true;
43
+ /** Function, executed when files get added or removed */
44
+ onChange: (files: DropzoneFile[]) => void;
45
+ /** Function, executed when a file gets removed */
46
+ onRemoveFile?: (file: DropzoneFile) => void;
47
+ /** Function, executed when a file gets selected */
48
+ onSelectFile?: (file: DropzoneFile) => void;
49
+ });
36
50
  export declare type State = {
37
- file: DropzoneFile | null | undefined;
51
+ files: DropzoneFile[];
38
52
  };
39
53
  /**
40
54
  * FileUpload enables the possibility to upload files conveniently
@@ -60,8 +74,8 @@ export default class FileUpload extends React.Component<Props, State> {
60
74
  };
61
75
  state: State;
62
76
  handleDrop: (accepted: Array<DropzoneFile>, rejected: Array<DropzoneFile>) => void;
63
- selectFile: (arg0: DropzoneFile) => void;
64
- handleRemoveFile: () => void;
77
+ selectFile: (files: DropzoneFile[]) => void;
78
+ handleRemoveFile: (file: DropzoneFile) => void;
65
79
  render(): React.JSX.Element;
66
80
  }
67
81
  //# sourceMappingURL=FileUpload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileUpload.d.ts","sourceRoot":"","sources":["../../../../../src/components/upload/FileUpload.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EAAC,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,oBAAY,YAAY,GAAG,IAAI,GAAG;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,oBAAY,qBAAqB,GAAG;IACnC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAEF,oBAAY,KAAK,GAAG;IACnB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,kDAAkD;IAClD,YAAY,EAAE,MAAM,IAAI,CAAC;IAEzB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,mDAAmD;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAE3C,gGAAgG;IAChG,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,gGAAgG;IAChG,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAEjD,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IAEjC,qDAAqD;IACrD,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAElC,wDAAwD;IACxD,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAEnC,wDAAwD;IACxD,UAAU,CAAC,EAAE,qBAAqB,CAAC;IAEnC,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAE9D,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,oBAAY,KAAK,GAAG;IACnB,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;IACpE,MAAM,CAAC,YAAY,EAAE;QACpB,UAAU,EAAE;YACX,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,QAAQ,EAAE;YACT,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,SAAS,EAAE;YACV,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;QACF,UAAU,EAAE;YACX,YAAY,EAAE,MAAM,CAAC;YACrB,EAAE,EAAE,MAAM,CAAC;SACX,CAAC;KACF,CAiBC;IAEF,KAAK,EAAE,KAAK,CAEV;IAEF,UAAU,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC,KAAK,IAAI,CAgBhF;IAEF,UAAU,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAMtC;IAEF,gBAAgB,EAAE,MAAM,IAAI,CAW1B;IAEF,MAAM;CAqEN"}
1
+ {"version":3,"file":"FileUpload.d.ts","sourceRoot":"","sources":["../../../../../src/components/upload/FileUpload.tsx"],"names":[],"mappings":"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"}
@@ -10,58 +10,66 @@ export default class FileUpload extends React.Component {
10
10
  constructor() {
11
11
  super(...arguments);
12
12
  this.state = {
13
- file: null
13
+ files: []
14
14
  };
15
15
  this.handleDrop = (accepted, rejected) => {
16
- if (accepted.length > 1) {
16
+ if (!this.props.multiple && accepted.length > 1) {
17
17
  return;
18
18
  }
19
19
  if (rejected.length > 0) {
20
20
  return;
21
21
  }
22
- const file = accepted[0];
23
22
  /** Prevent console error on <Dropzone /> component */
24
- setTimeout(() => this.selectFile(file), 100);
23
+ setTimeout(() => this.selectFile(accepted), 100);
25
24
  };
26
- this.selectFile = (file) => {
27
- file.preview = URL.createObjectURL(file);
28
- this.setState({
29
- file
25
+ this.selectFile = (files) => {
26
+ const { onSelectFile, onChange } = this.props;
27
+ files.forEach((file) => {
28
+ file.preview = URL.createObjectURL(file);
30
29
  });
31
- this.props.onSelectFile(file);
30
+ const newFiles = [...this.state.files, ...files];
31
+ this.setState({ files: newFiles });
32
+ onChange?.(newFiles);
33
+ if (onSelectFile) {
34
+ files.forEach((file) => {
35
+ onSelectFile(file);
36
+ });
37
+ }
32
38
  };
33
- this.handleRemoveFile = () => {
34
- const { file } = this.state;
35
- const { onRemoveFile } = this.props;
39
+ this.handleRemoveFile = (file) => {
40
+ const { files } = this.state;
36
41
  if (file) {
37
42
  if (file.preview)
38
43
  window.URL.revokeObjectURL(file.preview);
39
- onRemoveFile();
40
- this.setState({
41
- file: null
42
- });
44
+ const newFiles = files.filter((f) => f !== file);
45
+ this.setState({ files: newFiles });
46
+ this.props.onChange?.(newFiles);
47
+ this.props.onRemoveFile?.(file);
43
48
  }
44
49
  };
45
50
  }
46
51
  render() {
47
- const { file } = this.state;
52
+ const { files } = this.state;
48
53
  const { accept, previewComponent: Preview, dropHint, hoverHint, acceptHint, rejectHint,
49
54
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
55
+ onChange,
56
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
50
57
  onRemoveFile, onDownloadFile,
51
58
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
52
- onSelectFile, onDropRejected, onDropAccepted, maxSize, ...otherProps } = this.props;
59
+ onSelectFile, onDropRejected, onDropAccepted, maxSize, multiple, ...otherProps } = this.props;
53
60
  const dropHintOrDefault = dropHint || FileUpload.defaultProps.dropHint;
54
61
  const hoverHintOrDefault = hoverHint || FileUpload.defaultProps.hoverHint;
55
62
  const acceptHintOrDefault = acceptHint || FileUpload.defaultProps.acceptHint;
56
63
  const rejectHintOrDefault = rejectHint || FileUpload.defaultProps.rejectHint;
57
64
  return (React.createElement("div", { ...otherProps, className: classNames('di upload', {
58
- clickable: !file,
59
- hasContent: !!file
65
+ clickable: !files.length,
66
+ hasContent: !!files.length
60
67
  }) },
61
- !!file && !!Preview && (
62
- // @ts-ignore
63
- React.createElement(Preview, { file: file, onRemoveFile: this.handleRemoveFile, onDownloadFile: onDownloadFile })),
64
- !file && (React.createElement(Dropzone, { accept: accept, multiple: false, style: {
68
+ !!Preview &&
69
+ files.map((file, i) => (React.createElement(Preview, { key: i, file: file, onRemoveFile: () => this.handleRemoveFile(file),
70
+ // @ts-ignore
71
+ onDownloadFile: onDownloadFile && (() => onDownloadFile(file)) }))),
72
+ (multiple || !files.length) && (React.createElement(Dropzone, { accept: accept, multiple: multiple ?? false, style: {
65
73
  border: 'none'
66
74
  }, onDrop: this.handleDrop, onDropRejected: onDropRejected, onDropAccepted: onDropAccepted, activeClassName: "active", acceptClassName: "accept", rejectClassName: "reject", maxSize: maxSize || Infinity },
67
75
  React.createElement("div", { className: "drag-drop-text-container" },
@@ -1,12 +1,13 @@
1
1
  import * as React from 'react';
2
- import { Props as FileUploadProps } from './FileUpload';
3
- export declare type Props = FileUploadProps & {
2
+ import { DropzoneFile, Props as FileUploadProps } from './FileUpload';
3
+ export declare type Props = Omit<FileUploadProps, 'multiple'> & {
4
4
  /** (Optional) Url for the image preview */
5
5
  imageUrl: string | null | undefined;
6
6
  imageSize?: 'contain' | 'cover';
7
7
  };
8
8
  declare type ImageUploadState = {
9
9
  dragOverPreview: boolean;
10
+ file: DropzoneFile | null;
10
11
  };
11
12
  /**
12
13
  * ImageUpload enables the possibility to upload images conveniently
@@ -1 +1 @@
1
- {"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../../../src/components/upload/ImageUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAmB,EAAC,KAAK,IAAI,eAAe,EAAC,MAAM,cAAc,CAAC;AA+BlE,oBAAY,KAAK,GAAG,eAAe,GAAG;IACrC,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAChC,CAAC;AAEF,aAAK,gBAAgB,GAAG;IACvB,eAAe,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAChF,KAAK,EAAE,gBAAgB,CAErB;IAEF,kBAAkB,CAAC,SAAS,EAAE,KAAK,GAAG,IAAI;IAQ1C,cAAc,EAAE,MAAM,IAAI,CAIxB;IAEF,MAAM;CAkBN"}
1
+ {"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../../../src/components/upload/ImageUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAmB,EAAC,YAAY,EAAE,KAAK,IAAI,eAAe,EAAC,MAAM,cAAc,CAAC;AA+BhF,oBAAY,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,GAAG;IACvD,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAChC,CAAC;AAEF,aAAK,gBAAgB,GAAG;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAChF,KAAK,EAAE,gBAAgB,CAGrB;IAEF,kBAAkB,CAAC,SAAS,EAAE,KAAK,GAAG,IAAI;IAQ1C,cAAc,EAAE,MAAM,IAAI,CAIxB;IAEF,MAAM;CA+BN"}
@@ -17,7 +17,8 @@ export default class ImageUpload extends React.Component {
17
17
  constructor() {
18
18
  super(...arguments);
19
19
  this.state = {
20
- dragOverPreview: false
20
+ dragOverPreview: false,
21
+ file: null
21
22
  };
22
23
  this.handleDragOver = () => {
23
24
  this.setState({
@@ -33,13 +34,19 @@ export default class ImageUpload extends React.Component {
33
34
  }
34
35
  }
35
36
  render() {
36
- const { accept, imageUrl, imageSize, ...otherProps } = this.props;
37
- const { dragOverPreview } = this.state;
38
- if (imageUrl && !dragOverPreview) {
39
- return (React.createElement(PreviewImage, { url: imageUrl, imageSize: imageSize, onRemoveFile: otherProps.onRemoveFile, onDownloadFile: otherProps.onDownloadFile, onDragOver: this.handleDragOver }));
37
+ const { accept, imageUrl, imageSize, onSelectFile, onRemoveFile, ...otherProps } = this.props;
38
+ const { dragOverPreview, file } = this.state;
39
+ if (imageUrl && !dragOverPreview && file) {
40
+ return (React.createElement(PreviewImage, { url: imageUrl, imageSize: imageSize, onRemoveFile: () => onRemoveFile?.(file), onDownloadFile: () => otherProps.onDownloadFile?.(file), onDragOver: this.handleDragOver }));
40
41
  }
41
42
  else {
42
- return React.createElement(FileUpload, { ...otherProps, accept: accept || 'image/jpeg, image/png' });
43
+ return (React.createElement(FileUpload, { ...otherProps, onRemoveFile: (file) => {
44
+ this.setState({ file: null });
45
+ onRemoveFile?.(file);
46
+ }, onSelectFile: (file) => {
47
+ this.setState({ file });
48
+ onSelectFile?.(file);
49
+ }, accept: accept || 'image/jpeg, image/png' }));
43
50
  }
44
51
  }
45
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deviceinsight/ng-ui-components",
3
- "version": "6.24.0",
3
+ "version": "6.26.0",
4
4
  "private": false,
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {
@@ -36,29 +36,29 @@
36
36
  "storybook": "start-storybook -p 6006"
37
37
  },
38
38
  "dependencies": {
39
- "@deviceinsight/ng-ui-api-client": "10.39.0",
40
- "@deviceinsight/ng-ui-basic-components": "3.16.0",
41
- "@dnd-kit/core": "6.0.5",
42
- "@dnd-kit/modifiers": "6.0.0",
43
- "@dnd-kit/sortable": "7.0.1",
44
- "@svgdotjs/svg.js": "3.0.16",
45
- "classnames": "2.3.1",
46
- "dayjs": "1.11.0",
47
- "highcharts": "10.2.1",
48
- "highcharts-react-official": "3.1.0",
49
- "lodash": "4.17.21",
50
- "nanoid": "3.3.8",
51
- "pure-color": "1.3.0",
52
- "rc-slider": "9.7.5",
53
- "react-colorful": "5.5.1",
54
- "react-datepicker": "4.10.0",
55
- "react-draggable": "4.4.3",
56
- "react-dropzone": "7.0.1",
57
- "react-onclickoutside": "6.12.2",
58
- "react-popper": "2.3.0",
59
- "react-select": "5.7.0",
60
- "react-select-async-paginate": "0.7.2",
61
- "react-toastify": "7.0.3"
39
+ "@deviceinsight/ng-ui-api-client": "^10.39.0",
40
+ "@deviceinsight/ng-ui-basic-components": "^3.16.0",
41
+ "@dnd-kit/core": "^6.0.5",
42
+ "@dnd-kit/modifiers": "^6.0.0",
43
+ "@dnd-kit/sortable": "^7.0.1",
44
+ "@svgdotjs/svg.js": "^3.0.16",
45
+ "classnames": "^2.3.1",
46
+ "dayjs": "^1.11.0",
47
+ "highcharts": "^10.2.1",
48
+ "highcharts-react-official": "^3.1.0",
49
+ "lodash": "^4.17.21",
50
+ "nanoid": "^3.3.8",
51
+ "pure-color": "^1.3.0",
52
+ "rc-slider": "^9.7.5",
53
+ "react-colorful": "^5.5.1",
54
+ "react-datepicker": "^4.10.0",
55
+ "react-draggable": "^4.4.3",
56
+ "react-dropzone": "^7.0.1",
57
+ "react-onclickoutside": "^6.12.2",
58
+ "react-popper": "^2.3.0",
59
+ "react-select": "^5.7.0",
60
+ "react-select-async-paginate": "^0.7.2",
61
+ "react-toastify": "^7.0.3"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "react": "^18.x",