uikit 3.14.4-dev.838f092aa → 3.14.4-dev.8a8016a73

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 +41 -12
  2. package/build/util.js +1 -0
  3. package/dist/css/uikit-core-rtl.css +380 -101
  4. package/dist/css/uikit-core-rtl.min.css +1 -1
  5. package/dist/css/uikit-core.css +380 -101
  6. package/dist/css/uikit-core.min.css +1 -1
  7. package/dist/css/uikit-rtl.css +397 -106
  8. package/dist/css/uikit-rtl.min.css +1 -1
  9. package/dist/css/uikit.css +397 -106
  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 +100 -136
  16. package/dist/js/components/lightbox-panel.min.js +1 -1
  17. package/dist/js/components/lightbox.js +100 -136
  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 +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 +22 -7
  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 +22 -7
  30. package/dist/js/components/slideshow.min.js +1 -1
  31. package/dist/js/components/sortable.js +3 -3
  32. package/dist/js/components/sortable.min.js +1 -1
  33. package/dist/js/components/tooltip.js +97 -135
  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 +501 -453
  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 +554 -489
  42. package/dist/js/uikit.min.js +14 -1
  43. package/package.json +1 -1
  44. package/src/images/{backgrounds/nav-parent-open.svg → components/nav-parent-icon-large.svg} +0 -0
  45. package/src/images/components/nav-parent-icon.svg +3 -0
  46. package/src/images/components/navbar-parent-icon.svg +3 -0
  47. package/src/images/components/navbar-toggle-icon.svg +22 -3
  48. package/src/js/api/state.js +2 -2
  49. package/src/js/components/filter.js +5 -3
  50. package/src/js/components/sortable.js +2 -3
  51. package/src/js/core/accordion.js +9 -17
  52. package/src/js/core/alert.js +35 -14
  53. package/src/js/core/drop.js +89 -62
  54. package/src/js/core/height-viewport.js +14 -6
  55. package/src/js/core/icon.js +16 -0
  56. package/src/js/core/index.js +2 -0
  57. package/src/js/core/leader.js +2 -2
  58. package/src/js/core/navbar.js +42 -30
  59. package/src/js/core/scroll.js +37 -10
  60. package/src/js/core/sticky.js +8 -9
  61. package/src/js/core/toggle.js +3 -5
  62. package/src/js/mixin/media.js +4 -5
  63. package/src/js/mixin/modal.js +10 -7
  64. package/src/js/mixin/position.js +26 -11
  65. package/src/js/mixin/slider-drag.js +20 -8
  66. package/src/js/mixin/style.js +11 -0
  67. package/src/js/mixin/togglable.js +80 -133
  68. package/src/js/util/animation.js +4 -3
  69. package/src/js/util/dimensions.js +6 -6
  70. package/src/js/util/filter.js +3 -7
  71. package/src/js/util/position.js +108 -107
  72. package/src/js/util/style.js +4 -13
  73. package/src/js/util/viewport.js +5 -32
  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 +115 -0
  77. package/src/less/components/dropdown.less +16 -16
  78. package/src/less/components/leader.less +1 -1
  79. package/src/less/components/nav.less +240 -63
  80. package/src/less/components/navbar.less +73 -27
  81. package/src/less/components/utility.less +21 -4
  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 +43 -9
  86. package/src/less/theme/navbar.less +4 -10
  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 +115 -0
  90. package/src/scss/components/dropdown.scss +16 -16
  91. package/src/scss/components/leader.scss +1 -1
  92. package/src/scss/components/nav.scss +189 -51
  93. package/src/scss/components/navbar.scss +61 -27
  94. package/src/scss/components/utility.scss +19 -3
  95. package/src/scss/mixins-theme.scss +93 -25
  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 +41 -9
  101. package/src/scss/theme/navbar.scss +4 -7
  102. package/src/scss/variables-theme.scss +69 -17
  103. package/src/scss/variables.scss +58 -13
  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 +451 -371
  108. package/tests/dropbar.html +456 -0
  109. package/tests/dropdown.html +26 -401
  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 +1997 -1138
  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 +5 -5
  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 +6 -6
  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-close.svg +0 -3
