@skyservice-developers/vue-dev-kit 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyservice-developers/vue-dev-kit",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "Vue 2 and Vue 3 developer toolkit - components and helpers",
5
5
  "type": "module",
6
6
  "main": "./dist/vue3/vue-dev-kit.cjs",
@@ -5,18 +5,40 @@
5
5
  class="sky-dialogbox sky-dialogbox-classic"
6
6
  :style="[zIndex ? { 'z-index': zIndex } : null]"
7
7
  >
8
- <div class="sky-dialog-overlay" :class="{ 'sky-dialog-animate': enableAnimation }">
8
+ <div
9
+ class="sky-dialog-overlay"
10
+ :class="{ 'sky-dialog-animate': enableAnimation }"
11
+ >
9
12
  <div ref="dialogContent" class="sky-dialog-content">
10
13
  <!-- Header -->
11
- <div class="sky-dialog-title" :class="{ 'sky-dialog-title-with-subtitle': subtitle }">
14
+ <div
15
+ class="sky-dialog-title"
16
+ :class="{ 'sky-dialog-title-with-subtitle': subtitle }"
17
+ >
12
18
  {{ title }}
13
- <span v-if="subtitle" class="sky-dialog-subtitle">{{ subtitle }}</span>
19
+ <span v-if="subtitle" class="sky-dialog-subtitle">{{
20
+ subtitle
21
+ }}</span>
14
22
  </div>
15
23
 
16
24
  <button class="sky-dialog-close" :title="closeText" @click="close">
17
25
  <svg viewBox="0 0 16 16" width="16" height="16">
18
- <line x1="1" y1="15" x2="15" y2="1" stroke="currentColor" stroke-width="2" />
19
- <line x1="1" y1="1" x2="15" y2="15" stroke="currentColor" stroke-width="2" />
26
+ <line
27
+ x1="1"
28
+ y1="15"
29
+ x2="15"
30
+ y2="1"
31
+ stroke="currentColor"
32
+ stroke-width="2"
33
+ />
34
+ <line
35
+ x1="1"
36
+ y1="1"
37
+ x2="15"
38
+ y2="15"
39
+ stroke="currentColor"
40
+ stroke-width="2"
41
+ />
20
42
  </svg>
21
43
  </button>
22
44
 
@@ -36,7 +58,11 @@
36
58
  </div>
37
59
 
38
60
  <!-- Footer -->
39
- <div v-if="showFooter" class="sky-dialog-footer" :class="{ 'sky-dialog-footer-animate': enableAnimation }">
61
+ <div
62
+ v-if="showFooter"
63
+ class="sky-dialog-footer"
64
+ :class="{ 'sky-dialog-footer-animate': enableAnimation }"
65
+ >
40
66
  <slot name="buttons"></slot>
41
67
  </div>
42
68
  </div>
@@ -46,142 +72,145 @@
46
72
  </template>
47
73
 
48
74
  <script>
49
- import { isIosWebview, isAndroidWebview } from '../../shared/utils/webviewCheck'
75
+ import {
76
+ isIosWebview,
77
+ isAndroidWebview,
78
+ } from "../../shared/utils/webviewCheck";
50
79
 
51
80
  export default {
52
- name: 'DialogModal',
81
+ name: "DialogModal",
53
82
  props: {
54
83
  modelValue: {
55
84
  type: Boolean,
56
- default: false
85
+ default: false,
57
86
  },
58
87
  title: {
59
88
  type: String,
60
- default: ''
89
+ default: "",
61
90
  },
62
91
  subtitle: {
63
92
  type: String,
64
- default: ''
93
+ default: "",
65
94
  },
66
95
  zIndex: {
67
96
  type: [Number, String],
68
- default: null
97
+ default: null,
69
98
  },
70
99
  closeText: {
71
100
  type: String,
72
- default: 'Закрити'
101
+ default: "Закрити",
73
102
  },
74
103
  enableAnimation: {
75
104
  type: Boolean,
76
- default: true
105
+ default: true,
77
106
  },
78
107
  closeOnEsc: {
79
108
  type: Boolean,
80
- default: true
109
+ default: true,
81
110
  },
82
111
  hasButtons: {
83
112
  type: Boolean,
84
- default: null
85
- }
113
+ default: null,
114
+ },
86
115
  },
