uikit 3.14.4-dev.f2e3be255 → 3.14.4-dev.fef7412a0

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 (137) hide show
  1. package/CHANGELOG.md +39 -18
  2. package/build/util.js +1 -0
  3. package/dist/css/uikit-core-rtl.css +349 -109
  4. package/dist/css/uikit-core-rtl.min.css +1 -1
  5. package/dist/css/uikit-core.css +349 -109
  6. package/dist/css/uikit-core.min.css +1 -1
  7. package/dist/css/uikit-rtl.css +372 -139
  8. package/dist/css/uikit-rtl.min.css +1 -1
  9. package/dist/css/uikit.css +372 -139
  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 +7 -5
  14. package/dist/js/components/filter.min.js +1 -1
  15. package/dist/js/components/lightbox-panel.js +96 -139
  16. package/dist/js/components/lightbox-panel.min.js +1 -1
  17. package/dist/js/components/lightbox.js +96 -139
  18. package/dist/js/components/lightbox.min.js +1 -1
  19. package/dist/js/components/notification.js +4 -2
  20. package/dist/js/components/notification.min.js +1 -1
  21. package/dist/js/components/parallax.js +4 -5
  22. package/dist/js/components/parallax.min.js +1 -1
  23. package/dist/js/components/slider-parallax.js +4 -5
  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 +4 -5
  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 +102 -147
  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 +522 -488
  38. package/dist/js/uikit-core.min.js +17 -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 +531 -493
  42. package/dist/js/uikit.min.js +17 -1
  43. package/package.json +11 -11
  44. package/src/images/{backgrounds/nav-parent-close.svg → components/nav-parent-icon-large.svg} +0 -0
  45. package/src/images/{backgrounds/navbar-parent-close.svg → components/nav-parent-icon.svg} +0 -0
  46. package/src/images/{backgrounds/navbar-parent-open.svg → components/navbar-parent-icon.svg} +1 -1
  47. package/src/images/components/navbar-toggle-icon.svg +25 -3
  48. package/src/js/api/hooks.js +5 -1
  49. package/src/js/api/state.js +2 -2
  50. package/src/js/components/filter.js +5 -3
  51. package/src/js/components/notification.js +3 -1
  52. package/src/js/core/accordion.js +9 -17
  53. package/src/js/core/alert.js +35 -14
  54. package/src/js/core/drop.js +110 -82
  55. package/src/js/core/height-viewport.js +6 -2
  56. package/src/js/core/icon.js +16 -0
  57. package/src/js/core/index.js +2 -0
  58. package/src/js/core/leader.js +2 -2
  59. package/src/js/core/navbar.js +30 -45
  60. package/src/js/core/offcanvas.js +8 -4
  61. package/src/js/core/scroll.js +37 -10
  62. package/src/js/core/toggle.js +3 -5
  63. package/src/js/mixin/media.js +4 -5
  64. package/src/js/mixin/modal.js +15 -12
  65. package/src/js/mixin/position.js +24 -26
  66. package/src/js/mixin/style.js +11 -0
  67. package/src/js/mixin/togglable.js +88 -133
  68. package/src/js/util/animation.js +9 -7
  69. package/src/js/util/class.js +3 -1
  70. package/src/js/util/filter.js +3 -7
  71. package/src/js/util/position.js +107 -107
  72. package/src/js/util/style.js +4 -13
  73. package/src/js/util/viewport.js +3 -5
  74. package/src/less/components/_import.less +1 -0
  75. package/src/less/components/drop.less +1 -18
  76. package/src/less/components/dropbar.less +126 -0
  77. package/src/less/components/dropdown.less +11 -19
  78. package/src/less/components/leader.less +1 -1
  79. package/src/less/components/nav.less +218 -59
  80. package/src/less/components/navbar.less +62 -47
  81. package/src/less/components/utility.less +10 -2
  82. package/src/less/theme/_import.less +1 -0
  83. package/src/less/theme/dropbar.less +44 -0
  84. package/src/less/theme/dropdown.less +0 -11
  85. package/src/less/theme/nav.less +45 -7
  86. package/src/less/theme/navbar.less +2 -37
  87. package/src/scss/components/_import.scss +1 -0
  88. package/src/scss/components/drop.scss +1 -18
  89. package/src/scss/components/dropbar.scss +126 -0
  90. package/src/scss/components/dropdown.scss +11 -19
  91. package/src/scss/components/leader.scss +1 -1
  92. package/src/scss/components/nav.scss +167 -47
  93. package/src/scss/components/navbar.scss +50 -47
  94. package/src/scss/components/utility.scss +8 -1
  95. package/src/scss/mixins-theme.scss +93 -49
  96. package/src/scss/mixins.scss +89 -17
  97. package/src/scss/theme/_import.scss +1 -0
  98. package/src/scss/theme/dropbar.scss +44 -0
  99. package/src/scss/theme/dropdown.scss +0 -8
  100. package/src/scss/theme/nav.scss +43 -7
  101. package/src/scss/theme/navbar.scss +2 -10
  102. package/src/scss/variables-theme.scss +61 -22
  103. package/src/scss/variables.scss +49 -17
  104. package/tests/accordion.html +2 -2
  105. package/tests/alert.html +2 -2
  106. package/tests/countdown.html +1 -1
  107. package/tests/drop.html +446 -416
  108. package/tests/dropbar.html +458 -0
  109. package/tests/dropdown.html +8 -470
  110. package/tests/filter.html +9 -12
  111. package/tests/form.html +1 -1
  112. package/tests/index.html +126 -107
  113. package/tests/js/index.js +1 -4
  114. package/tests/lightbox.html +5 -5
  115. package/tests/list.html +8 -8
  116. package/tests/modal.html +13 -13
  117. package/tests/nav.html +117 -75
  118. package/tests/navbar.html +125 -245
  119. package/tests/offcanvas.html +17 -21
  120. package/tests/parallax.html +1 -1
  121. package/tests/position.html +18 -16
  122. package/tests/progress.html +9 -9
  123. package/tests/scroll.html +7 -10
  124. package/tests/search.html +6 -6
  125. package/tests/slider.html +6 -5
  126. package/tests/slideshow.html +8 -8
  127. package/tests/sortable.html +6 -8
  128. package/tests/sticky-navbar.html +15 -15
  129. package/tests/sticky.html +8 -8
  130. package/tests/switcher.html +1 -1
  131. package/tests/tab.html +1 -1
  132. package/tests/table.html +7 -7
  133. package/tests/toggle.html +2 -2
  134. package/tests/tooltip.html +1 -1
  135. package/tests/upload.html +11 -11
  136. package/tests/utility.html +19 -0
  137. package/src/images/backgrounds/nav-parent-open.svg +0 -3
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.f2e3be255",
5
+ "version": "3.14.4-dev.fef7412a0",
6
6
  "main": "dist/js/uikit.js",
