renusify 2.5.2 → 3.0.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 (212) hide show
  1. package/components/app/index.vue +74 -22
  2. package/components/app/toast/index.vue +76 -71
  3. package/components/app/toast/toast.vue +62 -44
  4. package/components/avatar/index.vue +208 -84
  5. package/components/button/buttonConfirm.vue +53 -26
  6. package/components/button/buttonGroup.js +0 -2
  7. package/components/button/buttonGroup.vue +310 -62
  8. package/components/button/index.vue +584 -100
  9. package/components/calendar/index.js +0 -2
  10. package/components/calendar/index.vue +326 -262
  11. package/components/calendar/month.vue +64 -55
  12. package/components/calendar/year.vue +30 -25
  13. package/components/card/index.vue +139 -59
  14. package/components/codeEditor/highlightCss.vue +38 -39
  15. package/components/codeEditor/highlightHtml.vue +64 -64
  16. package/components/codeEditor/highlightJs.vue +37 -38
  17. package/components/codeEditor/index.vue +129 -79
  18. package/components/codeEditor/run.vue +225 -39
  19. package/components/codeEditor/useCodeFormatter.js +150 -0
  20. package/components/confirm/index.vue +139 -80
  21. package/components/container/col.vue +5 -4
  22. package/components/container/divider.vue +28 -19
  23. package/components/container/index.vue +34 -15
  24. package/components/container/row.vue +26 -9
  25. package/components/container/spacer.vue +2 -4
  26. package/components/container/style.scss +3 -0
  27. package/components/content/index.vue +49 -32
  28. package/components/cropper/index.vue +401 -244
  29. package/components/float/index.vue +542 -415
  30. package/components/form/addressInput/index.vue +184 -109
  31. package/components/form/camInput/index.vue +370 -244
  32. package/components/form/checkInput/index.vue +138 -71
  33. package/components/form/checkboxInput/index.vue +87 -47
  34. package/components/form/colorInput/Alpha.vue +81 -83
  35. package/components/form/colorInput/Hue.vue +91 -68
  36. package/components/form/colorInput/Preview.vue +43 -47
  37. package/components/form/colorInput/Saturation.vue +101 -86
  38. package/components/form/colorInput/index.vue +71 -39
  39. package/components/form/colorInput/picker.vue +111 -106
  40. package/components/form/colorInput/useColor.js +153 -0
  41. package/components/form/dateInput/index.vue +691 -356
  42. package/components/form/dateInput/month.vue +63 -54
  43. package/components/form/dateInput/year.vue +35 -25
  44. package/components/form/fileInput/index.js +0 -1
  45. package/components/form/fileInput/index.vue +263 -106
  46. package/components/form/fileInput/single.vue +323 -164
  47. package/components/form/groupInput/index.vue +199 -101
  48. package/components/form/index.vue +189 -83
  49. package/components/form/input/index.vue +416 -377
  50. package/components/form/jsonInput/JsonView.vue +54 -56
  51. package/components/form/jsonInput/index.vue +247 -165
  52. package/components/form/maskInput/index.vue +252 -132
  53. package/components/form/numberInput/index.js +0 -1
  54. package/components/form/numberInput/index.vue +226 -117
  55. package/components/form/passwordInput/index.js +2 -1
  56. package/components/form/passwordInput/index.vue +269 -102
  57. package/components/form/radioInput/index.vue +143 -72
  58. package/components/form/rangeInput/index.vue +280 -167
  59. package/components/form/ratingInput/index.vue +57 -57
  60. package/components/form/selectInput/index.js +1 -3
  61. package/components/form/selectInput/index.vue +584 -296
  62. package/components/form/switchInput/index.vue +73 -59
  63. package/components/form/telInput/index.js +0 -1
  64. package/components/form/telInput/index.vue +238 -135
  65. package/components/form/textArea/index.vue +72 -35
  66. package/components/form/textEditor/index.vue +739 -0
  67. package/components/form/{text-editor → textEditor}/style.scss +8 -16
  68. package/components/form/textInput/index.vue +54 -32
  69. package/components/form/timeInput/index.vue +82 -55
  70. package/components/form/timeInput/range.vue +115 -94
  71. package/components/form/timeInput/timepicker.vue +382 -449
  72. package/components/form/uniqueInput/index.vue +105 -48
  73. package/components/form/unitInput/index.vue +139 -84
  74. package/components/formCreator/index.js +0 -1
  75. package/components/formCreator/index.vue +314 -148
  76. package/components/highlight/index.vue +41 -25
  77. package/components/highlight/style.scss +2 -2
  78. package/components/highlight/{mixin.js → useHighlight.js} +181 -160
  79. package/components/icon/index.vue +79 -33
  80. package/components/img/index.vue +249 -147
  81. package/components/img/preview.vue +180 -198
  82. package/components/img/svgImg.vue +42 -39
  83. package/components/index.js +5 -20
  84. package/components/infinite/index.js +1 -2
  85. package/components/infinite/index.vue +248 -66
  86. package/components/map/index.vue +428 -261
  87. package/components/map/route.vue +794 -487
  88. package/components/map/select.vue +118 -58
  89. package/components/menu/index.vue +201 -91
  90. package/components/meta/meta.js +26 -3
  91. package/components/modal/index.vue +382 -156
  92. package/components/notify/index.vue +204 -86
  93. package/components/notify/notification.vue +38 -55
  94. package/components/progress/circle.vue +189 -70
  95. package/components/progress/line.vue +266 -46
  96. package/components/searchBox/index.js +1 -3
  97. package/components/searchBox/index.vue +194 -101
  98. package/components/skeleton/index.vue +45 -20
  99. package/components/slider/index.vue +318 -156
  100. package/components/swiper/index.vue +254 -106
  101. package/components/table/crud/footer.vue +77 -53
  102. package/components/table/crud/header.vue +71 -72
  103. package/components/table/crud/index.vue +629 -399
  104. package/components/table/index.vue +721 -278
  105. package/components/timeAgo/index.vue +145 -96
  106. package/components/tour/index.vue +338 -235
  107. package/components/tree/index.vue +235 -89
  108. package/components/tree/tree-element.vue +106 -106
  109. package/directive/animate/index.js +77 -0
  110. package/directive/clickOutSide/index.js +98 -0
  111. package/directive/drag/index.js +153 -0
  112. package/directive/index.js +11 -13
  113. package/directive/intersect/index.js +263 -0
  114. package/directive/mask/index.js +67 -0
  115. package/directive/parallax/index.js +78 -0
  116. package/directive/ripple/index.js +14 -0
  117. package/directive/scroll/index.js +244 -0
  118. package/directive/sortable/index.js +274 -0
  119. package/directive/title/index.js +75 -0
  120. package/directive/touch/index.js +268 -0
  121. package/index.js +10 -8
  122. package/package.json +5 -2
  123. package/plugins/validation/Validate.js +88 -79
  124. package/scripts/generate-docs.mjs +226 -0
  125. package/scripts/menu.mjs +240 -0
  126. package/scripts/parser.mjs +1086 -0
  127. package/style/_index.scss +7 -0
  128. package/style/app.scss +13 -65
  129. package/style/colors.scss +5 -22
  130. package/style/functions/index.scss +8 -0
  131. package/style/mixins/index.scss +17 -5
  132. package/style/variables/base.scss +154 -175
  133. package/style/variables/color.scss +0 -12
  134. package/style/variables/utilities.scss +0 -180
  135. package/tools/helper.js +0 -8
  136. package/tools/icons.js +6 -1
  137. package/tools/root.js +71 -0
  138. package/components/app/style.scss +0 -41
  139. package/components/app/toast/style.scss +0 -20
  140. package/components/avatar/style.scss +0 -32
  141. package/components/bar/bottomNav.js +0 -1
  142. package/components/bar/bottomNav.vue +0 -28
  143. package/components/bar/bottomNavigationCircle.js +0 -2
  144. package/components/bar/bottomNavigationCircle.vue +0 -99
  145. package/components/bar/scss/bottomNav.scss +0 -67
  146. package/components/bar/scss/toolbar.scss +0 -174
  147. package/components/bar/toolbar/index.js +0 -8
  148. package/components/bar/toolbar/index.vue +0 -35
  149. package/components/bar/toolbar/laptop.vue +0 -33
  150. package/components/bar/toolbar/menuChilds.vue +0 -41
  151. package/components/bar/toolbar/menuLaptop.vue +0 -41
  152. package/components/bar/toolbar/menuMob.vue +0 -39
  153. package/components/bar/toolbar/mixin.js +0 -43
  154. package/components/bar/toolbar/mobile.vue +0 -34
  155. package/components/breadcrumb/bredcrumbItem.vue +0 -39
  156. package/components/breadcrumb/index.js +0 -3
  157. package/components/breadcrumb/index.vue +0 -71
  158. package/components/breadcrumb/style.scss +0 -51
  159. package/components/button/style.scss +0 -411
  160. package/components/card/style.scss +0 -86
  161. package/components/chart/chart.js +0 -1
  162. package/components/chart/chart.vue +0 -69
  163. package/components/chart/worldMap.js +0 -2
  164. package/components/chart/worldMap.vue +0 -1112
  165. package/components/chat/MessageList.vue +0 -163
  166. package/components/chat/chatInput.vue +0 -150
  167. package/components/chat/chatMsg.vue +0 -276
  168. package/components/chat/index.js +0 -11
  169. package/components/chat/index.vue +0 -113
  170. package/components/chip/index.js +0 -3
  171. package/components/chip/index.vue +0 -77
  172. package/components/chip/style.scss +0 -199
  173. package/components/codeEditor/mixin.js +0 -145
  174. package/components/countdown/index.js +0 -1
  175. package/components/countdown/index.vue +0 -105
  176. package/components/form/colorInput/mixin.js +0 -132
  177. package/components/form/fileInput/file.js +0 -148
  178. package/components/form/telInput/assets/flags.png +0 -0
  179. package/components/form/telInput/assets/flags@2x.png +0 -0
  180. package/components/form/text-editor/index.vue +0 -705
  181. package/components/icon/style.scss +0 -17
  182. package/components/infinite/div.js +0 -6
  183. package/components/infinite/div.vue +0 -193
  184. package/components/infinite/page.js +0 -3
  185. package/components/infinite/page.vue +0 -105
  186. package/components/list/index.js +0 -3
  187. package/components/list/index.vue +0 -122
  188. package/components/list/style.scss +0 -66
  189. package/components/message/index.js +0 -4
  190. package/components/message/index.vue +0 -40
  191. package/components/modal/style.scss +0 -146
  192. package/components/nestable/NestableItem.vue +0 -307
  193. package/components/nestable/editable.js +0 -44
  194. package/components/nestable/index.js +0 -1
  195. package/components/nestable/index.vue +0 -226
  196. package/components/nestable/methods.js +0 -416
  197. package/components/progress/style.scss +0 -229
  198. package/components/table/style.scss +0 -338
  199. package/components/tabs/index.js +0 -3
  200. package/components/tabs/index.vue +0 -151
  201. package/components/timeline/index.js +0 -6
  202. package/components/timeline/index.vue +0 -76
  203. package/directive/resize/index.js +0 -30
  204. package/directive/skeleton/index.js +0 -27
  205. package/directive/skeleton/style.scss +0 -37
  206. package/plugins/request/Request.js +0 -68
  207. package/style/animation.scss +0 -94
  208. package/style/style.scss +0 -8
  209. package/tools/rootable.js +0 -75
  210. /package/components/form/{text-editor → textEditor}/index.js +0 -0
  211. /package/components/form/{text-editor → textEditor}/preview.js +0 -0
  212. /package/components/form/{text-editor → textEditor}/preview.vue +0 -0
