bfg-common 1.5.452 → 1.5.453

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.
@@ -3252,7 +3252,8 @@
3252
3252
  "channels": "Каналы ({0})",
3253
3253
  "metricsNotFound": "Паказчыкі не знойдзены",
3254
3254
  "uploadFolder": "Тэчка загрузкі",
3255
- "uploadFiles": "Запампаваць файлы"
3255
+ "uploadFiles": "Запампаваць файлы",
3256
+ "clickForUse": "Націсніце для выкарыстання"
3256
3257
  },
3257
3258
  "vmWizard": {
3258
3259
  "selectCreationType": "Выберыце тып стварэння",
@@ -3256,7 +3256,8 @@
3256
3256
  "channels": "Channels ({0})",
3257
3257
  "metricsNotFound": "Metrics not found",
3258
3258
  "uploadFolder": "Upload folder",
3259
- "uploadFiles": "Upload files"
3259
+ "uploadFiles": "Upload files",
3260
+ "clickForUse": "Click for use"
3260
3261
  },
3261
3262
  "vmWizard": {
3262
3263
  "selectCreationType": "Select a Creation Type",
@@ -3256,7 +3256,8 @@
3256
3256
  "channels": "Ալիքներ ({0})",
3257
3257
  "metricsNotFound": "Չափանիշները չեն գտնվել",
3258
3258
  "uploadFolder": "Վերբեռնեք թղթապանակը",
3259
- "uploadFiles": "Վերբեռնեք ֆայլեր"
3259
+ "uploadFiles": "Վերբեռնեք ֆայլեր",
3260
+ "clickForUse": "Կտտացրեք օգտագործման համար"
3260
3261
  },
3261
3262
  "vmWizard": {
3262
3263
  "selectCreationType": "Ընտրեք ստեղծման տեսակը",
@@ -3255,7 +3255,8 @@
3255
3255
  "channels": "Арналар ({0})",
3256
3256
  "metricsNotFound": "Көрсеткіштер табылмады",
3257
3257
  "uploadFolder": "Қалтаны жүктеп салу",
3258
- "uploadFiles": "Файлдарды жүктеп салу"
3258
+ "uploadFiles": "Файлдарды жүктеп салу",
3259
+ "clickForUse": "Пайдалану үшін басыңыз"
3259
3260
  },
3260
3261
  "vmWizard": {
3261
3262
  "selectCreationType": "Жасау түрін таңдаңыз",
@@ -3255,7 +3255,8 @@
3255
3255
  "channels": "Каналы ({0})",
3256
3256
  "metricsNotFound": "Метрики не найдены",
3257
3257
  "uploadFolder": "Загрузить папку",
3258
- "uploadFiles": "Загрузить файлы"
3258
+ "uploadFiles": "Загрузить файлы",
3259
+ "clickForUse": "Нажмите для использования"
3259
3260
  },
3260
3261
  "vmWizard": {
3261
3262
  "selectCreationType": "Выбор типа создания",
@@ -3253,7 +3253,8 @@
3253
3253
  "channels": "频道 ({0})",
3254
3254
  "metricsNotFound": "未找到指标",
3255
3255
  "uploadFolder": "上传文件夹",
3256
- "uploadFiles": "上传文件"
3256
+ "uploadFiles": "上传文件",
3257
+ "clickForUse": "点击使用"
3257
3258
  },
3258
3259
  "vmWizard": {
3259
3260
  "selectCreationType": "选择创建类型",
@@ -2906,7 +2906,8 @@
2906
2906
  "channels": "القنوات ({0})",
2907
2907
  "metricsNotFound": "لم يتم العثور على المقاييس",
2908
2908
  "uploadFolder": "تحميل مجلد",
2909
- "uploadFiles": "تحميل ملفات"
2909
+ "uploadFiles": "تحميل ملفات",
2910
+ "clickForUse": "انقر للاستخدام"
2910
2911
  },