7
7
  "style": "dist/css/uikit.css",
8
8
  "sideEffects": [
@@ -34,27 +34,27 @@
34
34
  },
35
35
  "homepage": "https://getuikit.com",
36
36
  "devDependencies": {
37
- "@babel/core": "^7.17.10",
38
- "@babel/preset-env": "^7.17.10",
37
+ "@babel/core": "^7.18.6",
38
+ "@babel/preset-env": "^7.18.6",
39
39
  "@rollup/plugin-alias": "^3.1.9",
40
40
  "@rollup/plugin-babel": "^5.3.1",
41
41
  "@rollup/plugin-replace": "^4.0.0",
42
42
  "archiver": "^5.3.1",
43
- "camelcase": "^6.3.0",
43
+ "camelcase": "^7.0.0",
44
44
  "clean-css": "^5.3.0",
45
45
  "dateformat": "^5.0.3",
46
- "esbuild": "^0.14.38",
47
- "eslint": "^8.15.0",
46
+ "esbuild": "^0.14.48",
47
+ "eslint": "^8.19.0",
48
48
  "eslint-config-prettier": "^8.5.0",
49
49
  "fs-extra": "^10.1.0",
50
- "glob": "^8.0.1",
51
- "inquirer": "^8.2.4",
52
- "less": "^4.1.2",
50
+ "glob": "^8.0.3",
51
+ "inquirer": "^9.0.0",
52
+ "less": "^4.1.3",
53
53
  "minimist": "^1.2.6",
54
54
  "number-precision": "^1.5.2",
55
55
  "p-limit": "^4.0.0",
56
- "prettier": "^2.6.2",
57
- "rollup": "^2.72.1",
56
+ "prettier": "^2.7.1",
57
+ "rollup": "^2.76.0",
58
58
  "rollup-plugin-esbuild": "^4.9.1",
59
59
  "rollup-plugin-html": "^0.2.1",
60
60
  "rollup-plugin-modify": "^3.0.0",
@@ -1,3 +1,3 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
2
- <polyline fill="none" stroke="#000" stroke-width="1.1" points="11 8.5 6 3.5 1 8.5" />
2
+ <polyline fill="none" stroke="#000" stroke-width="1.1" points="1 3.5 6 8.5 11 3.5"/>
3
3
  </svg>
@@ -1,5 +1,27 @@
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-animate 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 svg > .line-3 { opacity: 0; }
12
+ .uk-navbar-toggle-animate[aria-expanded="true"] svg > .line-3 { opacity: 1; }
13
+
14
+ .uk-navbar-toggle-animate[aria-expanded="true"] svg > .line-2 { transform: rotate(45deg); }
15
+ .uk-navbar-toggle-animate[aria-expanded="true"] svg > .line-3 { transform: rotate(-45deg); }
16
+
17
+ .uk-navbar-toggle-animate[aria-expanded="true"] svg > .line-1,
18
+ .uk-navbar-toggle-animate[aria-expanded="true"] svg > .line-4 { opacity: 0; }
19
+ .uk-navbar-toggle-animate[aria-expanded="true"] svg > .line-1 { transform: translateY(6px) scaleX(0); }
20
+ .uk-navbar-toggle-animate[aria-expanded="true"] svg > .line-4 { transform: translateY(-6px) scaleX(0); }
21
+
22
+ </style>
23
+ <rect class="line-1" y="3" width="20" height="2" />
24
+ <rect class="line-2" y="9" width="20" height="2" />
25
+ <rect class="line-3" y="9" width="20" height="2" />
26
+ <rect class="line-4" y="15" width="20" height="2" />
5
27
  </svg>
@@ -96,7 +96,11 @@ export default function (UIkit) {
96
96
  }
97
97
 
98
98
  if (write && result !== false) {
99
- fastdom.write(() => write.call(this, this._data, types));
99
+ fastdom.write(() => {
100
+ if (this._connected) {
101
+ write.call(this, this._data, types);
102
+ }
103
+ });
100
104
  }
101
105
  }