87
116
  data() {
88
117
  return {
89
- touchStartX: 0
90
- }
118
+ touchStartX: 0,
119
+ };
91
120
  },
92
121
  computed: {
93
122
  isIos() {
94
123
  try {
95
- return isIosWebview()
124
+ return isIosWebview();
96
125
  } catch {
97
- return false
126
+ return false;
98
127
  }
99
128
  },
100
129
  isAndroid() {
101
130
  try {
102
- return isAndroidWebview()
131
+ return isAndroidWebview();
103
132
  } catch {
104
- return false
133
+ return false;
105
134
  }
106
135
  },
107
136
  // Determine if footer should be shown
108
137
  showFooter() {
109
138
  // If hasButtons prop is explicitly set, use it
110
139
  if (this.hasButtons !== null) {
111
- return this.hasButtons
140
+ return this.hasButtons;
112
141
  }
113
142
  // Fallback to slot check (for direct usage without Dialog wrapper)
114
- return !!this.$slots.buttons
115
- }
143
+ return !!this.$slots.buttons;
144
+ },
116
145
  },
117
146
  watch: {
118
147
  // Body scroll lock
119
148
  modelValue(value) {
120
149
  if (value) {
121
- document.body.style.overflow = 'hidden'
150
+ document.body.style.overflow = "hidden";
122
151
  this.$nextTick(() => {
123
- this.androidFix()
124
- })
152
+ this.androidFix();
153
+ });
125
154
  } else {
126
- document.body.style.overflow = ''
155
+ document.body.style.overflow = "";
127
156
  }
128
- }
157
+ },
129
158
  },
130
159
  mounted() {
131
- document.addEventListener('keydown', this.handleKeydown)
132
- window.addEventListener('resize', this.androidFix)
160
+ document.addEventListener("keydown", this.handleKeydown);
161
+ window.addEventListener("resize", this.androidFix);
133
162
  },
134
163
  beforeDestroy() {
135
- document.removeEventListener('keydown', this.handleKeydown)
136
- window.removeEventListener('resize', this.androidFix)
137
- document.body.style.overflow = ''
164
+ document.removeEventListener("keydown", this.handleKeydown);
165
+ window.removeEventListener("resize", this.androidFix);
166
+ document.body.style.overflow = "";
138
167
  },
139
168
  methods: {
140
169
  close() {
141
- this.$emit('update:modelValue', false)
142
- this.$emit('close')
170
+ this.$emit("update:modelValue", false);
171
+ this.$emit("close");
143
172
  },
144
173
  handleKeydown(e) {
145
- if (e.key === 'Escape' && this.closeOnEsc && this.modelValue) {
146
- this.close()
174
+ if (e.key === "Escape" && this.closeOnEsc && this.modelValue) {
175
+ this.close();
147
176
  }
148
- if (e.key === 'Enter' && this.modelValue) {
149
- this.$emit('save')
177
+ if (e.key === "Enter" && this.modelValue) {
178
+ this.$emit("save");
150
179
  }
151
180
  },
152
181
  // Touch handling for iOS swipe back
153
182
  handleTouchStart(e) {
154
183
  if (e.touches[0].clientX < 35) {
155
- this.touchStartX = e.touches[0].clientX
184
+ this.touchStartX = e.touches[0].clientX;
156
185
  }
157
186
  },
158
187
  handleTouchEnd(e) {
159
188
  if (this.touchStartX > 0 && this.touchStartX < 35) {
160
- const touchEndX = e.changedTouches[0].clientX
189
+ const touchEndX = e.changedTouches[0].clientX;
161
190
  if (touchEndX - this.touchStartX > 50) {
162
- this.close()
191
+ this.close();
163
192
  }
164
193
  }
165
- this.touchStartX = 0
194
+ this.touchStartX = 0;
166
195
  },
167
196
  // Android notch fix
168
197
  androidFix() {
169
- if (!this.isAndroid || !this.$refs.dialogContent) return
198
+ if (!this.isAndroid || !this.$refs.dialogContent) return;
170
199
 
171
200
  try {
172
- if (typeof Android !== 'undefined' && Android.getDisplayCutoutTop) {
173
- const cutoutTop = Android.getDisplayCutoutTop()
201
+ if (typeof Android !== "undefined" && Android.getDisplayCutoutTop) {
202
+ const cutoutTop = Android.getDisplayCutoutTop();
174
203
  if (cutoutTop && window.devicePixelRatio > 1.0) {
175
- const paddingTop = cutoutTop / window.devicePixelRatio
176
- this.$refs.dialogContent.style.paddingTop = paddingTop + 'px'
204
+ const paddingTop = cutoutTop / window.devicePixelRatio;
205
+ this.$refs.dialogContent.style.paddingTop = paddingTop + "px";
177
206
  }
178
207
  }
179
208
  } catch (err) {
180
209
  // Android interface not available
181
210
  }
182
- }
183
- }
184
- }
211
+ },
212
+ },
213
+ };
185
214
  </script>
