@iobroker/adapter-react-v5 7.0.1 → 7.1.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 (314) hide show
  1. package/Components/404.d.ts +3 -2
  2. package/Components/404.js +16 -15
  3. package/Components/ColorPicker.d.ts +22 -8
  4. package/Components/ColorPicker.js +34 -17
  5. package/Components/ComplexCron.js +24 -24
  6. package/Components/CopyToClipboard.d.ts +10 -1
  7. package/Components/CopyToClipboard.js +17 -8
  8. package/Components/CustomModal.d.ts +1 -1
  9. package/Components/CustomModal.js +8 -8
  10. package/Components/FileBrowser.d.ts +11 -11
  11. package/Components/FileBrowser.js +173 -164
  12. package/Components/FileViewer.js +34 -23
  13. package/Components/Icon.d.ts +16 -2
  14. package/Components/Icon.js +19 -8
  15. package/Components/IconPicker.js +10 -14
  16. package/Components/IconSelector.d.ts +1 -1
  17. package/Components/IconSelector.js +64 -74
  18. package/Components/Image.d.ts +8 -4
  19. package/Components/Image.js +13 -32
  20. package/Components/Loader.d.ts +2 -2
  21. package/Components/Loader.js +244 -241
  22. package/Components/Loaders/MV.d.ts +6 -1
  23. package/Components/Loaders/MV.js +23 -7
  24. package/Components/Loaders/PT.d.ts +7 -2
  25. package/Components/Loaders/PT.js +123 -110
  26. package/Components/Loaders/Vendor.d.ts +2 -2
  27. package/Components/Loaders/Vendor.js +22 -14
  28. package/Components/Logo.js +16 -18
  29. package/Components/MDUtils.d.ts +1 -1
  30. package/Components/MDUtils.js +8 -4
  31. package/Components/ObjectBrowser.d.ts +49 -38
  32. package/Components/ObjectBrowser.js +757 -494
  33. package/Components/Router.d.ts +1 -3
  34. package/Components/Router.js +3 -1
  35. package/Components/SaveCloseButtons.d.ts +3 -3
  36. package/Components/SaveCloseButtons.js +3 -3
  37. package/Components/Schedule.d.ts +15 -15
  38. package/Components/Schedule.js +177 -154
  39. package/Components/SelectWithIcon.d.ts +2 -2
  40. package/Components/SelectWithIcon.js +45 -34
  41. package/Components/SimpleCron/index.js +83 -43
  42. package/Components/TabContainer.js +2 -2
  43. package/Components/TabContent.js +1 -1
  44. package/Components/TabHeader.js +1 -1
  45. package/Components/TableResize.d.ts +2 -2
  46. package/Components/TableResize.js +5 -5
  47. package/Components/TextWithIcon.d.ts +1 -1
  48. package/Components/TextWithIcon.js +10 -8
  49. package/Components/ToggleThemeMenu.d.ts +2 -2
  50. package/Components/ToggleThemeMenu.js +3 -3
  51. package/Components/TreeTable.d.ts +18 -18
  52. package/Components/TreeTable.js +76 -72
  53. package/Components/UploadImage.d.ts +2 -2
  54. package/Components/UploadImage.js +330 -326
  55. package/Components/Utils.d.ts +42 -22
  56. package/Components/Utils.js +66 -65
  57. package/Components/withWidth.d.ts +2 -2
  58. package/Components/withWidth.js +10 -6
  59. package/Dialogs/ComplexCron.d.ts +2 -2
  60. package/Dialogs/ComplexCron.js +3 -3
  61. package/Dialogs/Confirm.d.ts +4 -4
  62. package/Dialogs/Confirm.js +18 -8
  63. package/Dialogs/Cron.d.ts +3 -3
  64. package/Dialogs/Cron.js +21 -17
  65. package/Dialogs/Error.d.ts +3 -3
  66. package/Dialogs/Error.js +6 -4
  67. package/Dialogs/Message.d.ts +3 -3
  68. package/Dialogs/Message.js +6 -4
  69. package/Dialogs/SelectFile.d.ts +4 -4
  70. package/Dialogs/SelectFile.js +6 -4
  71. package/Dialogs/SelectID.d.ts +12 -10
  72. package/Dialogs/SelectID.js +12 -8
  73. package/Dialogs/SimpleCron.d.ts +2 -2
  74. package/Dialogs/SimpleCron.js +2 -2
  75. package/Dialogs/TextInput.d.ts +2 -2
  76. package/Dialogs/TextInput.js +3 -3
  77. package/GenericApp.d.ts +19 -13
  78. package/GenericApp.js +177 -134
  79. package/LICENSE +22 -22
  80. package/LegacyConnection.d.ts +240 -248
  81. package/LegacyConnection.js +500 -525
  82. package/Prompt.js +7 -7
  83. package/README.md +1239 -1166
  84. package/Theme.d.ts +1 -1
  85. package/Theme.js +9 -12
  86. package/assets/devices.json +1 -0
  87. package/assets/lamp_ceiling.svg +8 -8
  88. package/assets/lamp_table.svg +7 -7
  89. package/assets/no_icon.svg +9 -9
  90. package/assets/rooms.json +1 -0
  91. package/craco-module-federation.js +62 -71
  92. package/i18n/de.json +434 -431
  93. package/i18n/en.json +434 -431
  94. package/i18n/es.json +434 -431
  95. package/i18n/fr.json +434 -431
  96. package/i18n/it.json +434 -431
  97. package/i18n/nl.json +434 -431
  98. package/i18n/pl.json +434 -431
  99. package/i18n/pt.json +434 -431
  100. package/i18n/ru.json +434 -431
  101. package/i18n/uk.json +434 -431
  102. package/i18n/zh-cn.json +434 -431
  103. package/i18n.d.ts +26 -19
  104. package/i18n.js +28 -22
  105. package/icons/IconAdapter.js +2 -2
  106. package/icons/IconAlias.js +2 -2
  107. package/icons/IconChannel.js +2 -2
  108. package/icons/IconClearFilter.js +2 -2
  109. package/icons/IconClosed.js +2 -2
  110. package/icons/IconCopy.js +2 -2
  111. package/icons/IconDevice.js +2 -2
  112. package/icons/IconDocument.js +2 -2
  113. package/icons/IconDocumentReadOnly.js +2 -2
  114. package/icons/IconExpert.js +2 -2
  115. package/icons/IconFx.js +2 -2
  116. package/icons/IconInstance.js +2 -2
  117. package/icons/IconLogout.js +2 -2
  118. package/icons/IconNoIcon.js +2 -2
  119. package/icons/IconOpen.d.ts +2 -2
  120. package/icons/IconOpen.js +2 -2
  121. package/icons/IconProps.d.ts +4 -3
  122. package/icons/IconState.d.ts +2 -2
  123. package/icons/IconState.js +2 -2
  124. package/index.css +56 -55
  125. package/modulefederation.admin.config.js +31 -31
  126. package/package.json +5 -5
  127. package/src/AdminConnection.tsx +3 -3
  128. package/src/Components/404.tsx +122 -121
  129. package/src/Components/ColorPicker.tsx +343 -315
  130. package/src/Components/ComplexCron.tsx +544 -507
  131. package/src/Components/CopyToClipboard.tsx +178 -165
  132. package/src/Components/CustomModal.tsx +170 -163
  133. package/src/Components/FileBrowser.tsx +2550 -2414
  134. package/src/Components/FileViewer.tsx +412 -393
  135. package/src/Components/Icon.tsx +238 -210
  136. package/src/Components/IconPicker.tsx +165 -149
  137. package/src/Components/IconSelector.tsx +2220 -2202
  138. package/src/Components/Image.tsx +193 -176
  139. package/src/Components/Loader.tsx +328 -304
  140. package/src/Components/Logo.tsx +176 -166
  141. package/src/Components/MDUtils.tsx +104 -100
  142. package/src/Components/ObjectBrowser.tsx +8935 -8032
  143. package/src/Components/Router.tsx +90 -90
  144. package/src/Components/SaveCloseButtons.tsx +117 -113
  145. package/src/Components/Schedule.tsx +1962 -1724
  146. package/src/Components/SelectWithIcon.tsx +239 -197
  147. package/src/Components/TabContainer.tsx +57 -55
  148. package/src/Components/TabContent.tsx +38 -37
  149. package/src/Components/TabHeader.tsx +20 -19
  150. package/src/Components/TableResize.tsx +274 -259
  151. package/src/Components/TextWithIcon.tsx +159 -148
  152. package/src/Components/ToggleThemeMenu.tsx +52 -34
  153. package/src/Components/TreeTable.tsx +1002 -919
  154. package/src/Components/UploadImage.tsx +631 -599
  155. package/src/Components/Utils.tsx +1802 -1794
  156. package/src/Components/loader.css +231 -222
  157. package/src/Components/withWidth.tsx +32 -21
  158. package/src/Connection.tsx +5 -7
  159. package/src/Dialogs/ComplexCron.tsx +123 -129
  160. package/src/Dialogs/Confirm.tsx +185 -162
  161. package/src/Dialogs/Cron.tsx +192 -182
  162. package/src/Dialogs/Error.tsx +67 -72
  163. package/src/Dialogs/Message.tsx +73 -71
  164. package/src/Dialogs/SelectFile.tsx +280 -270
  165. package/src/Dialogs/SelectID.tsx +310 -298
  166. package/src/Dialogs/SimpleCron.tsx +100 -100
  167. package/src/Dialogs/TextInput.tsx +99 -107
  168. package/src/GenericApp.tsx +1076 -976
  169. package/src/LegacyConnection.tsx +3719 -3589
  170. package/src/Prompt.tsx +22 -20
  171. package/src/Theme.tsx +472 -479
  172. package/src/icons/IconAdapter.tsx +22 -20
  173. package/src/icons/IconAlias.tsx +22 -20
  174. package/src/icons/IconChannel.tsx +60 -21
  175. package/src/icons/IconClearFilter.tsx +24 -22
  176. package/src/icons/IconClosed.tsx +22 -17
  177. package/src/icons/IconCopy.tsx +21 -16
  178. package/src/icons/IconDevice.tsx +126 -27
  179. package/src/icons/IconDocument.tsx +22 -17
  180. package/src/icons/IconDocumentReadOnly.tsx +27 -18
  181. package/src/icons/IconExpert.tsx +26 -18
  182. package/src/icons/IconFx.tsx +38 -36
  183. package/src/icons/IconInstance.tsx +22 -20
  184. package/src/icons/IconLogout.tsx +32 -30
  185. package/src/icons/IconNoIcon.tsx +21 -19
  186. package/src/icons/IconOpen.tsx +22 -17
  187. package/src/icons/IconProps.tsx +16 -15
  188. package/src/icons/IconState.tsx +38 -17
  189. package/src/index.css +56 -55
  190. package/tasks.js +91 -0
  191. package/types.d.ts +141 -134
  192. package/Components/Loaders/PT.css +0 -109
  193. package/Components/Loaders/Vendor.css +0 -13
  194. package/Components/loader.css +0 -222
  195. package/Components/types.d.ts +0 -82
  196. package/assets/devices/Alarm Systems.svg +0 -19
  197. package/assets/devices/Amplifier.svg +0 -22
  198. package/assets/devices/Awnings.svg +0 -5
  199. package/assets/devices/Battery Status.svg +0 -5
  200. package/assets/devices/Ceiling Spotlights.svg +0 -16
  201. package/assets/devices/Chandelier.svg +0 -7
  202. package/assets/devices/Climate.svg +0 -12
  203. package/assets/devices/Coffee Makers.svg +0 -6
  204. package/assets/devices/Cold Water.svg +0 -31
  205. package/assets/devices/Computer.svg +0 -21
  206. package/assets/devices/Consumption.svg +0 -8
  207. package/assets/devices/Curtains.svg +0 -43
  208. package/assets/devices/Dishwashers.svg +0 -12
  209. package/assets/devices/Doors.svg +0 -6
  210. package/assets/devices/Doorstep.svg +0 -35
  211. package/assets/devices/Dryer.svg +0 -14
  212. package/assets/devices/Fan.svg +0 -20
  213. package/assets/devices/Floor Lamps.svg +0 -5
  214. package/assets/devices/Garage Doors.svg +0 -9
  215. package/assets/devices/Gates.svg +0 -32
  216. package/assets/devices/Hairdryer.svg +0 -23
  217. package/assets/devices/Handle.svg +0 -6
  218. package/assets/devices/Hanging Lamps.svg +0 -9
  219. package/assets/devices/Heater.svg +0 -44
  220. package/assets/devices/Hoods.svg +0 -12
  221. package/assets/devices/Hot Water.svg +0 -10
  222. package/assets/devices/Humidity.svg +0 -41
  223. package/assets/devices/Iron.svg +0 -5
  224. package/assets/devices/Irrigation.svg +0 -23
  225. package/assets/devices/Led Strip.svg +0 -31
  226. package/assets/devices/Light.svg +0 -30
  227. package/assets/devices/Lightings.svg +0 -46
  228. package/assets/devices/Lock.svg +0 -19
  229. package/assets/devices/Louvre.svg +0 -7
  230. package/assets/devices/Mowing Machine.svg +0 -9
  231. package/assets/devices/Music.svg +0 -13
  232. package/assets/devices/Outdoor Blinds.svg +0 -7
  233. package/assets/devices/People.svg +0 -19
  234. package/assets/devices/Pool.svg +0 -8
  235. package/assets/devices/Power Consumption.svg +0 -13
  236. package/assets/devices/Printer.svg +0 -10
  237. package/assets/devices/Pump.svg +0 -10
  238. package/assets/devices/Receiver.svg +0 -19
  239. package/assets/devices/Sconces.svg +0 -10
  240. package/assets/devices/Security.svg +0 -34
  241. package/assets/devices/Shading.svg +0 -5
  242. package/assets/devices/Shutters.svg +0 -11
  243. package/assets/devices/SmokeDetector.svg +0 -13
  244. package/assets/devices/Sockets.svg +0 -13
  245. package/assets/devices/Speaker.svg +0 -35
  246. package/assets/devices/Stove.svg +0 -12
  247. package/assets/devices/Table Lamps.svg +0 -12
  248. package/assets/devices/Temperature Sensors.svg +0 -28
  249. package/assets/devices/Tv.svg +0 -8
  250. package/assets/devices/Vacuum Cleaner.svg +0 -16
  251. package/assets/devices/Ventilation.svg +0 -12
  252. package/assets/devices/Washing Machines.svg +0 -16
  253. package/assets/devices/Water Consumption.svg +0 -6
  254. package/assets/devices/Water Heater.svg +0 -8
  255. package/assets/devices/Water.svg +0 -40
  256. package/assets/devices/Weather.svg +0 -28
  257. package/assets/devices/Window.svg +0 -8
  258. package/assets/rooms/Anteroom.svg +0 -53
  259. package/assets/rooms/Attic.svg +0 -21
  260. package/assets/rooms/Balcony.svg +0 -13
  261. package/assets/rooms/Barn.svg +0 -6
  262. package/assets/rooms/Basement.svg +0 -5
  263. package/assets/rooms/Bathroom.svg +0 -38
  264. package/assets/rooms/Bedroom.svg +0 -5
  265. package/assets/rooms/Boiler Room.svg +0 -13
  266. package/assets/rooms/Carport.svg +0 -17
  267. package/assets/rooms/Cellar.svg +0 -89
  268. package/assets/rooms/Chamber.svg +0 -9
  269. package/assets/rooms/Corridor.svg +0 -53
  270. package/assets/rooms/Dining Area.svg +0 -37
  271. package/assets/rooms/Dining Room.svg +0 -37
  272. package/assets/rooms/Dining.svg +0 -37
  273. package/assets/rooms/Dressing Room.svg +0 -5
  274. package/assets/rooms/Driveway.svg +0 -15
  275. package/assets/rooms/Entrance.svg +0 -44
  276. package/assets/rooms/Equipment Room.svg +0 -15
  277. package/assets/rooms/Front Yard.svg +0 -64
  278. package/assets/rooms/Gallery.svg +0 -14
  279. package/assets/rooms/Garage.svg +0 -20
  280. package/assets/rooms/Garden.svg +0 -13
  281. package/assets/rooms/Ground Floor.svg +0 -95
  282. package/assets/rooms/Guest Bathroom.svg +0 -33
  283. package/assets/rooms/Guest Room.svg +0 -5
  284. package/assets/rooms/Gym.svg +0 -5
  285. package/assets/rooms/Hall.svg +0 -19
  286. package/assets/rooms/Home Theater.svg +0 -8
  287. package/assets/rooms/Kitchen.svg +0 -18
  288. package/assets/rooms/Laundry Room.svg +0 -12
  289. package/assets/rooms/Living Area.svg +0 -11
  290. package/assets/rooms/Living Room.svg +0 -10
  291. package/assets/rooms/Locker Room.svg +0 -17
  292. package/assets/rooms/Nursery.svg +0 -5
  293. package/assets/rooms/Office.svg +0 -8
  294. package/assets/rooms/Outdoors.svg +0 -7
  295. package/assets/rooms/Playroom.svg +0 -6
  296. package/assets/rooms/Pool.svg +0 -8
  297. package/assets/rooms/Rear Wall.svg +0 -30
  298. package/assets/rooms/Second Floor.svg +0 -95
  299. package/assets/rooms/Shed.svg +0 -16
  300. package/assets/rooms/Sleeping Area.svg +0 -22
  301. package/assets/rooms/Stairway.svg +0 -5
  302. package/assets/rooms/Stairwell.svg +0 -15
  303. package/assets/rooms/Storeroom.svg +0 -5
  304. package/assets/rooms/Summer House.svg +0 -27
  305. package/assets/rooms/Swimming Pool.svg +0 -21
  306. package/assets/rooms/Terrace.svg +0 -7
  307. package/assets/rooms/Toilet.svg +0 -10
  308. package/assets/rooms/Upstairs.svg +0 -6
  309. package/assets/rooms/Wardrobe.svg +0 -60
  310. package/assets/rooms/Washroom.svg +0 -20
  311. package/assets/rooms/Wc.svg +0 -10
  312. package/assets/rooms/Windscreen.svg +0 -60
  313. package/assets/rooms/Workshop.svg +0 -23
  314. package/assets/rooms/Workspace.svg +0 -8