102
106
  }
@@ -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
 
@@ -153,7 +153,7 @@ function getProps(opts, name) {
153
153
 
154
154
  for (const key in options) {
155
155
  const prop = camelize(key);
156
- if (props[prop] !== undefined) {
156
+ if (!isUndefined(props[prop])) {
157
157
  data[prop] = coerce(props[prop], options[key]);
158
158
  }
159
159
  }
@@ -103,7 +103,7 @@ export default {
103
103
  });
104
104
  },
105
105
 
106
- setState(state, animate = true) {
106
+ async setState(state, animate = true) {
107
107
  state = { filter: { '': '' }, sort: [], ...state };
108
108
 
109
109
  trigger(this.$el, 'beforeFilter', [this, state]);
@@ -112,7 +112,7 @@ export default {
112
112
  toggleClass(el, this.cls, !!matchFilter(el, this.attrItem, state))
113
113
  );
114
114
 
115
- Promise.all(
115
+ await Promise.all(
116
116
  $$(this.target, this.$el).map((target) => {
117
117
  const filterFn = () => {
118
118
  applyState(state, target, getChildren(target));
@@ -120,7 +120,9 @@ export default {
120
120
  };
121
121
  return animate ? this.animate(filterFn, target) : filterFn();
122
122
  })
123
- ).then(() => trigger(this.$el, 'afterFilter', [this]));
123
+ );
124
+
125
+ trigger(this.$el, 'afterFilter', [this]);
124
126
  },
125
127
 
126
128
  updateState() {
@@ -56,7 +56,9 @@ export default {
56
56
  this.$mount(
57
57
  append(
58
58
  container,
59
- `<div class="${this.clsMsg}${this.status ? ` ${this.clsMsg}-${this.status}` : ''}">
59
+ `<div class="${this.clsMsg}${
60
+ this.status ? ` ${this.clsMsg}-${this.status}` : ''
61
+ }" role="alert">
60
62
  <a href class="${this.clsClose}" data-uk-close></a>
61
63
  <div>${this.message}</div>
62
64
  </div>`
@@ -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
+ }
@@ -1,6 +1,7 @@
1
1
  import Container from '../mixin/container';
2
2
  import Lazyload from '../mixin/lazyload';
3
3
  import Position from '../mixin/position';
4
+ import Style from '../mixin/style';
4
5
  import Togglable from '../mixin/togglable';
5
6
  import {
6
7
  addClass,
@@ -27,7 +28,6 @@ import {
27
28
  query,
28
29
  removeClass,
29
30
  scrollParents,
30
- toggleClass,
31
31
  within,
32
32
  } from 'uikit-util';
33
33
  import { preventBackgroundScroll, preventOverscroll } from '../mixin/modal';
@@ -35,7 +35,7 @@ import { preventBackgroundScroll, preventOverscroll } from '../mixin/modal';
35
35
  export let active;
36
36
 
37
37
  export default {
38
- mixins: [Container, Lazyload, Position, Togglable],
38
+ mixins: [Container, Lazyload, Position, Style, Togglable],
39
39
 
40
40
  args: 'pos',
41
41
 
@@ -43,10 +43,13 @@ export default {
43
43
  mode: 'list',
44
44
  toggle: Boolean,
45
45
  boundary: Boolean,
46
- boundaryAlign: Boolean,
46
+ target: Boolean,
47
+ targetX: Boolean,
48
+ targetY: Boolean,
49
+ stretch: Boolean,
47
50
  delayShow: Number,
48
51
  delayHide: Number,
49
- display: String,
52
+ autoUpdate: Boolean,
50
53
  clsDrop: String,
51
54
  animateOut: Boolean,
52
55
  bgScroll: Boolean,
@@ -55,17 +58,32 @@ export default {
55
58
  data: {
56
59
  mode: ['click', 'hover'],
57
60
  toggle: '- *',
58
- boundary: true,
59
- boundaryAlign: false,
61
+ boundary: false,
62
+ target: false,
63
+ targetX: false,
64
+ targetY: false,
65
+ stretch: false,
60
66
  delayShow: 0,
61
67
  delayHide: 800,
62
- display: null,
68
+ autoUpdate: true,
63
69
  clsDrop: false,
70
+ animateOut: false,
71
+ bgScroll: true,
64
72
  animation: ['uk-animation-fade'],
65
73
  cls: 'uk-open',
66
74
  container: false,
67
- animateOut: false,
68
- bgScroll: true,
75
+ },
76
+
77
+ computed: {
78
+ target({ target, targetX, targetY }, $el) {
79
+ targetX = targetX || target || this.targetEl;
80
+ targetY = targetY || target || this.targetEl;
81
+
82
+ return [
83
+ targetX === true ? window : query(targetX, $el),
84
+ targetY === true ? window : query(targetY, $el),
85
+ ];
86
+ },
69
87
  },
70
88
 
71
89
  created() {
@@ -79,18 +97,19 @@ export default {
79
97
  connected() {
80
98
  addClass(this.$el, this.clsDrop);
81
99
 
82
- if (this.toggle && !this.target) {
83
- this.target = this.$create('toggle', query(this.toggle, this.$el), {
100
+ if (this.toggle && !this.targetEl) {
101
+ this.targetEl = this.$create('toggle', query(this.toggle, this.$el), {
84
102
  target: this.$el,
85
103
  mode: this.mode,
86
104
  }).$el;
87
- attr(this.target, 'aria-haspopup', true);
88
- this.lazyload(this.target);
105
+ attr(this.targetEl, 'aria-haspopup', true);
106
+ this.lazyload(this.targetEl);
89
107
  }
90
108
  },
91
109
 
92
110
  disconnected() {
93
111
  if (this.isActive()) {
112
+ this.hide(false);
94
113
  active = null;
95
114
  }
96
115
  },
@@ -224,7 +243,8 @@ export default {
224
243
 
225
244
  this.tracker.init();
226
245
 
227
- for (const handler of [
246
+ const update = () => this.$emit();
247
+ const handlers = [
228
248
  on(
229
249
  document,
230
250
  pointerDown,
@@ -238,7 +258,7 @@ export default {
238
258
  !defaultPrevented &&
239
259
  type === pointerUp &&
240
260
  target === newTarget &&
241
- !(this.target && within(target, this.target))
261
+ !(this.targetEl && within(target, this.targetEl))
242
262
  ) {
243
263
  this.hide(false);
244
264
  }
@@ -253,29 +273,28 @@ export default {
253
273
  }
254
274
  }),
255
275
 
276
+ on(window, 'resize', update),
277
+
278
+ (() => {
279
+ const observer = observeResize(
280
+ scrollParents(this.$el).concat(this.targetEl),
281
+ update
282
+ );
283
+ return () => observer.disconnect();
284
+ })(),
285
+
286
+ ...(this.autoUpdate
287
+ ? [on([document, scrollParents(this.$el)], 'scroll', update)]
288
+ : []),
289
+
256
290
  ...(this.bgScroll
257
291
  ? []
258
292
  : [preventOverscroll(this.$el), preventBackgroundScroll()]),
293
+ ];
259
294
 
260
- ...(this.display === 'static' && this.align !== 'stretch'
261
- ? []
262
- : (() => {
263
- const handler = () => this.$emit();
264
- return [
265
- on(window, 'resize', handler),
266
- on(document, 'scroll', handler, true),
267
- (() => {
268
- const observer = observeResize(
269
- scrollParents(this.$el),
270
- handler
271
- );
272
- return () => observer.disconnect();
273
- })(),
274
- ];
275
- })()),
276
- ]) {
277
- once(this.$el, 'hide', handler, { self: true });
278
- }
295
+ once(this.$el, 'hide', () => handlers.forEach((handler) => handler()), {
296
+ self: true,
297
+ });
279
298
  },
280
299
  },
281
300
 
@@ -316,12 +335,12 @@ export default {
316
335
  },
317
336
 
318
337
  methods: {
319
- show(target = this.target, delay = true) {
320
- if (this.isToggled() && target && this.target && target !== this.target) {
338
+ show(target = this.targetEl, delay = true) {
339
+ if (this.isToggled() && target && this.targetEl && target !== this.targetEl) {
321
340
  this.hide(false, false);
322
341
  }
323
342
 
324
- this.target = target;
343
+ this.targetEl = target;
325
344
 
326
345
  this.clearTimers();
327
346
 
@@ -384,60 +403,69 @@ export default {
384
403
 
385
404
  position() {
386
405
  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');
406
+ attr(this.$el, 'style', this._style);
407
+
408
+ // Ensure none positioned element does not generate scrollbars
409
+ this.$el.hidden = true;
389
410
 
390
411
  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;
412
+ const boundaryOffset = offsetViewport(boundary || window);
413
+ const viewports = this.target.map((target) => offsetViewport(scrollParents(target)[0]));
397
414
  const viewportOffset = this.getViewportOffset(this.$el);
398
415
 
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) {
416
+ const dirs = [
417
+ [0, ['x', 'width', 'left', 'right']],
418
+ [1, ['y', 'height', 'top', 'bottom']],
419
+ ];
420
+
421
+ for (const [i, [axis, prop]] of dirs) {
422
+ if (this.axis !== axis && includes([axis, true], this.stretch)) {
423
+ css(this.$el, {
424
+ [prop]: Math.min(
425
+ boundaryOffset[prop],
426
+ viewports[i][prop] - 2 * viewportOffset
427
+ ),
428
+ [`overflow-${axis}`]: 'auto',
429
+ });
430
+ }
431
+ }
432
+
433
+ const maxWidth = viewports[0].width - 2 * viewportOffset;
434
+
435
+ if (this.$el.offsetWidth > maxWidth) {
435
436
  addClass(this.$el, `${this.clsDrop}-stack`);
436
437
  }
437
438
 
438
439
  css(this.$el, 'maxWidth', maxWidth);
439
440
 
440
- this.positionAt(this.$el, target, boundary);
441
+ this.$el.hidden = false;
442
+
443
+ this.positionAt(this.$el, this.target, boundary);
444
+
445
+ for (const [i, [axis, prop, start, end]] of dirs) {
446
+ if (this.axis === axis && includes([axis, true], this.stretch)) {
447
+ const positionOffset = Math.abs(this.getPositionOffset(this.$el));
448
+ const targetOffset = offset(this.target[i]);
449
+ const elOffset = offset(this.$el);
450
+
451
+ css(this.$el, {
452
+ [prop]:
453
+ (targetOffset[start] > elOffset[start]
454
+ ? targetOffset[start] -
455
+ Math.max(
456
+ boundaryOffset[start],
457
+ viewports[i][start] + viewportOffset
458
+ )
459
+ : Math.min(
460
+ boundaryOffset[end],
461
+ viewports[i][end] - viewportOffset
462
+ ) - targetOffset[end]) - positionOffset,
463
+ [`overflow-${axis}`]: 'auto',
464
+ });
465
+
466
+ this.positionAt(this.$el, this.target, boundary);
467
+ }
468
+ }
441
469
  },
442
470
  },
443
471
  };
@@ -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,8 @@ export default {
56
59
  0
57
60
  );
58
61
  } else {
59
- const isScrollingElement = document.scrollingElement === scrollElement;
62
+ const isScrollingElement =
63
+ scrollingElement === scrollElement || body === scrollElement;
60
64
 
61
65
  // on mobile devices (iOS and Android) window.innerHeight !== 100vh
62
66
  minHeight = `calc(${isScrollingElement ? '100vh' : `${viewportHeight}px`}`;