186
215
 
187
216
  <style>
@@ -304,7 +333,10 @@ export default {
304
333
  max-width: 100%;
305
334
  }
306
335
 
307
- .sky-dialog-footer:has(> :deep(*:nth-child(2)):not(:has(> :deep(*:nth-child(3))))) > :deep(*) {
336
+ .sky-dialog-footer:has(
337
+ > :deep(*:nth-child(2)):not(:has(> :deep(*:nth-child(3))))
338
+ )
339
+ > :deep(*) {
308
340
  flex: 1 1 50%;
309
341
  }
310
342
 
@@ -9,8 +9,16 @@
9
9
  @click="handleBack"
10
10
  :title="backButtonTitle"
11
11
  >
12
- <svg width="15" height="15" viewBox="0 0 451.847 451.847" style="transform: rotate(90deg)">
13
- <path fill="currentColor" d="M225.923,354.706c-8.098,0-16.195-3.092-22.369-9.263L9.27,151.157c-12.359-12.359-12.359-32.397,0-44.751c12.354-12.354,32.388-12.354,44.748,0l171.905,171.915l171.906-171.909c12.359-12.354,32.391-12.354,44.744,0c12.365,12.354,12.365,32.392,0,44.751L248.292,345.449C242.115,351.621,234.018,354.706,225.923,354.706z"/>
12
+ <svg
13
+ width="15"
14
+ height="15"
15
+ viewBox="0 0 451.847 451.847"
16
+ style="transform: rotate(90deg)"
17
+ >
18
+ <path
19
+ fill="currentColor"
20
+ d="M225.923,354.706c-8.098,0-16.195-3.092-22.369-9.263L9.27,151.157c-12.359-12.359-12.359-32.397,0-44.751c12.354-12.354,32.388-12.354,44.748,0l171.905,171.915l171.906-171.909c12.359-12.354,32.391-12.354,44.744,0c12.365,12.354,12.365,32.392,0,44.751L248.292,345.449C242.115,351.621,234.018,354.706,225.923,354.706z"
21
+ />
14
22
  </svg>
15
23
  </button>
16
24
  <div class="header-title-content">
@@ -24,7 +32,9 @@
24
32
  </div>
25
33
 
26
34
  <div class="header-actions">
35
+ <div></div>
27
36
  <slot></slot>
37
+ <div></div>
28
38
  </div>
29
39
  </div>
30
40
  </div>
@@ -33,54 +43,54 @@
33
43
 
34
44
  <script>
35
45
  export default {
36
- name: 'Header',
46
+ name: "Header",
37
47
  props: {
38
48
  title: {
39
49
  type: String,
40
- default: ''
50
+ default: "",
41
51
  },
42
52
  subtitle: {
43
53
  type: String,
44
- default: ''
54
+ default: "",
45
55
  },
46
56
  showBackButton: {
47
57
  type: Boolean,
48
- default: true
58
+ default: true,
49
59
  },
50
60
  backButtonTitle: {
51
61
  type: String,
52
- default: 'Назад'
62
+ default: "Назад",
53
63
  },
54
64
  backEvent: {
55
65
  type: Function,
56
- default: null
57
- }
66
+ default: null,
67
+ },
58
68
  },
59
69
  computed: {
60
70
  // Перевіряємо чи сторінка в iframe
61
71
  isInIframe() {
62
72
  try {
63
- return window.self !== window.top
73
+ return window.self !== window.top;
64
74
  } catch (e) {
65
- return true
75
+ return true;
66
76
  }
67
77
  },
68
78
  // Показуємо кнопку якщо є backEvent АБО (showBackButton=true І сторінка в iframe)
69
79
  shouldShowBackButton() {
70
- return this.backEvent || (this.showBackButton && this.isInIframe)
71
- }
80
+ return this.backEvent || (this.showBackButton && this.isInIframe);
81
+ },
72
82
  },
