@skyservice-developers/vue-dev-kit 1.1.1 → 1.2.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.
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.2.0",
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",
@@ -31,6 +31,7 @@
31
31
  ],
32
32
  "scripts": {
33
33
  "dev": "vite",
34
+ "playground": "vite --config playground/vite.config.js playground",
34
35
  "build:vue2": "vite build --config vite.vue2.config.js",
35
36
  "build:vue3": "vite build --config vite.vue3.config.js",
36
37
  "build": "npm run build:vue2 && npm run build:vue3",
@@ -2,11 +2,26 @@ import { DefineComponent } from 'vue'
2
2
 
3
3
  // ============ Components ============
4
4
 
5
+ export interface HeaderDropdownItem {
6
+ name: string
7
+ path: string
8
+ lastVisit: number
9
+ }
10
+
5
11
  export interface HeaderProps {
6
12
  title?: string
7
13
  subtitle?: string
8
14
  showBackButton?: boolean
9
15
  backButtonTitle?: string
16
+ backEvent?: (() => void) | null
17
+ dropdownItems?: HeaderDropdownItem[]
18
+ dropdownTitle?: string
19
+ visitLabel?: string
20
+ }
21
+
22
+ export interface HeaderEmits {
23
+ 'back': () => void
24
+ 'navigate': (path: string) => void
10
25
  }
11
26
 
12
27
  export interface HeaderSlots {
@@ -1 +1 @@
1
- export { webviewCheck, isIosWebview, isAndroidWebview, isCefWebview, isWebview } from './webviewCheck'
1
+ export { webviewCheck, isIosWebview, isAndroidWebview, isCefWebview, isWebview, isInIframe } from './webviewCheck'
@@ -44,3 +44,11 @@ export function isWebview() {
44
44
  const check = webviewCheck()
45
45
  return check !== 'browser'
46
46
  }
47
+
48
+ export function isInIframe() {
49
+ try {
50
+ return window.self !== window.top
51
+ } catch (e) {
52
+ return true
53
+ }
54
+ }
@@ -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