2911
2912
  "vmWizard": {
2912
2913
  "devices": "الأجهزة ({0})",
@@ -1,27 +1,37 @@
1
1
  <template>
2
2
  <div
3
- class="window-container"
3
+ :class="['window-container', { loading: props.loading }]"
4
4
  :style="{
5
- left: x + 'px',
6
- top: y + 'px',
7
- width: width + 'px',
8
- height: height + 'px',
5
+ left: leftLocal + 'px',
6
+ top: topLocal + 'px',
7
+ width: widthLocal + 'px',
8
+ height: heightLocal + 'px',
9
9
  }"
10
10
  >
11
11
  <div ref="headerEl" class="window-header">
12
- <div class="window-title">{{ props.title }}</div>
13
- <button class="window-close" @click="onHide">
14
- <ui-icon name="close" class="close-icon" />
15
- </button>
12
+ <slot name="header">
13
+ <div class="window-title">{{ props.title }}</div>
14
+ </slot>
15
+
16
+ <div class="flex-align-center">
17
+ <button class="window-close" @click="onCollapse">
18
+ <ui-icon
19
+ :name="collapseData.isCollapsed ? 'arrow' : 'check-line'"
20
+ class="hide-icon"
21
+ />
22
+ </button>
23
+ <button class="window-close ml-1" @click="onHide">
24
+ <ui-icon name="close" class="close-icon" />
25
+ </button>
26
+ </div>
16
27
  </div>
17
28
 
18
29
  <div class="window-content">
30
+ <div v-show="props.loading" class="absolute-center">
31
+ <ui-icon name="spinner" />
32
+ </div>
19
33
  <slot></slot>
20
- <div
21
- v-show="isShowContentBlocker"
22
- :style="{}"
23
- class="content-blocker"
24
- ></div>
34
+ <div v-show="isShowContentBlocker" class="content-blocker"></div>
25
35
  </div>
26
36
 
27
37
  <!-- Ручки для ресайза -->
@@ -62,14 +72,27 @@
62
72
 
63
73
  <script setup lang="ts">
64
74
  import { useDraggable } from '@vueuse/core'
65
-
66
- const props = defineProps<{
67
- top: number
68
- left: number
69
- width: number
70
- height: number
71
- title: string
72
- }>()
75
+ import type { UI_I_WindowCollapsedData } from '~/components/atoms/window/lib/models/interfaces'
76
+ import {
77
+ minWidth,
78
+ minHeight,
79
+ headerHeight,
80
+ windowPadding,
81
+ } from '~/components/atoms/window/lib/config/config'
82
+
83
+ const props = withDefaults(
84
+ defineProps<{
85
+ top: number
86
+ left: number
87
+ width: number
88
+ height: number
89
+ title: string
90
+ loading?: boolean
91
+ }>(),
92
+ {
93
+ loading: false,
94
+ }
95
+ )
73
96
  const emits = defineEmits<{
74
97
  (event: 'hide'): void
75
98
  }>()