73
83
  methods: {
74
84
  // Обробник кнопки "Назад" - викликає backEvent або відправляє повідомлення батьківському вікну
75
85
  handleBack() {
76
86
  if (this.backEvent) {
77
- this.backEvent()
87
+ this.backEvent();
78
88
  } else {
79
- window.parent.postMessage({ type: 'exit' }, '*')
89
+ window.parent.postMessage({ type: "exit" }, "*");
80
90
  }
81
- }
82
- }
83
- }
91
+ },
92
+ },
93
+ };
84
94
  </script>
85
95
 
86
96
  <style scoped>
@@ -6,18 +6,40 @@
6
6
  class="sky-dialogbox sky-dialogbox-classic"
7
7
  :style="[zIndex ? { 'z-index': zIndex } : null]"
8
8
  >
9
- <div class="sky-dialog-overlay" :class="{ 'sky-dialog-animate': enableAnimation }">
9
+ <div
10
+ class="sky-dialog-overlay"
11
+ :class="{ 'sky-dialog-animate': enableAnimation }"
12
+ >
10
13
  <div ref="dialogContent" class="sky-dialog-content">
11
14
  <!-- Header -->
12
- <div class="sky-dialog-title" :class="{ 'sky-dialog-title-with-subtitle': subtitle }">
15
+ <div
16
+ class="sky-dialog-title"
17
+ :class="{ 'sky-dialog-title-with-subtitle': subtitle }"
18
+ >
13
19
  {{ title }}
14
- <span v-if="subtitle" class="sky-dialog-subtitle">{{ subtitle }}</span>
20
+ <span v-if="subtitle" class="sky-dialog-subtitle">{{
21
+ subtitle
22
+ }}</span>
15
23
  </div>
16
24
 
17
25
  <button class="sky-dialog-close" :title="closeText" @click="close">
18
26
  <svg viewBox="0 0 16 16" width="16" height="16">
19
- <line x1="1" y1="15" x2="15" y2="1" stroke="currentColor" stroke-width="2" />
20
- <line x1="1" y1="1" x2="15" y2="15" stroke="currentColor" stroke-width="2" />
27
+ <line
28
+ x1="1"
29
+ y1="15"
30
+ x2="15"
31
+ y2="1"
32
+ stroke="currentColor"
33
+ stroke-width="2"
34
+ />
35
+ <line
36
+ x1="1"
37
+ y1="1"
38
+ x2="15"
39
+ y2="15"
40
+ stroke="currentColor"
41
+ stroke-width="2"
42
+ />
21
43
  </svg>
22
44
  </button>
23
45
 
@@ -37,8 +59,15 @@
37
59
  </div>
38
60
 
39
61
  <!-- Footer -->
40
- <div v-if="showFooter" class="sky-dialog-footer" :class="{ 'sky-dialog-footer-animate': enableAnimation }">
62
+ <div
63
+ v-if="showFooter"
64
+ class="sky-dialog-footer"
65
+ :class="{ 'sky-dialog-footer-animate': enableAnimation }"
66
+ >
67
+ <!-- Порожні блоки ремонтують відображення на windows в додатку, не видаляти! -->
68
+ <div></div>
41
69
  <slot name="buttons"></slot>
