uikit 3.14.4-dev.3a6c538ab → 3.14.4-dev.5e7e87ba7

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.
Files changed (114) hide show
  1. package/CHANGELOG.md +27 -17
  2. package/build/util.js +1 -0
  3. package/dist/css/uikit-core-rtl.css +271 -61
  4. package/dist/css/uikit-core-rtl.min.css +1 -1
  5. package/dist/css/uikit-core.css +271 -61
  6. package/dist/css/uikit-core.min.css +1 -1
  7. package/dist/css/uikit-rtl.css +291 -65
  8. package/dist/css/uikit-rtl.min.css +1 -1
  9. package/dist/css/uikit.css +291 -65
  10. package/dist/css/uikit.min.css +1 -1
  11. package/dist/js/components/countdown.js +1 -1
  12. package/dist/js/components/countdown.min.js +1 -1
  13. package/dist/js/components/filter.js +1 -1
  14. package/dist/js/components/filter.min.js +1 -1
  15. package/dist/js/components/lightbox-panel.js +69 -114
  16. package/dist/js/components/lightbox-panel.min.js +1 -1
  17. package/dist/js/components/lightbox.js +69 -114
  18. package/dist/js/components/lightbox.min.js +1 -1
  19. package/dist/js/components/notification.js +1 -1
  20. package/dist/js/components/notification.min.js +1 -1
  21. package/dist/js/components/parallax.js +1 -1
  22. package/dist/js/components/parallax.min.js +1 -1
  23. package/dist/js/components/slider-parallax.js +1 -1
  24. package/dist/js/components/slider-parallax.min.js +1 -1
  25. package/dist/js/components/slider.js +1 -1
  26. package/dist/js/components/slider.min.js +1 -1
  27. package/dist/js/components/slideshow-parallax.js +1 -1
  28. package/dist/js/components/slideshow-parallax.min.js +1 -1
  29. package/dist/js/components/slideshow.js +1 -1
  30. package/dist/js/components/slideshow.min.js +1 -1
  31. package/dist/js/components/sortable.js +1 -1
  32. package/dist/js/components/sortable.min.js +1 -1
  33. package/dist/js/components/tooltip.js +85 -131
  34. package/dist/js/components/tooltip.min.js +1 -1
  35. package/dist/js/components/upload.js +1 -1
  36. package/dist/js/components/upload.min.js +1 -1
  37. package/dist/js/uikit-core.js +339 -339
  38. package/dist/js/uikit-core.min.js +14 -1
  39. package/dist/js/uikit-icons.js +1 -1
  40. package/dist/js/uikit-icons.min.js +1 -1
  41. package/dist/js/uikit.js +339 -339
  42. package/dist/js/uikit.min.js +14 -1
  43. package/package.json +1 -1
  44. package/src/images/components/navbar-toggle-icon.svg +22 -3
  45. package/src/js/api/state.js +1 -1
  46. package/src/js/core/accordion.js +9 -17
  47. package/src/js/core/alert.js +35 -14
  48. package/src/js/core/drop.js +90 -61
  49. package/src/js/core/height-viewport.js +4 -2
  50. package/src/js/core/navbar.js +28 -45
  51. package/src/js/core/scroll.js +37 -10
  52. package/src/js/mixin/position.js +18 -20
  53. package/src/js/mixin/togglable.js +80 -124
  54. package/src/js/util/animation.js +4 -3
  55. package/src/js/util/filter.js +3 -7
  56. package/src/js/util/position.js +42 -47
  57. package/src/js/util/viewport.js +3 -5
  58. package/src/less/components/_import.less +1 -0
  59. package/src/less/components/drop.less +1 -18
  60. package/src/less/components/dropbar.less +115 -0
  61. package/src/less/components/dropdown.less +6 -20
  62. package/src/less/components/nav.less +211 -22
  63. package/src/less/components/navbar.less +10 -52
  64. package/src/less/theme/_import.less +1 -0
  65. package/src/less/theme/dropbar.less +44 -0
  66. package/src/less/theme/dropdown.less +0 -11
  67. package/src/less/theme/nav.less +46 -0
  68. package/src/less/theme/navbar.less +1 -5
  69. package/src/scss/components/_import.scss +1 -0
  70. package/src/scss/components/drop.scss +1 -18
  71. package/src/scss/components/dropbar.scss +115 -0
  72. package/src/scss/components/dropdown.scss +6 -20
  73. package/src/scss/components/nav.scss +160 -21
  74. package/src/scss/components/navbar.scss +10 -52
  75. package/src/scss/mixins-theme.scss +78 -7
  76. package/src/scss/mixins.scss +75 -3
  77. package/src/scss/theme/_import.scss +1 -0
  78. package/src/scss/theme/dropbar.scss +44 -0
  79. package/src/scss/theme/dropdown.scss +0 -8
  80. package/src/scss/theme/nav.scss +44 -0
  81. package/src/scss/theme/navbar.scss +1 -5
  82. package/src/scss/variables-theme.scss +50 -9
  83. package/src/scss/variables.scss +39 -7
  84. package/tests/accordion.html +2 -2
  85. package/tests/alert.html +2 -2
  86. package/tests/countdown.html +1 -1
  87. package/tests/drop.html +444 -412
  88. package/tests/dropbar.html +456 -0
  89. package/tests/dropdown.html +8 -470
  90. package/tests/filter.html +9 -12
  91. package/tests/form.html +1 -1
  92. package/tests/index.html +124 -105
  93. package/tests/lightbox.html +5 -5
  94. package/tests/list.html +8 -8
  95. package/tests/modal.html +13 -13
  96. package/tests/nav.html +121 -12
  97. package/tests/navbar.html +76 -212
  98. package/tests/offcanvas.html +10 -14
  99. package/tests/parallax.html +1 -1
  100. package/tests/position.html +13 -24
  101. package/tests/progress.html +9 -9
  102. package/tests/scroll.html +7 -10
  103. package/tests/search.html +5 -5
  104. package/tests/slider.html +6 -5
  105. package/tests/slideshow.html +8 -8
  106. package/tests/sortable.html +6 -8
  107. package/tests/sticky-navbar.html +6 -6
  108. package/tests/sticky.html +8 -8
  109. package/tests/switcher.html +1 -1
  110. package/tests/tab.html +1 -1
  111. package/tests/table.html +7 -7
  112. package/tests/toggle.html +2 -2
  113. package/tests/tooltip.html +1 -1
  114. package/tests/upload.html +11 -11
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "uikit",
3
3
  "title": "UIkit",