@@ -1,17 +1,16 @@
1
1
  <template>
2
2
  <div :class="$r.prefix + 'cropper'">
3
- <div v-if="show && allWPH.length > 1">
4
- <r-chip
3
+ <div v-if="show && allWPH.length > 1" class="py-1">
4
+ <r-btn
5
5
  v-for="(item, i) in allWPH"
6
6
  :key="i"
7
- :class="{ 'color-one-text': item === currentWPH }"
8
- class="ma-1 cursor-pointer"
9
- label
7
+ :class="{ 'color-one': item === currentWPH }"
8
+ class="ma-1 "
9
+ size="sm"
10
10
  outlined
11
11
  @click.prevent="changeWPH(item)"
12
12
  >{{ item }}
13
- </r-chip
14
- >
13
+ </r-btn>
15
14
  </div>
16
15
  <div
17
16
  v-if="show"
@@ -22,14 +21,23 @@
22
21
  }"
23
22
  class="image-box"
24
23
  >
25
- <div ref="thumbBox" class="thumb-box"></div>
24
+ <div ref="thumbBox" class="thumb-box">
25
+ <div class="handle handle-nw"></div>
26
+ <div class="handle handle-ne"></div>
27
+ <div class="handle handle-sw"></div>
28
+ <div class="handle handle-se"></div>
29
+ </div>
26
30
  </div>