70
+ <div></div>
42
71
  </div>
43
72
  </div>
44
73
  </div>
@@ -48,148 +77,162 @@
48
77
  </template>
49
78
 
50
79
  <script setup>
51
- import { ref, computed, watch, onMounted, onUnmounted, nextTick, useSlots } from 'vue'
52
- import { isIosWebview, isAndroidWebview } from '../../shared/utils/webviewCheck'
53
-
54
- const slots = useSlots()
80
+ import {
81
+ ref,
82
+ computed,
83
+ watch,
84
+ onMounted,
85
+ onUnmounted,
86
+ nextTick,
87
+ useSlots,
88
+ } from "vue";
89
+ import {
90
+ isIosWebview,
91
+ isAndroidWebview,
92
+ } from "../../shared/utils/webviewCheck";
93
+
94
+ const slots = useSlots();
55
95
 
56
96
  const props = defineProps({
57
97
  modelValue: {
58
98
  type: Boolean,
59
- default: false
99
+ default: false,
60
100
  },
61
101
  title: {
62
102
  type: String,
63
- default: ''
103
+ default: "",
64
104
  },
65
105
  subtitle: {
66
106
  type: String,
67
- default: ''
107
+ default: "",
68
108
  },
69
109
  zIndex: {
70
110
  type: [Number, String],
71
- default: null
111
+ default: null,
72
112
  },
73
113
  closeText: {
74
114
  type: String,
75
- default: 'Закрити'
115
+ default: "Закрити",
76
116
  },
77
117
  enableAnimation: {
78
118
  type: Boolean,
79
- default: true
119
+ default: true,
80
120
  },
81
121
  closeOnEsc: {
82
122
  type: Boolean,
83
- default: true
123
+ default: true,
84
124
  },
85
125
  hasButtons: {
86
126
  type: Boolean,
87
- default: null
88
- }
89
- })
127
+ default: null,
128
+ },
129
+ });
90
130
 
91
- const emit = defineEmits(['update:modelValue', 'close', 'save'])
131
+ const emit = defineEmits(["update:modelValue", "close", "save"]);
92
132
 
93
- const dialogContent = ref(null)
94
- const dialogPaper = ref(null)
95
- const touchStartX = ref(0)
133
+ const dialogContent = ref(null);
134
+ const dialogPaper = ref(null);
135
+ const touchStartX = ref(0);
96
136
 
97
137
  const isIos = computed(() => {
98
138
  try {
99
- return isIosWebview()
139
+ return isIosWebview();
100
140
  } catch {
101
- return false
141
+ return false;
102
142
  }
103
- })
143
+ });
104
144
 
105
145
  const isAndroid = computed(() => {
106
146
  try {
107
- return isAndroidWebview()
147
+ return isAndroidWebview();
108
148
  } catch {
109
- return false
149
+ return false;
110
150
  }
111
- })
151
+ });
112
152
 
113
153
  // Determine if footer should be shown
114
154
  const showFooter = computed(() => {
115
155
  // If hasButtons prop is explicitly set, use it
116
156
  if (props.hasButtons !== null) {
117
- return props.hasButtons
157
+ return props.hasButtons;
118
158
  }
119
159
  // Fallback to slot check (for direct usage without Dialog wrapper)
120
- return !!slots.buttons
121
- })
160
+ return !!slots.buttons;
161
+ });
122
162
 
123
163
  const close = () => {
124
- emit('update:modelValue', false)
125
- emit('close')
126
- }
164
+ emit("update:modelValue", false);
165
+ emit("close");
166
+ };
127
167
 
