vgapp 1.5.8 → 1.6.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/app/modules/module-fn.js +1 -1
- package/app/modules/vgalert/js/vgalert.js +7 -4
- package/app/modules/vgalert/scss/vgalert.scss +13 -6
- package/app/modules/vgnav/js/vgnav.js +317 -36
- package/app/modules/vgnav/scss/vgnav.scss +35 -0
- package/app/modules/vgtable/scss/_fixed-columns.scss +23 -25
- package/app/modules/vgtooltip/js/vgtooltip.js +27 -17
- package/app/modules/vgtooltip/scss/_variables.scss +2 -2
- package/app/modules/vgtooltip/scss/vgtooltip.scss +25 -4
- package/app/utils/js/dom/event.js +25 -23
- package/build/vgapp.css +1 -1
- package/build/vgapp.css.map +1 -1
- package/build/vgapp.js +1 -1
- package/build/vgapp.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Описание: всплывающие подсказки и информационные popover VGApp.
|
|
3
|
-
* Возможности: Data API,
|
|
3
|
+
* Возможности: Data API, подавление нативного title, позиционирование со стрелкой без зазоров и очистка при удалении триггера.
|
|
4
4
|
*/
|
|
5
5
|
import BaseModule from "../../base-module";
|
|
6
6
|
import {isDisabled, makeRandomString, mergeDeepObject} from "../../../utils/js/functions";
|
|
@@ -94,7 +94,8 @@ class VGTooltip extends BaseModule {
|
|
|
94
94
|
this._isHiding = false;
|
|
95
95
|
this._showTimeout = null;
|
|
96
96
|
this._hideTimeout = null;
|
|
97
|
-
this._triggerObserver = null;
|
|
97
|
+
this._triggerObserver = null;
|
|
98
|
+
this._titleSuppressed = false;
|
|
98
99
|
|
|
99
100
|
this._fixTitle();
|
|
100
101
|
|
|
@@ -122,10 +123,15 @@ class VGTooltip extends BaseModule {
|
|
|
122
123
|
return this._isShown() ? this.hide() : this.show(relatedTarget);
|
|
123
124
|
}
|
|
124
125
|
|
|
125
|
-
show(relatedTarget) {
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
this.
|
|
126
|
+
show(relatedTarget) {
|
|
127
|
+
if (!this._element || isDisabled(this._element)) return;
|
|
128
|
+
|
|
129
|
+
this._fixTitle();
|
|
130
|
+
this._clearTimeouts();
|
|
131
|
+
if (this._isShown()) {
|
|
132
|
+
if (!this._isHiding) this._observeTrigger();
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
129
135
|
|
|
130
136
|
this._showTimeout = setTimeout(() => {
|
|
131
137
|
this._showTimeout = null;
|
|
@@ -226,7 +232,9 @@ class VGTooltip extends BaseModule {
|
|
|
226
232
|
|
|
227
233
|
if (Object.prototype.hasOwnProperty.call(this._element.dataset, 'vgOriginalTitle')) {
|
|
228
234
|
this._element.setAttribute('title', this._element.dataset.vgOriginalTitle);
|
|
229
|
-
this._element.removeAttribute('data-vg-original-title');
|
|
235
|
+
this._element.removeAttribute('data-vg-original-title');
|
|
236
|
+
} else {
|
|
237
|
+
this._element.removeAttribute('title');
|
|
230
238
|
}
|
|
231
239
|
}
|
|
232
240
|
|
|
@@ -319,10 +327,12 @@ class VGTooltip extends BaseModule {
|
|
|
319
327
|
_fixTitle() {
|
|
320
328
|
const title = this._element.getAttribute('title');
|
|
321
329
|
|
|
322
|
-
if (title
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
330
|
+
if (title !== null && (title !== '' || !this._titleSuppressed)) {
|
|
331
|
+
this._element.setAttribute('data-vg-original-title', title);
|
|
332
|
+
}
|
|
333
|
+
// Пустой title также блокирует нативную подсказку, унаследованную от предка.
|
|
334
|
+
this._element.setAttribute('title', '');
|
|
335
|
+
this._titleSuppressed = true;
|
|
326
336
|
}
|
|
327
337
|
|
|
328
338
|
_setPlacement() {
|
|
@@ -378,12 +388,12 @@ class VGTooltip extends BaseModule {
|
|
|
378
388
|
);
|
|
379
389
|
|
|
380
390
|
arrow.style.left = `${arrowLeft}px`;
|
|
381
|
-
arrow.style.transform = 'translateX(-50%)
|
|
391
|
+
arrow.style.transform = 'translateX(-50%)';
|
|
382
392
|
|
|
383
393
|
if (placement.startsWith('top')) {
|
|
384
|
-
arrow.style.bottom = '-
|
|
394
|
+
arrow.style.bottom = 'calc(var(--vg-tooltip-arrow-height) / -2 + 1px)';
|
|
385
395
|
} else {
|
|
386
|
-
arrow.style.top = '-
|
|
396
|
+
arrow.style.top = 'calc(var(--vg-tooltip-arrow-height) / -2 + 1px)';
|
|
387
397
|
}
|
|
388
398
|
}
|
|
389
399
|
|
|
@@ -396,12 +406,12 @@ class VGTooltip extends BaseModule {
|
|
|
396
406
|
);
|
|
397
407
|
|
|
398
408
|
arrow.style.top = `${arrowTop}px`;
|
|
399
|
-
arrow.style.transform = 'translateY(-50%)
|
|
409
|
+
arrow.style.transform = 'translateY(-50%)';
|
|
400
410
|
|
|
401
411
|
if (placement.startsWith('left')) {
|
|
402
|
-
arrow.style.right = '-
|
|
412
|
+
arrow.style.right = 'calc(var(--vg-tooltip-arrow-width) / -2 + 1px)';
|
|
403
413
|
} else {
|
|
404
|
-
arrow.style.left = '-
|
|
414
|
+
arrow.style.left = 'calc(var(--vg-tooltip-arrow-width) / -2 + 1px)';
|
|
405
415
|
}
|
|
406
416
|
}
|
|
407
417
|
}
|
|
@@ -11,7 +11,7 @@ $tooltip-map: (
|
|
|
11
11
|
border-radius: 6px,
|
|
12
12
|
box-shadow: 0 6px 20px var(--vg-shadow-soft-color, rgba(0, 0, 0, .18)),
|
|
13
13
|
word-break: break-word,
|
|
14
|
-
arrow-width:
|
|
15
|
-
arrow-height:
|
|
14
|
+
arrow-width: 10px,
|
|
15
|
+
arrow-height: 10px,
|
|
16
16
|
border-color: var(--vg-border-color, #{vg.$border-color}),
|
|
17
17
|
) !default;
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
|
|
13
13
|
.vg-tooltip {
|
|
14
14
|
@include vg.mix-vars('tooltip', vars.$tooltip-map);
|
|
15
|
-
position: absolute;
|
|
15
|
+
position: absolute;
|
|
16
|
+
// Координатами управляет Placement; общие data-vg-placement правила не должны задавать противоположный край.
|
|
17
|
+
inset: auto;
|
|
16
18
|
z-index: var(--vg-tooltip-zindex);
|
|
17
19
|
pointer-events: none;
|
|
18
20
|
opacity: 0;
|
|
@@ -42,9 +44,28 @@
|
|
|
42
44
|
position: absolute;
|
|
43
45
|
width: var(--vg-tooltip-arrow-width);
|
|
44
46
|
height: var(--vg-tooltip-arrow-height);
|
|
45
|
-
background: var(--vg-tooltip-background, #222);
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
background: var(--vg-tooltip-background, #222);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&[data-vg-placement^="top"] &-arrow {
|
|
51
|
+
height: calc(var(--vg-tooltip-arrow-height) / 2);
|
|
52
|
+
clip-path: polygon(0 0, 100% 0, 50% 100%);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&[data-vg-placement^="bottom"] &-arrow {
|
|
56
|
+
height: calc(var(--vg-tooltip-arrow-height) / 2);
|
|
57
|
+
clip-path: polygon(50% 0, 100% 100%, 0 100%);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&[data-vg-placement^="left"] &-arrow {
|
|
61
|
+
width: calc(var(--vg-tooltip-arrow-width) / 2);
|
|
62
|
+
clip-path: polygon(0 0, 100% 50%, 0 100%);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&[data-vg-placement^="right"] &-arrow {
|
|
66
|
+
width: calc(var(--vg-tooltip-arrow-width) / 2);
|
|
67
|
+
clip-path: polygon(100% 0, 100% 100%, 0 50%);
|
|
68
|
+
}
|
|
48
69
|
|
|
49
70
|
&-popover {
|
|
50
71
|
.vg-tooltip-inner {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Описание: управление DOM-событиями VGApp.
|
|
3
|
+
* Возможности: делегирование, пространства имён, одноразовые подписки и границы mouseenter/mouseleave.
|
|
2
4
|
* --------------------------------------------------------------------------
|
|
3
5
|
* Bootstrap event.js (рефакторинг)
|
|
4
6
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
@@ -79,9 +81,10 @@ const getElementEvents = (element) => {
|
|
|
79
81
|
* @param {boolean} isOneOff
|
|
80
82
|
* @returns {Function}
|
|
81
83
|
*/
|
|
82
|
-
const createHandler = (element, fn, isOneOff) => {
|
|
83
|
-
const handler = function (event) {
|
|
84
|
-
hydrateObj(event, { delegateTarget: element });
|
|
84
|
+
const createHandler = (element, fn, isOneOff, checkRelatedTarget) => {
|
|
85
|
+
const handler = function (event) {
|
|
86
|
+
hydrateObj(event, { delegateTarget: element });
|
|
87
|
+
if (checkRelatedTarget && isRelatedTargetInside(event)) return;
|
|
85
88
|
|
|
86
89
|
if (isOneOff) {
|
|
87
90
|
EventHandler.off(element, event.type, fn);
|
|
@@ -106,13 +109,14 @@ const createHandler = (element, fn, isOneOff) => {
|
|
|
106
109
|
* @param {boolean} isOneOff
|
|
107
110
|
* @returns {Function}
|
|
108
111
|
*/
|
|
109
|
-
const createDelegatedHandler = (element, selector, fn, isOneOff) => {
|
|
112
|
+
const createDelegatedHandler = (element, selector, fn, isOneOff, checkRelatedTarget) => {
|
|
110
113
|
const handler = function (event) {
|
|
111
114
|
const candidates = Array.from(element.querySelectorAll(selector));
|
|
112
115
|
for (let target = event.target; target && target !== element; target = target.parentNode) {
|
|
113
116
|
if (!candidates.includes(target)) continue;
|
|
114
117
|
|
|
115
|
-
hydrateObj(event, { delegateTarget: target });
|
|
118
|
+
hydrateObj(event, { delegateTarget: target });
|
|
119
|
+
if (checkRelatedTarget && isRelatedTargetInside(event)) return;
|
|
116
120
|
|
|
117
121
|
if (isOneOff) {
|
|
118
122
|
EventHandler.off(element, event.type, selector, fn);
|
|
@@ -131,19 +135,16 @@ const createDelegatedHandler = (element, selector, fn, isOneOff) => {
|
|
|
131
135
|
};
|
|
132
136
|
|
|
133
137
|
/**
|
|
134
|
-
*
|
|
135
|
-
* @param {
|
|
136
|
-
* @returns {
|
|
137
|
-
*/
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return fn.call(this, event);
|
|
145
|
-
}
|
|
146
|
-
};
|
|
138
|
+
* Проверяет переход внутри одного триггера mouseenter/mouseleave.
|
|
139
|
+
* @param {Event} event
|
|
140
|
+
* @returns {boolean}
|
|
141
|
+
*/
|
|
142
|
+
const isRelatedTargetInside = (event) => {
|
|
143
|
+
const relatedTarget = event.relatedTarget;
|
|
144
|
+
return !!relatedTarget && (
|
|
145
|
+
relatedTarget === event.delegateTarget ||
|
|
146
|
+
(relatedTarget.nodeType && event.delegateTarget.contains(relatedTarget))
|
|
147
|
+
);
|
|
147
148
|
};
|
|
148
149
|
|
|
149
150
|
/**
|
|
@@ -193,9 +194,10 @@ const addHandler = (element, originalTypeEvent, handler, delegationFunction, one
|
|
|
193
194
|
return;
|
|
194
195
|
}
|
|
195
196
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
const checkRelatedTarget = Boolean(customEvents[originalTypeEvent.replace(STRIP_NAME_REGEX, '')]);
|
|
198
|
+
let fn = isDelegated
|
|
199
|
+
? createDelegatedHandler(element, handler, callable, oneOff, checkRelatedTarget)
|
|
200
|
+
: createHandler(element, callable, oneOff, checkRelatedTarget);
|
|
199
201
|
|
|
200
202
|
const uid = makeEventUid(fn, originalTypeEvent.replace(NAMESPACE_REGEX, ''));
|
|
201
203
|
fn.uidEvent = uid;
|
|
@@ -362,4 +364,4 @@ const EventHandler = {
|
|
|
362
364
|
}
|
|
363
365
|
};
|
|
364
366
|
|
|
365
|
-
export default EventHandler;
|
|
367
|
+
export default EventHandler;
|