renusify 2.5.1 → 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 +140 -81
  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 +72 -40
  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 +83 -56
  70. package/components/form/timeInput/range.vue +116 -95
  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 +383 -158
  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 +631 -401
  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 +107 -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 -710
  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,5 +1,5 @@
1
1
  <template>
2
- <div ref="map"
2
+ <div ref="mapRef"
3
3
  :style="{
4
4
  '--map-image-layers':`url(${iconLayers})`
5
5
  }"
@@ -28,12 +28,12 @@
28
28
  icon
29
29
  @click.prevent="showConfirm"
30
30
  >
31
- <r-icon v-html="$r.icons.crosshairs_gps"></r-icon>
31
+ <r-icon v-html="$r.icons.gps"></r-icon>
32
32
  </r-btn>
33
33
  <r-btn
34
34
  class="map-attribution color-white color-black-text"
35
35
  icon
36
- size="x-small"
36
+ size="xs"
37
37
  @click.prevent="attribution = !attribution"
38
38
  >
39
39
  C
@@ -46,275 +46,442 @@
46
46
 
47
47
  </template>
48
48
 
49
- <script>
50
- export default {
51
- name: "rMap",
52
- props: {
53
- modelValue: Array,
54
- height: {type: String, default: "500px"},
55
- zoom: {type: Number, default: 13},
56
- center: {
57
- type: Array,
58
- default: () => {
59
- return [
60
- 35.69973857757377,
61
- 51.33806092139637
62
- ];
63
- }
64
- },
65
- markers: {
66
- type: Array,
67
- default: () => {
68
- return [];
69
- }
70
- },
71
- searchBox: Boolean,
72
- zoomControl: {type: Boolean, default: true},
73
- layerControl: {type: Boolean, default: true},
74
- meLocation: {type: Boolean, default: true},
75
- disableMove: {type: Boolean, default: false},
76
- darkMode: Boolean,
77
- mapImageMarker: String,
78
- mapImageLayers: String
49
+ <script setup>
50
+ import {ref, computed, onMounted, onUnmounted, watch, inject, nextTick} from 'vue'
51
+ import './leaflet.css'
52
+
53
+ const props = defineProps({
54
+ /**
55
+ * Two-way binding for selected locations/markers
56
+ * @type {Array}
57
+ * @model
58
+ * @description Array of selected marker coordinates or location data.
59
+ * Updates when markers are added/removed via user interaction.
60
+ * @example [[35.6997, 51.3380], [35.7000, 51.3400]]
61
+ */
62
+ modelValue: Array,
63
+
64
+ /**
65
+ * Map container height
66
+ * @type {String}
67
+ * @default '500px'
68
+ * @description CSS height for the map container.
69
+ * Accepts any valid CSS height value.
70
+ * @example '400px'
71
+ * @example '80vh'
72
+ * @example '100%'
73
+ */
74
+ height: {type: String, default: "500px"},
75
+
76
+ /**
77
+ * Initial zoom level
78
+ * @type {Number}
79
+ * @default 13
80
+ * @description Initial zoom level of the map (0-20 typical range).
81
+ * Higher values = more zoomed in.
82
+ * @example 10 // World view
83
+ * @example 15 // City view
84
+ * @example 18 // Street view
85
+ */
86
+ zoom: {type: Number, default: 13},
87
+
88
+ /**
89
+ * Initial map center coordinates
90
+ * @type {Array<Number>}
91
+ * @default [35.69973857757377, 51.33806092139637] // Tehran coordinates
92
+ * @description [latitude, longitude] pair for initial map center.
93
+ * @example [40.7128, -74.0060] // New York
94
+ * @example [51.5074, -0.1278] // London
95
+ * @example [35.6895, 139.6917] // Tokyo
96
+ */
97
+ center: {
98
+ type: Array,
99
+ default: () => [35.69973857757377, 51.33806092139637]
79
100
  },
80
- data() {
81
- return {
82
- timeout_id: null,
83
- dark: this.darkMode,
84
- attribution: false,
85
- confirm: false,
86
- loading: false,
87
- L: null,
88
- map: null,
89
- layerGroup: null,
90
- map_id: "map_" + this.$helper.uniqueId(12),
91
- layers: {},
92
- license: '&copy; | <a href="https://leafletjs.com" target="_blank">Leaflet</a> | <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors | Renusify'
93
- };
101
+
102
+ /**
103
+ * Array of markers to display
104
+ * @type {Array<Object|Array>}
105
+ * @default () => []
106
+ * @description Markers to display on the map. Can be:
107
+ * - Simple coordinate arrays: [[lat, lng], [lat, lng]]
108
+ * - Marker objects with properties: {lat, lng, title, popup, icon}
109
+ * @example [[35.6997, 51.3380]]
110
+ * @example [{lat: 35.6997, lng: 51.3380, title: 'Tehran'}]
111
+ */
112
+ markers: {
113
+ type: Array,
114
+ default: () => []
94
115
  },
95
- emits: ['update:modelValue', 'leaflet', 'map'],
96
- created() {
97
- if (!this.$r.icons.crosshairs_gps) {
98
- this.$r.icons.crosshairs_gps = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M12 8a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m-8.95 5H1v-2h2.05C3.5 6.83 6.83 3.5 11 3.05V1h2v2.05c4.17.45 7.5 3.78 7.95 7.95H23v2h-2.05c-.45 4.17-3.78 7.5-7.95 7.95V23h-2v-2.05C6.83 20.5 3.5 17.17 3.05 13M12 5a7 7 0 0 0-7 7a7 7 0 0 0 7 7a7 7 0 0 0 7-7a7 7 0 0 0-7-7Z"/></svg>'
116
+
117
+ /**
118
+ * Enable search/geocoding box
119
+ * @type {Boolean}
120
+ * @default false
121
+ * @description Shows a search input for finding locations.
122
+ * Uses geocoding service to convert addresses to coordinates.
123
+ */
124
+ searchBox: Boolean,
125
+
126
+ /**
127
+ * Show zoom controls
128
+ * @type {Boolean}
129
+ * @default true
130
+ * @description Display +/- zoom buttons on the map.
131
+ */
132
+ zoomControl: {type: Boolean, default: true},
133
+
134
+ /**
135
+ * Show layer controls
136
+ * @type {Boolean}
137
+ * @default true
138
+ * @description Display layer switcher (base maps, overlays).
139
+ */
140
+ layerControl: {type: Boolean, default: true},
141
+
142
+ /**
143
+ * Enable "My Location" feature
144
+ * @type {Boolean}
145
+ * @default true
146
+ * @description Shows a button to center map on user's current location.
147
+ * Requires browser geolocation permissions.
148
+ */
149
+ meLocation: {type: Boolean, default: true},
150
+
151
+ /**
152
+ * Disable map panning/dragging
153
+ * @type {Boolean}
154
+ * @default false
155
+ * @description Prevents users from moving/panning the map.
156
+ * Useful for static map views.
157
+ */
158
+ disableMove: {type: Boolean, default: false},
159
+
160
+ /**
161
+ * Enable dark mode theme
162
+ * @type {Boolean}
163
+ * @default false
164
+ * @description Applies dark theme to map tiles and controls.
165
+ * Uses dark base maps when available.
166
+ */
167
+ darkMode: Boolean,
168
+
169
+ /**
170
+ * Custom marker icon image URL
171
+ * @type {String}
172
+ * @description URL to custom marker icon image.
173
+ * Overrides default marker icon for all markers.
174
+ * @example '/assets/marker.png'
175
+ * @example 'https://example.com/pin.png'
176
+ */
177
+ mapImageMarker: String,
178
+
179
+ /**
180
+ * Custom layer tile URL template
181
+ * @type {String}
182
+ * @description URL template for custom map tile layers.
183
+ * Uses Leaflet tile layer syntax with {x}, {y}, {z} placeholders.
184
+ * @example 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
185
+ * @example '/tiles/{z}/{x}/{y}.png'
186
+ */
187
+ mapImageLayers: String
188
+ })
189
+
190
+ const emit = defineEmits([
191
+ /**
192
+ * Emitted when map data changes
193
+ * @event update:modelValue
194
+ * @param {Array} value - Updated array of selected locations/markers
195
+ */
196
+ 'update:modelValue',
197
+
198
+ /**
199
+ * Emitted for Leaflet.js events
200
+ * @description Forwarded Leaflet.js map events for custom handling.
201
+ */
202
+ 'leaflet',
203
+
204
+ /**
205
+ * Emitted when map instance is ready
206
+ * @description Provides direct access to Leaflet map object for advanced usage.
207
+ */
208
+ 'map'
209
+ ])
210
+
211
+ const {$r, $helper, $t, $toast, $storage} = inject('renusify')
212
+
213
+ const timeout_id = ref(null)
214
+ const dark = ref(props.darkMode)
215
+ const attribution = ref(false)
216
+ const confirm = ref(false)
217
+ const loading = ref(false)
218
+ const L = ref(null)
219
+ const map = ref(null)
220
+ const layerGroup = ref(null)
221
+ const layers = ref({})
222
+ const mapRef = ref(null)
223
+
224
+ const map_id = computed(() => `map_${$helper?.uniqueId(12) || Date.now()}`)
225
+ const license = '&copy; | <a href="https://leafletjs.com" target="_blank">Leaflet</a> | <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors | Renusify'
226
+
227
+ const iconLayers = computed(() => {
228
+ if (props.mapImageLayers) {
229
+ return props.mapImageLayers
230
+ }
231
+ return require('./images/layers.png')
232
+ })
233
+
234
+ const iconMarker = computed(() => {
235
+ if (props.mapImageMarker) {
236
+ return props.mapImageMarker
237
+ }
238
+ return require('./images/marker-icon.png')
239
+ })
240
+
241
+
242
+ const showConfirm = () => {
243
+ if ($storage?.has('map_location_access')) {
244
+ getLocation()
245
+ } else {
246
+ confirm.value = true
247
+ }
248
+ }
249
+
250
+ const go = (e) => {
251
+ if (e.lat) {
252
+ emit("update:modelValue", [parseFloat(e.lat), parseFloat(e.lon)])
253
+ }
254
+ }
255
+
256
+ const initMap = () => {
257
+ const opt = {
258
+ maxZoom: 19,
259
+ zoomControl: false,
260
+ minZoom: 3,
261
+ noWrap: true
262
+ }
263
+
264
+ layers.value[$t('map_hot', 'renusify')] = L.value.tileLayer(
265
+ "https://tile-{s}.openstreetmap.fr/hot/{z}/{x}/{y}.png",
266
+ opt
267
+ )
268
+
269
+ opt.dark = true
270
+ layers.value[$t('map_hot_dark', 'renusify')] = L.value.tileLayer(
271
+ "https://tile-{s}.openstreetmap.fr/hot/{z}/{x}/{y}.png",
272
+ opt
273
+ )
274
+
275
+ opt.dark = false
276
+ layers.value[$t('map_standard', 'renusify')] = L.value.tileLayer(
277
+ "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
278
+ opt
279
+ )
280
+
281
+ opt.dark = true
282
+ layers.value[$t('map_standard_dark', 'renusify')] = L.value.tileLayer(
283
+ "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
284
+ opt
285
+ )
286
+
287
+ opt.dark = false
288
+ opt.subdomains = ["mt0", "mt1", "mt2", "mt3"]
289
+ layers.value[$t('map_google', 'renusify')] = L.value.tileLayer(
290
+ "http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}",
291
+ opt
292
+ )
293
+
294
+ opt.dark = true
295
+ layers.value[$t('map_google_dark', 'renusify')] = L.value.tileLayer(
296
+ "http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}",
297
+ opt
298
+ )
299
+
300
+ opt.dark = false
301
+ layers.value[$t('map_satelite', 'renusify')] = L.value.tileLayer(
302
+ "http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}",
303
+ opt
304
+ )
305
+
306
+ layers.value[$t('map_hot', 'renusify')].addTo(map.value)
307
+
308
+ if (props.zoomControl) {
309
+ L.value.control
310
+ .zoom({
311
+ zoomInTitle: $t?.("map_zoom_in", 'renusify') || "Zoom in",
312
+ zoomOutTitle: $t?.("map_zoom_out", 'renusify') || "Zoom out"
313
+ })
314
+ .addTo(map.value)
315
+ } else {
316
+ map.value.touchZoom.disable()
317
+ map.value.doubleClickZoom.disable()
318
+ map.value.scrollWheelZoom.disable()
319
+ map.value.boxZoom.disable()
320
+ map.value.keyboard.disable()
321
+ }
322
+
323
+ if (props.layerControl) {
324
+ L.value.control.layers(layers.value).addTo(map.value)
325
+ }
326
+
327
+ map.value.on("baselayerchange", (e) => {
328
+ if ($helper?.ifHas(e, false, "layer", "options", "dark")) {
329
+ dark.value = true
330
+ } else {
331
+ dark.value = props.darkMode
99
332
  }
100
- },
101
- mounted() {
102
- this.add();
103
- },
104
- watch: {
105
- modelValue: function (n, o) {
106
- this.map.flyTo(this.modelValue);
107
- },
108
- markers: function () {
109
- this.printMarkers()
333
+ })
334
+
335
+ map.value.on("move", (e) => {
336
+ if (e.originalEvent) {
337
+ clearTimeout(timeout_id.value)
338
+ timeout_id.value = setTimeout(() => {
339
+ const center = Object.values(map.value.getCenter())
340
+ emit("update:modelValue", center)
341
+ }, 100)
110
342
  }
111
- },
112
- computed: {
113
- iconLayers() {
114
- if (this.mapImageLayers) {
115
- return this.mapImageLayers
116
- }
117
- return require('./images/layers.png')
118
- },
119
- iconMarker() {
120
- if (this.mapImageMarker) {
121
- return this.mapImageMarker
122
- }
123
- return require('./images/marker-icon.png')
343
+ })
344
+ }
345
+
346
+ const run = () => {
347
+ map.value = L.value.map(map_id.value, {
348
+ center: props.center,
349
+ zoom: props.zoom,
350
+ zoomControl: false,
351
+ dragging: !props.disableMove,
352
+ tap: !props.disableMove
353
+ })
354
+
355
+ initMap()
356
+ layerGroup.value = new L.value.layerGroup().addTo(map.value)
357
+ printMarkers()
358
+ emit("update:modelValue", props.center)
359
+ emit("leaflet", L.value)
360
+ emit("map", map.value)
361
+ printCopy()
362
+ }
363
+
364
+ const printCopy = () => {
365
+ nextTick(() => {
366
+ const attr = mapRef.value?.querySelector('.leaflet-control-attribution')
367
+ if (attr) {
368
+ attr.innerHTML = license
124
369
  }
125
- },
126
- methods: {
127
- showConfirm() {
128
- if (this.$storage.has('map_location_access')) {
129
- this.getLocation()
130
- } else {
131
- this.confirm = true
132
- }
133
- },
134
- go(e) {
135
- if (e.lat) {
136
- this.$emit("update:modelValue", [parseFloat(e.lat), parseFloat(e.lon)]);
137
- }
138
- },
139
- initMap() {
140
- let opt = {
141
- maxZoom: 19,
142
- zoomControl: false,
143
- minZoom: 3,
144
- noWrap: true
145
- };
146
- this.layers[this.$t('map_hot', 'renusify')] = this.L.tileLayer(
147
- "https://tile-{s}.openstreetmap.fr/hot/{z}/{x}/{y}.png",
148
- opt
149
- );
150
- opt.dark = true;
151
- this.layers[this.$t('map_hot_dark', 'renusify')] = this.L.tileLayer(
152
- "https://tile-{s}.openstreetmap.fr/hot/{z}/{x}/{y}.png",
153
- opt
154
- );
155
- opt.dark = false;
156
- this.layers[this.$t('map_standard', 'renusify')] = this.L.tileLayer(
157
- "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
158
- opt
159
- );
160
- opt.dark = true;
161
- this.layers[this.$t('map_standard_dark', 'renusify')] = this.L.tileLayer(
162
- "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
163
- opt
164
- );
165
- opt.dark = false;
166
- opt.subdomains = ["mt0", "mt1", "mt2", "mt3"];
167
- this.layers[this.$t('map_google', 'renusify')] = this.L.tileLayer(
168
- "http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}",
169
- opt
170
- );
171
- opt.dark = true;
172
- this.layers[this.$t('map_google_dark', 'renusify')] = this.L.tileLayer(
173
- "http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}",
174
- opt
175
- );
176
- opt.dark = false;
177
- this.layers[this.$t('map_satelite', 'renusify')] = this.L.tileLayer(
178
- "http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}",
179
- opt
180
- );
181
-
182
- this.layers[this.$t('map_hot', 'renusify')].addTo(this.map);
183
- if (this.zoomControl) {
184
- this.L.control
185
- .zoom({
186
- zoomInTitle: this.$t("map_zoom_in", 'renusify'),
187
- zoomOutTitle: this.$t("map_zoom_out", 'renusify')
188
- })
189
- .addTo(this.map);
190
- } else {
191
- this.map.touchZoom.disable();
192
- this.map.doubleClickZoom.disable();
193
- this.map.scrollWheelZoom.disable();
194
- this.map.boxZoom.disable();
195
- this.map.keyboard.disable();
196
- }
197
- if (this.layerControl) {
198
- this.L.control.layers(this.layers).addTo(this.map);
199
- }
200
- const that = this;
201
- this.map.on("baselayerchange", function (e) {
202
- if (that.$helper.ifHas(e, false, "layer", "options", "dark")) {
203
- that.dark = true;
204
- } else {
205
- that.dark = that.darkMode;
206
- }
207
- });
208
- this.map.on("move", function (e) {
209
- if (e.originalEvent) {
210
- clearTimeout(that.timeout_id)
211
- that.timeout_id = setTimeout(() => {
212
- that.$emit("update:modelValue", Object.values(that.map.getCenter()));
213
- }, 100)
214
- }
215
- });
216
- },
217
- run() {
218
- this.map = this.L.map(this.map_id, {
219
- center: this.center,
220
- zoom: this.zoom,
221
- zoomControl: false,
222
- dragging: !this.disableMove,
223
- tap: !this.disableMove
224
- });
225
- this.initMap();
226
- this.layerGroup = new this.L.layerGroup().addTo(this.map);
227
- this.printMarkers()
228
- this.$emit("update:modelValue", this.center);
229
- this.$emit("leaflet", this.L);
230
- this.$emit("map", this.map);
231
- this.printCopy()
232
- },
233
- printCopy() {
234
- const attr = this.$refs.map.querySelector('.leaflet-control-attribution')
235
- attr.innerHTML = '&copy; | <a href="https://leafletjs.com" target="_blank">Leaflet</a> | <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors | Renusify'
236
- },
237
- printMarkers() {
238
- if (!this.layerGroup) {
239
- return
240
- }
241
- this.layerGroup.clearLayers();
242
- this.markers.forEach((item) => {
243
- let options = {riseOnHover: true, item: item}
244
- if (item.icon) {
245
- options.icon = new this.L.icon(item.icon);
246
- } else {
247
- options.icon = new this.L.icon({
248
- iconUrl: this.iconMarker,
249
- iconSize: [30, 30],
250
- iconAnchor: [15, 30],
251
- popupAnchor: [0, -30]
252
- });
253
- }
254
- let marker = new this.L.Marker(item.loc, options);
255
- marker.addTo(this.layerGroup)
256
- if (item.popup) {
257
- marker.bindPopup(item.popup);
258
- }
259
- if (item.open_popup) {
260
- marker.openPopup();
261
- }
262
- if (item.tooltip) {
263
- marker.bindTooltip(item.tooltip);
264
- }
265
- if (item.open_tooltip) {
266
- marker.openTooltip();
267
- }
268
- if (item.click) {
269
- marker.on('click', item.click)
270
- }
271
- })
272
- },
273
- getLocation() {
274
- this.$storage.set('map_location_access', true)
275
- this.confirm = false
276
- this.loading = true;
277
- if (navigator.geolocation) {
278
- navigator.geolocation.getCurrentPosition(
279
- this.showPosition,
280
- this.showError
281
- );
282
- } else {
283
- this.loading = false;
284
- this.$toast(this.$t("map_not_support_location", 'renusify'), {type: "error"});
285
- }
286
- },
287
- showPosition(position) {
288
- this.map.flyTo([position.coords.latitude, position.coords.longitude]);
289
- this.map.zoom = 18;
290
- this.loading = false;
291
- },
292
- showError(error) {
293
- this.loading = false;
294
- switch (error.code) {
295
- case error.PERMISSION_DENIED:
296
- this.$toast(this.$t("map_access_denied", 'renusify'), {type: "error"});
297
- break;
298
- default:
299
- this.$toast(this.$t("map_unavailable", 'renusify'), {type: "error"});
300
- break;
301
- }
302
- },
303
- add() {
304
- import('./leaflet.css')
305
- import('./leaflet.js').then(() => {
306
- this.L = global.L
307
- this.run();
370
+ })
371
+ }
372
+
373
+ const printMarkers = () => {
374
+ if (!layerGroup.value) return
375
+
376
+ layerGroup.value.clearLayers()
377
+ props.markers.forEach((item) => {
378
+ const options = {riseOnHover: true, item: item}
379
+
380
+ if (item.icon) {
381
+ options.icon = new L.value.icon(item.icon)
382
+ } else {
383
+ options.icon = new L.value.icon({
384
+ iconUrl: iconMarker.value,
385
+ iconSize: [30, 30],
386
+ iconAnchor: [15, 30],
387
+ popupAnchor: [0, -30]
308
388
  })
309
- },
389
+ }
390
+
391
+ const marker = new L.value.Marker(item.loc, options)
392
+ marker.addTo(layerGroup.value)
393
+
394
+ if (item.popup) {
395
+ marker.bindPopup(item.popup)
396
+ }
397
+ if (item.open_popup) {
398
+ marker.openPopup()
399
+ }
400
+ if (item.tooltip) {
401
+ marker.bindTooltip(item.tooltip)
402
+ }
403
+ if (item.open_tooltip) {
404
+ marker.openTooltip()
405
+ }
406
+ if (item.click) {
407
+ marker.on('click', item.click)
408
+ }
409
+ })
410
+ }
411
+
412
+ const getLocation = () => {
413
+ if ($storage) {
414
+ $storage.set('map_location_access', true)
415
+ }
416
+ confirm.value = false
417
+ loading.value = true
418
+
419
+ if (navigator.geolocation) {
420
+ navigator.geolocation.getCurrentPosition(showPosition, showError)
421
+ } else {
422
+ loading.value = false
423
+ if ($toast) {
424
+ $toast($t?.("map_not_support_location", 'renusify') || "Geolocation not supported", {type: "error"})
425
+ }
426
+ }
427
+ }
428
+
429
+ const showPosition = (position) => {
430
+ map.value.flyTo([position.coords.latitude, position.coords.longitude])
431
+ map.value.zoom = 18
432
+ loading.value = false
433
+ }
434
+
435
+ const showError = (error) => {
436
+ loading.value = false
437
+
438
+ if (!$toast) return
439
+
440
+ switch (error.code) {
441
+ case error.PERMISSION_DENIED:
442
+ $toast($t?.("map_access_denied", 'renusify') || "Location access denied", {type: "error"})
443
+ break
444
+ default:
445
+ $toast($t?.("map_unavailable", 'renusify') || "Location unavailable", {type: "error"})
446
+ break
447
+ }
448
+ }
449
+
450
+ const add = () => {
451
+ import('./leaflet.js').then(() => {
452
+ L.value = global.L
453
+ run()
454
+ })
455
+ }
456
+
457
+ watch(() => props.modelValue, (newValue) => {
458
+ if (map.value && newValue) {
459
+ map.value.flyTo(newValue)
460
+ }
461
+ })
462
+
463
+ watch(() => props.markers, () => {
464
+ printMarkers()
465
+ })
466
+
467
+ onMounted(() => {
468
+ add()
469
+ })
470
+
471
+ onUnmounted(() => {
472
+ if (timeout_id.value) {
473
+ clearTimeout(timeout_id.value)
474
+ }
475
+ if (map.value) {
476
+ map.value.remove()
310
477
  }
311
- };
478
+ })
312
479
  </script>
313
480
 
314
481
  <style lang="scss">
315
- @use "../../style/variables/base";
482
+ @use "../../style" as *;
316
483
 
317
- .#{base.$prefix}map {
484
+ .#{$prefix}map {
318
485
  position: relative;
319
486
 
320
487
  .leaflet-popup {