128
168
  const handleKeydown = (e) => {
129
- if (e.key === 'Escape' && props.closeOnEsc && props.modelValue) {
130
- close()
169
+ if (e.key === "Escape" && props.closeOnEsc && props.modelValue) {
170
+ close();
131
171
  }
132
- if (e.key === 'Enter' && props.modelValue) {
133
- emit('save')
172
+ if (e.key === "Enter" && props.modelValue) {
173
+ emit("save");
134
174
  }
135
- }
175
+ };
136
176
 
137
177
  // Touch handling for iOS swipe back
138
178
  const handleTouchStart = (e) => {
139
179
  if (e.touches[0].clientX < 35) {
140
- touchStartX.value = e.touches[0].clientX
180
+ touchStartX.value = e.touches[0].clientX;
141
181
  }
142
- }
182
+ };
143
183
 
144
184
  const handleTouchEnd = (e) => {
145
185
  if (touchStartX.value > 0 && touchStartX.value < 35) {
146
- const touchEndX = e.changedTouches[0].clientX
186
+ const touchEndX = e.changedTouches[0].clientX;
147
187
  if (touchEndX - touchStartX.value > 50) {
148
- close()
188
+ close();
149
189
  }
150
190
  }
151
- touchStartX.value = 0
152
- }
191
+ touchStartX.value = 0;
192
+ };
153
193
 
154
194
  // Android notch fix
155
195
  const androidFix = () => {
156
- if (!isAndroid.value || !dialogContent.value) return
196
+ if (!isAndroid.value || !dialogContent.value) return;
157
197
 
158
198
  try {
159
- if (typeof Android !== 'undefined' && Android.getDisplayCutoutTop) {
160
- const cutoutTop = Android.getDisplayCutoutTop()
199
+ if (typeof Android !== "undefined" && Android.getDisplayCutoutTop) {
200
+ const cutoutTop = Android.getDisplayCutoutTop();
161
201
  if (cutoutTop && window.devicePixelRatio > 1.0) {
162
- const paddingTop = cutoutTop / window.devicePixelRatio
163
- dialogContent.value.style.paddingTop = paddingTop + 'px'
202
+ const paddingTop = cutoutTop / window.devicePixelRatio;
203
+ dialogContent.value.style.paddingTop = paddingTop + "px";
164
204
  }
165
205
  }
166
206
  } catch (err) {
167
207
  // Android interface not available
168
208
  }
169
- }
209
+ };
170
210
 
171
211
  // Body scroll lock
172
- watch(() => props.modelValue, (value) => {
173
- if (value) {
174
- document.body.style.overflow = 'hidden'
175
- nextTick(() => {
176
- androidFix()
177
- })
178
- } else {
179
- document.body.style.overflow = ''
180
- }
181
- })
212
+ watch(
213
+ () => props.modelValue,
214
+ (value) => {
215
+ if (value) {
216
+ document.body.style.overflow = "hidden";
217
+ nextTick(() => {
218
+ androidFix();
219
+ });
220
+ } else {
221
+ document.body.style.overflow = "";
222
+ }
223
+ },
224
+ );
182
225
 
183
226
  onMounted(() => {
184
- document.addEventListener('keydown', handleKeydown)
185
- window.addEventListener('resize', androidFix)
186
- })
227
+ document.addEventListener("keydown", handleKeydown);
228
+ window.addEventListener("resize", androidFix);
229
+ });
187
230
 
188
231
  onUnmounted(() => {
189
- document.removeEventListener('keydown', handleKeydown)
190
- window.removeEventListener('resize', androidFix)
191
- document.body.style.overflow = ''
192
- })
232
+ document.removeEventListener("keydown", handleKeydown);
233
+ window.removeEventListener("resize", androidFix);
234
+ document.body.style.overflow = "";
235
+ });
193
236
  </script>
194
237
 
195
238
  <style>
@@ -312,7 +355,10 @@ onUnmounted(() => {
312
355
  max-width: 100%;
313
356
  }
314
357
 
315
- .sky-dialog-footer:has(> :deep(*:nth-child(2)):not(:has(> :deep(*:nth-child(3))))) > :deep(*) {
358
+ .sky-dialog-footer:has(
359
+ > :deep(*:nth-child(2)):not(:has(> :deep(*:nth-child(3))))
360
+ )
361
+ > :deep(*) {
316
362
  flex: 1 1 50%;
317
363
  }
318
364