@@ -3,22 +3,22 @@ import {
3
3
  addClass,
4
4
  Animation,
5
5
  css,
6
- fastdom,
6
+ dimensions,
7
7
  hasClass,
8
8
  includes,
9
9
  isBoolean,
10
10
  isFunction,
11
11
  isVisible,
12
12
  noop,
13
- offset,
14
13
  removeClass,
15
- scrollParents,
16
14
  startsWith,
17
15
  toFloat,
18
16
  toggleClass,
19
17
  toNodes,
20
18
  Transition,
21
19
  trigger,
20
+ unwrap,
21
+ wrapInner,
22
22
  } from 'uikit-util';
23
23
 
24
24
  export default {
@@ -40,26 +40,6 @@ export default {
40
40
  transition: 'ease',
41
41
  clsEnter: 'uk-togglabe-enter',
42
42
  clsLeave: 'uk-togglabe-leave',
43
-
44
- initProps: {
45
- overflow: '',
46
- maxHeight: '',
47
- paddingTop: '',
48
- paddingBottom: '',
49
- marginTop: '',
50
- marginBottom: '',
51
- boxShadow: '',
52
- },
53
-
54
- hideProps: {
55
- overflow: 'hidden',
56
- maxHeight: 0,
57
- paddingTop: 0,
58
- paddingBottom: 0,
59
- marginTop: 0,
60
- marginBottom: 0,
61
- boxShadow: 'none',
62
- },
63
43
  },
64
44
 
65
45
  computed: {
@@ -68,7 +48,7 @@ export default {
68
48
  },
69
49
 
70
50
  hasTransition({ animation }) {
71
- return startsWith(animation[0], 'slide');
51
+ return ['slide', 'reveal'].some((transition) => startsWith(animation[0], transition));
72
52
  },
73
53
  },
74
54
 
@@ -161,130 +141,97 @@ function toggleInstant({ _toggle }) {
161
141
  };
162
142
  }
163
143
 