@@ -1,599 +1,631 @@
1
- import React, { Component, createRef } from 'react';
2
- import Dropzone from 'react-dropzone';
3
- import { Cropper, ReactCropperElement } from 'react-cropper';
4
-
5
- import {
6
- Menu, MenuItem, Tooltip, IconButton,
7
- } from '@mui/material';
8
-
9
- import {
10
- Close as IconClose,
11
- Crop as CropIcon,
12
- } from '@mui/icons-material';
13
- import { FaFileUpload as UploadIcon } from 'react-icons/fa';
14
-
15
- import I18n from '../i18n';
16
- import Icon from './Icon';
17
-
18
- // import 'cropperjs/dist/cropper.css';
19
- const cropperStyles = `
20
- /*!
21
- * Cropper.js v1.5.12
22
- * https://fengyuanchen.github.io/cropperjs
23
- *
24
- * Copyright 2015-present Chen Fengyuan
25
- * Released under the MIT license
26
- *
27
- * Date: 2021-06-12T08:00:11.623Z
28
- */
29
-
30
- .cropper-container {
31
- direction: ltr;
32
- font-size: 0;
33
- line-height: 0;
34
- position: relative;
35
- -ms-touch-action: none;
36
- touch-action: none;
37
- -webkit-user-select: none;
38
- -moz-user-select: none;
39
- -ms-user-select: none;
40
- user-select: none;
41
- }
42
-
43
- .cropper-container img {
44
- display: block;
45
- height: 100%;
46
- image-orientation: 0deg;
47
- max-height: none !important;
48
- max-width: none !important;
49
- min-height: 0 !important;
50
- min-width: 0 !important;
51
- width: 100%;
52
- }
53
-
54
- .cropper-wrap-box,
55
- .cropper-canvas,
56
- .cropper-drag-box,
57
- .cropper-crop-box,
58
- .cropper-modal {
59
- bottom: 0;
60
- left: 0;
61
- position: absolute;
62
- right: 0;
63
- top: 0;
64
- }
65
-
66
- .cropper-wrap-box,
67
- .cropper-canvas {
68
- overflow: hidden;
69
- }
70
-
71
- .cropper-drag-box {
72
- background-color: #fff;
73
- opacity: 0;
74
- }
75
-
76
- .cropper-modal {
77
- background-color: #000;
78
- opacity: 0.5;
79
- }
80
-
81
- .cropper-view-box {
82
- display: block;
83
- height: 100%;
84
- outline: 1px solid #39f;
85
- outline-color: rgba(51, 153, 255, 0.75);
86
- overflow: hidden;
87
- width: 100%;
88
- }
89
-
90
- .cropper-dashed {
91
- border: 0 dashed #eee;
92
- display: block;
93
- opacity: 0.5;
94
- position: absolute;
95
- }
96
-
97
- .cropper-dashed.dashed-h {
98
- border-bottom-width: 1px;
99
- border-top-width: 1px;
100
- height: calc(100% / 3);
101
- left: 0;
102
- top: calc(100% / 3);
103
- width: 100%;
104
- }
105
-
106
- .cropper-dashed.dashed-v {
107
- border-left-width: 1px;
108
- border-right-width: 1px;
109
- height: 100%;
110
- left: calc(100% / 3);
111
- top: 0;
112
- width: calc(100% / 3);
113
- }
114
-
115
- .cropper-center {
116
- display: block;
117
- height: 0;
118
- left: 50%;
119
- opacity: 0.75;
120
- position: absolute;
121
- top: 50%;
122
- width: 0;
123
- }
124
-
125
- .cropper-center::before,
126
- .cropper-center::after {
127
- background-color: #eee;
128
- content: ' ';
129
- display: block;
130
- position: absolute;
131
- }
132
-
133
- .cropper-center::before {
134
- height: 1px;
135
- left: -3px;
136
- top: 0;
137
- width: 7px;
138
- }
139
-
140
- .cropper-center::after {
141
- height: 7px;
142
- left: 0;
143
- top: -3px;
144
- width: 1px;
145
- }
146
-
147
- .cropper-face,
148
- .cropper-line,
149
- .cropper-point {
150
- display: block;
151
- height: 100%;
152
- opacity: 0.1;
153
- position: absolute;
154
- width: 100%;
155
- }
156
-
157
- .cropper-face {
158
- background-color: #fff;
159
- left: 0;
160
- top: 0;
161
- }
162
-
163
- .cropper-line {
164
- background-color: #39f;
165
- }
166
-
167
- .cropper-line.line-e {
168
- cursor: ew-resize;
169
- right: -3px;
170
- top: 0;
171
- width: 5px;
172
- }
173
-
174
- .cropper-line.line-n {
175
- cursor: ns-resize;
176
- height: 5px;
177
- left: 0;
178
- top: -3px;
179
- }
180
-
181
- .cropper-line.line-w {
182
- cursor: ew-resize;
183
- left: -3px;
184
- top: 0;
185
- width: 5px;
186
- }
187
-
188
- .cropper-line.line-s {
189
- bottom: -3px;
190
- cursor: ns-resize;
191
- height: 5px;
192
- left: 0;
193
- }
194
-
195
- .cropper-point {
196
- background-color: #39f;
197
- height: 5px;
198
- opacity: 0.75;
199
- width: 5px;
200
- }
201
-
202
- .cropper-point.point-e {
203
- cursor: ew-resize;
204
- margin-top: -3px;
205
- right: -3px;
206
- top: 50%;
207
- }
208
-
209
- .cropper-point.point-n {
210
- cursor: ns-resize;
211
- left: 50%;
212
- margin-left: -3px;
213
- top: -3px;
214
- }
215
-
216
- .cropper-point.point-w {
217
- cursor: ew-resize;
218
- left: -3px;
219
- margin-top: -3px;
220
- top: 50%;
221
- }
222
-
223
- .cropper-point.point-s {
224
- bottom: -3px;
225
- cursor: s-resize;
226
- left: 50%;
227
- margin-left: -3px;
228
- }
229
-
230
- .cropper-point.point-ne {
231
- cursor: nesw-resize;
232
- right: -3px;
233
- top: -3px;
234
- }
235
-
236
- .cropper-point.point-nw {
237
- cursor: nwse-resize;
238
- left: -3px;
239
- top: -3px;
240
- }
241
-
242
- .cropper-point.point-sw {
243
- bottom: -3px;
244
- cursor: nesw-resize;
245
- left: -3px;
246
- }
247
-
248
- .cropper-point.point-se {
249
- bottom: -3px;
250
- cursor: nwse-resize;
251
- height: 20px;
252
- opacity: 1;
253
- right: -3px;
254
- width: 20px;
255
- }
256
-
257
- @media (min-width: 768px) {
258
- .cropper-point.point-se {
259
- height: 15px;
260
- width: 15px;
261
- }
262
- }
263
-
264
- @media (min-width: 992px) {
265
- .cropper-point.point-se {
266
- height: 10px;
267
- width: 10px;
268
- }
269
- }
270
-
271
- @media (min-width: 1200px) {
272
- .cropper-point.point-se {
273
- height: 5px;
274
- opacity: 0.75;
275
- width: 5px;
276
- }
277
- }
278
-
279
- .cropper-point.point-se::before {
280
- background-color: #39f;
281
- bottom: -50%;
282
- content: ' ';
283
- display: block;
284
- height: 200%;
285
- opacity: 0;
286
- position: absolute;
287
- right: -50%;
288
- width: 200%;
289
- }
290
-
291
- .cropper-invisible {
292
- opacity: 0;
293
- }
294
-
295
- .cropper-bg {
296
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
297
- }
298
-
299
- .cropper-hide {
300
- display: block;
301
- height: 0;
302
- position: absolute;
303
- width: 0;
304
- }
305
-
306
- .cropper-hidden {
307
- display: none !important;
308
- }
309
-
310
- .cropper-move {
311
- cursor: move;
312
- }
313
-
314
- .cropper-crop {
315
- cursor: crosshair;
316
- }
317
-
318
- .cropper-disabled .cropper-drag-box,
319
- .cropper-disabled .cropper-face,
320
- .cropper-disabled .cropper-line,
321
- .cropper-disabled .cropper-point {
322
- cursor: not-allowed;
323
- }
324
- `;
325
-
326
- const styles: Record<string, React.CSSProperties> = {
327
- dropZone: {
328
- width: '100%',
329
- height: 100,
330
- position: 'relative',
331
- },
332
- dropZoneEmpty: {
333
-
334
- },
335
- image: {
336
- objectFit: 'contain',
337
- margin: 'auto',
338
- display: 'flex',
339
- width: '100%',
340
- height: '100%',
341
- },
342
-
343
- uploadDiv: {
344
- position: 'relative',
345
- width: '100%',
346
- height: 300,
347
- opacity: 0.9,
348
- marginTop: 30,
349
- cursor: 'pointer',
350
- outline: 'none',
351
- },
352
- uploadDivDragging: {
353
- opacity: 1,
354
- background: 'rgba(128,255,128,0.1)',
355
- },
356
-
357
- uploadCenterDiv: {
358
- margin: 5,
359
- border: '3px dashed grey',
360
- borderRadius: 5,
361
- width: 'calc(100% - 10px)',
362
- height: 'calc(100% - 10px)',
363
- position: 'relative',
364
- display: 'flex',
365
- },
366
- uploadCenterIcon: {
367
- paddingTop: 10,
368
- width: 48,
369
- height: 48,
370
- },
371
- uploadCenterText: {
372
- fontSize: 16,
373
- },
374
- uploadCenterTextAndIcon: {
375
- textAlign: 'center',
376
- position: 'absolute',
377
- top: 0,
378
- bottom: 0,
379
- left: 0,
380
- right: 0,
381
- display: 'flex',
382
- flexDirection: 'column',
383
- alignItems: 'center',
384
- justifyContent: 'center',
385
-
386
- },
387
- disabledOpacity: {
388
- opacity: 0.3,
389
- cursor: 'default',
390
- },
391
- buttonRemoveWrapper: {
392
- position: 'absolute',
393
- zIndex: 222,
394
- right: 0,
395
- },
396
- buttonCropWrapper: {
397
- position: 'absolute',
398
- zIndex: 222,
399
- right: 0,
400
- top: 50,
401
- },
402
- error: {
403
- border: '2px solid red',
404
- boxSizing: 'border-box',
405
- },
406
- };
407
-
408
- interface UploadImageProps {
409
- maxSize?: number;
410
- disabled?: boolean;
411
- crop?: boolean;
412
- error?: boolean;
413
- onChange: (base64: string) => void | undefined;
414
- icon: string | null;
415
- removeIconFunc: () => void | null;
416
- accept?: Record<string, string[]>;
417
- }
418
-
419
- interface UploadImageState {
420
- uploadFile: boolean | 'dragging';
421
- anchorEl: HTMLElement | null;
422
- cropHandler: boolean;
423
- }
424
-
425
- class UploadImage extends Component<UploadImageProps, UploadImageState> {
426
- private readonly cropperRef: React.RefObject<ReactCropperElement>;
427
-
428
- constructor(props: UploadImageProps) {
429
- super(props);
430
-
431
- this.state = {
432
- uploadFile: false,
433
- anchorEl: null,
434
- cropHandler: false,
435
- };
436
- this.cropperRef = createRef();
437
-
438
- if (!window.document.getElementById('cropper-style-json-component')) {
439
- const style = window.document.createElement('style');
440
- style.setAttribute('id', 'cropper-style-json-component');
441
- style.innerHTML = cropperStyles;
442
- window.document.head.appendChild(style);
443
- }
444
- }
445
-
446
- onDrop(acceptedFiles: File[]) {
447
- const onChange = this.props.onChange;
448
- const maxSize = this.props.maxSize || 10 * 1024;
449
-
450
- const file = acceptedFiles[0];
451
- const reader = new FileReader();
452
-
453
- reader.onabort = () => console.log('file reading was aborted');
454
- reader.onerror = () => console.log('file reading has failed');
455
- reader.onload = () => {
456
- if (!file || !file.name) {
457
- return;
458
- }
459
- const parts = file.name?.split('.');
460
- let ext = parts?.length ? `image/${parts.pop()?.toLowerCase()}` : 'image/jpeg';
461
- if (ext === 'image/jpg') {
462
- ext = 'image/jpeg';
463
- } else if (ext.includes('svg')) {
464
- ext = 'image/svg+xml';
465
- }
466
- if (file.size > maxSize) {
467
- window.alert(I18n.t('ra_File is too big. Max %sk allowed. Try use SVG.', Math.round(maxSize / 1024)));
468
- } else {
469
- const base64 = `data:${ext};base64,${btoa(
470
- new Uint8Array(reader.result as ArrayBufferLike)
471
- .reduce((data, byte) => data + String.fromCharCode(byte), ''),
472
- )}`;
473
-
474
- if (onChange) {
475
- onChange(base64);
476
- } else {
477
- console.log(base64);
478
- }
479
- }
480
- };
481
- reader.readAsArrayBuffer(file);
482
- }
483
-
484
- render() {
485
- const {
486
- disabled, icon, removeIconFunc, error, crop, onChange,
487
- } = this.props;
488
- const maxSize = this.props.maxSize || 10 * 1024;
489
- const accept = this.props.accept || { 'image/*': [] };
490
- const { uploadFile, anchorEl, cropHandler } = this.state;
491
- return <Dropzone
492
- disabled={!!disabled || cropHandler}
493
- key="dropzone"
494
- multiple={false}
495
- accept={accept}
496
- maxSize={maxSize}
497
- onDragEnter={() => this.setState({ uploadFile: 'dragging' })}
498
- onDragLeave={() => this.setState({ uploadFile: true })}
499
- onDrop={(acceptedFiles: File[], errors) => {
500
- this.setState({ uploadFile: false });
501
- if (!acceptedFiles.length) {
502
- window.alert((errors && errors[0] && errors[0].errors && errors[0].errors[0] && errors[0].errors[0].message) || I18n.t('ra_Cannot upload'));
503
- } else {
504
- this.onDrop(acceptedFiles);
505
- }
506
- }}
507
- >
508
- {({ getRootProps, getInputProps }) => <div
509
- style={{
510
- ...styles.uploadDiv,
511
- ...(uploadFile === 'dragging' ? styles.uploadDivDragging : undefined),
512
- ...styles.dropZone,
513
- ...(disabled ? styles.disabledOpacity : undefined),
514
- ...(!icon ? styles.dropZoneEmpty : undefined),
515
- }}
516
- {...getRootProps()}
517
- >
518
- <input {...getInputProps()} />
519
- <div style={{ ...styles.uploadCenterDiv, ...(error ? styles.error : undefined) }}>
520
- {!icon ? <div style={styles.uploadCenterTextAndIcon}>
521
- <UploadIcon style={styles.uploadCenterIcon} />
522
- <div style={styles.uploadCenterText}>
523
- {uploadFile === 'dragging' ? I18n.t('ra_Drop file here') :
524
- I18n.t('ra_Place your files here or click here to open the browse dialog')}
525
- </div>
526
- </div>
527
- :
528
- removeIconFunc && !cropHandler && <div style={styles.buttonRemoveWrapper}>
529
- <Tooltip title={I18n.t('ra_Clear')} componentsProps={{ popper: { sx: { pointerEvents: 'none' } } }}>
530
- <IconButton
531
- size="large"
532
- onClick={e => {
533
- removeIconFunc && removeIconFunc();
534
- e.stopPropagation();
535
- }}
536
- >
537
- <IconClose />
538
- </IconButton>
539
- </Tooltip>
540
- </div>}
541
- {icon && crop && <div style={styles.buttonCropWrapper}>
542
- <Tooltip title={I18n.t('ra_Crop')} componentsProps={{ popper: { sx: { pointerEvents: 'none' } } }}>
543
- <IconButton
544
- size="large"
545
- onClick={e => {
546
- if (!cropHandler) {
547
- this.setState({ cropHandler: true });
548
- } else {
549
- this.setState({ anchorEl: e.currentTarget });
550
- }
551
- e.stopPropagation();
552
- }}
553
- >
554
- <CropIcon color={cropHandler ? 'primary' : 'inherit'} />
555
- </IconButton>
556
- </Tooltip>
557
- <Menu
558
- anchorEl={anchorEl}
559
- keepMounted
560
- open={Boolean(anchorEl)}
561
- onClose={() => this.setState({ anchorEl: null })}
562
- >
563
- <MenuItem onClick={() => this.setState({ anchorEl: null, cropHandler: false }, () => {
564
- const imageElement = this.cropperRef?.current?.cropper;
565
- if (imageElement) {
566
- if (onChange) {
567
- onChange(imageElement.getCroppedCanvas().toDataURL());
568
- } else {
569
- console.log(imageElement.getCroppedCanvas().toDataURL());
570
- }
571
- }
572
- })}
573
- >
574
- {I18n.t('ra_Save')}
575
- </MenuItem>
576
- <MenuItem onClick={() => this.setState({ anchorEl: null, cropHandler: false })}>{I18n.t('ra_Close')}</MenuItem>
577
- </Menu>
578
- </div>}
579
- {icon && !cropHandler ? <Icon src={icon} style={styles.image} alt="icon" /> : null}
580
-
581
- {icon && crop && cropHandler ? <Cropper
582
- ref={this.cropperRef}
583
- style={styles.image}
584
- src={icon}
585
- initialAspectRatio={1}
586
- viewMode={1}
587
- guides={false}
588
- minCropBoxHeight={10}
589
- minCropBoxWidth={10}
590
- background={false}
591
- checkOrientation={false}
592
- /> : null}
593
- </div>
594
- </div>}
595
- </Dropzone>;
596
- }
597
- }
598
-
599
- export default UploadImage;
1
+ import React, { Component, createRef, type JSX } from 'react';
2
+ import Dropzone from 'react-dropzone';
3
+ import { Cropper, type ReactCropperElement } from 'react-cropper';
4
+
5
+ import { Menu, MenuItem, Tooltip, IconButton } from '@mui/material';
6
+
7
+ import { Close as IconClose, Crop as CropIcon } from '@mui/icons-material';
8
+ import { FaFileUpload as UploadIcon } from 'react-icons/fa';
9
+
10
+ import I18n from '../i18n';
11
+ import Icon from './Icon';
12
+
13
+ // import 'cropperjs/dist/cropper.css';
14
+ const cropperStyles = `
15
+ /*!
16
+ * Cropper.js v1.5.12
17
+ * https://fengyuanchen.github.io/cropperjs
18
+ *
19
+ * Copyright 2015-present Chen Fengyuan
20
+ * Released under the MIT license
21
+ *
22
+ * Date: 2021-06-12T08:00:11.623Z
23
+ */
24
+
25
+ .cropper-container {
26
+ direction: ltr;
27
+ font-size: 0;
28
+ line-height: 0;
29
+ position: relative;
30
+ -ms-touch-action: none;
31
+ touch-action: none;
32
+ -webkit-user-select: none;
33
+ -moz-user-select: none;
34
+ -ms-user-select: none;
35
+ user-select: none;
36
+ }
37
+
38
+ .cropper-container img {
39
+ display: block;
40
+ height: 100%;
41
+ image-orientation: 0deg;
42
+ max-height: none !important;
43
+ max-width: none !important;
44
+ min-height: 0 !important;
45
+ min-width: 0 !important;
46
+ width: 100%;
47
+ }
48
+
49
+ .cropper-wrap-box,
50
+ .cropper-canvas,
51
+ .cropper-drag-box,
52
+ .cropper-crop-box,
53
+ .cropper-modal {
54
+ bottom: 0;
55
+ left: 0;
56
+ position: absolute;
57
+ right: 0;
58
+ top: 0;
59
+ }
60
+
61
+ .cropper-wrap-box,
62
+ .cropper-canvas {
63
+ overflow: hidden;
64
+ }
65
+
66
+ .cropper-drag-box {
67
+ background-color: #fff;
68
+ opacity: 0;
69
+ }
70
+
71
+ .cropper-modal {
72
+ background-color: #000;
73
+ opacity: 0.5;
74
+ }
75
+
76
+ .cropper-view-box {
77
+ display: block;
78
+ height: 100%;
79
+ outline: 1px solid #39f;
80
+ outline-color: rgba(51, 153, 255, 0.75);
81
+ overflow: hidden;
82
+ width: 100%;
83
+ }
84
+
85
+ .cropper-dashed {
86
+ border: 0 dashed #eee;
87
+ display: block;
88
+ opacity: 0.5;
89
+ position: absolute;
90
+ }
91
+
92
+ .cropper-dashed.dashed-h {
93
+ border-bottom-width: 1px;
94
+ border-top-width: 1px;
95
+ height: calc(100% / 3);
96
+ left: 0;
97
+ top: calc(100% / 3);
98
+ width: 100%;
99
+ }
100
+
101
+ .cropper-dashed.dashed-v {
102
+ border-left-width: 1px;
103
+ border-right-width: 1px;
104
+ height: 100%;
105
+ left: calc(100% / 3);
106
+ top: 0;
107
+ width: calc(100% / 3);
108
+ }
109
+
110
+ .cropper-center {
111
+ display: block;
112
+ height: 0;
113
+ left: 50%;
114
+ opacity: 0.75;
115
+ position: absolute;
116
+ top: 50%;
117
+ width: 0;
118
+ }
119
+
120
+ .cropper-center::before,
121
+ .cropper-center::after {
122
+ background-color: #eee;
123
+ content: ' ';
124
+ display: block;
125
+ position: absolute;
126
+ }
127
+
128
+ .cropper-center::before {
129
+ height: 1px;
130
+ left: -3px;
131
+ top: 0;
132
+ width: 7px;
133
+ }
134
+
135
+ .cropper-center::after {
136
+ height: 7px;
137
+ left: 0;
138
+ top: -3px;
139
+ width: 1px;
140
+ }
141
+
142
+ .cropper-face,
143
+ .cropper-line,
144
+ .cropper-point {
145
+ display: block;
146
+ height: 100%;
147
+ opacity: 0.1;
148
+ position: absolute;
149
+ width: 100%;
150
+ }
151
+
152
+ .cropper-face {
153
+ background-color: #fff;
154
+ left: 0;
155
+ top: 0;
156
+ }
157
+
158
+ .cropper-line {
159
+ background-color: #39f;
160
+ }
161
+
162
+ .cropper-line.line-e {
163
+ cursor: ew-resize;
164
+ right: -3px;
165
+ top: 0;
166
+ width: 5px;
167
+ }
168
+
169
+ .cropper-line.line-n {
170
+ cursor: ns-resize;
171
+ height: 5px;
172
+ left: 0;
173
+ top: -3px;
174
+ }
175
+
176
+ .cropper-line.line-w {
177
+ cursor: ew-resize;
178
+ left: -3px;
179
+ top: 0;
180
+ width: 5px;
181
+ }
182
+
183
+ .cropper-line.line-s {
184
+ bottom: -3px;
185
+ cursor: ns-resize;
186
+ height: 5px;
187
+ left: 0;
188
+ }
189
+
190
+ .cropper-point {
191
+ background-color: #39f;
192
+ height: 5px;
193
+ opacity: 0.75;
194
+ width: 5px;
195
+ }
196
+
197
+ .cropper-point.point-e {
198
+ cursor: ew-resize;
199
+ margin-top: -3px;
200
+ right: -3px;
201
+ top: 50%;
202
+ }
203
+
204
+ .cropper-point.point-n {
205
+ cursor: ns-resize;
206
+ left: 50%;
207
+ margin-left: -3px;
208
+ top: -3px;
209
+ }
210
+
211
+ .cropper-point.point-w {
212
+ cursor: ew-resize;
213
+ left: -3px;
214
+ margin-top: -3px;
215
+ top: 50%;
216
+ }
217
+
218
+ .cropper-point.point-s {
219
+ bottom: -3px;
220
+ cursor: s-resize;
221
+ left: 50%;
222
+ margin-left: -3px;
223
+ }
224
+
225
+ .cropper-point.point-ne {
226
+ cursor: nesw-resize;
227
+ right: -3px;
228
+ top: -3px;
229
+ }
230
+
231
+ .cropper-point.point-nw {
232
+ cursor: nwse-resize;
233
+ left: -3px;
234
+ top: -3px;
235
+ }
236
+
237
+ .cropper-point.point-sw {
238
+ bottom: -3px;
239
+ cursor: nesw-resize;
240
+ left: -3px;
241
+ }
242
+
243
+ .cropper-point.point-se {
244
+ bottom: -3px;
245
+ cursor: nwse-resize;
246
+ height: 20px;
247
+ opacity: 1;
248
+ right: -3px;
249
+ width: 20px;
250
+ }
251
+
252
+ @media (min-width: 768px) {
253
+ .cropper-point.point-se {
254
+ height: 15px;
255
+ width: 15px;
256
+ }
257
+ }
258
+
259
+ @media (min-width: 992px) {
260
+ .cropper-point.point-se {
261
+ height: 10px;
262
+ width: 10px;
263
+ }
264
+ }
265
+
266
+ @media (min-width: 1200px) {
267
+ .cropper-point.point-se {
268
+ height: 5px;
269
+ opacity: 0.75;
270
+ width: 5px;
271
+ }
272
+ }
273
+
274
+ .cropper-point.point-se::before {
275
+ background-color: #39f;
276
+ bottom: -50%;
277
+ content: ' ';
278
+ display: block;
279
+ height: 200%;
280
+ opacity: 0;
281
+ position: absolute;
282
+ right: -50%;
283
+ width: 200%;
284
+ }
285
+
286
+ .cropper-invisible {
287
+ opacity: 0;
288
+ }
289
+
290
+ .cropper-bg {
291
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
292
+ }
293
+
294
+ .cropper-hide {
295
+ display: block;
296
+ height: 0;
297
+ position: absolute;
298
+ width: 0;
299
+ }
300
+
301
+ .cropper-hidden {
302
+ display: none !important;
303
+ }
304
+
305
+ .cropper-move {
306
+ cursor: move;
307
+ }
308
+
309
+ .cropper-crop {
310
+ cursor: crosshair;
311
+ }
312
+
313
+ .cropper-disabled .cropper-drag-box,
314
+ .cropper-disabled .cropper-face,
315
+ .cropper-disabled .cropper-line,
316
+ .cropper-disabled .cropper-point {
317
+ cursor: not-allowed;
318
+ }
319
+ `;
320
+
321
+ const styles: Record<string, React.CSSProperties> = {
322
+ dropZone: {
323
+ width: '100%',
324
+ height: 100,
325
+ position: 'relative',
326
+ },
327
+ dropZoneEmpty: {},
328
+ image: {
329
+ objectFit: 'contain',
330
+ margin: 'auto',
331
+ display: 'flex',
332
+ width: '100%',
333
+ height: '100%',
334
+ },
335
+
336
+ uploadDiv: {
337
+ position: 'relative',
338
+ width: '100%',
339
+ height: 300,
340
+ opacity: 0.9,
341
+ marginTop: 30,
342
+ cursor: 'pointer',
343
+ outline: 'none',
344
+ },
345
+ uploadDivDragging: {
346
+ opacity: 1,
347
+ background: 'rgba(128,255,128,0.1)',
348
+ },
349
+
350
+ uploadCenterDiv: {
351
+ margin: 5,
352
+ border: '3px dashed grey',
353
+ borderRadius: 5,
354
+ width: 'calc(100% - 10px)',
355
+ height: 'calc(100% - 10px)',
356
+ position: 'relative',
357
+ display: 'flex',
358
+ },
359
+ uploadCenterIcon: {
360
+ paddingTop: 10,
361
+ width: 48,
362
+ height: 48,
363
+ },
364
+ uploadCenterText: {
365
+ fontSize: 16,
366
+ },
367
+ uploadCenterTextAndIcon: {
368
+ textAlign: 'center',
369
+ position: 'absolute',
370
+ top: 0,
371
+ bottom: 0,
372
+ left: 0,
373
+ right: 0,
374
+ display: 'flex',
375
+ flexDirection: 'column',
376
+ alignItems: 'center',
377
+ justifyContent: 'center',
378
+ },
379
+ disabledOpacity: {
380
+ opacity: 0.3,
381
+ cursor: 'default',
382
+ },
383
+ buttonRemoveWrapper: {
384
+ position: 'absolute',
385
+ zIndex: 222,
386
+ right: 0,
387
+ },
388
+ buttonCropWrapper: {
389
+ position: 'absolute',
390
+ zIndex: 222,
391
+ right: 0,
392
+ top: 50,
393
+ },
394
+ error: {
395
+ border: '2px solid red',
396
+ boxSizing: 'border-box',
397
+ },
398
+ };
399
+
400
+ interface UploadImageProps {
401
+ maxSize?: number;
402
+ disabled?: boolean;
403
+ crop?: boolean;
404
+ error?: boolean;
405
+ onChange: (base64: string) => void | undefined;
406
+ icon: string | null;
407
+ removeIconFunc: () => void | null;
408
+ accept?: Record<string, string[]>;
409
+ }
410
+
411
+ interface UploadImageState {
412
+ uploadFile: boolean | 'dragging';
413
+ anchorEl: HTMLElement | null;
414
+ cropHandler: boolean;
415
+ }
416
+
417
+ class UploadImage extends Component<UploadImageProps, UploadImageState> {
418
+ private readonly cropperRef: React.RefObject<ReactCropperElement>;
419
+
420
+ constructor(props: UploadImageProps) {
421
+ super(props);
422
+
423
+ this.state = {
424
+ uploadFile: false,
425
+ anchorEl: null,
426
+ cropHandler: false,
427
+ };
428
+ this.cropperRef = createRef();
429
+
430
+ if (!window.document.getElementById('cropper-style-json-component')) {
431
+ const style = window.document.createElement('style');
432
+ style.setAttribute('id', 'cropper-style-json-component');
433
+ style.innerHTML = cropperStyles;
434
+ window.document.head.appendChild(style);
435
+ }
436
+ }
437
+
438
+ onDrop(acceptedFiles: File[]): void {
439
+ const onChange = this.props.onChange;
440
+ const maxSize = this.props.maxSize || 10 * 1024;
441
+
442
+ const file = acceptedFiles[0];
443
+ const reader = new FileReader();
444
+
445
+ reader.onabort = () => console.log('file reading was aborted');
446
+ reader.onerror = () => console.log('file reading has failed');
447
+ reader.onload = () => {
448
+ if (!file || !file.name) {
449
+ return;
450
+ }
451
+ const parts = file.name?.split('.');
452
+ let ext = parts?.length ? `image/${parts.pop()?.toLowerCase()}` : 'image/jpeg';
453
+ if (ext === 'image/jpg') {
454
+ ext = 'image/jpeg';
455
+ } else if (ext.includes('svg')) {
456
+ ext = 'image/svg+xml';
457
+ }
458
+ if (file.size > maxSize) {
459
+ window.alert(I18n.t('ra_File is too big. Max %sk allowed. Try use SVG.', Math.round(maxSize / 1024)));
460
+ } else {
461
+ const base64 = `data:${ext};base64,${btoa(
462
+ new Uint8Array(reader.result as ArrayBufferLike).reduce(
463
+ (data, byte) => data + String.fromCharCode(byte),
464
+ '',
465
+ ),
466
+ )}`;
467
+
468
+ if (onChange) {
469
+ onChange(base64);
470
+ } else {
471
+ console.log(base64);
472
+ }
473
+ }
474
+ };
475
+ reader.readAsArrayBuffer(file);
476
+ }
477
+
478
+ render(): JSX.Element {
479
+ const { disabled, icon, removeIconFunc, error, crop, onChange } = this.props;
480
+ const maxSize = this.props.maxSize || 10 * 1024;
481
+ const accept = this.props.accept || { 'image/*': [] };
482
+ const { uploadFile, anchorEl, cropHandler } = this.state;
483
+ return (
484
+ <Dropzone
485
+ disabled={!!disabled || cropHandler}
486
+ key="dropzone"
487
+ multiple={false}
488
+ accept={accept}
489
+ maxSize={maxSize}
490
+ onDragEnter={() => this.setState({ uploadFile: 'dragging' })}
491
+ onDragLeave={() => this.setState({ uploadFile: true })}
492
+ onDrop={(acceptedFiles: File[], errors) => {
493
+ this.setState({ uploadFile: false });
494
+ if (!acceptedFiles.length) {
495
+ window.alert(
496
+ (errors &&
497
+ errors[0] &&
498
+ errors[0].errors &&
499
+ errors[0].errors[0] &&
500
+ errors[0].errors[0].message) ||
501
+ I18n.t('ra_Cannot upload'),
502
+ );
503
+ } else {
504
+ this.onDrop(acceptedFiles);
505
+ }
506
+ }}
507
+ >
508
+ {({ getRootProps, getInputProps }) => (
509
+ <div
510
+ style={{
511
+ ...styles.uploadDiv,
512
+ ...(uploadFile === 'dragging' ? styles.uploadDivDragging : undefined),
513
+ ...styles.dropZone,
514
+ ...(disabled ? styles.disabledOpacity : undefined),
515
+ ...(!icon ? styles.dropZoneEmpty : undefined),
516
+ }}
517
+ {...getRootProps()}
518
+ >
519
+ <input {...getInputProps()} />
520
+ <div style={{ ...styles.uploadCenterDiv, ...(error ? styles.error : undefined) }}>
521
+ {!icon ? (
522
+ <div style={styles.uploadCenterTextAndIcon}>
523
+ <UploadIcon style={styles.uploadCenterIcon} />
524
+ <div style={styles.uploadCenterText}>
525
+ {uploadFile === 'dragging'
526
+ ? I18n.t('ra_Drop file here')
527
+ : I18n.t(
528
+ 'ra_Place your files here or click here to open the browse dialog',
529
+ )}
530
+ </div>
531
+ </div>
532
+ ) : (
533
+ removeIconFunc &&
534
+ !cropHandler && (
535
+ <div style={styles.buttonRemoveWrapper}>
536
+ <Tooltip
537
+ title={I18n.t('ra_Clear')}
538
+ componentsProps={{ popper: { sx: { pointerEvents: 'none' } } }}
539
+ >
540
+ <IconButton
541
+ size="large"
542
+ onClick={e => {
543
+ removeIconFunc && removeIconFunc();
544
+ e.stopPropagation();
545
+ }}
546
+ >
547
+ <IconClose />
548
+ </IconButton>
549
+ </Tooltip>
550
+ </div>
551
+ )
552
+ )}
553
+ {icon && crop && (
554
+ <div style={styles.buttonCropWrapper}>
555
+ <Tooltip
556
+ title={I18n.t('ra_Crop')}
557
+ componentsProps={{ popper: { sx: { pointerEvents: 'none' } } }}
558
+ >
559
+ <IconButton
560
+ size="large"
561
+ onClick={e => {
562
+ if (!cropHandler) {
563
+ this.setState({ cropHandler: true });
564
+ } else {
565
+ this.setState({ anchorEl: e.currentTarget });
566
+ }
567
+ e.stopPropagation();
568
+ }}
569
+ >
570
+ <CropIcon color={cropHandler ? 'primary' : 'inherit'} />
571
+ </IconButton>
572
+ </Tooltip>
573
+ <Menu
574
+ anchorEl={anchorEl}
575
+ keepMounted
576
+ open={Boolean(anchorEl)}
577
+ onClose={() => this.setState({ anchorEl: null })}
578
+ >
579
+ <MenuItem
580
+ onClick={() =>
581
+ this.setState({ anchorEl: null, cropHandler: false }, () => {
582
+ const imageElement = this.cropperRef?.current?.cropper;
583
+ if (imageElement) {
584
+ if (onChange) {
585
+ onChange(imageElement.getCroppedCanvas().toDataURL());
586
+ } else {
587
+ console.log(imageElement.getCroppedCanvas().toDataURL());
588
+ }
589
+ }
590
+ })
591
+ }
592
+ >
593
+ {I18n.t('ra_Save')}
594
+ </MenuItem>
595
+ <MenuItem onClick={() => this.setState({ anchorEl: null, cropHandler: false })}>
596
+ {I18n.t('ra_Close')}
597
+ </MenuItem>
598
+ </Menu>
599
+ </div>
600
+ )}
601
+ {icon && !cropHandler ? (
602
+ <Icon
603
+ src={icon}
604
+ style={styles.image}
605
+ alt="icon"
606
+ />
607
+ ) : null}
608
+
609
+ {icon && crop && cropHandler ? (
610
+ <Cropper
611
+ ref={this.cropperRef}
612
+ style={styles.image}
613
+ src={icon}
614
+ initialAspectRatio={1}
615
+ viewMode={1}
616
+ guides={false}
617
+ minCropBoxHeight={10}
618
+ minCropBoxWidth={10}
619
+ background={false}
620
+ checkOrientation={false}
621
+ />
622
+ ) : null}
623
+ </div>
624
+ </div>
625
+ )}
626
+ </Dropzone>
627
+ );
628
+ }
629
+ }
630
+
631
+ export default UploadImage;