@iobroker/gui-components 10.4.0 → 10.4.1

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
@@ -36,7 +36,7 @@ npm create vite@latest src -- --template react-ts
36
36
  "dependencies": {
37
37
  "@emotion/react": "^11.14.0",
38
38
  "@emotion/styled": "^11.14.1",
39
- "@iobroker/gui-components": "^10.4.0",
39
+ "@iobroker/gui-components": "^10.4.1",
40
40
  "@mui/icons-material": "^9.0.1",
41
41
  "@mui/material": "^9.0.1",
42
42
  "react": "^19.2.5",
@@ -877,6 +877,10 @@ You can find the migration instructions:
877
877
  -->
878
878
 
879
879
  ## Changelog
880
+ ### 10.4.1 (2026-11-05)
881
+ - (@GermanBluefox) Changed: `UploadImage`: the upload symbol is animated (it bobs while a file is dragged over the drop area and moves up while the file is read), the drop area pulses while a file is dragged over it, also over an existing image, and a new image fades in
882
+ - (@GermanBluefox) Added: `UploadImage` got the props `uploading` and `uploadError`: while the parent uploads the image (e.g. writes it into a file) an upload arrow is shown in the corner of the image, followed by a check mark or a cross
883
+
880
884
  ### 10.4.0 (2026-11-04)
881
885
  - (@GermanBluefox) Changed: the animated trash can is used for all delete buttons: file browser, `TreeTable`, `ColorPicker`, `DialogComplexCron` and the context menu of the object browser. The lid stays open while the delete confirmation is shown
882
886
  - (@GermanBluefox) Changed: file browser: the reload button turns while the files are read
@@ -8,16 +8,38 @@ interface UploadImageProps {
8
8
  icon: string | null;
9
9
  removeIconFunc: () => void | null;
10
10
  accept?: Record<string, string[]>;
11
+ /**
12
+ * The parent uploads the image given with `onChange`, e.g. writes it into a file: the upload arrow moves up in
13
+ * the corner of the image. When it becomes false, a check mark is shown there for a moment.
14
+ */
15
+ uploading?: boolean;
16
+ /** The upload failed: when `uploading` becomes false, a cross is shown instead of the check mark */
17
+ uploadError?: boolean;
11
18
  }
12
19
  interface UploadImageState {
13
20
  uploadFile: boolean | 'dragging';
14
21
  anchorEl: HTMLElement | null;
15
22
  cropHandler: boolean;
23
+ /** The dropped file is being read */
24
+ reading: boolean;
25
+ /** Result of the last upload of the parent, shown for a moment */
26
+ result: {
27
+ type: 'success' | 'error';
28
+ count: number;
29
+ } | null;
16
30
  }
17
31
  export declare class UploadImage extends Component<UploadImageProps, UploadImageState> {
18
32
  private readonly cropperRef;
33
+ private readonly imageRef;
34
+ private resultTimeout;
19
35
  constructor(props: UploadImageProps);
36
+ componentDidUpdate(prevProps: UploadImageProps): void;
37
+ componentWillUnmount(): void;
38
+ /** Shows a check mark or a cross in the corner of the image for a moment */
39
+ showResult(type: 'success' | 'error'): void;
20
40
  onDrop(acceptedFiles: File[]): void;
41
+ /** Upload of the parent and its result in the corner of the image (without image, the big upload symbol shows it) */
42
+ renderUploadIndicator(): JSX.Element | null;
21
43
  render(): JSX.Element;
22
44
  }
23
45
  export {};
@@ -1,10 +1,16 @@
1
1
  import React, { Component, createRef } from 'react';
2
2
  import Dropzone from 'react-dropzone';
3
3
  import { Cropper } from 'react-cropper';
4
- import { Menu, MenuItem, Tooltip, IconButton } from '@mui/material';
5
- import { Close as IconClose, Crop as CropIcon, UploadFileOutlined as UploadIcon } from '@mui/icons-material';
4
+ import { Menu, MenuItem, Tooltip, IconButton, Box } from '@mui/material';
5
+ import { alpha } from '@mui/material/styles';
6
+ import { Close as IconClose, Crop as CropIcon } from '@mui/icons-material';
6
7
  import { I18n } from '../i18n';
7
8
  import { Icon } from './Icon';
9
+ import { IconUpload } from './AnimatedIcons/IconUpload';
10
+ import { IconResult } from './AnimatedIcons/IconResult';
11
+ import { play } from './AnimatedIcons/common';
12
+ /** How long the result of an upload stays visible */
13
+ const RESULT_DURATION = 2500;
8
14
  // import 'cropperjs/dist/cropper.css';
9
15
  const cropperStyles = `
10
16
  /*!
@@ -326,6 +332,12 @@ const styles = {
326
332
  width: '100%',
327
333
  height: '100%',
328
334
  },
335
+ /** The new image fades in */
336
+ imageWrapper: {
337
+ display: 'flex',
338
+ width: '100%',
339
+ height: '100%',
340
+ },
329
341
  uploadDiv: {
330
342
  position: 'relative',
331
343
  width: '100%',
@@ -339,9 +351,9 @@ const styles = {
339
351
  opacity: 1,
340
352
  background: 'rgba(128,255,128,0.1)',
341
353
  },
354
+ /** The border is set with `dropAreaSx`, so that it can pulse */
342
355
  uploadCenterDiv: {
343
356
  margin: 5,
344
- border: '3px dashed grey',
345
357
  borderRadius: 5,
346
358
  width: 'calc(100% - 10px)',
347
359
  height: 'calc(100% - 10px)',
@@ -349,13 +361,29 @@ const styles = {
349
361
  display: 'flex',
350
362
  },
351
363
  uploadCenterIcon: {
352
- paddingTop: 10,
353
- width: 48,
354
- height: 48,
364
+ marginTop: 10,
355
365
  },
356
366
  uploadCenterText: {
357
367
  fontSize: 16,
358
368
  },
369
+ /** A file is dragged over an existing image */
370
+ dropOverImage: {
371
+ position: 'absolute',
372
+ inset: 0,
373
+ zIndex: 1,
374
+ pointerEvents: 'none',
375
+ },
376
+ /** Upload and its result in the corner of the image */
377
+ uploadIndicator: {
378
+ position: 'absolute',
379
+ top: 8,
380
+ left: 8,
381
+ zIndex: 223,
382
+ display: 'flex',
383
+ padding: 4,
384
+ borderRadius: '50%',
385
+ pointerEvents: 'none',
386
+ },
359
387
  uploadCenterTextAndIcon: {
360
388
  textAlign: 'center',
361
389
  position: 'absolute',
@@ -383,21 +411,42 @@ const styles = {
383
411
  right: 0,
384
412
  top: 50,
385
413
  },
386
- error: {
387
- border: '2px solid red',
388
- boxSizing: 'border-box',
389
- },
390
414
  };
415
+ /** Border of the drop area: red on error, and it pulses while a file is dragged over it */
416
+ function dropAreaSx(theme, error, dragging) {
417
+ if (error) {
418
+ return { border: '2px solid red', boxSizing: 'border-box' };
419
+ }
420
+ if (!dragging) {
421
+ return { border: '3px dashed grey' };
422
+ }
423
+ return {
424
+ border: `3px dashed ${theme.palette.primary.main}`,
425
+ animation: 'iob-upload-image-pulse 1.2s ease-in-out infinite',
426
+ '@keyframes iob-upload-image-pulse': {
427
+ '0%': { boxShadow: `0 0 0 0 ${alpha(theme.palette.primary.main, 0.4)}` },
428
+ '70%, 100%': { boxShadow: `0 0 0 14px ${alpha(theme.palette.primary.main, 0)}` },
429
+ },
430
+ '@media (prefers-reduced-motion: reduce)': {
431
+ animation: 'none',
432
+ },
433
+ };
434
+ }
391
435
  export class UploadImage extends Component {
392
436
  cropperRef;
437
+ imageRef;
438
+ resultTimeout = null;
393
439
  constructor(props) {
394
440
  super(props);
395
441
  this.state = {
396
442
  uploadFile: false,
397
443
  anchorEl: null,
398
444
  cropHandler: false,
445
+ reading: false,
446
+ result: null,
399
447
  };
400
448
  this.cropperRef = createRef();
449
+ this.imageRef = createRef();
401
450
  if (!window.document.getElementById('cropper-style-json-component')) {
402
451
  const style = window.document.createElement('style');
403
452
  style.setAttribute('id', 'cropper-style-json-component');
@@ -405,14 +454,51 @@ export class UploadImage extends Component {
405
454
  window.document.head.appendChild(style);
406
455
  }
407
456
  }
457
+ componentDidUpdate(prevProps) {
458
+ if (prevProps.uploading && !this.props.uploading) {
459
+ this.showResult(this.props.uploadError ? 'error' : 'success');
460
+ }
461
+ if (this.props.icon && prevProps.icon !== this.props.icon) {
462
+ // the new image fades in
463
+ play(this.imageRef.current, [
464
+ { opacity: 0, transform: 'scale(0.92)' },
465
+ { opacity: 1, transform: 'scale(1)' },
466
+ ], { duration: 280, easing: 'cubic-bezier(0.2, 0.8, 0.3, 1)' });
467
+ }
468
+ }
469
+ componentWillUnmount() {
470
+ if (this.resultTimeout) {
471
+ clearTimeout(this.resultTimeout);
472
+ this.resultTimeout = null;
473
+ }
474
+ }
475
+ /** Shows a check mark or a cross in the corner of the image for a moment */
476
+ showResult(type) {
477
+ if (this.resultTimeout) {
478
+ clearTimeout(this.resultTimeout);
479
+ }
480
+ this.setState({ result: { type, count: (this.state.result?.count || 0) + 1 } });
481
+ this.resultTimeout = setTimeout(() => {
482
+ this.resultTimeout = null;
483
+ this.setState({ result: null });
484
+ }, RESULT_DURATION);
485
+ }
408
486
  onDrop(acceptedFiles) {
409
487
  const onChange = this.props.onChange;
410
488
  const maxSize = this.props.maxSize || 10 * 1024;
411
489
  const file = acceptedFiles[0];
412
490
  const reader = new FileReader();
413
- reader.onabort = () => console.log('file reading was aborted');
414
- reader.onerror = () => console.log('file reading has failed');
491
+ // the upload arrow moves up while the file is read
492
+ reader.onabort = () => {
493
+ console.log('file reading was aborted');
494
+ this.setState({ reading: false });
495
+ };
496
+ reader.onerror = () => {
497
+ console.log('file reading has failed');
498
+ this.setState({ reading: false });
499
+ };
415
500
  reader.onload = () => {
501
+ this.setState({ reading: false });
416
502
  if (!file || !file.name) {
417
503
  return;
418
504
  }
@@ -437,13 +523,23 @@ export class UploadImage extends Component {
437
523
  }
438
524
  }
439
525
  };
526
+ this.setState({ reading: true });
440
527
  reader.readAsArrayBuffer(file);
441
528
  }
529
+ /** Upload of the parent and its result in the corner of the image (without image, the big upload symbol shows it) */
530
+ renderUploadIndicator() {
531
+ const { result } = this.state;
532
+ if (!this.props.icon || (!result && !this.props.uploading)) {
533
+ return null;
534
+ }
535
+ return (React.createElement(Box, { style: styles.uploadIndicator, sx: { bgcolor: 'background.paper', color: 'text.primary' } }, result ? (React.createElement(IconResult, { type: result.type, replay: result.count })) : (React.createElement(IconUpload, { uploading: true }))));
536
+ }
442
537
  render() {
443
538
  const { disabled, icon, removeIconFunc, error, crop, onChange } = this.props;
444
539
  const maxSize = this.props.maxSize || 10 * 1024;
445
540
  let accept = this.props.accept || { 'image/*': [] };
446
541
  const { uploadFile, anchorEl, cropHandler } = this.state;
542
+ const dragging = uploadFile === 'dragging';
447
543
  // covert '"image/png"' to { 'image/*': [] }
448
544
  if (typeof accept === 'string') {
449
545
  accept = { [accept]: [] };
@@ -471,10 +567,10 @@ export class UploadImage extends Component {
471
567
  ...(!icon ? styles.dropZoneEmpty : undefined),
472
568
  }, ...getRootProps() },
473
569
  React.createElement("input", { ...getInputProps() }),
474
- React.createElement("div", { style: { ...styles.uploadCenterDiv, ...(error ? styles.error : undefined) } },
570
+ React.createElement(Box, { style: styles.uploadCenterDiv, sx: (theme) => dropAreaSx(theme, !!error, dragging) },
475
571
  !icon ? (React.createElement("div", { style: styles.uploadCenterTextAndIcon },
476
- React.createElement(UploadIcon, { style: styles.uploadCenterIcon }),
477
- React.createElement("div", { style: styles.uploadCenterText }, uploadFile === 'dragging'
572
+ React.createElement(IconUpload, { fontSize: 48, style: styles.uploadCenterIcon, ready: dragging, uploading: this.state.reading || !!this.props.uploading }),
573
+ React.createElement("div", { style: styles.uploadCenterText }, dragging
478
574
  ? I18n.t('ra_Drop file here')
479
575
  : I18n.t('ra_Place your files here or click here to open the browse dialog')))) : (removeIconFunc &&
480
576
  !cropHandler && (React.createElement("div", { style: styles.buttonRemoveWrapper },
@@ -509,7 +605,14 @@ export class UploadImage extends Component {
509
605
  }
510
606
  }) }, I18n.t('ra_Save')),
511
607
  React.createElement(MenuItem, { onClick: () => this.setState({ anchorEl: null, cropHandler: false }) }, I18n.t('ra_Close'))))),
512
- icon && !cropHandler ? (React.createElement(Icon, { src: icon, style: styles.image, alt: "icon" })) : null,
608
+ icon && !cropHandler ? (React.createElement("div", { ref: this.imageRef, style: styles.imageWrapper },
609
+ React.createElement(Icon, { src: icon, style: styles.image, alt: "icon" }))) : null,
610
+ icon && dragging ? (React.createElement(Box, { style: { ...styles.uploadCenterTextAndIcon, ...styles.dropOverImage }, sx: (theme) => ({
611
+ bgcolor: alpha(theme.palette.background.paper, 0.85),
612
+ }) },
613
+ React.createElement(IconUpload, { fontSize: 48, style: styles.uploadCenterIcon, ready: true }),
614
+ React.createElement("div", { style: styles.uploadCenterText }, I18n.t('ra_Drop file here')))) : null,
615
+ this.renderUploadIndicator(),
513
616
  icon && crop && cropHandler ? (React.createElement(Cropper, { ref: this.cropperRef, style: styles.image, src: icon, initialAspectRatio: 1, viewMode: 1, guides: false, minCropBoxHeight: 10, minCropBoxWidth: 10, background: false, checkOrientation: false })) : null)))));
514
617
  }
515
618
  }
@@ -1 +1 @@
1
- {"version":3,"file":"UploadImage.js","sourceRoot":"./src/","sources":["Components/UploadImage.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { Component, createRef, type JSX } from 'react';\nimport Dropzone, { type FileRejection } from 'react-dropzone';\nimport { Cropper, type ReactCropperElement } from 'react-cropper';\n\nimport { Menu, MenuItem, Tooltip, IconButton } from '@mui/material';\n\nimport { Close as IconClose, Crop as CropIcon, UploadFileOutlined as UploadIcon } from '@mui/icons-material';\n\nimport { I18n } from '../i18n';\nimport { Icon } from './Icon';\n\n// import 'cropperjs/dist/cropper.css';\nconst cropperStyles = `\n/*!\n * Cropper.js v1.5.12\n * https://fengyuanchen.github.io/cropperjs\n *\n * Copyright 2015-present Chen Fengyuan\n * Released under the MIT license\n *\n * Date: 2021-06-12T08:00:11.623Z\n */\n\n.cropper-container {\n direction: ltr;\n font-size: 0;\n line-height: 0;\n position: relative;\n -ms-touch-action: none;\n touch-action: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n\n.cropper-container img {\n display: block;\n height: 100%;\n image-orientation: 0deg;\n max-height: none !important;\n max-width: none !important;\n min-height: 0 !important;\n min-width: 0 !important;\n width: 100%;\n}\n\n.cropper-wrap-box,\n.cropper-canvas,\n.cropper-drag-box,\n.cropper-crop-box,\n.cropper-modal {\n bottom: 0;\n left: 0;\n position: absolute;\n right: 0;\n top: 0;\n}\n\n.cropper-wrap-box,\n.cropper-canvas {\n overflow: hidden;\n}\n\n.cropper-drag-box {\n background-color: #fff;\n opacity: 0;\n}\n\n.cropper-modal {\n background-color: #000;\n opacity: 0.5;\n}\n\n.cropper-view-box {\n display: block;\n height: 100%;\n outline: 1px solid #39f;\n outline-color: rgba(51, 153, 255, 0.75);\n overflow: hidden;\n width: 100%;\n}\n\n.cropper-dashed {\n border: 0 dashed #eee;\n display: block;\n opacity: 0.5;\n position: absolute;\n}\n\n.cropper-dashed.dashed-h {\n border-bottom-width: 1px;\n border-top-width: 1px;\n height: calc(100% / 3);\n left: 0;\n top: calc(100% / 3);\n width: 100%;\n}\n\n.cropper-dashed.dashed-v {\n border-left-width: 1px;\n border-right-width: 1px;\n height: 100%;\n left: calc(100% / 3);\n top: 0;\n width: calc(100% / 3);\n}\n\n.cropper-center {\n display: block;\n height: 0;\n left: 50%;\n opacity: 0.75;\n position: absolute;\n top: 50%;\n width: 0;\n}\n\n.cropper-center::before,\n.cropper-center::after {\n background-color: #eee;\n content: ' ';\n display: block;\n position: absolute;\n}\n\n.cropper-center::before {\n height: 1px;\n left: -3px;\n top: 0;\n width: 7px;\n}\n\n.cropper-center::after {\n height: 7px;\n left: 0;\n top: -3px;\n width: 1px;\n}\n\n.cropper-face,\n.cropper-line,\n.cropper-point {\n display: block;\n height: 100%;\n opacity: 0.1;\n position: absolute;\n width: 100%;\n}\n\n.cropper-face {\n background-color: #fff;\n left: 0;\n top: 0;\n}\n\n.cropper-line {\n background-color: #39f;\n}\n\n.cropper-line.line-e {\n cursor: ew-resize;\n right: -3px;\n top: 0;\n width: 5px;\n}\n\n.cropper-line.line-n {\n cursor: ns-resize;\n height: 5px;\n left: 0;\n top: -3px;\n}\n\n.cropper-line.line-w {\n cursor: ew-resize;\n left: -3px;\n top: 0;\n width: 5px;\n}\n\n.cropper-line.line-s {\n bottom: -3px;\n cursor: ns-resize;\n height: 5px;\n left: 0;\n}\n\n.cropper-point {\n background-color: #39f;\n height: 5px;\n opacity: 0.75;\n width: 5px;\n}\n\n.cropper-point.point-e {\n cursor: ew-resize;\n margin-top: -3px;\n right: -3px;\n top: 50%;\n}\n\n.cropper-point.point-n {\n cursor: ns-resize;\n left: 50%;\n margin-left: -3px;\n top: -3px;\n}\n\n.cropper-point.point-w {\n cursor: ew-resize;\n left: -3px;\n margin-top: -3px;\n top: 50%;\n}\n\n.cropper-point.point-s {\n bottom: -3px;\n cursor: s-resize;\n left: 50%;\n margin-left: -3px;\n}\n\n.cropper-point.point-ne {\n cursor: nesw-resize;\n right: -3px;\n top: -3px;\n}\n\n.cropper-point.point-nw {\n cursor: nwse-resize;\n left: -3px;\n top: -3px;\n}\n\n.cropper-point.point-sw {\n bottom: -3px;\n cursor: nesw-resize;\n left: -3px;\n}\n\n.cropper-point.point-se {\n bottom: -3px;\n cursor: nwse-resize;\n height: 20px;\n opacity: 1;\n right: -3px;\n width: 20px;\n}\n\n@media (min-width: 768px) {\n .cropper-point.point-se {\n height: 15px;\n width: 15px;\n }\n}\n\n@media (min-width: 992px) {\n .cropper-point.point-se {\n height: 10px;\n width: 10px;\n }\n}\n\n@media (min-width: 1200px) {\n .cropper-point.point-se {\n height: 5px;\n opacity: 0.75;\n width: 5px;\n }\n}\n\n.cropper-point.point-se::before {\n background-color: #39f;\n bottom: -50%;\n content: ' ';\n display: block;\n height: 200%;\n opacity: 0;\n position: absolute;\n right: -50%;\n width: 200%;\n}\n\n.cropper-invisible {\n opacity: 0;\n}\n\n.cropper-bg {\n background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');\n}\n\n.cropper-hide {\n display: block;\n height: 0;\n position: absolute;\n width: 0;\n}\n\n.cropper-hidden {\n display: none !important;\n}\n\n.cropper-move {\n cursor: move;\n}\n\n.cropper-crop {\n cursor: crosshair;\n}\n\n.cropper-disabled .cropper-drag-box,\n.cropper-disabled .cropper-face,\n.cropper-disabled .cropper-line,\n.cropper-disabled .cropper-point {\n cursor: not-allowed;\n}\n`;\n\nconst styles: Record<string, React.CSSProperties> = {\n dropZone: {\n width: '100%',\n height: 100,\n position: 'relative',\n },\n dropZoneEmpty: {},\n image: {\n objectFit: 'contain',\n margin: 'auto',\n display: 'flex',\n width: '100%',\n height: '100%',\n },\n\n uploadDiv: {\n position: 'relative',\n width: '100%',\n height: 300,\n opacity: 0.9,\n marginTop: 30,\n cursor: 'pointer',\n outline: 'none',\n },\n uploadDivDragging: {\n opacity: 1,\n background: 'rgba(128,255,128,0.1)',\n },\n\n uploadCenterDiv: {\n margin: 5,\n border: '3px dashed grey',\n borderRadius: 5,\n width: 'calc(100% - 10px)',\n height: 'calc(100% - 10px)',\n position: 'relative',\n display: 'flex',\n },\n uploadCenterIcon: {\n paddingTop: 10,\n width: 48,\n height: 48,\n },\n uploadCenterText: {\n fontSize: 16,\n },\n uploadCenterTextAndIcon: {\n textAlign: 'center',\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n },\n disabledOpacity: {\n opacity: 0.3,\n cursor: 'default',\n },\n buttonRemoveWrapper: {\n position: 'absolute',\n zIndex: 222,\n right: 0,\n },\n buttonCropWrapper: {\n position: 'absolute',\n zIndex: 222,\n right: 0,\n top: 50,\n },\n error: {\n border: '2px solid red',\n boxSizing: 'border-box',\n },\n};\n\ninterface UploadImageProps {\n maxSize?: number;\n disabled?: boolean;\n crop?: boolean;\n error?: boolean;\n onChange: (base64: string) => void | undefined;\n icon: string | null;\n removeIconFunc: () => void | null;\n accept?: Record<string, string[]>;\n}\n\ninterface UploadImageState {\n uploadFile: boolean | 'dragging';\n anchorEl: HTMLElement | null;\n cropHandler: boolean;\n}\n\nexport class UploadImage extends Component<UploadImageProps, UploadImageState> {\n private readonly cropperRef: React.RefObject<ReactCropperElement | null>;\n\n constructor(props: UploadImageProps) {\n super(props);\n\n this.state = {\n uploadFile: false,\n anchorEl: null,\n cropHandler: false,\n };\n this.cropperRef = createRef();\n\n if (!window.document.getElementById('cropper-style-json-component')) {\n const style = window.document.createElement('style');\n style.setAttribute('id', 'cropper-style-json-component');\n style.innerHTML = cropperStyles;\n window.document.head.appendChild(style);\n }\n }\n\n onDrop(acceptedFiles: File[]): void {\n const onChange = this.props.onChange;\n const maxSize = this.props.maxSize || 10 * 1024;\n\n const file = acceptedFiles[0];\n const reader = new FileReader();\n\n reader.onabort = () => console.log('file reading was aborted');\n reader.onerror = () => console.log('file reading has failed');\n reader.onload = () => {\n if (!file || !file.name) {\n return;\n }\n const parts = file.name?.split('.');\n let ext = parts?.length ? `image/${parts.pop()?.toLowerCase()}` : 'image/jpeg';\n if (ext === 'image/jpg') {\n ext = 'image/jpeg';\n } else if (ext.includes('svg')) {\n ext = 'image/svg+xml';\n }\n if (file.size > maxSize) {\n window.alert(I18n.t('ra_File is too big. Max %sk allowed. Try use SVG.', Math.round(maxSize / 1024)));\n } else {\n const base64 = `data:${ext};base64,${btoa(\n new Uint8Array(reader.result as ArrayBufferLike).reduce(\n (data, byte) => data + String.fromCharCode(byte),\n '',\n ),\n )}`;\n\n if (onChange) {\n onChange(base64);\n } else {\n console.log(base64);\n }\n }\n };\n reader.readAsArrayBuffer(file);\n }\n\n render(): JSX.Element {\n const { disabled, icon, removeIconFunc, error, crop, onChange } = this.props;\n const maxSize = this.props.maxSize || 10 * 1024;\n let accept = this.props.accept || { 'image/*': [] };\n const { uploadFile, anchorEl, cropHandler } = this.state;\n\n // covert '\"image/png\"' to { 'image/*': [] }\n if (typeof accept === 'string') {\n accept = { [accept]: [] };\n } else if (Array.isArray(accept)) {\n const result: Record<string, string[]> = {};\n accept.forEach(item => {\n result[item] = [];\n });\n accept = result;\n }\n\n return (\n <Dropzone\n disabled={!!disabled || cropHandler}\n key=\"dropzone\"\n multiple={false}\n accept={accept}\n maxSize={maxSize}\n onDragEnter={() => this.setState({ uploadFile: 'dragging' })}\n onDragLeave={() => this.setState({ uploadFile: true })}\n onDrop={(acceptedFiles: File[], errors: FileRejection[]) => {\n this.setState({ uploadFile: false });\n if (!acceptedFiles.length) {\n window.alert(errors?.[0]?.errors?.[0]?.message || I18n.t('ra_Cannot upload'));\n } else {\n this.onDrop(acceptedFiles);\n }\n }}\n >\n {({ getRootProps, getInputProps }) => (\n <div\n style={{\n ...styles.uploadDiv,\n ...(uploadFile === 'dragging' ? styles.uploadDivDragging : undefined),\n ...styles.dropZone,\n ...(disabled ? styles.disabledOpacity : undefined),\n ...(!icon ? styles.dropZoneEmpty : undefined),\n }}\n {...getRootProps()}\n >\n <input {...getInputProps()} />\n <div style={{ ...styles.uploadCenterDiv, ...(error ? styles.error : undefined) }}>\n {!icon ? (\n <div style={styles.uploadCenterTextAndIcon}>\n <UploadIcon style={styles.uploadCenterIcon} />\n <div style={styles.uploadCenterText}>\n {uploadFile === 'dragging'\n ? I18n.t('ra_Drop file here')\n : I18n.t(\n 'ra_Place your files here or click here to open the browse dialog',\n )}\n </div>\n </div>\n ) : (\n removeIconFunc &&\n !cropHandler && (\n <div style={styles.buttonRemoveWrapper}>\n <Tooltip\n title={I18n.t('ra_Clear')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n size=\"large\"\n onClick={e => {\n removeIconFunc && removeIconFunc();\n e.stopPropagation();\n }}\n >\n <IconClose />\n </IconButton>\n </Tooltip>\n </div>\n )\n )}\n {icon && crop && (\n <div style={styles.buttonCropWrapper}>\n <Tooltip\n title={I18n.t('ra_Crop')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n size=\"large\"\n onClick={e => {\n if (!cropHandler) {\n this.setState({ cropHandler: true });\n } else {\n this.setState({ anchorEl: e.currentTarget });\n }\n e.stopPropagation();\n }}\n >\n <CropIcon color={cropHandler ? 'primary' : 'inherit'} />\n </IconButton>\n </Tooltip>\n <Menu\n anchorEl={anchorEl}\n keepMounted\n open={Boolean(anchorEl)}\n onClose={() => this.setState({ anchorEl: null })}\n >\n <MenuItem\n onClick={() =>\n this.setState({ anchorEl: null, cropHandler: false }, () => {\n const imageElement = this.cropperRef?.current?.cropper;\n if (imageElement) {\n if (onChange) {\n onChange(imageElement.getCroppedCanvas().toDataURL());\n } else {\n console.log(imageElement.getCroppedCanvas().toDataURL());\n }\n }\n })\n }\n >\n {I18n.t('ra_Save')}\n </MenuItem>\n <MenuItem onClick={() => this.setState({ anchorEl: null, cropHandler: false })}>\n {I18n.t('ra_Close')}\n </MenuItem>\n </Menu>\n </div>\n )}\n {icon && !cropHandler ? (\n <Icon\n src={icon}\n style={styles.image}\n alt=\"icon\"\n />\n ) : null}\n\n {icon && crop && cropHandler ? (\n <Cropper\n ref={this.cropperRef}\n style={styles.image}\n src={icon}\n initialAspectRatio={1}\n viewMode={1}\n guides={false}\n minCropBoxHeight={10}\n minCropBoxWidth={10}\n background={false}\n checkOrientation={false}\n />\n ) : null}\n </div>\n </div>\n )}\n </Dropzone>\n );\n }\n}\n"]}
1
+ {"version":3,"file":"UploadImage.js","sourceRoot":"./src/","sources":["Components/UploadImage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAC9D,OAAO,QAAgC,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAA4B,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,KAAK,EAAc,MAAM,sBAAsB,CAAC;AAEzD,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAE9C,qDAAqD;AACrD,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B,uCAAuC;AACvC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiTrB,CAAC;AAEF,MAAM,MAAM,GAAwC;IAChD,QAAQ,EAAE;QACN,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,GAAG;QACX,QAAQ,EAAE,UAAU;KACvB;IACD,aAAa,EAAE,EAAE;IACjB,KAAK,EAAE;QACH,SAAS,EAAE,SAAS;QACpB,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,MAAM;KACjB;IACD,6BAA6B;IAC7B,YAAY,EAAE;QACV,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,MAAM;KACjB;IAED,SAAS,EAAE;QACP,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,GAAG;QACZ,SAAS,EAAE,EAAE;QACb,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,MAAM;KAClB;IACD,iBAAiB,EAAE;QACf,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,uBAAuB;KACtC;IAED,gEAAgE;IAChE,eAAe,EAAE;QACb,MAAM,EAAE,CAAC;QACT,YAAY,EAAE,CAAC;QACf,KAAK,EAAE,mBAAmB;QAC1B,MAAM,EAAE,mBAAmB;QAC3B,QAAQ,EAAE,UAAU;QACpB,OAAO,EAAE,MAAM;KAClB;IACD,gBAAgB,EAAE;QACd,SAAS,EAAE,EAAE;KAChB;IACD,gBAAgB,EAAE;QACd,QAAQ,EAAE,EAAE;KACf;IACD,+CAA+C;IAC/C,aAAa,EAAE;QACX,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,aAAa,EAAE,MAAM;KACxB;IACD,uDAAuD;IACvD,eAAe,EAAE;QACb,QAAQ,EAAE,UAAU;QACpB,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,CAAC;QACV,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,MAAM;KACxB;IACD,uBAAuB,EAAE;QACrB,SAAS,EAAE,QAAQ;QACnB,QAAQ,EAAE,UAAU;QACpB,GAAG,EAAE,CAAC;QACN,MAAM,EAAE,CAAC;QACT,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,CAAC;QACR,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;QACvB,UAAU,EAAE,QAAQ;QACpB,cAAc,EAAE,QAAQ;KAC3B;IACD,eAAe,EAAE;QACb,OAAO,EAAE,GAAG;QACZ,MAAM,EAAE,SAAS;KACpB;IACD,mBAAmB,EAAE;QACjB,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,GAAG;QACX,KAAK,EAAE,CAAC;KACX;IACD,iBAAiB,EAAE;QACf,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,GAAG;QACX,KAAK,EAAE,CAAC;QACR,GAAG,EAAE,EAAE;KACV;CACJ,CAAC;AAEF,2FAA2F;AAC3F,SAAS,UAAU,CAAC,KAAY,EAAE,KAAc,EAAE,QAAiB;IAC/D,IAAI,KAAK,EAAE,CAAC;QACR,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;IAChE,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACzC,CAAC;IACD,OAAO;QACH,MAAM,EAAE,cAAc,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE;QAClD,SAAS,EAAE,kDAAkD;QAC7D,mCAAmC,EAAE;YACjC,IAAI,EAAE,EAAE,SAAS,EAAE,WAAW,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE;YACxE,WAAW,EAAE,EAAE,SAAS,EAAE,cAAc,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;SACnF;QACD,yCAAyC,EAAE;YACvC,SAAS,EAAE,MAAM;SACpB;KACJ,CAAC;AACN,CAAC;AA8BD,MAAM,OAAO,WAAY,SAAQ,SAA6C;IACzD,UAAU,CAA8C;IAExD,QAAQ,CAAyC;IAE1D,aAAa,GAAyC,IAAI,CAAC;IAEnE,YAAY,KAAuB;QAC/B,KAAK,CAAC,KAAK,CAAC,CAAC;QAEb,IAAI,CAAC,KAAK,GAAG;YACT,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,KAAK;YAClB,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;SACf,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,SAAS,EAAE,CAAC;QAE5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,8BAA8B,CAAC,EAAE,CAAC;YAClE,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACrD,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,8BAA8B,CAAC,CAAC;YACzD,KAAK,CAAC,SAAS,GAAG,aAAa,CAAC;YAChC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;IACL,CAAC;IAED,kBAAkB,CAAC,SAA2B;QAC1C,IAAI,SAAS,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACxD,yBAAyB;YACzB,IAAI,CACA,IAAI,CAAC,QAAQ,CAAC,OAAO,EACrB;gBACI,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE;gBACxC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE;aACxC,EACD,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,gCAAgC,EAAE,CAC9D,CAAC;QACN,CAAC;IACL,CAAC;IAED,oBAAoB;QAChB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC9B,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,UAAU,CAAC,IAAyB;QAChC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAChF,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,CAAC,EAAE,eAAe,CAAC,CAAC;IACxB,CAAC;IAED,MAAM,CAAC,aAAqB;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,GAAG,IAAI,CAAC;QAEhD,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAEhC,mDAAmD;QACnD,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;YAClB,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;YACxC,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACtC,CAAC,CAAC;QACF,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;YAClB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACtC,CAAC,CAAC;QACF,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE;YACjB,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAClC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACtB,OAAO;YACX,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,GAAG,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;YAC/E,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;gBACtB,GAAG,GAAG,YAAY,CAAC;YACvB,CAAC;iBAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,GAAG,GAAG,eAAe,CAAC;YAC1B,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,CAAC;gBACtB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,mDAAmD,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAC1G,CAAC;iBAAM,CAAC;gBACJ,MAAM,MAAM,GAAG,QAAQ,GAAG,WAAW,IAAI,CACrC,IAAI,UAAU,CAAC,MAAM,CAAC,MAAyB,CAAC,CAAC,MAAM,CACnD,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EAChD,EAAE,CACL,CACJ,EAAE,CAAC;gBAEJ,IAAI,QAAQ,EAAE,CAAC;oBACX,QAAQ,CAAC,MAAM,CAAC,CAAC;gBACrB,CAAC;qBAAM,CAAC;oBACJ,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACxB,CAAC;YACL,CAAC;QACL,CAAC,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,qHAAqH;IACrH,qBAAqB;QACjB,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YACzD,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,CACH,oBAAC,GAAG,IACA,KAAK,EAAE,MAAM,CAAC,eAAe,EAC7B,EAAE,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,cAAc,EAAE,IAEzD,MAAM,CAAC,CAAC,CAAC,CACN,oBAAC,UAAU,IACP,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,MAAM,EAAE,MAAM,CAAC,KAAK,GACtB,CACL,CAAC,CAAC,CAAC,CACA,oBAAC,UAAU,IAAC,SAAS,SAAG,CAC3B,CACC,CACT,CAAC;IACN,CAAC;IAED,MAAM;QACF,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,GAAG,IAAI,CAAC;QAChD,IAAI,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QACpD,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QACzD,MAAM,QAAQ,GAAG,UAAU,KAAK,UAAU,CAAC;QAE3C,4CAA4C;QAC5C,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC;QAC9B,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,MAAM,MAAM,GAA6B,EAAE,CAAC;YAC5C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBAClB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACtB,CAAC,CAAC,CAAC;YACH,MAAM,GAAG,MAAM,CAAC;QACpB,CAAC;QAED,OAAO,CACH,oBAAC,QAAQ,IACL,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,WAAW,EACnC,GAAG,EAAC,UAAU,EACd,QAAQ,EAAE,KAAK,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,EAC5D,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EACtD,MAAM,EAAE,CAAC,aAAqB,EAAE,MAAuB,EAAE,EAAE;gBACvD,IAAI,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;gBACrC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;oBACxB,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;gBAClF,CAAC;qBAAM,CAAC;oBACJ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;gBAC/B,CAAC;YACL,CAAC,IAEA,CAAC,EAAE,YAAY,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAClC,6BACI,KAAK,EAAE;gBACH,GAAG,MAAM,CAAC,SAAS;gBACnB,GAAG,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC;gBACrE,GAAG,MAAM,CAAC,QAAQ;gBAClB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC;gBAClD,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;aAChD,KACG,YAAY,EAAE;YAElB,kCAAW,aAAa,EAAE,GAAI;YAC9B,oBAAC,GAAG,IACA,KAAK,EAAE,MAAM,CAAC,eAAe,EAC7B,EAAE,EAAE,CAAC,KAAY,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC;gBAEzD,CAAC,IAAI,CAAC,CAAC,CAAC,CACL,6BAAK,KAAK,EAAE,MAAM,CAAC,uBAAuB;oBAEtC,oBAAC,UAAU,IACP,QAAQ,EAAE,EAAE,EACZ,KAAK,EAAE,MAAM,CAAC,gBAAgB,EAC9B,KAAK,EAAE,QAAQ,EACf,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,GACzD;oBACF,6BAAK,KAAK,EAAE,MAAM,CAAC,gBAAgB,IAC9B,QAAQ;wBACL,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC;wBAC7B,CAAC,CAAC,IAAI,CAAC,CAAC,CACF,kEAAkE,CACrE,CACL,CACJ,CACT,CAAC,CAAC,CAAC,CACA,cAAc;oBACd,CAAC,WAAW,IAAI,CACZ,6BAAK,KAAK,EAAE,MAAM,CAAC,mBAAmB;oBAClC,oBAAC,OAAO,IACJ,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EACzB,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE;wBAExD,oBAAC,UAAU,IACP,IAAI,EAAC,OAAO,EACZ,OAAO,EAAE,CAAC,CAAC,EAAE;gCACT,cAAc,IAAI,cAAc,EAAE,CAAC;gCACnC,CAAC,CAAC,eAAe,EAAE,CAAC;4BACxB,CAAC;4BAED,oBAAC,SAAS,OAAG,CACJ,CACP,CACR,CACT,CACJ;gBACA,IAAI,IAAI,IAAI,IAAI,CACb,6BAAK,KAAK,EAAE,MAAM,CAAC,iBAAiB;oBAChC,oBAAC,OAAO,IACJ,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,EACxB,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE;wBAExD,oBAAC,UAAU,IACP,IAAI,EAAC,OAAO,EACZ,OAAO,EAAE,CAAC,CAAC,EAAE;gCACT,IAAI,CAAC,WAAW,EAAE,CAAC;oCACf,IAAI,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;gCACzC,CAAC;qCAAM,CAAC;oCACJ,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;gCACjD,CAAC;gCACD,CAAC,CAAC,eAAe,EAAE,CAAC;4BACxB,CAAC;4BAED,oBAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,GAAI,CAC/C,CACP;oBACV,oBAAC,IAAI,IACD,QAAQ,EAAE,QAAQ,EAClB,WAAW,QACX,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,EACvB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;wBAEhD,oBAAC,QAAQ,IACL,OAAO,EAAE,GAAG,EAAE,CACV,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE;gCACvD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC;gCACvD,IAAI,YAAY,EAAE,CAAC;oCACf,IAAI,QAAQ,EAAE,CAAC;wCACX,QAAQ,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;oCAC1D,CAAC;yCAAM,CAAC;wCACJ,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;oCAC7D,CAAC;gCACL,CAAC;4BACL,CAAC,CAAC,IAGL,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CACX;wBACX,oBAAC,QAAQ,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,IACzE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CACZ,CACR,CACL,CACT;gBACA,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CACpB,6BACI,GAAG,EAAE,IAAI,CAAC,QAAQ,EAClB,KAAK,EAAE,MAAM,CAAC,YAAY;oBAE1B,oBAAC,IAAI,IACD,GAAG,EAAE,IAAI,EACT,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,GAAG,EAAC,MAAM,GACZ,CACA,CACT,CAAC,CAAC,CAAC,IAAI;gBACP,IAAI,IAAI,QAAQ,CAAC,CAAC,CAAC,CAEhB,oBAAC,GAAG,IACA,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,uBAAuB,EAAE,GAAG,MAAM,CAAC,aAAa,EAAE,EACrE,EAAE,EAAE,CAAC,KAAY,EAAE,EAAE,CAAC,CAAC;wBACnB,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC;qBACvD,CAAC;oBAEF,oBAAC,UAAU,IACP,QAAQ,EAAE,EAAE,EACZ,KAAK,EAAE,MAAM,CAAC,gBAAgB,EAC9B,KAAK,SACP;oBACF,6BAAK,KAAK,EAAE,MAAM,CAAC,gBAAgB,IAAG,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAO,CACtE,CACT,CAAC,CAAC,CAAC,IAAI;gBACP,IAAI,CAAC,qBAAqB,EAAE;gBAE5B,IAAI,IAAI,IAAI,IAAI,WAAW,CAAC,CAAC,CAAC,CAC3B,oBAAC,OAAO,IACJ,GAAG,EAAE,IAAI,CAAC,UAAU,EACpB,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,GAAG,EAAE,IAAI,EACT,kBAAkB,EAAE,CAAC,EACrB,QAAQ,EAAE,CAAC,EACX,MAAM,EAAE,KAAK,EACb,gBAAgB,EAAE,EAAE,EACpB,eAAe,EAAE,EAAE,EACnB,UAAU,EAAE,KAAK,EACjB,gBAAgB,EAAE,KAAK,GACzB,CACL,CAAC,CAAC,CAAC,IAAI,CACN,CACJ,CACT,CACM,CACd,CAAC;IACN,CAAC;CACJ","sourcesContent":["import React, { Component, createRef, type JSX } from 'react';\nimport Dropzone, { type FileRejection } from 'react-dropzone';\nimport { Cropper, type ReactCropperElement } from 'react-cropper';\n\nimport { Menu, MenuItem, Tooltip, IconButton, Box } from '@mui/material';\nimport { alpha, type Theme } from '@mui/material/styles';\n\nimport { Close as IconClose, Crop as CropIcon } from '@mui/icons-material';\n\nimport { I18n } from '../i18n';\nimport { Icon } from './Icon';\nimport { IconUpload } from './AnimatedIcons/IconUpload';\nimport { IconResult } from './AnimatedIcons/IconResult';\nimport { play } from './AnimatedIcons/common';\n\n/** How long the result of an upload stays visible */\nconst RESULT_DURATION = 2500;\n\n// import 'cropperjs/dist/cropper.css';\nconst cropperStyles = `\n/*!\n * Cropper.js v1.5.12\n * https://fengyuanchen.github.io/cropperjs\n *\n * Copyright 2015-present Chen Fengyuan\n * Released under the MIT license\n *\n * Date: 2021-06-12T08:00:11.623Z\n */\n\n.cropper-container {\n direction: ltr;\n font-size: 0;\n line-height: 0;\n position: relative;\n -ms-touch-action: none;\n touch-action: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n\n.cropper-container img {\n display: block;\n height: 100%;\n image-orientation: 0deg;\n max-height: none !important;\n max-width: none !important;\n min-height: 0 !important;\n min-width: 0 !important;\n width: 100%;\n}\n\n.cropper-wrap-box,\n.cropper-canvas,\n.cropper-drag-box,\n.cropper-crop-box,\n.cropper-modal {\n bottom: 0;\n left: 0;\n position: absolute;\n right: 0;\n top: 0;\n}\n\n.cropper-wrap-box,\n.cropper-canvas {\n overflow: hidden;\n}\n\n.cropper-drag-box {\n background-color: #fff;\n opacity: 0;\n}\n\n.cropper-modal {\n background-color: #000;\n opacity: 0.5;\n}\n\n.cropper-view-box {\n display: block;\n height: 100%;\n outline: 1px solid #39f;\n outline-color: rgba(51, 153, 255, 0.75);\n overflow: hidden;\n width: 100%;\n}\n\n.cropper-dashed {\n border: 0 dashed #eee;\n display: block;\n opacity: 0.5;\n position: absolute;\n}\n\n.cropper-dashed.dashed-h {\n border-bottom-width: 1px;\n border-top-width: 1px;\n height: calc(100% / 3);\n left: 0;\n top: calc(100% / 3);\n width: 100%;\n}\n\n.cropper-dashed.dashed-v {\n border-left-width: 1px;\n border-right-width: 1px;\n height: 100%;\n left: calc(100% / 3);\n top: 0;\n width: calc(100% / 3);\n}\n\n.cropper-center {\n display: block;\n height: 0;\n left: 50%;\n opacity: 0.75;\n position: absolute;\n top: 50%;\n width: 0;\n}\n\n.cropper-center::before,\n.cropper-center::after {\n background-color: #eee;\n content: ' ';\n display: block;\n position: absolute;\n}\n\n.cropper-center::before {\n height: 1px;\n left: -3px;\n top: 0;\n width: 7px;\n}\n\n.cropper-center::after {\n height: 7px;\n left: 0;\n top: -3px;\n width: 1px;\n}\n\n.cropper-face,\n.cropper-line,\n.cropper-point {\n display: block;\n height: 100%;\n opacity: 0.1;\n position: absolute;\n width: 100%;\n}\n\n.cropper-face {\n background-color: #fff;\n left: 0;\n top: 0;\n}\n\n.cropper-line {\n background-color: #39f;\n}\n\n.cropper-line.line-e {\n cursor: ew-resize;\n right: -3px;\n top: 0;\n width: 5px;\n}\n\n.cropper-line.line-n {\n cursor: ns-resize;\n height: 5px;\n left: 0;\n top: -3px;\n}\n\n.cropper-line.line-w {\n cursor: ew-resize;\n left: -3px;\n top: 0;\n width: 5px;\n}\n\n.cropper-line.line-s {\n bottom: -3px;\n cursor: ns-resize;\n height: 5px;\n left: 0;\n}\n\n.cropper-point {\n background-color: #39f;\n height: 5px;\n opacity: 0.75;\n width: 5px;\n}\n\n.cropper-point.point-e {\n cursor: ew-resize;\n margin-top: -3px;\n right: -3px;\n top: 50%;\n}\n\n.cropper-point.point-n {\n cursor: ns-resize;\n left: 50%;\n margin-left: -3px;\n top: -3px;\n}\n\n.cropper-point.point-w {\n cursor: ew-resize;\n left: -3px;\n margin-top: -3px;\n top: 50%;\n}\n\n.cropper-point.point-s {\n bottom: -3px;\n cursor: s-resize;\n left: 50%;\n margin-left: -3px;\n}\n\n.cropper-point.point-ne {\n cursor: nesw-resize;\n right: -3px;\n top: -3px;\n}\n\n.cropper-point.point-nw {\n cursor: nwse-resize;\n left: -3px;\n top: -3px;\n}\n\n.cropper-point.point-sw {\n bottom: -3px;\n cursor: nesw-resize;\n left: -3px;\n}\n\n.cropper-point.point-se {\n bottom: -3px;\n cursor: nwse-resize;\n height: 20px;\n opacity: 1;\n right: -3px;\n width: 20px;\n}\n\n@media (min-width: 768px) {\n .cropper-point.point-se {\n height: 15px;\n width: 15px;\n }\n}\n\n@media (min-width: 992px) {\n .cropper-point.point-se {\n height: 10px;\n width: 10px;\n }\n}\n\n@media (min-width: 1200px) {\n .cropper-point.point-se {\n height: 5px;\n opacity: 0.75;\n width: 5px;\n }\n}\n\n.cropper-point.point-se::before {\n background-color: #39f;\n bottom: -50%;\n content: ' ';\n display: block;\n height: 200%;\n opacity: 0;\n position: absolute;\n right: -50%;\n width: 200%;\n}\n\n.cropper-invisible {\n opacity: 0;\n}\n\n.cropper-bg {\n background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');\n}\n\n.cropper-hide {\n display: block;\n height: 0;\n position: absolute;\n width: 0;\n}\n\n.cropper-hidden {\n display: none !important;\n}\n\n.cropper-move {\n cursor: move;\n}\n\n.cropper-crop {\n cursor: crosshair;\n}\n\n.cropper-disabled .cropper-drag-box,\n.cropper-disabled .cropper-face,\n.cropper-disabled .cropper-line,\n.cropper-disabled .cropper-point {\n cursor: not-allowed;\n}\n`;\n\nconst styles: Record<string, React.CSSProperties> = {\n dropZone: {\n width: '100%',\n height: 100,\n position: 'relative',\n },\n dropZoneEmpty: {},\n image: {\n objectFit: 'contain',\n margin: 'auto',\n display: 'flex',\n width: '100%',\n height: '100%',\n },\n /** The new image fades in */\n imageWrapper: {\n display: 'flex',\n width: '100%',\n height: '100%',\n },\n\n uploadDiv: {\n position: 'relative',\n width: '100%',\n height: 300,\n opacity: 0.9,\n marginTop: 30,\n cursor: 'pointer',\n outline: 'none',\n },\n uploadDivDragging: {\n opacity: 1,\n background: 'rgba(128,255,128,0.1)',\n },\n\n /** The border is set with `dropAreaSx`, so that it can pulse */\n uploadCenterDiv: {\n margin: 5,\n borderRadius: 5,\n width: 'calc(100% - 10px)',\n height: 'calc(100% - 10px)',\n position: 'relative',\n display: 'flex',\n },\n uploadCenterIcon: {\n marginTop: 10,\n },\n uploadCenterText: {\n fontSize: 16,\n },\n /** A file is dragged over an existing image */\n dropOverImage: {\n position: 'absolute',\n inset: 0,\n zIndex: 1,\n pointerEvents: 'none',\n },\n /** Upload and its result in the corner of the image */\n uploadIndicator: {\n position: 'absolute',\n top: 8,\n left: 8,\n zIndex: 223,\n display: 'flex',\n padding: 4,\n borderRadius: '50%',\n pointerEvents: 'none',\n },\n uploadCenterTextAndIcon: {\n textAlign: 'center',\n position: 'absolute',\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n },\n disabledOpacity: {\n opacity: 0.3,\n cursor: 'default',\n },\n buttonRemoveWrapper: {\n position: 'absolute',\n zIndex: 222,\n right: 0,\n },\n buttonCropWrapper: {\n position: 'absolute',\n zIndex: 222,\n right: 0,\n top: 50,\n },\n};\n\n/** Border of the drop area: red on error, and it pulses while a file is dragged over it */\nfunction dropAreaSx(theme: Theme, error: boolean, dragging: boolean): any {\n if (error) {\n return { border: '2px solid red', boxSizing: 'border-box' };\n }\n if (!dragging) {\n return { border: '3px dashed grey' };\n }\n return {\n border: `3px dashed ${theme.palette.primary.main}`,\n animation: 'iob-upload-image-pulse 1.2s ease-in-out infinite',\n '@keyframes iob-upload-image-pulse': {\n '0%': { boxShadow: `0 0 0 0 ${alpha(theme.palette.primary.main, 0.4)}` },\n '70%, 100%': { boxShadow: `0 0 0 14px ${alpha(theme.palette.primary.main, 0)}` },\n },\n '@media (prefers-reduced-motion: reduce)': {\n animation: 'none',\n },\n };\n}\n\ninterface UploadImageProps {\n maxSize?: number;\n disabled?: boolean;\n crop?: boolean;\n error?: boolean;\n onChange: (base64: string) => void | undefined;\n icon: string | null;\n removeIconFunc: () => void | null;\n accept?: Record<string, string[]>;\n /**\n * The parent uploads the image given with `onChange`, e.g. writes it into a file: the upload arrow moves up in\n * the corner of the image. When it becomes false, a check mark is shown there for a moment.\n */\n uploading?: boolean;\n /** The upload failed: when `uploading` becomes false, a cross is shown instead of the check mark */\n uploadError?: boolean;\n}\n\ninterface UploadImageState {\n uploadFile: boolean | 'dragging';\n anchorEl: HTMLElement | null;\n cropHandler: boolean;\n /** The dropped file is being read */\n reading: boolean;\n /** Result of the last upload of the parent, shown for a moment */\n result: { type: 'success' | 'error'; count: number } | null;\n}\n\nexport class UploadImage extends Component<UploadImageProps, UploadImageState> {\n private readonly cropperRef: React.RefObject<ReactCropperElement | null>;\n\n private readonly imageRef: React.RefObject<HTMLDivElement | null>;\n\n private resultTimeout: ReturnType<typeof setTimeout> | null = null;\n\n constructor(props: UploadImageProps) {\n super(props);\n\n this.state = {\n uploadFile: false,\n anchorEl: null,\n cropHandler: false,\n reading: false,\n result: null,\n };\n this.cropperRef = createRef();\n this.imageRef = createRef();\n\n if (!window.document.getElementById('cropper-style-json-component')) {\n const style = window.document.createElement('style');\n style.setAttribute('id', 'cropper-style-json-component');\n style.innerHTML = cropperStyles;\n window.document.head.appendChild(style);\n }\n }\n\n componentDidUpdate(prevProps: UploadImageProps): void {\n if (prevProps.uploading && !this.props.uploading) {\n this.showResult(this.props.uploadError ? 'error' : 'success');\n }\n if (this.props.icon && prevProps.icon !== this.props.icon) {\n // the new image fades in\n play(\n this.imageRef.current,\n [\n { opacity: 0, transform: 'scale(0.92)' },\n { opacity: 1, transform: 'scale(1)' },\n ],\n { duration: 280, easing: 'cubic-bezier(0.2, 0.8, 0.3, 1)' },\n );\n }\n }\n\n componentWillUnmount(): void {\n if (this.resultTimeout) {\n clearTimeout(this.resultTimeout);\n this.resultTimeout = null;\n }\n }\n\n /** Shows a check mark or a cross in the corner of the image for a moment */\n showResult(type: 'success' | 'error'): void {\n if (this.resultTimeout) {\n clearTimeout(this.resultTimeout);\n }\n this.setState({ result: { type, count: (this.state.result?.count || 0) + 1 } });\n this.resultTimeout = setTimeout(() => {\n this.resultTimeout = null;\n this.setState({ result: null });\n }, RESULT_DURATION);\n }\n\n onDrop(acceptedFiles: File[]): void {\n const onChange = this.props.onChange;\n const maxSize = this.props.maxSize || 10 * 1024;\n\n const file = acceptedFiles[0];\n const reader = new FileReader();\n\n // the upload arrow moves up while the file is read\n reader.onabort = () => {\n console.log('file reading was aborted');\n this.setState({ reading: false });\n };\n reader.onerror = () => {\n console.log('file reading has failed');\n this.setState({ reading: false });\n };\n reader.onload = () => {\n this.setState({ reading: false });\n if (!file || !file.name) {\n return;\n }\n const parts = file.name?.split('.');\n let ext = parts?.length ? `image/${parts.pop()?.toLowerCase()}` : 'image/jpeg';\n if (ext === 'image/jpg') {\n ext = 'image/jpeg';\n } else if (ext.includes('svg')) {\n ext = 'image/svg+xml';\n }\n if (file.size > maxSize) {\n window.alert(I18n.t('ra_File is too big. Max %sk allowed. Try use SVG.', Math.round(maxSize / 1024)));\n } else {\n const base64 = `data:${ext};base64,${btoa(\n new Uint8Array(reader.result as ArrayBufferLike).reduce(\n (data, byte) => data + String.fromCharCode(byte),\n '',\n ),\n )}`;\n\n if (onChange) {\n onChange(base64);\n } else {\n console.log(base64);\n }\n }\n };\n this.setState({ reading: true });\n reader.readAsArrayBuffer(file);\n }\n\n /** Upload of the parent and its result in the corner of the image (without image, the big upload symbol shows it) */\n renderUploadIndicator(): JSX.Element | null {\n const { result } = this.state;\n if (!this.props.icon || (!result && !this.props.uploading)) {\n return null;\n }\n return (\n <Box\n style={styles.uploadIndicator}\n sx={{ bgcolor: 'background.paper', color: 'text.primary' }}\n >\n {result ? (\n <IconResult\n type={result.type}\n replay={result.count}\n />\n ) : (\n <IconUpload uploading />\n )}\n </Box>\n );\n }\n\n render(): JSX.Element {\n const { disabled, icon, removeIconFunc, error, crop, onChange } = this.props;\n const maxSize = this.props.maxSize || 10 * 1024;\n let accept = this.props.accept || { 'image/*': [] };\n const { uploadFile, anchorEl, cropHandler } = this.state;\n const dragging = uploadFile === 'dragging';\n\n // covert '\"image/png\"' to { 'image/*': [] }\n if (typeof accept === 'string') {\n accept = { [accept]: [] };\n } else if (Array.isArray(accept)) {\n const result: Record<string, string[]> = {};\n accept.forEach(item => {\n result[item] = [];\n });\n accept = result;\n }\n\n return (\n <Dropzone\n disabled={!!disabled || cropHandler}\n key=\"dropzone\"\n multiple={false}\n accept={accept}\n maxSize={maxSize}\n onDragEnter={() => this.setState({ uploadFile: 'dragging' })}\n onDragLeave={() => this.setState({ uploadFile: true })}\n onDrop={(acceptedFiles: File[], errors: FileRejection[]) => {\n this.setState({ uploadFile: false });\n if (!acceptedFiles.length) {\n window.alert(errors?.[0]?.errors?.[0]?.message || I18n.t('ra_Cannot upload'));\n } else {\n this.onDrop(acceptedFiles);\n }\n }}\n >\n {({ getRootProps, getInputProps }) => (\n <div\n style={{\n ...styles.uploadDiv,\n ...(uploadFile === 'dragging' ? styles.uploadDivDragging : undefined),\n ...styles.dropZone,\n ...(disabled ? styles.disabledOpacity : undefined),\n ...(!icon ? styles.dropZoneEmpty : undefined),\n }}\n {...getRootProps()}\n >\n <input {...getInputProps()} />\n <Box\n style={styles.uploadCenterDiv}\n sx={(theme: Theme) => dropAreaSx(theme, !!error, dragging)}\n >\n {!icon ? (\n <div style={styles.uploadCenterTextAndIcon}>\n {/* bobs while a file is dragged over it, moves up while it is read or uploaded */}\n <IconUpload\n fontSize={48}\n style={styles.uploadCenterIcon}\n ready={dragging}\n uploading={this.state.reading || !!this.props.uploading}\n />\n <div style={styles.uploadCenterText}>\n {dragging\n ? I18n.t('ra_Drop file here')\n : I18n.t(\n 'ra_Place your files here or click here to open the browse dialog',\n )}\n </div>\n </div>\n ) : (\n removeIconFunc &&\n !cropHandler && (\n <div style={styles.buttonRemoveWrapper}>\n <Tooltip\n title={I18n.t('ra_Clear')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n size=\"large\"\n onClick={e => {\n removeIconFunc && removeIconFunc();\n e.stopPropagation();\n }}\n >\n <IconClose />\n </IconButton>\n </Tooltip>\n </div>\n )\n )}\n {icon && crop && (\n <div style={styles.buttonCropWrapper}>\n <Tooltip\n title={I18n.t('ra_Crop')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n size=\"large\"\n onClick={e => {\n if (!cropHandler) {\n this.setState({ cropHandler: true });\n } else {\n this.setState({ anchorEl: e.currentTarget });\n }\n e.stopPropagation();\n }}\n >\n <CropIcon color={cropHandler ? 'primary' : 'inherit'} />\n </IconButton>\n </Tooltip>\n <Menu\n anchorEl={anchorEl}\n keepMounted\n open={Boolean(anchorEl)}\n onClose={() => this.setState({ anchorEl: null })}\n >\n <MenuItem\n onClick={() =>\n this.setState({ anchorEl: null, cropHandler: false }, () => {\n const imageElement = this.cropperRef?.current?.cropper;\n if (imageElement) {\n if (onChange) {\n onChange(imageElement.getCroppedCanvas().toDataURL());\n } else {\n console.log(imageElement.getCroppedCanvas().toDataURL());\n }\n }\n })\n }\n >\n {I18n.t('ra_Save')}\n </MenuItem>\n <MenuItem onClick={() => this.setState({ anchorEl: null, cropHandler: false })}>\n {I18n.t('ra_Close')}\n </MenuItem>\n </Menu>\n </div>\n )}\n {icon && !cropHandler ? (\n <div\n ref={this.imageRef}\n style={styles.imageWrapper}\n >\n <Icon\n src={icon}\n style={styles.image}\n alt=\"icon\"\n />\n </div>\n ) : null}\n {icon && dragging ? (\n // a new image is dragged over the existing one\n <Box\n style={{ ...styles.uploadCenterTextAndIcon, ...styles.dropOverImage }}\n sx={(theme: Theme) => ({\n bgcolor: alpha(theme.palette.background.paper, 0.85),\n })}\n >\n <IconUpload\n fontSize={48}\n style={styles.uploadCenterIcon}\n ready\n />\n <div style={styles.uploadCenterText}>{I18n.t('ra_Drop file here')}</div>\n </Box>\n ) : null}\n {this.renderUploadIndicator()}\n\n {icon && crop && cropHandler ? (\n <Cropper\n ref={this.cropperRef}\n style={styles.image}\n src={icon}\n initialAspectRatio={1}\n viewMode={1}\n guides={false}\n minCropBoxHeight={10}\n minCropBoxWidth={10}\n background={false}\n checkOrientation={false}\n />\n ) : null}\n </Box>\n </div>\n )}\n </Dropzone>\n );\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iobroker/gui-components",
3
- "version": "10.4.0",
3
+ "version": "10.4.1",
4
4
  "description": "Shared React components (React 19 / MUI 9) to develop ioBroker interfaces. Successor of @iobroker/adapter-react-v5.",
5
5
  "author": {
6
6
  "name": "bluefox",