@@ -77,20 +100,34 @@ const emits = defineEmits<{
77
100
  const headerEl = ref(null)
78
101
  const isShowContentBlocker = ref<boolean>(false)
79
102
 
80
- const x = ref(props.left)
81
- const y = ref(props.top)
82
- const width = ref(props.width)
83
- const height = ref(props.height)
103
+ const leftLocal = ref<number>(props.left)
104
+ const topLocal = ref<number>(props.top)
105
+ const widthLocal = ref<number>(Math.max(minWidth, props.width))
106
+ const heightLocal = ref<number>(Math.max(minHeight, props.height))
107
+
108
+ const collapseData = ref<UI_I_WindowCollapsedData>({
109
+ isCollapsed: false,
110
+ cashTop: -1,
111
+ cashLeft: -1,
112
+ cashWidth: -1,
113
+ cashHeight: -1,
114
+ })
84
115
 
85
116
  // Используем vueuse для перетаскивания
86
117
  useDraggable(headerEl, {
87
- initialValue: { x: props.left, y: props.top },
118
+ initialValue: { x: leftLocal.value, y: topLocal.value },
88
119
  onMove({ x: newX, y: newY }) {
89
- x.value = newX
90
- y.value = newY
120
+ leftLocal.value = newX
121
+ topLocal.value = newY
91
122
  },
92
123
  onStart() {
93
124
  isShowContentBlocker.value = true
125
+ if (!collapseData.value.isCollapsed) {
126
+ collapseData.value.cashTop = topLocal.value
127
+ collapseData.value.cashLeft = leftLocal.value
128
+ collapseData.value.cashWidth = widthLocal.value
129
+ collapseData.value.cashHeight = heightLocal.value
130
+ }
94
131
  },
95
132
  onEnd() {
96
133
  isShowContentBlocker.value = false
@@ -102,35 +139,48 @@ const fixSize = (): void => {
102
139
  const globalWindowWidth = window.innerWidth
103
140
  const globalWindowHeight = window.innerHeight
104
141
 
105
- width.value = Math.min(globalWindowWidth - 8 * 2, width.value)
106
- height.value = Math.min(globalWindowHeight - 8 * 2, height.value)
142
+ widthLocal.value = Math.min(
143
+ globalWindowWidth - windowPadding * 2,
144
+ widthLocal.value
145
+ )
146
+ heightLocal.value = Math.min(
147
+ globalWindowHeight - windowPadding * 2,
148
+ heightLocal.value
149
+ )
107
150
  }
108
151
  const fixPosition = (): void => {
109
152
  const globalWindowWidth = window.innerWidth
110
153
  const globalWindowHeight = window.innerHeight
111
- let newX = x.value
112
- let newY = y.value
113
- if (x.value + width.value / 2 > globalWindowWidth) {
114
- newX = globalWindowWidth - 20
115
- } else if (x.value + width.value > globalWindowWidth - 8) {
116
- newX = globalWindowWidth - width.value - 8
117
- } else if (x.value < 8) {
118
- newX = 8
154
+ let newX = leftLocal.value
155
+ let newY = topLocal.value
156
+
157
+ if (leftLocal.value + widthLocal.value > globalWindowWidth - windowPadding) {
158
+ newX = globalWindowWidth - widthLocal.value - windowPadding
159
+ } else if (leftLocal.value < windowPadding) {
160
+ newX = windowPadding
119
161
  }
120
162
 
121
- if (y.value + height.value / 2 > globalWindowHeight) {
122
- newY = globalWindowHeight - 20
123
- } else if (y.value + height.value > globalWindowHeight - 8) {
124
- newY = globalWindowHeight - height.value - 8
125
- } else if (y.value < 8) {
126
- newY = 8
163
+ if (topLocal.value + heightLocal.value / 2 > globalWindowHeight) {
164
+ newY = globalWindowHeight - headerHeight
165
+ collapseData.value.isCollapsed = true
166
+ } else if (
167
+ topLocal.value + heightLocal.value >
168
+ globalWindowHeight - windowPadding
169
+ ) {
170
+ newY = globalWindowHeight - heightLocal.value - windowPadding
171
+ collapseData.value.isCollapsed = false
172
+ } else if (topLocal.value < windowPadding) {
173
+ newY = windowPadding
174
+ collapseData.value.isCollapsed = false
175
+ } else {
176
+ collapseData.value.isCollapsed = false
127
177
  }
128
178
 
129
179
  smoothMove(newX, newY)
130
180
  }
131
181
  const smoothMove = (newX: number, newY: number, duration = 100): void => {
132
- const startX = x.value
133
- const startY = y.value
182
+ const startX = leftLocal.value
183
+ const startY = topLocal.value
134
184
 
135
185
  // Время начала анимации
136
186
  const startTime = performance.now()
@@ -144,8 +194,8 @@ const smoothMove = (newX: number, newY: number, duration = 100): void => {
144
194
  const progress = Math.min(elapsedTime / duration, 1)
145
195
 
146
196
  // Вычисляем новые координаты с помощью линейной интерполяции
147
- x.value = startX + (newX - startX) * progress
148
- y.value = startY + (newY - startY) * progress
197
+ leftLocal.value = startX + (newX - startX) * progress
198
+ topLocal.value = startY + (newY - startY) * progress
149
199
 
150
200
  // Если анимация не завершена, продолжаем
151
201
  if (progress < 1) {
@@ -157,39 +207,65 @@ const smoothMove = (newX: number, newY: number, duration = 100): void => {
157
207
  requestAnimationFrame(animate)
158
208
  }
159
209
 
210
+ const onCollapse = (): void => {
211
+ collapseData.value.isCollapsed = !collapseData.value.isCollapsed
212
+
213
+ if (collapseData.value.isCollapsed) {
214
+ collapseData.value.cashTop = topLocal.value
215
+ collapseData.value.cashLeft = leftLocal.value
216
+ collapseData.value.cashWidth = widthLocal.value
217
+ collapseData.value.cashHeight = heightLocal.value
218
+
219
+ const globalWindowWidth = window.innerWidth
220
+ const globalWindowHeight = window.innerHeight
221
+
222
+ widthLocal.value = minWidth
223
+ heightLocal.value = minHeight
224
+ leftLocal.value = globalWindowWidth - widthLocal.value - windowPadding
225
+ topLocal.value = globalWindowHeight - headerHeight
226
+ fixPosition()
227
+ } else {
228
+ leftLocal.value = collapseData.value.cashLeft
229
+ topLocal.value = collapseData.value.cashTop
230
+ widthLocal.value = collapseData.value.cashWidth
231
+ heightLocal.value = collapseData.value.cashHeight
232
+ fixPosition()
233
+ }
234
+ }
235
+
160
236
  // Функция для ресайза
161
237
  const startResize = (e: any, direction: any): void => {
162
238
  e.preventDefault()
163
239
 
164
240
  const startX = e.clientX
165
241
  const startY = e.clientY
166
- const startWidth = width.value
167
- const startHeight = height.value
168
- const startLeft = x.value
169
- const startTop = y.value
242
+ const startWidth = widthLocal.value
243
+ const startHeight = heightLocal.value
244
+ const startLeft = leftLocal.value
245
+ const startTop = topLocal.value
170
246
 
171
247
  const onMouseMove = (e: any): void => {
172
248
  const deltaX = e.clientX - startX
173
249
  const deltaY = e.clientY - startY
174
250
 
175
251
  if (direction.includes('right')) {
176
- width.value = Math.max(200, startWidth + deltaX)
252
+ widthLocal.value = Math.max(minWidth, startWidth + deltaX)
177
253
  }
178
254
  if (direction.includes('bottom')) {
179
- height.value = Math.max(150, startHeight + deltaY)
255
+ heightLocal.value = Math.max(minHeight, startHeight + deltaY)
180
256
  }
181
257
  if (direction.includes('left')) {
182
- const newWidth = Math.max(200, startWidth - deltaX)
183
- if (newWidth !== width.value) {
184
- x.value = startLeft + deltaX
185
- width.value = newWidth
258
+ const newWidth = Math.max(minWidth, startWidth - deltaX)
259
+ if (newWidth !== widthLocal.value) {
260
+ leftLocal.value = startLeft + deltaX
261
+ widthLocal.value = newWidth
186
262
  }
187
263
  }
188
264
  if (direction.includes('top')) {
189
- const newHeight = Math.max(150, startHeight - deltaY)
190
- if (newHeight !== height.value) {
191
- y.value = startTop + deltaY
192
- height.value = newHeight
265
+ const newHeight = Math.max(minHeight, startHeight - deltaY)
266
+ if (newHeight !== heightLocal.value) {
267
+ topLocal.value = startTop + deltaY
268
+ heightLocal.value = newHeight
193
269
  }
194
270
  }
195
271
  fixSize()
@@ -241,6 +317,10 @@ const onHide = (): void => {
241
317
  min-height: 200px;
242
318
  z-index: var(--z-toast);
243
319
 
320
+ &.loading {
321
+ opacity: 0.5;
322
+ }
323
+
244
324
  .window-header {
245
325
  background-color: #314351;
246
326
  color: white;
@@ -0,0 +1,4 @@
1
+ export const minWidth = 300
2
+ export const minHeight = 200
3
+ export const windowPadding = 8
4
+ export const headerHeight = 36
@@ -0,0 +1,7 @@
1
+ export interface UI_I_WindowCollapsedData {
2
+ isCollapsed: boolean
3
+ cashTop: number
4
+ cashLeft: number
5
+ cashWidth: number
6
+ cashHeight: number
7
+ }
@@ -53,7 +53,7 @@
53
53
  @submit-options="emits('submit-options', $event)"
54
54
  />
55
55
 
56
- <div v-show="!props.data" class="empty-container">
56
+ <div v-show="!props.data && !props.advancedLoading" class="empty-container">
57
57
  {{
58
58
  localization.inventoryMonitor
59
59
  .noPerformanceCurrentlySelectedMetrics
@@ -16,90 +16,92 @@
16
16
  <atoms-the-icon2 name="drag" class="vmw-drawer__drag-icon" />
17
17
  </div>
18
18
 
19
- <div class="vmw-drawer-header">
20
- <h3>{{ localization.common.consolePanel }}</h3>
21
- <atoms-the-icon
22
- class="vmw-drawer-header__close"
23
- data-id="spice-console-drawer-toggle-icon"
24
- name="close"
25
- @click="toggleDrawer"
26
- />
27
- </div>
19
+ <div class="drawer-content">
20
+ <div class="vmw-drawer-header">
21
+ <h3>{{ localization.common.consolePanel }}</h3>
22
+ <atoms-the-icon
23
+ class="vmw-drawer-header__close"
24
+ data-id="spice-console-drawer-toggle-icon"
25
+ name="close"
26
+ @click="toggleDrawer"
27
+ />
28
+ </div>
28
29
 
29
- <div class="vmw-drawer-body">
30
- <button
31
- class="vmw-drawer-body__btn animation toggle-fullscreen"
32
- data-id="spice-console-drawer-toggle-fullscreen"
33
- @click="emits('toggle-fullscreen')"
34
- >
35
- {{ localization.common.toggleFullscreenMode }}
36
- </button>
37
- <button
38
- class="vmw-drawer-body__btn animation toggle-fullscreen"
39
- @click="emits('send-alt-command')"
40
- >
41
- {{ localization.common.sendAltCommand }}
42
- </button>
43
- <label
44
- v-development="true"
45
- class="vmw-drawer-body__btn animation relative"
46
- >
47
- {{ localization.remoteConsole.uploadFolder }}
48
- <input type="file" webkitdirectory directory multiple />
49
- </label>
50
- <label
51
- v-development="true"
52
- class="vmw-drawer-body__btn animation relative"
53
- >
54
- {{ localization.remoteConsole.uploadFiles }}
55
- <input type="file" multiple />
56
- </label>
57
-
58
- <select
59
- v-model="usbDevice"
60
- v-development="true"
61
- @mouseenter="hover = true"
62
- @mouseleave="hover = false"
63
- @change="onChangeUsbDevice"
64
- >
65
- <option
66
- v-for="item in usbDevices"
67
- :key="item.value"
68
- :value="item.value"
69
- :disabled="item.disabled"
30
+ <div class="vmw-drawer-body">
31
+ <button
32
+ class="vmw-drawer-body__btn animation toggle-fullscreen"
33
+ data-id="spice-console-drawer-toggle-fullscreen"
34
+ @click="emits('toggle-fullscreen')"
70
35
  >
71
- {{ item.label }}
72
- </option>
73
- </select>
74
-
75
- <select
76
- :value="codec"
77
- @mouseenter="hover = true"
78
- @mouseleave="hover = false"
79
- @change="onChangeCodec"
80
- >
81
- <option :value="1">MJPEG</option>
82
- <option :value="2">VP8</option>
83
- <option :value="3">H264</option>
84
- <option :value="4" disabled>VP9</option>
85
- <option :value="5">H265</option>
86
- </select>
87
-
88
- <hr />
89
- <button
90
- class="vmw-drawer-body__btn animation show-keyboard"
91
- @click="onToggleKeyboard"
92
- >
93
- {{ showOrHideKeyboard }}
94
- </button>
95
- </div>
36
+ {{ localization.common.toggleFullscreenMode }}
37
+ </button>
38
+ <button
39
+ class="vmw-drawer-body__btn animation toggle-fullscreen"
40
+ @click="emits('send-alt-command')"
41
+ >
42
+ {{ localization.common.sendAltCommand }}
43
+ </button>
44
+ <label
45
+ v-development="true"
46
+ class="vmw-drawer-body__btn animation relative"
47
+ >
48
+ {{ localization.remoteConsole.uploadFolder }}
49
+ <input type="file" webkitdirectory directory multiple />
50
+ </label>
51
+ <label
52
+ v-development="true"
53
+ class="vmw-drawer-body__btn animation relative"
54
+ >
55
+ {{ localization.remoteConsole.uploadFiles }}
56
+ <input type="file" multiple />
57
+ </label>
58
+
59
+ <select
60
+ v-model="usbDevice"
61
+ v-development="true"
62
+ @mouseenter="hover = true"
63
+ @mouseleave="hover = false"
64
+ @change="onChangeUsbDevice"
65
+ >
66
+ <option
67
+ v-for="item in usbDevices"
68
+ :key="item.value"
69
+ :value="item.value"
70
+ :disabled="item.disabled"
71
+ >
72
+ {{ item.label }}
73
+ </option>
74
+ </select>
75
+
76
+ <select
77
+ :value="codec"
78
+ @mouseenter="hover = true"
79
+ @mouseleave="hover = false"
80
+ @change="onChangeCodec"
81
+ >
82
+ <option :value="1">MJPEG</option>
83
+ <option :value="2">VP8</option>
84
+ <option :value="3">H264</option>
85
+ <option :value="4" disabled>VP9</option>
86
+ <option :value="5">H265</option>
87
+ </select>
88
+
89
+ <hr />
90
+ <button
91
+ class="vmw-drawer-body__btn animation show-keyboard"
92
+ @click="onToggleKeyboard"
93
+ >
94
+ {{ showOrHideKeyboard }}
95
+ </button>
96
+ </div>
96
97
 
97
- <div class="vmw-drawer-footer">
98
- <div class="size-info">
99
- <p class="size-info-text">View size: {{ viewSize }}</p>
100
- <p class="size-info-text">Canvas size: {{ canvasSize }}</p>
98
+ <div class="vmw-drawer-footer">
99
+ <div class="size-info">
100
+ <p class="size-info-text">View size: {{ viewSize }}</p>
101
+ <p class="size-info-text">Canvas size: {{ canvasSize }}</p>
102
+ </div>
103
+ <div id="debug-stream"></div>
101
104
  </div>
102
- <div id="debug-stream"></div>
103
105
  </div>
104
106
  <div v-if="isKeyboardShown">
105
107
  <common-spice-console-keyboard />
@@ -256,7 +258,9 @@ setDefaultDevices()
256
258
  right: -300px;
257
259
  width: 300px;
258
260
  height: 100vh;
259
- padding: 20px;
261
+ display: flex;
262
+ flex-direction: column;
263
+ padding: 20px 0 20px 20px;
260
264
  z-index: var(--z-modal);
261
265
 
262
266
  &.show {
@@ -306,6 +310,10 @@ setDefaultDevices()
306
310
  }
307
311
  }
308
312
 
313
+ .drawer-content {
314
+ overflow: auto;
315
+ padding-right: 20px;
316
+ }
309
317
  .vmw-drawer-header {
310
318
  & h3 {
311
319
  color: #fff;
@@ -1,6 +1,14 @@
1
1
  <template>
2
2
  <div ref="fullScreen" class="spice-console">
3
3
  <div id="vmw" ref="vmScreen" @scroll="onConsoleScroll"></div>
4
+ <div
5
+ v-if="isWindow"
6
+ v-show="isShowBlocker"
7
+ class="blocker"
8
+ @click="onFocus"
9
+ >
10
+ <p class="blocker-text">{{ localization.remoteConsole.clickForUse }}</p>
11
+ </div>
4
12
  <common-spice-console-drawer
5
13
  @toggle-fullscreen="toggle"
6
14
  @send-alt-command="onSendAltCommand"
@@ -11,6 +19,7 @@
11
19
  import { useFullscreen } from '@vueuse/core'
12
20
  import RFB from '@novnc/novnc/core/rfb.js'
13
21
  import SpiceConsole from '~/plugins/spice-console/spice.console'
22
+ import type { UI_I_Localization } from '~/lib/models/interfaces'
14
23
 
15
24
  const props = defineProps<{
16
25
  wsUrl: string
@@ -20,6 +29,8 @@ const props = defineProps<{
20
29
  port: number
21
30
  }>()
22
31
 
32
+ const localization = computed<UI_I_Localization>(() => useLocal())
33
+
23
34
  let rfb: any
24
35
  const vmScreen = ref<any>(null)
25
36
  const fullScreen = ref<any>(null)
@@ -100,14 +111,28 @@ const blockCtrlOrCmdCommands = (e): void => {
100
111
  // return false;
101
112
  // }
102
113
  }
114
+
115
+ const isWindow = computed<boolean>(() => useRoute().query.window === 'true')
116
+ const isShowBlocker = ref<boolean>(true)
117
+ const onFocus = (): void => {
118
+ document.getElementById('inputmanager')?.focus()
119
+ isShowBlocker.value = false
120
+ }
121
+
122
+ const inputManagerBlur = (): void => {
123
+ isShowBlocker.value = true
124
+ }
125
+
103
126
  onMounted(() => {
104
127
  connectWS()
105
128
  document.addEventListener('keydown', blockCtrlOrCmdCommands)
129
+ window.addEventListener('blur', inputManagerBlur)
106
130
  })
107
131
 
108
132
  onBeforeUnmount(() => {
109
133
  vmDisconnect()
110
134
  document.removeEventListener('keydown', blockCtrlOrCmdCommands)
135
+ window.removeEventListener('blur', inputManagerBlur)
111
136
  })
112
137
  </script>
113
138
  <style scoped lang="scss">
@@ -124,4 +149,20 @@ onBeforeUnmount(() => {
124
149
  height: 100vh;
125
150
  background-color: #000;
126
151
  }
152
+ .blocker {
153
+ position: fixed;
154
+ top: 0;
155
+ left: 0;
156
+ width: 100%;
157
+ height: 100%;
158
+ display: flex;
159
+ justify-content: center;
160
+ align-items: center;
161
+ background-color: rgba(0, 0, 0, 0.5);
162
+ z-index: 9999;
163
+
164
+ .blocker-text {
165
+ color: #e4e4e4;
166
+ }
167
+ }
127
168
  </style>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bfg-common",
3
3
  "private": false,
4
- "version": "1.5.452",
4
+ "version": "1.5.453",
5
5
  "scripts": {
6
6
  "build": "nuxt build",
7
7
  "dev": "nuxt dev --port=3002",