27
31
  <div class="action d-flex">
28
32
  <template v-if="show">
29
33
  <r-btn @click.prevent="getCrop">{{ $t("crop", "renusify") }}</r-btn>
30
34
  <r-spacer></r-spacer>
31
- <r-btn icon tile @click.prevent="zoomIn()">+</r-btn>
32
- <r-btn icon tile @click.prevent="zoomOut()">-</r-btn>
35
+ <r-btn class="me-1" icon tile @click.prevent="zoomIn()">
36
+ <r-icon v-html="$r.icons.plus"></r-icon>
37
+ </r-btn>
38
+ <r-btn icon tile @click.prevent="zoomOut()">
39
+ <r-icon v-html="$r.icons.minus"></r-icon>
40
+ </r-btn>
33
41
  </template>
34
42
 
35
43
  <input
@@ -50,253 +58,368 @@
50
58
  </div>
51
59
  </template>
52
60
 
53
- <script>
54
- export default {
55
- name: "r-cropper",
56
- props: {
57
- wPH: {type: [Number, String, Array], default: 1},
58
- imgSrc: [String, Blob],
59
- maxWidth: Number,
60
- showCropped: Boolean,
61
- getBlob: Boolean,
62
- selectImg: {type: Boolean, default: true},
63
- },
64
- emits: ['cropped', 'original'],
65
- data() {
66
- return {
67
- show: false,
68
- cropped: null,
69
- width: null,
70
- height: null,
71
- state: {},
72
- ratio: 1,
73
- image: new Image(),
74
- currentWPH: null,
75
- };
76
- },
77
- mounted() {
78
- this.width = 280;
79
- this.height = 280;
80
- this.currentWPH = this.allWPH[0];
81
- if (this.currentWPH > 1) {
82
- this.height = this.width / this.currentWPH;
83
- } else {
84
- this.width = this.height * this.currentWPH;
85
- }
86
- if (typeof this.imgSrc === "string") {
87
- this.crop(this.imgSrc);
88
- } else if (this.imgSrc) {
89
- const that = this;
90
- const reader = new FileReader();
91
- reader.onload = function (e) {
92
- that.crop(e.target.result);
93
- };
61
+ <script setup>
62
+ import {ref, computed, onMounted, watch} from 'vue'
94
63
 
95
- reader.readAsDataURL(this.imgSrc);
96
- }
97
- },
98
- computed: {
99
- allWPH() {
100
- const is_array = Array.isArray(this.wPH);
101
- let wPH = [];
102
- if (is_array) {
103
- this.wPH.forEach((item) => {
104
- item = item.toString().split("/");
105
- if (item.length === 2) {
106
- wPH.push(
107
- parseFloat((parseFloat(item[0]) / parseFloat(item[1])).toFixed(4))
108
- );
109
- } else {
110
- wPH.push(parseFloat(parseFloat(item[0]).toFixed(4)));
111
- }
112
- });
64
+ const props = defineProps({
65
+ /**
66
+ * Width-to-height ratio(s) for cropping
67
+ * @type {Number|String|Array}
68
+ * @default 1
69
+ */
70
+ wPH: {type: [Number, String, Array], default: 1},
71
+
72
+ /**
73
+ * Image source to crop
74
+ * @type {String|Blob}
75
+ */
76
+ imgSrc: [String, Blob],
77
+
78
+ /**
79
+ * Maximum width of the cropped image
80
+ * @type {Number}
81
+ */
82
+ maxWidth: Number,
83
+
84
+ /**
85
+ * Whether to show the cropped result
86
+ * @type {Boolean}
87
+ */
88
+ showCropped: Boolean,
89
+
90
+ /**
91
+ * Whether to emit Blob instead of DataURL
92
+ * @type {Boolean}
93
+ */
94
+ getBlob: Boolean,
95
+
96
+ /**
97
+ * Enables image selection
98
+ * @type {Boolean}
99
+ * @default true
100
+ */
101
+ selectImg: {type: Boolean, default: true},
102
+ })
103
+
104
+ const emit = defineEmits([
105
+ /**
106
+ * Emitted when image is cropped
107
+ * @param {String|Blob} result - Cropped image as DataURL or Blob
108
+ */
109
+ 'cropped',
110
+
111
+ /**
112
+ * Emitted when original image is selected
113
+ * @param {File} file - Original image file
114
+ */
115
+ 'original'
116
+ ])
117
+
118
+ const show = ref(false)
119
+ const cropped = ref(null)
120
+ const width = ref(null)
121
+ const height = ref(null)
122
+ const state = ref({})
123
+ const ratio = ref(1)
124
+ const image = ref(new Image())
125
+ const currentWPH = ref(null)
126
+
127
+ const imageBox = ref(null)
128
+ const thumbBox = ref(null)
129
+
130
+ const allWPH = computed(() => {
131
+ const is_array = Array.isArray(props.wPH)
132
+ let wPH = []
133
+ if (is_array) {
134
+ props.wPH.forEach((item) => {
135
+ item = item.toString().split("/")
136
+ if (item.length === 2) {
137
+ wPH.push(
138
+ parseFloat((parseFloat(item[0]) / parseFloat(item[1])).toFixed(4))
139
+ )
113
140
  } else {
114
- if (typeof this.wPH === "string") {
115
- let item = this.wPH;
116
- item = item.split("/");
117
- if (item.length === 2) {
118
- wPH.push(
119
- parseFloat((parseFloat(item[0]) / parseFloat(item[1])).toFixed(4))
120
- );
121
- } else {
122
- wPH.push(parseFloat(parseFloat(item[0]).toFixed(4)));
123
- }
124
- } else {
125
- wPH.push(parseFloat(parseFloat(this.wPH).toFixed(4)));
126
- }
141
+ wPH.push(parseFloat(parseFloat(item[0]).toFixed(4)))
127
142
  }
128
- return wPH;
129
- },
130
- },
131
- methods: {
132
- getCrop() {
133
- this.cropped = this.getDataURL();
134
- if (this.getBlob) {
135
- this.$emit("cropped", this.get_blob());
143
+ })
144
+ } else {
145
+ if (typeof props.wPH === "string") {
146
+ let item = props.wPH
147
+ item = item.split("/")
148
+ if (item.length === 2) {
149
+ wPH.push(
150
+ parseFloat((parseFloat(item[0]) / parseFloat(item[1])).toFixed(4))
151
+ )
136
152
  } else {
137
- this.$emit("cropped", this.cropped);
153
+ wPH.push(parseFloat(parseFloat(item[0]).toFixed(4)))
138
154
  }
155
+ } else {
156
+ wPH.push(parseFloat(parseFloat(props.wPH).toFixed(4)))
157
+ }
158
+ }
159
+ return wPH
160
+ })
139
161
 
140
- this.show = false;
141
- },
142
- changeWPH(e) {
143
- this.currentWPH = e;
144
- this.width = 280;
145
- this.height = 280;
146
- if (this.currentWPH > 1) {
147
- this.height = this.width / this.currentWPH;
148
- } else {
149
- this.width = this.height * this.currentWPH;
150
- }
151
- let thumbBox = this.$refs.thumbBox;
152
- thumbBox.style.width = this.width + "px";
153
- thumbBox.style.height = this.height + "px";
154
- },
155
- moveStart() {
156
- let el = this.$refs.imageBox;
157
- let bg = el.style.backgroundPosition.split(" ");
158
- this.state.x = parseInt(bg[0]);
159
- this.state.y = parseInt(bg[1]);
160
- },
161
- setPosition(e) {
162
- let el = this.$refs.imageBox;
163
-
164
- let bgX = e.goX + this.state.x;
165
- let bgY = e.goY + this.state.y;
166
-
167
- el.style.backgroundPosition = bgX + "px " + bgY + "px";
168
- },
169
- select_img(e) {
170
- const that = this;
171
- const reader = new FileReader();
162
+ // Methods
163
+ /**
164
+ * Generates and emits the cropped image
165
+ */
166
+ const getCrop = () => {
167
+ cropped.value = getDataURL()
168
+ if (props.getBlob) {
169
+ emit("cropped", get_blob())
170
+ } else {
171
+ emit("cropped", cropped.value)
172
+ }
173
+ show.value = false
174
+ }
175
+
176
+ /**
177
+ * Changes the width-to-height ratio
178
+ * @param {Number} e - New width-to-height ratio
179
+ */
180
+ const changeWPH = (e) => {
181
+ currentWPH.value = e
182
+ width.value = 280
183
+ height.value = 280
184
+ if (currentWPH.value > 1) {
185
+ height.value = width.value / currentWPH.value
186
+ } else {
187
+ width.value = height.value * currentWPH.value
188
+ }
189
+
190
+ if (thumbBox.value) {
191
+ thumbBox.value.style.width = width.value + "px"
192
+ thumbBox.value.style.height = height.value + "px"
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Starts image positioning movement
198
+ */
199
+ const moveStart = () => {
200
+ if (!imageBox.value) return
201
+ let bg = imageBox.value.style.backgroundPosition.split(" ")
202
+ state.value.x = parseInt(bg[0])
203
+ state.value.y = parseInt(bg[1])
204
+ }
205
+
206
+ /**
207
+ * Sets image position
208
+ * @param {Object} e - Movement data
209
+ * @param {Number} e.goX - X coordinate movement
210
+ * @param {Number} e.goY - Y coordinate movement
211
+ */
212
+ const setPosition = (e) => {
213
+ if (!imageBox.value) return
214
+ let bgX = e.goX + state.value.x
215
+ let bgY = e.goY + state.value.y
216
+ imageBox.value.style.backgroundPosition = bgX + "px " + bgY + "px"
217
+ }
218
+
219
+ /**
220
+ * Handles image file selection
221
+ * @param {Event} e - File input event
222
+ */
223
+ const select_img = (e) => {
224
+ const reader = new FileReader()
225
+ reader.onload = function (e) {
226
+ crop(e.target.result)
227
+ }
228
+ emit("original", e.target.files[0])
229
+ reader.readAsDataURL(e.target.files[0])
230
+ }
231
+
232
+ /**
233
+ * Generates DataURL from cropped image
234
+ * @returns {String} - DataURL of cropped image
235
+ */
236
+ const getDataURL = () => {
237
+ if (!imageBox.value || !thumbBox.value) return ''
238
+
239
+ let el = imageBox.value
240
+ let thumb = thumbBox.value
241
+ let widthVal = thumb.clientWidth,
242
+ heightVal = thumb.clientHeight,
243
+ canvas = document.createElement("canvas"),
244
+ dim = el.style.backgroundPosition.split(" "),
245
+ size = el.style.backgroundSize.split(" "),
246
+ dx = parseInt(dim[0]) - el.clientWidth / 2 + widthVal / 2 + 1,
247
+ dy = parseInt(dim[1]) - el.clientHeight / 2 + heightVal / 2 + 1,
248
+ dw = parseInt(size[0]),
249
+ dh = parseInt(size[1]),
250
+ sh = parseInt(image.value.height),
251
+ sw = parseInt(image.value.width)
252
+
253
+ let n = 0
254
+ if (dw >= 280) {
255
+ n = Math.abs((sw / dw) * dx * 2)
256
+ }
257
+ canvas.width = sw - n
258
+ if (props.maxWidth && canvas.width > props.maxWidth) {
259
+ canvas.width = props.maxWidth
260
+ }
261
+ canvas.height = canvas.width / currentWPH.value
262
+ while (
263
+ parseFloat((canvas.width / canvas.height).toFixed(4)) !==
264
+ currentWPH.value
265
+ ) {
266
+ canvas.width -= 1
267
+ canvas.height = canvas.width / currentWPH.value
268
+ if (canvas.width < 1) {
269
+ break
270
+ }
271
+ }
272
+ let context = canvas.getContext("2d")
273
+ context.drawImage(
274
+ image.value,
275
+ 0,
276
+ 0,
277
+ sw,
278
+ sh,
279
+ (dx * canvas.width) / widthVal,
280
+ (dy * canvas.height) / heightVal,
281
+ (dw * canvas.width) / widthVal,
282
+ (dh * canvas.height) / heightVal
283
+ )
284
+ return canvas.toDataURL("image/png")
285
+ }
286
+
287
+ /**
288
+ * Converts DataURL to Blob
289
+ * @returns {Blob} - Blob of cropped image
290
+ */
291
+ const get_blob = () => {
292
+ if (!cropped.value) return null
293
+ let b64 = cropped.value.replace("data:image/png;base64,", "")
294
+ let binary = atob(b64)
295
+ let array = []
296
+ for (let i = 0; i < binary.length; i++) {
297
+ array.push(binary.charCodeAt(i))
298
+ }
299
+ let b = new Blob([new Uint8Array(array)], {
300
+ type: "image/png",
301
+ })
302
+ b.name = "file.png"
303
+ return b
304
+ }
305
+
306
+ /**
307
+ * Zooms in the image
308
+ */
309
+ const zoomIn = () => {
310
+ ratio.value += 0.01
311
+ setBackground()
312
+ }
313
+
314
+ /**
315
+ * Zooms out the image
316
+ */
317
+ const zoomOut = () => {
318
+ ratio.value -= 0.01
319
+ setBackground()
320
+ }
321
+
322
+ /**
323
+ * Updates background image style
324
+ */
325
+ const setBackground = () => {
326
+ if (!imageBox.value || !image.value) return
327
+
328
+ let el = imageBox.value
329
+ let w = parseInt(image.value.width) * ratio.value
330
+ let h = parseInt(image.value.height) * ratio.value
331
+
332
+ let pw = (el.clientWidth - w) / 2
333
+ let ph = (el.clientHeight - h) / 2
334
+
335
+ el.setAttribute(
336
+ "style",
337
+ "background-image: url(" +
338
+ image.value.src +
339
+ "); " +
340
+ "background-size: " +
341
+ w +
342
+ "px " +
343
+ h +
344
+ "px; " +
345
+ "background-position: " +
346
+ pw +
347
+ "px " +
348
+ ph +
349
+ "px; " +
350
+ "background-repeat: no-repeat"
351
+ )
352
+ }
353
+
354
+ /**
355
+ * Initiates cropping process
356
+ * @param {String} img - Image DataURL
357
+ */
358
+ const crop = (img) => {
359
+ show.value = true
360
+ cropped.value = null
361
+ setTimeout(() => {
362
+ if (!thumbBox.value) return
363
+
364
+ let thumb = thumbBox.value
365
+ thumb.style.width = width.value + "px"
366
+ thumb.style.height = height.value + "px"
367
+
368
+ image.value.onload = function () {
369
+ ratio.value = parseInt(width.value) / image.value.width
370
+ setBackground()
371
+ }
372
+ image.value.src = img
373
+ }, 100)
374
+ }
375
+
376
+ onMounted(() => {
377
+ width.value = 280
378
+ height.value = 280
379
+ currentWPH.value = allWPH.value[0]
380
+ if (currentWPH.value > 1) {
381
+ height.value = width.value / currentWPH.value
382
+ } else {
383
+ width.value = height.value * currentWPH.value
384
+ }
385
+
386
+ if (typeof props.imgSrc === "string") {
387
+ crop(props.imgSrc)
388
+ } else if (props.imgSrc) {
389
+ const reader = new FileReader()
390
+ reader.onload = function (e) {
391
+ crop(e.target.result)
392
+ }
393
+ reader.readAsDataURL(props.imgSrc)
394
+ }
395
+ })
396
+
397
+ watch(() => props.imgSrc, (newVal) => {
398
+ if (newVal) {
399
+ if (typeof newVal === "string") {
400
+ crop(newVal)
401
+ } else {
402
+ const reader = new FileReader()
172
403
  reader.onload = function (e) {
173
- that.crop(e.target.result);
174
- };
175
-
176
- this.$emit("original", e.target.files[0]);
177
- reader.readAsDataURL(e.target.files[0]);
178
- },
179
- getDataURL() {
180
- let el = this.$refs.imageBox;
181
- let thumbBox = this.$refs.thumbBox;
182
- let width = thumbBox.clientWidth,
183
- height = thumbBox.clientHeight,
184
- canvas = document.createElement("canvas"),
185
- dim = el.style.backgroundPosition.split(" "),
186
- size = el.style.backgroundSize.split(" "),
187
- dx = parseInt(dim[0]) - el.clientWidth / 2 + width / 2 + 1,
188
- dy = parseInt(dim[1]) - el.clientHeight / 2 + height / 2 + 1,
189
- dw = parseInt(size[0]),
190
- dh = parseInt(size[1]),
191
- sh = parseInt(this.image.height),
192
- sw = parseInt(this.image.width);
193
-
194
- let n = 0;
195
- if (dw >= 280) {
196
- n = Math.abs((sw / dw) * dx * 2);
197
- }
198
- canvas.width = sw - n;
199
- if (this.maxWidth && canvas.width > this.maxWidth) {
200
- canvas.width = this.maxWidth;
201
- }
202
- canvas.height = canvas.width / this.currentWPH;
203
- while (
204
- parseFloat((canvas.width / canvas.height).toFixed(4)) !==
205
- this.currentWPH
206
- ) {
207
- canvas.width -= 1;
208
- canvas.height = canvas.width / this.currentWPH;
209
- if (canvas.width < 1) {
210
- break;
211
- }
404
+ crop(e.target.result)
212
405
  }
213
- let context = canvas.getContext("2d");
214
- context.drawImage(
215
- this.image,
216
- 0,
217
- 0,
218
- sw,
219
- sh,
220
- (dx * canvas.width) / width,
221
- (dy * canvas.height) / height,
222
- (dw * canvas.width) / width,
223
- (dh * canvas.height) / height
224
- );
225
- return canvas.toDataURL("image/png");
226
- },
227
- get_blob() {
228
- let b64 = this.cropped.replace("data:image/png;base64,", "");
229
- let binary = atob(b64);
230
- let array = [];
231
- for (let i = 0; i < binary.length; i++) {
232
- array.push(binary.charCodeAt(i));
233
- }
234
- let b = new Blob([new Uint8Array(array)], {
235
- type: "image/png",
236
- });
237
- b.name = "file.png";
238
- return b;
239
- },
240
- zoomIn() {
241
- this.ratio += 0.01;
242
- this.setBackground();
243
- },
244
- zoomOut() {
245
- this.ratio -= 0.01;
246
- this.setBackground();
247
- },
248
- setBackground() {
249
- let el = this.$refs.imageBox;
250
- let w = parseInt(this.image.width) * this.ratio;
251
- let h = parseInt(this.image.height) * this.ratio;
252
-
253
- let pw = (el.clientWidth - w) / 2;
254
- let ph = (el.clientHeight - h) / 2;
255
-
256
- el.setAttribute(
257
- "style",
258
- "background-image: url(" +
259
- this.image.src +
260
- "); " +
261
- "background-size: " +
262
- w +
263
- "px " +
264
- h +
265
- "px; " +
266
- "background-position: " +
267
- pw +
268
- "px " +
269
- ph +
270
- "px; " +
271
- "background-repeat: no-repeat"
272
- );
273
- },
274
- crop(img) {
275
- this.show = true;
276
- this.cropped = null;
277
- setTimeout(() => {
278
- const that = this;
279
- let thumbBox = this.$refs.thumbBox;
280
- thumbBox.style.width = this.width + "px";
281
- thumbBox.style.height = this.height + "px";
282
-
283
- this.image.onload = function () {
284
- that.ratio = parseInt(that.width) / that.image.width;
285
- that.setBackground();
286
- };
287
- this.image.src = img;
288
- }, 100);
289
- },
290
- },
291
- };
406
+ reader.readAsDataURL(newVal)
407
+ }
408
+ }
409
+ })
292
410
  </script>
293
411
 
294
412
  <style lang="scss">
295
- @use "../../style/variables/base";
413
+ @use "../../style" as *;
296
414
 
297
- .#{base.$prefix}cropper {
415
+ .#{$prefix}cropper {
298
416
  width: 300px;
299
417
 
418
+ .action {
419
+ background: var(--color-sheet-container-lowest);
420
+ padding: 4px;
421
+ }
422
+
300
423
  .image-box {
301
424
  position: relative;
302
425
  height: 300px;
@@ -315,9 +438,43 @@ export default {
315
438
  height: 200px;
316
439
  transform: translate(-50%, -50%);
317
440
  box-sizing: border-box;
318
- border: 1px solid rgb(130, 130, 130);
441
+ border: 2px solid rgb(14, 59, 209);
319
442
  box-shadow: 0 0 0 2000px rgba(0, 0, 0, 0.4);
320
443
  background: none repeat scroll 0 0 transparent;
444
+
445
+ .handle {
446
+ position: absolute;
447
+ width: 12px;
448
+ height: 12px;
449
+ background-color: #1976d2;
450
+ border: 2px solid #fff;
451
+ border-radius: 50%;
452
+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
453
+
454
+ &.handle-nw {
455
+ top: -6px;
456
+ left: -6px;
457
+ cursor: nw-resize;
458
+ }
459
+
460
+ &.handle-ne {
461
+ top: -6px;
462
+ right: -6px;
463
+ cursor: ne-resize;
464
+ }
465
+
466
+ &.handle-sw {
467
+ bottom: -6px;
468
+ left: -6px;
469
+ cursor: sw-resize;
470
+ }
471
+
472
+ &.handle-se {
473
+ bottom: -6px;
474
+ right: -6px;
475
+ cursor: se-resize;
476
+ }
477
+ }
321
478
  }
322
479
  }
323
480
  </style>