@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/dist/vue2/style.css +1 -1
- package/dist/vue2/vue-dev-kit.cjs +1 -1
- package/dist/vue2/vue-dev-kit.js +3 -3
- package/dist/vue3/style.css +1 -1
- package/dist/vue3/vue-dev-kit.cjs +1 -1
- package/dist/vue3/vue-dev-kit.js +246 -228
- package/package.json +1 -1
- package/src/vue2/components/DialogModal.vue +87 -55
- package/src/vue2/components/Header.vue +28 -18
- package/src/vue3/components/DialogModal.vue +117 -71
- package/src/vue3/components/DialogNext.vue +117 -72
- package/src/vue3/components/Header.vue +29 -18
- package/src/vue3/components/Modal.vue +62 -40
package/package.json
CHANGED
|
@@ -5,18 +5,40 @@
|
|
|
5
5
|
class="sky-dialogbox sky-dialogbox-classic"
|
|
6
6
|
:style="[zIndex ? { 'z-index': zIndex } : null]"
|
|
7
7
|
>
|
|
8
|
-
<div
|
|
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
|
|
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">{{
|
|
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
|
|
19
|
-
|
|
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
|
|
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 {
|
|
75
|
+
import {
|
|
76
|
+
isIosWebview,
|
|
77
|
+
isAndroidWebview,
|
|
78
|
+
} from "../../shared/utils/webviewCheck";
|
|
50
79
|
|
|
51
80
|
export default {
|
|
52
|
-
name:
|
|
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 =
|
|
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(
|
|
132
|
-
window.addEventListener(
|
|
160
|
+
document.addEventListener("keydown", this.handleKeydown);
|
|
161
|
+
window.addEventListener("resize", this.androidFix);
|
|
133
162
|
},
|
|
134
163
|
beforeDestroy() {
|
|
135
|
-
document.removeEventListener(
|
|
136
|
-
window.removeEventListener(
|
|
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(
|
|
142
|
-
this.$emit(
|
|
170
|
+
this.$emit("update:modelValue", false);
|
|
171
|
+
this.$emit("close");
|
|
143
172
|
},
|
|
144
173
|
handleKeydown(e) {
|
|
145
|
-
if (e.key ===
|
|
146
|
-
this.close()
|
|
174
|
+
if (e.key === "Escape" && this.closeOnEsc && this.modelValue) {
|
|
175
|
+
this.close();
|
|
147
176
|
}
|
|
148
|
-
if (e.key ===
|
|
149
|
-
this.$emit(
|
|
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 !==
|
|
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 +
|
|
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(
|
|
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
|
|
13
|
-
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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">{{
|
|
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
|
|
20
|
-
|
|
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
|
|
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 {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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([
|
|
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(
|
|
125
|
-
emit(
|
|
126
|
-
}
|
|
164
|
+
emit("update:modelValue", false);
|
|
165
|
+
emit("close");
|
|
166
|
+
};
|
|
127
167
|
|
|
128
168
|
const handleKeydown = (e) => {
|
|
129
|
-
if (e.key ===
|
|
130
|
-
close()
|
|
169
|
+
if (e.key === "Escape" && props.closeOnEsc && props.modelValue) {
|
|
170
|
+
close();
|
|
131
171
|
}
|
|
132
|
-
if (e.key ===
|
|
133
|
-
emit(
|
|
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 !==
|
|
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 +
|
|
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(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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(
|
|
185
|
-
window.addEventListener(
|
|
186
|
-
})
|
|
227
|
+
document.addEventListener("keydown", handleKeydown);
|
|
228
|
+
window.addEventListener("resize", androidFix);
|
|
229
|
+
});
|
|
187
230
|
|
|
188
231
|
onUnmounted(() => {
|
|
189
|
-
document.removeEventListener(
|
|
190
|
-
window.removeEventListener(
|
|
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(
|
|
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
|
|