4
4
  "description": "UIkit is a lightweight and modular front-end framework for developing fast and powerful web interfaces.",
5
- "version": "3.14.4-dev.3a6c538ab",
5
+ "version": "3.14.4-dev.5e7e87ba7",
6
6
  "main": "dist/js/uikit.js",
7
7
  "style": "dist/css/uikit.css",
8
8
  "sideEffects": [
@@ -1,5 +1,24 @@
1
1
  <svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
2
- <rect y="9" width="20" height="2" />
3
- <rect y="3" width="20" height="2" />
4
- <rect y="15" width="20" height="2" />
2
+ <style>
3
+
4
+ .uk-navbar-toggle svg > [class*='line-'] {
5
+ transition: 0.2s ease-in-out;
6
+ transition-property: transform, opacity,;
7
+ transform-origin: center;
8
+ opacity: 1;
9
+ }
10
+
11
+ .uk-navbar-toggle[aria-expanded="true"] svg > .line-2 { transform: rotate(45deg); }
12
+ .uk-navbar-toggle[aria-expanded="true"] svg > .line-3 { transform: rotate(-45deg); }
13
+
14
+ .uk-navbar-toggle[aria-expanded="true"] svg > .line-1,
15
+ .uk-navbar-toggle[aria-expanded="true"] svg > .line-4 { opacity: 0; }
16
+ .uk-navbar-toggle[aria-expanded="true"] svg > .line-1 { transform: translateY(6px) scaleX(0); }
17
+ .uk-navbar-toggle[aria-expanded="true"] svg > .line-4 { transform: translateY(-6px) scaleX(0); }
18
+
19
+ </style>
20
+ <rect class="line-1" y="3" width="20" height="2" />
21
+ <rect class="line-2" y="9" width="20" height="2" />
22
+ <rect class="line-3" y="9" width="20" height="2" />
23
+ <rect class="line-4" y="15" width="20" height="2" />
5
24
  </svg>
@@ -142,7 +142,7 @@ function getProps(opts, name) {
142
142
 
143
143
  value = props[key] === Boolean && value === '' ? true : coerce(props[key], value);
144
144
 
145
- if (prop === 'target' && (!value || startsWith(value, '_'))) {
145
+ if (prop === 'target' && startsWith(value, '_')) {
146
146
  continue;
147
147
  }
148
148
 
@@ -1,6 +1,6 @@
1
1
  import Class from '../mixin/class';
2
2
  import Lazyload from '../mixin/lazyload';
3
- import { slide, default as Togglable } from '../mixin/togglable';
3
+ import { default as Togglable, toggleTransition } from '../mixin/togglable';
4
4
  import {
5
5
  $,
6
6
  $$,
@@ -14,14 +14,14 @@ import {
14
14
  isInView,
15
15
  scrollIntoView,
16
16
  toggleClass,
17
- unwrap,
18
- wrapAll,
17
+ within,
19
18
  } from 'uikit-util';
20
19
 
21
20
  export default {
22
21
  mixins: [Class, Lazyload, Togglable],
23
22
 
24
23
  props: {
24
+ animation: Boolean,
25
25
  targets: String,
26
26
  active: null,
27
27
  collapsible: Boolean,
@@ -34,7 +34,7 @@ export default {
34
34
  data: {
35
35
  targets: '> *',
36
36
  active: false,
37
- animation: ['slide'],
37
+ animation: true,
38
38
  collapsible: true,
39
39
  multiple: false,
40
40
  clsOpen: 'uk-open',
@@ -80,7 +80,7 @@ export default {
80
80
  hide(
81
81
  el,
82
82
  !hasClass(
83
- this.items.find((item) => item.contains(el)),
83
+ this.items.find((item) => within(el, item)),
84
84
  this.clsOpen
85
85
  )
86
86
  );
@@ -132,23 +132,15 @@ export default {
132
132
  toggleClass(el, this.clsOpen, show);
133
133
  attr($(this.$props.toggle, el), 'aria-expanded', show);
134
134
 
135
- const content = $(`${el._wrapper ? '> * ' : ''}${this.content}`, el);
135
+ const content = $(this.content, el);
136
136
 
137
- if (animate === false || !this.hasTransition) {
137
+ if (animate === false || !this.animation) {
138
+ content.hidden = !show;
138
139
  hide(content, !show);
139
140
  return;
140
141
  }
141
142
 
142
- if (!el._wrapper) {
143
- el._wrapper = wrapAll(content, `<div${show ? ' hidden' : ''}>`);
144
- }
145
-
146
- hide(content, false);
147
- await slide(this)(el._wrapper, show);
148
- hide(content, !show);
149
-
150
- delete el._wrapper;
151
- unwrap(content);
143
+ await toggleTransition(this)(content, show);
152
144
 
153
145
  if (show) {
154
146
  const toggle = $(this.$props.toggle, el);
@@ -1,5 +1,6 @@
1
1
  import Class from '../mixin/class';
2
2
  import Togglable from '../mixin/togglable';
3
+ import { css, toFloat, Transition } from 'uikit-util';
3
4
 
4
5
  export default {
5
6
  mixins: [Class, Togglable],
@@ -7,35 +8,55 @@ export default {
7
8
  args: 'animation',
8
9
 
9
10
  props: {
11
+ animation: Boolean,
10
12
  close: String,
11
13
  },
12
14
 
13
15
  data: {
14
- animation: ['slide'],
16
+ animation: true,
15
17
  selClose: '.uk-alert-close',
16
18
  duration: 150,
17
- hideProps: { opacity: 0, ...Togglable.data.hideProps },
18
19
  },
19
20
 
20
- events: [
21
- {
22
- name: 'click',
21
+ events: {
22
+ name: 'click',
23
23
 
24
- delegate() {
25
- return this.selClose;
26
- },
24
+ delegate() {
25
+ return this.selClose;
26
+ },
27
27
 
28
- handler(e) {
29
- e.preventDefault();
30
- this.close();
31
- },
28
+ handler(e) {
29
+ e.preventDefault();
30
+ this.close();
32
31
  },
33
- ],
32
+ },
34
33
 
35
34
  methods: {
36
35
  async close() {
37
- await this.toggleElement(this.$el);
36
+ await this.toggleElement(this.$el, false, animate(this));
38
37
  this.$destroy(true);
39
38
  },
40
39
  },
41
40
  };
41
+
42
+ function animate({ duration, transition, velocity }) {
43
+ return (el) => {
44
+ const height = toFloat(css(el, 'height'));
45
+ css(el, 'height', height);
46
+ return Transition.start(
47
+ el,
48
+ {
49
+ height: 0,
50
+ marginTop: 0,
51
+ marginBottom: 0,
52
+ paddingTop: 0,
53
+ paddingBottom: 0,
54
+ borderTop: 0,
55
+ borderBottom: 0,
56
+ opacity: 0,
57
+ },
58
+ velocity * height + duration,
59
+ transition
60
+ );
61
+ };
62
+ }
@@ -27,7 +27,6 @@ import {
27
27
  query,
28
28
  removeClass,
29
29
  scrollParents,
30
- toggleClass,
31
30
  within,
32
31
  } from 'uikit-util';
33
32
  import { preventBackgroundScroll, preventOverscroll } from '../mixin/modal';
@@ -43,7 +42,10 @@ export default {
43
42
  mode: 'list',
44
43
  toggle: Boolean,
45
44
  boundary: Boolean,
46
- boundaryAlign: Boolean,
45
+ target: Boolean,
46
+ targetX: Boolean,
47
+ targetY: Boolean,
48
+ stretch: Boolean,
47
49
  delayShow: Number,
48
50
  delayHide: Number,
49
51
  display: String,
@@ -55,17 +57,32 @@ export default {
55
57
  data: {
56
58
  mode: ['click', 'hover'],
57
59
  toggle: '- *',
58
- boundary: true,
59
- boundaryAlign: false,
60
+ boundary: false,
61
+ target: false,
62
+ targetX: false,
63
+ targetY: false,
64
+ stretch: false,
60
65
  delayShow: 0,
61
66
  delayHide: 800,
62
67
  display: null,
63
68
  clsDrop: false,
69
+ animateOut: false,
70
+ bgScroll: true,
64
71
  animation: ['uk-animation-fade'],
65
72
  cls: 'uk-open',
66
73
  container: false,
67
- animateOut: false,
68
- bgScroll: true,
74
+ },
75
+
76
+ computed: {
77
+ target({ target, targetX, targetY }, $el) {
78
+ targetX = targetX || target || this.targetEl;
79
+ targetY = targetY || target || this.targetEl;
80
+
81
+ return [
82
+ targetX === true ? window : query(targetX, $el),
83
+ targetY === true ? window : query(targetY, $el),
84
+ ];
85
+ },
69
86
  },
70
87
 
71
88
  created() {
@@ -79,13 +96,13 @@ export default {
79
96
  connected() {
80
97
  addClass(this.$el, this.clsDrop);
81
98
 
82
- if (this.toggle && !this.target) {
83
- this.target = this.$create('toggle', query(this.toggle, this.$el), {
99
+ if (this.toggle && !this.targetEl) {
100
+ this.targetEl = this.$create('toggle', query(this.toggle, this.$el), {
84
101
  target: this.$el,
85
102
  mode: this.mode,
86
103
  }).$el;
87
- attr(this.target, 'aria-haspopup', true);
88
- this.lazyload(this.target);
104
+ attr(this.targetEl, 'aria-haspopup', true);
105
+ this.lazyload(this.targetEl);
89
106
  }
90
107
  },
91
108
 
@@ -238,7 +255,7 @@ export default {
238
255
  !defaultPrevented &&
239
256
  type === pointerUp &&
240
257
  target === newTarget &&
241
- !(this.target && within(target, this.target))
258
+ !(this.targetEl && within(target, this.targetEl))
242
259
  ) {
243
260
  this.hide(false);
244
261
  }
@@ -257,13 +274,13 @@ export default {
257
274
  ? []
258
275
  : [preventOverscroll(this.$el), preventBackgroundScroll()]),
259
276
 
260
- ...(this.display === 'static' && this.align !== 'stretch'
277
+ ...(this.display === 'static'
261
278
  ? []
262
279
  : (() => {
263
280
  const handler = () => this.$emit();
264
281
  return [
265
282
  on(window, 'resize', handler),
266
- on(document, 'scroll', handler, true),
283
+ on([document, scrollParents(this.$el)], 'scroll', handler),
267
284
  (() => {
268
285
  const observer = observeResize(
269
286
  scrollParents(this.$el),
@@ -316,12 +333,12 @@ export default {
316
333
  },
317
334
 
318
335
  methods: {
319
- show(target = this.target, delay = true) {
320
- if (this.isToggled() && target && this.target && target !== this.target) {
336
+ show(target = this.targetEl, delay = true) {
337
+ if (this.isToggled() && target && this.targetEl && target !== this.targetEl) {
321
338
  this.hide(false, false);
322
339
  }
323
340
 
324
- this.target = target;
341
+ this.targetEl = target;
325
342
 
326
343
  this.clearTimers();
327
344
 
@@ -384,60 +401,72 @@ export default {
384
401
 
385
402
  position() {
386
403
  removeClass(this.$el, `${this.clsDrop}-stack`);
387
- toggleClass(this.$el, `${this.clsDrop}-boundary`, this.boundaryAlign);
388
- toggleClass(this.$el, `${this.clsDrop}-stretch`, this.align === 'stretch');
404
+ css(this.$el, { maxWidth: '', top: '', left: '' });
405
+
406
+ // Ensure none positioned element does not generate scrollbars
407
+ this.$el.hidden = true;
389
408
 
390
409
  const boundary = query(this.boundary, this.$el);
391
- const target = boundary && this.boundaryAlign ? boundary : this.target;
392
- const [scrollParent] = scrollParents(
393
- boundary && this.boundaryAlign ? boundary : this.$el
394
- );
395
- const scrollParentOffset = offset(scrollParent);
396
- const boundaryOffset = boundary ? offset(boundary) : scrollParentOffset;
410
+ const boundaryOffset = offsetViewport(boundary || window);
411
+ const viewports = this.target.map((target) => offsetViewport(scrollParents(target)[0]));
397
412
  const viewportOffset = this.getViewportOffset(this.$el);
398
413
 
399
- css(this.$el, 'maxWidth', '');
400
- const maxWidth = scrollParentOffset.width - 2 * viewportOffset;
401
-
402
- if (this.align === 'justify') {
403
- const prop = this.axis === 'y' ? 'width' : 'height';
404
- css(
405
- this.$el,
406
- prop,
407
- Math.min(
408
- (boundary ? boundaryOffset : offset(this.target))[prop],
409
- scrollParentOffset[prop] - 2 * viewportOffset
410
- )
411
- );
412
- } else if (this.align === 'stretch') {
413
- this.flip = this.axis === 'y' ? 'x' : 'y';
414
- this.display = 'static';
415
-
416
- const viewport = offsetViewport(scrollParent);
417
- const targetDim = offset(target);
418
- const elOffset = Math.abs(this.getPositionOffset(this.$el)) + viewportOffset;
419
-
420
- css(this.$el, {
421
- width:
422
- this.axis === 'y'
423
- ? viewport.width
424
- : (this.dir === 'left'
425
- ? targetDim.left - viewport.left
426
- : viewport.right - targetDim.right) - elOffset,
427
- height:
428
- this.axis === 'x'
429
- ? viewport.height
430
- : (this.dir === 'top'
431
- ? targetDim.top - viewport.top
432
- : viewport.bottom - targetDim.bottom) - elOffset,
433
- });
434
- } else if (this.$el.offsetWidth > maxWidth) {
414
+ const dirs = [
415
+ [0, ['x', 'width', 'left', 'right']],
416
+ [1, ['y', 'height', 'top', 'bottom']],
417
+ ];
418
+
419
+ for (const [i, [axis, prop]] of dirs) {
420
+ if (includes([axis, true], this.stretch)) {
421
+ css(this.$el, {
422
+ [prop]:
423
+ this.axis === axis
424
+ ? '' // Reset prop in main axis before positioning to not cause the drop to flip prematurely
425
+ : Math.min(
426
+ boundaryOffset[prop],
427
+ viewports[i][prop] - 2 * viewportOffset
428
+ ),
429
+ [`overflow-${axis}`]: 'auto',
430
+ });
431
+ }
432
+ }
433
+
434
+ const maxWidth = viewports[0].width - 2 * viewportOffset;
435
+
436
+ if (this.$el.offsetWidth > maxWidth) {
435
437
  addClass(this.$el, `${this.clsDrop}-stack`);
436
438
  }
437
439
 
438
440
  css(this.$el, 'maxWidth', maxWidth);
439
441
 
440
- this.positionAt(this.$el, target, boundary);
442
+ this.$el.hidden = false;
443
+
444
+ this.positionAt(this.$el, this.target, boundary);
445
+
446
+ for (const [i, [axis, prop, start, end]] of dirs) {
447
+ if (this.axis === axis && includes([axis, true], this.stretch)) {
448
+ const positionOffset = Math.abs(this.getPositionOffset(this.$el));
449
+ const targetOffset = offset(this.target[i]);
450
+ const elOffset = offset(this.$el);
451
+
452
+ css(this.$el, {
453
+ [prop]:
454
+ (targetOffset[start] > elOffset[start]
455
+ ? targetOffset[start] -
456
+ Math.max(
457
+ boundaryOffset[start],
458
+ viewports[i][start] + viewportOffset
459
+ )
460
+ : Math.min(
461
+ boundaryOffset[end],
462
+ viewports[i][end] - viewportOffset
463
+ ) - targetOffset[end]) - positionOffset,
464
+ [`overflow-${axis}`]: 'auto',
465
+ });
466
+
467
+ this.positionAt(this.$el, this.target, boundary);
468
+ }
469
+ }
441
470
  },
442
471
  },
443
472
  };
@@ -45,8 +45,11 @@ export default {
45
45
  let minHeight = '';
46
46
  const box = boxModelAdjust(this.$el, 'height', 'content-box');
47
47
 
48
+ const { body, scrollingElement } = document;
48
49
  const [scrollElement] = scrollParents(this.$el, /auto|scroll/);
49
- const { height: viewportHeight } = offsetViewport(scrollElement);
50
+ const { height: viewportHeight } = offsetViewport(
51
+ scrollElement === body ? scrollingElement : scrollElement
52
+ );
50
53
 
51
54
  if (this.expand) {
52
55
  minHeight = Math.max(
@@ -56,7 +59,6 @@ export default {
56
59
  0
57
60
  );
58
61
  } else {
59
- const { body, scrollingElement } = document;
60
62
  const isScrollingElement =
61
63
  scrollingElement === scrollElement || body === scrollElement;
62
64
 
@@ -19,6 +19,7 @@ import {
19
19
  offset,
20
20
  once,
21
21
  parent,
22
+ parents,
22
23
  query,
23
24
  remove,
24
25
  selFocusable,
@@ -36,7 +37,7 @@ export default {
36
37
  align: String,
37
38
  offset: Number,
38
39
  boundary: Boolean,
39
- boundaryAlign: Boolean,
40
+ target: Boolean,
40
41
  clsDrop: String,
41
42
  delayShow: Number,
42
43
  delayHide: Number,
@@ -53,9 +54,12 @@ export default {
53
54
  offset: undefined,
54
55
  delayShow: undefined,
55
56
  delayHide: undefined,
56
- boundaryAlign: undefined,
57
- flip: 'x',
57
+ flip: false,
58
+ shift: true,
58
59
  boundary: true,
60
+ target: false,
61
+ targetX: false,
62
+ targetY: false,
59
63
  dropbar: false,
60
64
  dropbarAnchor: false,
61
65
  duration: 200,
@@ -90,7 +94,7 @@ export default {
90
94
  },
91
95
 
92
96
  watch(dropbar) {
93
- addClass(dropbar, 'uk-navbar-dropbar');
97
+ addClass(dropbar, 'uk-dropbar', 'uk-dropbar-top', 'uk-navbar-dropbar');
94
98
  },
95
99
 
96
100
  immediate: true,
@@ -106,7 +110,7 @@ export default {
106
110
 
107
111
  if (this.dropContainer !== $el) {
108
112
  for (const el of $$(`.${clsDrop}`, this.dropContainer)) {
109
- const target = this.getDropdown(el)?.target;
113
+ const target = this.getDropdown(el)?.targetEl;
110
114
  if (!includes(dropdowns, el) && target && within(target, this.$el)) {
111
115
  dropdowns.push(el);
112
116
  }
@@ -168,8 +172,8 @@ export default {
168
172
  if (
169
173
  active &&
170
174
  includes(active.mode, 'hover') &&
171
- active.target &&
172
- !within(active.target, current) &&
175
+ active.targetEl &&
176
+ !within(active.targetEl, current) &&
173
177
  !active.isDelaying
174
178
  ) {
175
179
  active.hide(false);
@@ -191,7 +195,7 @@ export default {
191
195
  if (keyCode === keyMap.DOWN && hasAttr(current, 'aria-expanded')) {
192
196
  e.preventDefault();
193
197
 
194
- if (!active || active.target !== current) {
198
+ if (!active || active.targetEl !== current) {
195
199
  current.click();
196
200
  once(this.dropContainer, 'show', ({ target }) =>
197
201
  focusFirstFocusableElement(target)
@@ -242,7 +246,7 @@ export default {
242
246
  }
243
247
 
244
248
  if (keyCode === keyMap.ESC) {
245
- active?.target?.focus();
249
+ active?.targetEl?.focus();
246
250
  }
247
251
 
248
252
  handleNavItemNavigation(e, this.toggles, active);
@@ -313,39 +317,19 @@ export default {
313
317
  return;
314
318
  }
315
319
 
316
- this._observer = observeResize(target, () =>
320
+ this._observer = observeResize(target, () => {
321
+ const targetOffsets = parents(target, `.${this.clsDrop}`)
322
+ .concat(target)
323
+ .map((el) => offset(el));
324
+ const minTop = Math.min(...targetOffsets.map(({ top }) => top));
325
+ const maxBottom = Math.max(...targetOffsets.map(({ bottom }) => bottom));
326
+ const dropbarOffset = offset(this.dropbar);
327
+ css(this.dropbar, 'top', this.dropbar.offsetTop - (dropbarOffset.top - minTop));
317
328
  this.transitionTo(
318
- offset(target).bottom -
319
- offset(this.dropbar).top +
320
- toFloat(css(target, 'marginBottom')),
329
+ maxBottom - minTop + toFloat(css(target, 'marginBottom')),
321
330
  target
322
- )
323
- );
324
- },
325
- },
326
-
327
- {
328
- name: 'beforeposition',
329
-
330
- el() {
331
- return this.dropContainer;
332
- },
333
-
334
- filter() {
335
- return this.dropbar;
336
- },
337
-
338
- handler(e, element, target, options) {
339
- if (!this.isDropbarDrop(element)) {
340
- return;
341
- }
342
-
343
- const dropbarOffset = offset(this.dropbar);
344
-
345
- css(element, 'maxWidth', dropbarOffset.width - options.viewportOffset * 2);
346
-
347
- options.offset[1] = dropbarOffset.top - offset(target).bottom;
348
- options.viewportOffset += dropbarOffset.left;
331
+ );
332
+ });
349
333
  },
350
334
  },
351
335
 
@@ -366,7 +350,7 @@ export default {
366
350
  if (
367
351
  matches(this.dropbar, ':hover') &&
368
352
  active?.$el === e.target &&
369
- !this.toggles.some((el) => active.target !== el && matches(el, ':focus'))
353
+ !this.toggles.some((el) => active.targetEl !== el && matches(el, ':focus'))
370
354
  ) {
371
355
  e.preventDefault();
372
356
  }
@@ -402,7 +386,7 @@ export default {
402
386
 
403
387
  methods: {
404
388
  getActive() {
405
- return active && within(active.target, this.$el) && active;
389
+ return active && within(active.targetEl, this.$el) && active;
406
390
  },
407
391
 
408
392
  transitionTo(newHeight, el) {
@@ -435,15 +419,14 @@ export default {
435
419
  },
436
420
 
437
421
  isDropbarDrop(el) {
438
- const drop = this.getDropdown(el);
439
- return drop && hasClass(el, this.clsDrop) && drop.align !== 'stretch';
422
+ return this.getDropdown(el) && hasClass(el, this.clsDrop);
440
423
  },
441
424
  },
442
425
  };
443
426
 
444
427
  function handleNavItemNavigation(e, toggles, active) {
445
428
  const { current, keyCode } = e;
446
- const target = active?.target || current;
429
+ const target = active?.targetEl || current;
447
430
  const i = toggles.indexOf(target);
448
431
 
449
432
  // Left
@@ -1,4 +1,4 @@
1
- import { $, scrollIntoView, trigger } from 'uikit-util';
1
+ import { $, off, on, scrollIntoView, trigger, within } from 'uikit-util';
2
2
 
3
3
  export default {
4
4
  props: {
@@ -9,6 +9,14 @@ export default {
9
9
  offset: 0,
10
10
  },
11
11
 
12
+ connected() {
13
+ registerClick(this);
14
+ },
15
+
16
+ disconnected() {
17
+ unregisterClick(this);
18
+ },
19
+
12
20
  methods: {
13
21
  async scrollTo(el) {
14
22
  el = (el && $(el)) || document.body;
@@ -19,18 +27,37 @@ export default {
19
27
  }
20
28
  },
21
29
  },
30
+ };
22
31
 
23
- events: {
24
- click(e) {
25
- if (e.defaultPrevented) {
26
- return;
27
- }
32
+ const components = new Set();
33
+ function registerClick(cmp) {
34
+ if (!components.size) {
35
+ on(document, 'click', clickHandler);
36
+ }
37
+
38
+ components.add(cmp);
39
+ }
28
40
 
41
+ function unregisterClick(cmp) {
42
+ components.delete(cmp);
43
+
44
+ if (!components.length) {
45
+ off(document, 'click', clickHandler);
46
+ }
47
+ }
48
+
49
+ function clickHandler(e) {
50
+ if (e.defaultPrevented) {
51
+ return;
52
+ }
53
+
54
+ for (const component of components) {
55
+ if (within(e.target, component.$el)) {
29
56
  e.preventDefault();
30
- this.scrollTo(getTargetElement(this.$el));
31
- },
32
- },
33
- };
57
+ component.scrollTo(getTargetElement(component.$el));
58
+ }
59
+ }
60
+ }
34
61
 
35
62
  export function getTargetElement(el) {
36
63
  return document.getElementById(decodeURIComponent(el.hash).substring(1));