164
- function toggleTransition(cmp) {
165
- switch (cmp.animation[0]) {
166
- case 'slide-left':
167
- return slideHorizontal(cmp);
168
- case 'slide-right':
169
- return slideHorizontal(cmp, true);
170
- }
171
- return slide(cmp);
172
- }
144
+ export function toggleTransition(cmp) {
145
+ const [mode = 'reveal', startProp = 'top'] = cmp.animation[0]?.split('-') || [];
173
146
 
174
- export function slide({
175
- isToggled,
176
- duration,
177
- velocity,
178
- initProps,
179
- hideProps,
180
- transition,
181
- _toggle,
182
- }) {
183
- return (el, show) => {
184
- const inProgress = Transition.inProgress(el);
185
- const inner =
186
- !inProgress && el.hasChildNodes()
187
- ? toFloat(css(el.firstElementChild, 'marginTop')) +
188
- toFloat(css(el.lastElementChild, 'marginBottom'))
189
- : 0;
190
- const currentHeight = isVisible(el) ? toFloat(css(el, 'height')) + inner : 0;
147
+ const dirs = [
148
+ ['left', 'right'],
149
+ ['top', 'bottom'],
150
+ ];
151
+ const dir = dirs[includes(dirs[0], startProp) ? 0 : 1];
152
+ const end = dir[1] === startProp;
153
+ const props = ['width', 'height'];
154
+ const dimProp = props[dirs.indexOf(dir)];
155
+ const marginProp = `margin-${dir[0]}`;
156
+ const marginStartProp = `margin-${startProp}`;
191
157
 
192
- const props = inProgress ? css(el, Object.keys(initProps)) : show ? hideProps : initProps;
158
+ return async (el, show) => {
159
+ let { duration, velocity, transition, _toggle } = cmp;
193
160
 
194
- Transition.cancel(el);
161
+ let currentDim = dimensions(el)[dimProp];
162
+
163
+ const inProgress = Transition.inProgress(el);
164
+ await Transition.cancel(el);
195
165
 
196
- if (!isToggled(el)) {
166
+ if (show) {
197
167
  _toggle(el, true);
198
168
  }
199
169
 
200
- css(el, 'maxHeight', '');
201
-
202
- // Update child components first
203
- fastdom.flush();
204
-
205
- const endHeight = toFloat(css(el, 'height')) + inner;
206
- duration = velocity * endHeight + duration;
207
-
208
- css(el, { ...props, maxHeight: currentHeight });
209
-
210
- return (
211
- show
212
- ? Transition.start(
213
- el,
214
- { ...initProps, overflow: 'hidden', maxHeight: endHeight },
215
- duration * (1 - currentHeight / endHeight),
216
- transition
217
- )
218
- : Transition.start(
219
- el,
220
- hideProps,
221
- duration * (currentHeight / endHeight),
222
- transition
223
- ).then(() => _toggle(el, false))
224
- ).then(() => css(el, initProps));
225
- };
226
- }
227
-
228
- function slideHorizontal({ isToggled, duration, velocity, transition, _toggle }, right) {
229
- return (el, show) => {
230
- const visible = isVisible(el);
231
- const marginLeft = toFloat(css(el, 'marginLeft'));
232
-
233
- Transition.cancel(el);
170
+ const prevProps = Object.fromEntries(
171
+ ['padding', 'border', 'width', 'height', 'overflow', marginProp, marginStartProp].map(
172
+ (key) => [key, el.style[key]]
173
+ )
174
+ );
234
175
 
235
- const [scrollElement] = scrollParents(el);
236
- css(scrollElement, 'overflowX', 'hidden');
176
+ const dim = dimensions(el);
177
+ const currentMargin = toFloat(css(el, marginProp));
178
+ const marginStart = toFloat(css(el, marginStartProp));
179
+ const endDim = dim[dimProp] + marginStart;
237
180
 
238
- if (!isToggled(el)) {
239
- _toggle(el, true);
181
+ if (!inProgress && !show) {
182
+ currentDim += marginStart;
240
183
  }
241
184
 
242
- const width = toFloat(css(el, 'width'));
243
- duration = velocity * width + duration;
244
-
245
- const percent = visible ? ((width + marginLeft * (right ? -1 : 1)) / width) * 100 : 0;
246
- const offsetEl = offset(el);
247
- const useClipPath = right
248
- ? offsetEl.right < scrollElement.clientWidth
249
- : Math.round(offsetEl.left) > 0;
185
+ const [wrapper] = wrapInner(el, '<div>');
186
+ css(wrapper, {
187
+ boxSizing: 'border-box',
188
+ height: dim.height,
189
+ width: dim.width,
190
+ ...css(el, [
191
+ 'padding',
192
+ 'borderTop',
193
+ 'borderRight',
194
+ 'borderBottom',
195
+ 'borderLeft',
196
+ 'borderImage',
197
+ marginStartProp,
198
+ ]),
199
+ });
250
200
 
251
201
  css(el, {
252
- clipPath: useClipPath
253
- ? right
254
- ? `polygon(0 0,${percent}% 0,${percent}% 100%,0 100%)`
255
- : `polygon(${100 - percent}% 0,100% 0,100% 100%,${100 - percent}% 100%)`
256
- : '',
257
- marginLeft: (((100 - percent) * (right ? 1 : -1)) / 100) * width,
202
+ padding: 0,
203
+ border: 0,
204
+ [marginStartProp]: 0,
205
+ width: dim.width,
206
+ height: dim.height,
207
+ overflow: 'hidden',
208
+ [dimProp]: currentDim,
258
209
  });
259
210
 
260
- return (
261
- show
262
- ? Transition.start(
263
- el,
264
- {
265
- clipPath: useClipPath ? `polygon(0 0,100% 0,100% 100%,0 100%)` : '',
266
- marginLeft: 0,
267
- },
268
- duration * (1 - percent / 100),
269
- transition
270
- )
271
- : Transition.start(
272
- el,
273
- {
274
- clipPath: useClipPath
275
- ? right
276
- ? `polygon(0 0,0 0,0 100%,0 100%)`
277
- : `polygon(100% 0,100% 0,100% 100%,100% 100%)`
278
- : '',
279
- marginLeft: (right ? 1 : -1) * width,
280
- },
281
- duration * (percent / 100),
282
- transition
283
- ).then(() => _toggle(el, false))
284
- ).then(() => {
285
- css(scrollElement, 'overflowX', '');
286
- css(el, { clipPath: '', marginLeft: '' });
287
- });
211
+ const percent = currentDim / endDim;
212
+ duration = (velocity * endDim + duration) * (show ? 1 - percent : percent);
213
+ const endProps = { [dimProp]: show ? endDim : 0 };
214
+
215
+ if (end) {
216
+ css(el, marginProp, endDim - currentDim + currentMargin);
217
+ endProps[marginProp] = show ? currentMargin : endDim + currentMargin;
218
+ }
219
+
220
+ if (!end ^ (mode === 'reveal')) {
221
+ css(wrapper, marginProp, -endDim + currentDim);
222
+ Transition.start(wrapper, { [marginProp]: show ? 0 : -endDim }, duration, transition);
223
+ }
224
+
225
+ try {
226
+ await Transition.start(el, endProps, duration, transition);
227
+ } finally {
228
+ css(el, prevProps);
229
+ unwrap(wrapper.firstChild);
230
+
231
+ if (!show) {
232
+ _toggle(el, false);
233
+ }
234
+ }
288
235
  };
289
236
  }
290
237
 
@@ -50,13 +50,14 @@ export function transition(element, props, duration = 400, timing = 'linear') {
50
50
  export const Transition = {
51
51
  start: transition,
52
52
 
53
- stop(element) {
53
+ async stop(element) {
54
54
  trigger(element, 'transitionend');
55
- return Promise.resolve();
55
+ await Promise.resolve();
56
56
  },
57
57
 
58
- cancel(element) {
58
+ async cancel(element) {
59
59
  trigger(element, 'transitioncanceled');
60
+ await Promise.resolve();
60
61
  },
61
62
 
62
63
  inProgress(element) {
@@ -94,13 +94,13 @@ export function position(element) {
94
94
  }
95
95
 
96
96
  export function offsetPosition(element) {
97
- const offset = [0, 0];
98
-
99
97
  element = toNode(element);
100
98
 
101
- do {
102
- offset[0] += element.offsetTop;
103
- offset[1] += element.offsetLeft;
99
+ const offset = [element.offsetTop, element.offsetLeft];
100
+
101
+ while ((element = element.offsetParent)) {
102
+ offset[0] += element.offsetTop + toFloat(css(element, `borderTopWidth`));
103
+ offset[1] += element.offsetLeft + toFloat(css(element, `borderLeftWidth`));
104
104
 
105
105
  if (css(element, 'position') === 'fixed') {
106
106
  const win = toWindow(element);
@@ -108,7 +108,7 @@ export function offsetPosition(element) {
108
108
  offset[1] += win.scrollX;
109
109
  return offset;
110
110
  }
111
- } while ((element = element.offsetParent));
111
+ }
112
112
 
113
113
  return offset;
114
114
  }
@@ -51,12 +51,8 @@ export function matches(element, selector) {
51
51
  }
52
52
 
53
53
  export function closest(element, selector) {
54
- if (startsWith(selector, '>')) {
55
- selector = selector.slice(1);
56
- }
57
-
58
54
  return isElement(element)
59
- ? element.closest(selector)
55
+ ? element.closest(startsWith(selector, '>') ? selector.slice(1) : selector)
60
56
  : toNodes(element)
61
57
  .map((element) => closest(element, selector))
62
58
  .filter(Boolean);
@@ -64,8 +60,8 @@ export function closest(element, selector) {
64
60
 
65
61
  export function within(element, selector) {
66
62
  return isString(selector)
67
- ? matches(element, selector) || !!closest(element, selector)
68
- : element === selector || toNode(selector).contains(toNode(element));
63
+ ? !!closest(element, selector)
64
+ : toNode(selector).contains(toNode(element));
69
65
  }
70
66
 
71
67
  export function parents(element, selector) {
@@ -1,5 +1,5 @@
1
1
  import { offset } from './dimensions';
2
- import { clamp, includes, ucfirst } from './lang';
2
+ import { clamp, isArray, ucfirst } from './lang';
3
3
  import { offsetViewport, scrollParents } from './viewport';
4
4
 
5
5
  const dirs = [
@@ -15,126 +15,65 @@ export function positionAt(element, target, options) {
15
15
  ...options.attach,
16
16
  },
17
17
  offset: [0, 0],
18
+ placement: [],
18
19
  ...options,
19
20
  };
20
21
 
21
- const dim = options.flip
22
- ? attachToWithFlip(element, target, options)
23
- : attachTo(element, target, options);
24
-
25
- offset(element, dim);
26
- }
27
-
28
- function attachTo(element, target, options) {
29
- let { attach, offset: offsetBy } = {
30
- attach: {
31
- element: ['left', 'top'],
32
- target: ['left', 'top'],
33
- ...options.attach,
34
- },
35
- offset: [0, 0],
36
- ...options,
37
- };
38
-
39
- const position = offset(element);
40
- const targetOffset = offset(target);
41
- for (const [i, [prop, dir, start, end]] of Object.entries(dirs)) {
42
- position[start] = position[dir] =
43
- targetOffset[start] +
44
- moveBy(attach.target[i], end, targetOffset[prop]) -
45
- moveBy(attach.element[i], end, position[prop]) +
46
- +offsetBy[i];
47
- position[end] = position[start] + position[prop];
22
+ if (!isArray(target)) {
23
+ target = [target, target];
48
24
  }
49
- return position;
50
- }
51
25
 
52
- function moveBy(start, end, dim) {
53
- return start === 'center' ? dim / 2 : start === end ? dim : 0;
26
+ offset(element, getPosition(element, target, options));
54
27
  }
55
28
 
56
- function attachToWithFlip(element, target, options) {
29
+ function getPosition(element, target, options) {
57
30
  const position = attachTo(element, target, options);
58
- const targetDim = offset(target);
59
31
 
60
32
  let {
61
- flip,
62
33
  attach: { element: elAttach, target: targetAttach },
63
34
  offset: elOffset,
64
35
  boundary,
65
- viewport,
66
36
  viewportOffset,
37
+ placement,
67
38
  } = options;
68
39
 
69
- let viewports = scrollParents(element);
70
- if (boundary === target) {
71
- viewports = viewports.filter((viewport) => viewport !== boundary);
72
- }
73
- const [scrollElement] = viewports;
74
- viewports.push(viewport);
40
+ let offsetPosition = position;
41
+ for (const [i, [prop, , start, end]] of Object.entries(dirs)) {
42
+ let viewports = scrollParents(target[i]);
43
+ const [scrollElement] = viewports;
75
44
 
76
- const offsetPosition = { ...position };
77
- for (const [i, [prop, dir, start, end]] of Object.entries(dirs)) {
78
- if (flip !== true && !includes(flip, dir)) {
79
- continue;
80
- }
81
-
82
- const willFlip =
83
- !intersectLine(position, targetDim, i) && intersectLine(position, targetDim, 1 - i);
84
-
85
- viewport = getIntersectionArea(...viewports.filter(Boolean).map(offsetViewport));
45
+ let viewport = getIntersectionArea(...viewports.map(offsetViewport));
86
46
 
87
47
  if (viewportOffset) {
88
48
  viewport[start] += viewportOffset;
89
49
  viewport[end] -= viewportOffset;
90
50
  }
91
51
 
92
- if (boundary && !willFlip && position[prop] <= offset(boundary)[prop]) {
93
- viewport = getIntersectionArea(viewport, offset(boundary));
52
+ if (boundary) {
53
+ viewport = getIntersectionArea(viewport, offsetViewport(boundary));
94
54
  }
95
55
 
96
- const isInStartBoundary = position[start] >= viewport[start];
97
- const isInEndBoundary = position[end] <= viewport[end];
56
+ const isInStartViewport = position[start] >= viewport[start];
57
+ const isInEndViewport = position[end] <= viewport[end];
98
58
 
99
- if (isInStartBoundary && isInEndBoundary) {
59
+ if (isInStartViewport && isInEndViewport) {
100
60
  continue;
101
61
  }
102
62
 
103
- let offsetBy;
63
+ let offsetBy = 0;
104
64
 
105
65
  // Flip
106
- if (willFlip) {
66
+ if (placement[i] === 'flip') {
107
67
  if (
108
- (elAttach[i] === end && isInStartBoundary) ||
109
- (elAttach[i] === start && isInEndBoundary)
68
+ (targetAttach[i] === end && isInEndViewport) ||
69
+ (targetAttach[i] === start && isInStartViewport)
110
70
  ) {
111
71
  continue;
112
72
  }
113
73
 
114
- offsetBy =
115
- (elAttach[i] === start
116
- ? -position[prop]
117
- : elAttach[i] === end
118
- ? position[prop]
119
- : 0) +
120
- (targetAttach[i] === start
121
- ? targetDim[prop]
122
- : targetAttach[i] === end
123
- ? -targetDim[prop]
124
- : 0) -
125
- elOffset[i] * 2;
74
+ offsetBy = flip(element, target, options, i)[start] - position[start];
126
75
 
127
- if (
128
- !isInScrollArea(
129
- {
130
- ...position,
131
- [start]: position[start] + offsetBy,
132
- [end]: position[end] + offsetBy,
133
- },
134
- scrollElement,
135
- i
136
- )
137
- ) {
76
+ if (!isInScrollArea(applyOffset(position, offsetBy, i), scrollElement, i)) {
138
77
  if (isInScrollArea(position, scrollElement, i)) {
139
78
  continue;
140
79
  }
@@ -143,26 +82,27 @@ function attachToWithFlip(element, target, options) {
143
82
  return false;
144
83
  }
145
84
 
146
- if (flip === true || includes(flip, dirs[1 - i][1])) {
147
- const newPos = attachToWithFlip(element, target, {
148
- ...options,
149
- attach: {
150
- element: elAttach.map(flipDir).reverse(),
151
- target: targetAttach.map(flipDir).reverse(),
152
- },
153
- offset: elOffset.reverse(),
154
- flip: flip === true ? flip : [...flip, dirs[1 - i][1]],
155
- recursion: true,
156
- });
157
-
158
- if (newPos && isInScrollArea(newPos, scrollElement, 1 - i)) {
159
- return newPos;
160
- }
85
+ const newPos = getPosition(element, target, {
86
+ ...options,
87
+ attach: {
88
+ element: elAttach.map(flipAxis).reverse(),
89
+ target: targetAttach.map(flipAxis).reverse(),
90
+ },
91
+ offset: elOffset.reverse(),
92
+ placement: placement.reverse(),
93
+ recursion: true,
94
+ });
95
+
96
+ if (newPos && isInScrollArea(newPos, scrollElement, 1 - i)) {
97
+ return newPos;
161
98
  }
99
+
100
+ continue;
162
101
  }
163
102
 
164
- // Move
165
- } else {
103
+ // Shift
104
+ } else if (placement[i] === 'shift') {
105
+ const targetDim = offset(target[i]);
166
106
  offsetBy =
167
107
  clamp(
168
108
  clamp(position[start], viewport[start], viewport[end] - position[prop]),
@@ -171,13 +111,54 @@ function attachToWithFlip(element, target, options) {
171
111
  ) - position[start];
172
112
  }
173
113
 
174
- offsetPosition[start] = position[dir] = position[start] + offsetBy;
175
- offsetPosition[end] += offsetBy;
114
+ offsetPosition = applyOffset(offsetPosition, offsetBy, i);
176
115
  }
177
116
 
178
117
  return offsetPosition;
179
118
  }
180
119
 
120
+ function attachTo(element, target, options) {
121
+ let { attach, offset: offsetBy } = {
122
+ attach: {
123
+ element: ['left', 'top'],
124
+ target: ['left', 'top'],
125
+ ...options.attach,
126
+ },
127
+ offset: [0, 0],
128
+ ...options,
129
+ };
130
+
131
+ let elOffset = offset(element);
132
+
133
+ for (const [i, [prop, , start, end]] of Object.entries(dirs)) {
134
+ const targetOffset =
135
+ attach.target[i] === attach.element[i] ? offsetViewport(target[i]) : offset(target[i]);
136
+
137
+ elOffset = applyOffset(
138
+ elOffset,
139
+ targetOffset[start] -
140
+ elOffset[start] +
141
+ moveBy(attach.target[i], end, targetOffset[prop]) -
142
+ moveBy(attach.element[i], end, elOffset[prop]) +
143
+ +offsetBy[i],
144
+ i
145
+ );
146
+ }
147
+ return elOffset;
148
+ }
149
+
150
+ function applyOffset(position, offset, i) {
151
+ const [, dir, start, end] = dirs[i];
152
+ const newPos = { ...position };
153
+ newPos[start] = position[dir] = position[start] + offset;
154
+ newPos[end] += offset;
155
+ return newPos;
156
+ }
157
+
158
+ function moveBy(attach, end, dim) {
159
+ return attach === 'center' ? dim / 2 : attach === end ? dim : 0;
160
+ }
161
+
181
162
  function getIntersectionArea(...rects) {
182
163
  let area = {};
183
164
  for (const rect of rects) {
@@ -198,12 +179,32 @@ function isInScrollArea(position, scrollElement, dir) {
198
179
  return position[start] >= viewport[start] && position[end] <= viewport[end];
199
180
  }
200
181
 
201
- function intersectLine(dimA, dimB, dir) {
202
- const [, , start, end] = dirs[dir];
203
- return dimA[end] > dimB[start] && dimB[end] > dimA[start];
182
+ function flip(element, target, { offset, attach }, i) {
183
+ return attachTo(element, target, {
184
+ attach: {
185
+ element: flipAttach(attach.element, i),
186
+ target: flipAttach(attach.target, i),
187
+ },
188
+ offset: flipOffset(offset, i),
189
+ });
190
+ }
191
+
192
+ function flipAttach(attach, i) {
193
+ const newAttach = [...attach];
194
+ const index = dirs[i].indexOf(attach[i]);
195
+ if (~index) {
196
+ newAttach[i] = dirs[i][1 - (index % 2) + 2];
197
+ }
198
+ return newAttach;
199
+ }
200
+
201
+ function flipOffset(offset, i) {
202
+ offset = [...offset];
203
+ offset[i] *= -1;
204
+ return offset;
204
205
  }
205
206
 
206
- function flipDir(prop) {
207
+ function flipAxis(prop) {
207
208
  for (let i = 0; i < dirs.length; i++) {
208
209
  const index = dirs[i].indexOf(prop);
209
210
  if (~index) {
@@ -8,6 +8,7 @@ import {
8
8
  isString,
9
9
  isUndefined,
10
10
  memoize,
11
+ startsWith,
11
12
  toNodes,
12
13
  } from './lang';
13
14
 
@@ -62,18 +63,11 @@ export function css(element, property, value, priority = '') {
62
63
  return elements[0];
63
64
  }
64
65
 
65
- const propertyRe = /^\s*(["'])?(.*?)\1\s*$/;
66
- export function getCssVar(name, element = document.documentElement) {
67
- return css(element, `--uk-${name}`).replace(propertyRe, '$2');
68
- }
69
-
70
66
  // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-setproperty
71
67
  export const propName = memoize((name) => vendorPropName(name));
72
68
 
73
- const cssPrefixes = ['webkit', 'moz'];
74
-
75
69
  function vendorPropName(name) {
76
- if (name[0] === '-') {
70
+ if (startsWith(name, '--')) {
77
71
  return name;
78
72
  }
79
73
 
@@ -85,11 +79,8 @@ function vendorPropName(name) {
85
79
  return name;
86
80
  }
87
81
 
88
- let i = cssPrefixes.length,
89
- prefixedName;
90
-
91
- while (i--) {
92
- prefixedName = `-${cssPrefixes[i]}-${name}`;
82
+ for (const prefix of ['webkit', 'moz']) {
83
+ const prefixedName = `-${prefix}-${name}`;
93
84
  if (prefixedName in style) {
94
85
  return prefixedName;
95
86
  }