uikit 3.13.8-dev.fd15ccb29 → 3.13.10-dev.4de12886e

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 (73) hide show
  1. package/CHANGELOG.md +33 -3
  2. package/build/build.js +4 -1
  3. package/dist/css/uikit-core-rtl.css +11 -2
  4. package/dist/css/uikit-core-rtl.min.css +1 -1
  5. package/dist/css/uikit-core.css +11 -2
  6. package/dist/css/uikit-core.min.css +1 -1
  7. package/dist/css/uikit-rtl.css +11 -2
  8. package/dist/css/uikit-rtl.min.css +1 -1
  9. package/dist/css/uikit.css +11 -2
  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 +7 -3
  16. package/dist/js/components/lightbox-panel.min.js +1 -1
  17. package/dist/js/components/lightbox.js +7 -3
  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 +6 -2
  22. package/dist/js/components/parallax.min.js +1 -1
  23. package/dist/js/components/slider-parallax.js +6 -2
  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 +6 -2
  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 +2 -2
  32. package/dist/js/components/sortable.min.js +1 -1
  33. package/dist/js/components/tooltip.js +4 -2
  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 +203 -134
  38. package/dist/js/uikit-core.min.js +1 -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 +209 -136
  42. package/dist/js/uikit.min.js +1 -1
  43. package/package.json +1 -1
  44. package/src/js/components/sortable.js +2 -3
  45. package/src/js/core/drop.js +19 -12
  46. package/src/js/core/height-match.js +1 -2
  47. package/src/js/core/margin.js +1 -1
  48. package/src/js/core/navbar.js +17 -7
  49. package/src/js/core/scrollspy-nav.js +4 -9
  50. package/src/js/core/sticky.js +26 -13
  51. package/src/js/core/toggle.js +8 -8
  52. package/src/js/mixin/modal.js +6 -2
  53. package/src/js/mixin/parallax.js +5 -1
  54. package/src/js/mixin/position.js +2 -0
  55. package/src/js/uikit-core.js +0 -4
  56. package/src/js/util/lang.js +0 -4
  57. package/src/js/util/position.js +80 -24
  58. package/src/js/util/viewport.js +42 -22
  59. package/src/less/components/drop.less +0 -1
  60. package/src/less/components/navbar.less +11 -0
  61. package/src/less/components/search.less +2 -0
  62. package/src/less/theme/search.less +6 -0
  63. package/src/scss/components/drop.scss +0 -1
  64. package/src/scss/components/navbar.scss +11 -0
  65. package/src/scss/components/search.scss +2 -0
  66. package/src/scss/mixins-theme.scss +1 -0
  67. package/src/scss/mixins.scss +1 -0
  68. package/src/scss/theme/search.scss +6 -0
  69. package/tests/animation.html +216 -214
  70. package/tests/navbar.html +37 -0
  71. package/tests/sticky-parallax.html +16 -0
  72. package/tests/sticky.html +212 -36
  73. package/src/js/core/core.js +0 -25
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.13.8-dev.fd15ccb29",
5
+ "version": "3.13.10-dev.4de12886e",
6
6
  "main": "dist/js/uikit.js",
7
7
  "style": "dist/css/uikit.css",
8
8
  "sideEffects": [
@@ -10,14 +10,13 @@ import {
10
10
  css,
11
11
  findIndex,
12
12
  getEventPos,
13
- getViewport,
14
13
  hasTouch,
15
14
  height,
16
15
  index,
17
16
  isEmpty,
18
17
  isInput,
19
18
  off,
20
- offset,
19
+ offsetViewport,
21
20
  on,
22
21
  parent,
23
22
  pointerDown,
@@ -324,7 +323,7 @@ function trackScroll(pos) {
324
323
  .some((scrollEl) => {
325
324
  let { scrollTop: scroll, scrollHeight } = scrollEl;
326
325
 
327
- const { top, bottom, height } = offset(getViewport(scrollEl));
326
+ const { top, bottom, height } = offsetViewport(scrollEl);
328
327
 
329
328
  if (top < y && top + 35 > y) {
330
329
  scroll -= dist;
@@ -14,6 +14,7 @@ import {
14
14
  matches,
15
15
  MouseTracker,
16
16
  offset,
17
+ offsetViewport,
17
18
  on,
18
19
  once,
19
20
  parent,
@@ -24,6 +25,7 @@ import {
24
25
  pointerUp,
25
26
  query,
26
27
  removeClass,
28
+ scrollParents,
27
29
  toggleClass,
28
30
  within,
29
31
  } from 'uikit-util';
@@ -242,7 +244,7 @@ export default {
242
244
  this.hide(false);
243
245
  }
244
246
  }),
245
- on(window, 'resize', () => this.$emit('resize')),
247
+ on(window, 'resize', () => this.$emit()),
246
248
  ]) {
247
249
  once(this.$el, 'hide', handler, { self: true });
248
250
  }
@@ -283,8 +285,6 @@ export default {
283
285
  this.position();
284
286
  }
285
287
  },
286
-
287
- events: ['resize'],
288
288
  },
289
289
 
290
290
  methods: {
@@ -355,26 +355,33 @@ export default {
355
355
  },
356
356
 
357
357
  position() {
358
- const boundary = query(this.boundary, this.$el) || window;
359
358
  removeClass(this.$el, `${this.clsDrop}-stack`);
360
359
  toggleClass(this.$el, `${this.clsDrop}-boundary`, this.boundaryAlign);
361
360
 
362
- const boundaryOffset = offset(boundary);
363
- const targetOffset = offset(this.target);
364
- const alignTo = this.boundaryAlign ? boundaryOffset : targetOffset;
365
- const prop = this.axis === 'y' ? 'width' : 'height';
361
+ const boundary = query(this.boundary, this.$el);
362
+ const [scrollParent] = scrollParents(this.$el);
363
+ const scrollParentOffset = offsetViewport(scrollParent);
364
+ const boundaryOffset = boundary ? offset(boundary) : scrollParentOffset;
366
365
 
367
- css(this.$el, `max-${prop}`, '');
366
+ css(this.$el, 'maxWidth', '');
367
+ const maxWidth = scrollParentOffset.width - (boundary ? 0 : 2 * this.viewportPadding);
368
368
 
369
369
  if (this.pos[1] === 'justify') {
370
+ const prop = this.axis === 'y' ? 'width' : 'height';
371
+ const targetOffset = offset(this.target);
372
+ const alignTo = this.boundaryAlign ? boundaryOffset : targetOffset;
370
373
  css(this.$el, prop, alignTo[prop]);
371
- } else if (this.$el.offsetWidth > boundaryOffset.width) {
374
+ } else if (this.$el.offsetWidth > maxWidth) {
372
375
  addClass(this.$el, `${this.clsDrop}-stack`);
373
376
  }
374
377
 
375
- css(this.$el, `max-${prop}`, boundaryOffset[prop]);
378
+ css(this.$el, 'maxWidth', maxWidth);
376
379
 
377
- this.positionAt(this.$el, this.boundaryAlign ? boundary : this.target, boundary);
380
+ this.positionAt(
381
+ this.$el,
382
+ boundary && this.boundaryAlign ? boundary : this.target,
383
+ boundary
384
+ );
378
385
  },
379
386
  },
380
387
  };
@@ -15,7 +15,6 @@ export default {
15
15
  data: {
16
16
  target: '> *',
17
17
  row: true,
18
- forceHeight: true,
19
18
  },
20
19
 
21
20
  computed: {
@@ -31,7 +30,7 @@ export default {
31
30
  },
32
31
 
33
32
  resizeTargets() {
34
- return this.elements;
33
+ return [this.$el, this.elements];
35
34
  },
36
35
 
37
36
  update: {
@@ -15,7 +15,7 @@ export default {
15
15
  },
16
16
 
17
17
  resizeTargets() {
18
- return this.$el.children;
18
+ return [this.$el, this.$el.children];
19
19
  },
20
20
 
21
21
  connected() {
@@ -27,8 +27,6 @@ import {
27
27
  within,
28
28
  } from 'uikit-util';
29
29
 
30
- const navItem = '.uk-navbar-nav > li > a, .uk-navbar-item, .uk-navbar-toggle';
31
-
32
30
  export default {
33
31
  mixins: [Class, Container],
34
32
 
@@ -48,7 +46,7 @@ export default {
48
46
  },
49
47
 
50
48
  data: {
51
- dropdown: navItem,
49
+ dropdown: '.uk-navbar-nav > li > a, .uk-navbar-item, .uk-navbar-toggle',
52
50
  align: isRtl ? 'right' : 'left',
53
51
  clsDrop: 'uk-navbar-dropdown',
54
52
  mode: undefined,
@@ -61,8 +59,6 @@ export default {
61
59
  dropbar: false,
62
60
  dropbarAnchor: false,
63
61
  duration: 200,
64
- forceHeight: true,
65
- selMinHeight: navItem,
66
62
  container: false,
67
63
  },
68
64
 
@@ -136,8 +132,22 @@ export default {
136
132
  immediate: true,
137
133
  },
138
134
 
139
- toggles({ dropdown }, $el) {
140
- return $$(dropdown, $el);
135
+ toggles: {
136
+ get({ dropdown }, $el) {
137
+ return $$(dropdown, $el);
138
+ },
139
+
140
+ watch() {
141
+ const justify = hasClass(this.$el, 'uk-navbar-justify');
142
+ for (const container of $$(
143
+ '.uk-navbar-nav, .uk-navbar-left, .uk-navbar-right',
144
+ this.$el
145
+ )) {
146
+ css(container, 'flexGrow', justify ? $$(this.dropdown, container).length : '');
147
+ }
148
+ },
149
+
150
+ immediate: true,
141
151
  },
142
152
  },
143
153
 
@@ -2,11 +2,10 @@ import Scroll from '../mixin/scroll';
2
2
  import {
3
3
  $$,
4
4
  closest,
5
- getViewport,
6
- getViewportClientHeight,
7
5
  hasClass,
8
6
  isVisible,
9
7
  offset,
8
+ offsetViewport,
10
9
  scrollParents,
11
10
  toggleClass,
12
11
  trigger,
@@ -65,19 +64,15 @@ export default {
65
64
 
66
65
  const [scrollElement] = scrollParents(targets, /auto|scroll/, true);
67
66
  const { scrollTop, scrollHeight } = scrollElement;
68
- const max = scrollHeight - getViewportClientHeight(scrollElement);
67
+ const viewport = offsetViewport(scrollElement);
68
+ const max = scrollHeight - viewport.height;
69
69
  let active = false;
70
70
 
71
71
  if (scrollTop === max) {
72
72
  active = length - 1;
73
73
  } else {
74
74
  for (const i in targets) {
75
- if (
76
- offset(targets[i]).top -
77
- offset(getViewport(scrollElement)).top -
78
- this.offset >
79
- 0
80
- ) {
75
+ if (offset(targets[i]).top - viewport.top - this.offset > 0) {
81
76
  break;
82
77
  }
83
78
  active = +i;
@@ -13,8 +13,8 @@ import {
13
13
  fastdom,
14
14
  height as getHeight,
15
15
  offset as getOffset,
16
- getScrollingElement,
17
16
  intersectRect,
17
+ isNumeric,
18
18
  isString,
19
19
  isVisible,
20
20
  noop,
@@ -37,8 +37,10 @@ export default {
37
37
 
38
38
  props: {
39
39
  position: String,
40
- top: null,
40
+ top: Boolean,
41
41
  bottom: Boolean,
42
+ start: Boolean,
43
+ end: Boolean,
42
44
  offset: String,
43
45
  animation: String,
44
46
  clsActive: String,
@@ -52,8 +54,10 @@ export default {
52
54
 
53
55
  data: {
54
56
  position: 'top',
55
- top: 0,
57
+ top: false,
56
58
  bottom: false,
59
+ start: false,
60
+ end: false,
57
61
  offset: 0,
58
62
  animation: '',
59
63
  clsActive: 'uk-active',
@@ -76,6 +80,9 @@ export default {
76
80
  },
77
81
 
78
82
  connected() {
83
+ this.start = this.start || this.top;
84
+ this.end = this.end || this.bottom;
85
+
79
86
  this.placeholder =
80
87
  $('+ .uk-sticky-placeholder', this.$el) ||
81
88
  $('<div class="uk-sticky-placeholder"></div>');
@@ -169,13 +176,17 @@ export default {
169
176
  const overflow = Math.max(0, height + offset - windowHeight);
170
177
  const topOffset = getOffset(referenceElement).top;
171
178
 
172
- const top = parseProp(this.top, this.$el, topOffset);
173
- const bottom = parseProp(this.bottom, this.$el, topOffset + height, true);
174
-
175
- const start = Math.max(top, topOffset) - offset;
176
- const end = bottom
177
- ? bottom - getOffset(this.$el).height + overflow - offset
178
- : getScrollingElement(this.$el).scrollHeight - windowHeight;
179
+ const start =
180
+ (this.start === false
181
+ ? topOffset
182
+ : parseProp(this.start, this.$el, topOffset)) - offset;
183
+ const end =
184
+ this.end === false
185
+ ? document.scrollingElement.scrollHeight - windowHeight
186
+ : parseProp(this.end, this.$el, topOffset + height, true) -
187
+ getOffset(this.$el).height +
188
+ overflow -
189
+ offset;
179
190
 
180
191
  return {
181
192
  start,
@@ -221,7 +232,9 @@ export default {
221
232
  prevDir,
222
233
  scroll,
223
234
  prevScroll,
224
- offsetParentTop: getOffset(this.$el.offsetParent).top,
235
+ offsetParentTop: getOffset(
236
+ (this.isFixed ? this.placeholder : this.$el).offsetParent
237
+ ).top,
225
238
  overflowScroll: clamp(
226
239
  overflowScroll + clamp(scroll, start, end) - clamp(prevScroll, start, end),
227
240
  0,
@@ -376,8 +389,8 @@ function parseProp(value, el, propOffset, padding) {
376
389
  return 0;
377
390
  }
378
391
 
379
- if (isString(value) && value.match(/^-?\d/)) {
380
- return propOffset + toPx(value);
392
+ if (isNumeric(value) || (isString(value) && value.match(/^-?\d/))) {
393
+ return propOffset + toPx(value, 'height', el, true);
381
394
  } else {
382
395
  const refElement = value === true ? parent(el) : query(value, el);
383
396
  return (
@@ -156,15 +156,7 @@ export default {
156
156
  {
157
157
  name: 'click',
158
158
 
159
- filter() {
160
- return includes(this.mode, 'click');
161
- },
162
-
163
159
  handler(e) {
164
- if (this._preventClick) {
165
- return (this._preventClick = null);
166
- }
167
-
168
160
  let link;
169
161
  if (
170
162
  closest(e.target, 'a[href="#"], a[href=""]') ||
@@ -175,6 +167,14 @@ export default {
175
167
  e.preventDefault();
176
168
  }
177
169
 
170
+ if (this._preventClick) {
171
+ return (this._preventClick = null);
172
+ }
173
+
174
+ if (!includes(this.mode, 'click')) {
175
+ return;
176
+ }
177
+
178
178
  this.toggle();
179
179
  },
180
180
  },
@@ -4,6 +4,7 @@ import {
4
4
  append,
5
5
  attr,
6
6
  css,
7
+ endsWith,
7
8
  includes,
8
9
  isFocusable,
9
10
  last,
@@ -15,7 +16,6 @@ import {
15
16
  pointerUp,
16
17
  removeClass,
17
18
  toFloat,
18
- toMs,
19
19
  width,
20
20
  within,
21
21
  } from 'uikit-util';
@@ -245,7 +245,7 @@ function animate({ transitionElement, _toggle }) {
245
245
  return (el, show) =>
246
246
  new Promise((resolve, reject) =>
247
247
  once(el, 'show hide', () => {
248
- el._reject && el._reject();
248
+ el._reject?.();
249
249
  el._reject = reject;
250
250
 
251
251
  _toggle(el, show);
@@ -269,3 +269,7 @@ function animate({ transitionElement, _toggle }) {
269
269
  })
270
270
  ).then(() => delete el._reject);
271
271
  }
272
+
273
+ function toMs(time) {
274
+ return time ? (endsWith(time, 'ms') ? toFloat(time) : toFloat(time) * 1000) : 0;
275
+ }
@@ -79,12 +79,16 @@ export default {
79
79
  };
80
80
 
81
81
  function transformFn(prop, el, stops) {
82
- const unit = getUnit(stops) || { x: 'px', y: 'px', rotate: 'deg' }[prop] || '';
82
+ let unit = getUnit(stops) || { x: 'px', y: 'px', rotate: 'deg' }[prop] || '';
83
83
  let transformFn;
84
84
 
85
85
  if (prop === 'x' || prop === 'y') {
86
86
  prop = `translate${ucfirst(prop)}`;
87
87
  transformFn = (stop) => toFloat(toFloat(stop).toFixed(unit === 'px' ? 0 : 6));
88
+ } else if (prop === 'scale') {
89
+ unit = '';
90
+ transformFn = (stop) =>
91
+ getUnit([stop]) ? toPx(stop, 'width', el, true) / el.offsetWidth : stop;
88
92
  }
89
93
 
90
94
  if (stops.length === 1) {
@@ -21,6 +21,7 @@ export default {
21
21
  pos: `bottom-${isRtl ? 'right' : 'left'}`,
22
22
  flip: true,
23
23
  offset: false,
24
+ viewportPadding: 10,
24
25
  },
25
26
 
26
27
  connected() {
@@ -59,6 +60,7 @@ export default {
59
60
  attach,
60
61
  offset,
61
62
  boundary,
63
+ viewportPadding: this.viewportPadding,
62
64
  flip: this.flip,
63
65
  });
64
66
  },
@@ -1,5 +1,4 @@
1
1
  import UIkit from './api/index';
2
- import Core from './core/core';
3
2
  import boot from './api/boot';
4
3
  import * as components from './core/index';
5
4
  import { each } from 'uikit-util';
@@ -7,9 +6,6 @@ import { each } from 'uikit-util';
7
6
  // register components
8
7
  each(components, (component, name) => UIkit.component(name, component));
9
8
 
10
- // core functionality
11
- UIkit.use(Core);
12
-
13
9
  boot(UIkit);
14
10
 
15
11
  export default UIkit;
@@ -133,10 +133,6 @@ export function toWindow(element) {
133
133
  return document?.defaultView || window;
134
134
  }
135
135
 
136
- export function toMs(time) {
137
- return time ? (endsWith(time, 'ms') ? toFloat(time) : toFloat(time) * 1000) : 0;
138
- }
139
-
140
136
  export function isEqual(value, other) {
141
137
  return (
142
138
  value === other ||
@@ -1,6 +1,6 @@
1
1
  import { offset } from './dimensions';
2
- import { clamp, includes } from './lang';
3
- import { getViewport, scrollParents } from './viewport';
2
+ import { clamp, includes, ucfirst } from './lang';
3
+ import { offsetViewport, scrollParents } from './viewport';
4
4
 
5
5
  const dirs = [
6
6
  ['width', 'x', 'left', 'right'],
@@ -53,7 +53,8 @@ function attachTo(element, target, options) {
53
53
  function attachToWithFlip(element, target, options) {
54
54
  const position = attachTo(element, target, options);
55
55
  const targetDim = offset(target);
56
- const viewports = scrollParents(element).map(getViewport);
56
+ const viewports = scrollParents(element, /auto|scroll/);
57
+ const [scrollElement] = viewports;
57
58
 
58
59
  let {
59
60
  flip,
@@ -61,10 +62,12 @@ function attachToWithFlip(element, target, options) {
61
62
  offset: elOffset,
62
63
  boundary,
63
64
  viewport,
65
+ viewportPadding,
64
66
  } = options;
65
67
 
66
68
  viewports.push(viewport);
67
69
 
70
+ const offsetPosition = { ...position };
68
71
  for (const i in dirs) {
69
72
  const [prop, dir, start, end] = dirs[i];
70
73
 
@@ -75,10 +78,17 @@ function attachToWithFlip(element, target, options) {
75
78
  const willFlip =
76
79
  !intersectLine(position, targetDim, i) && intersectLine(position, targetDim, 1 - i);
77
80
 
78
- viewport = getIntersectionArea(
79
- ...viewports,
80
- willFlip || position[prop] > offset(boundary)[prop] ? null : boundary
81
- );
81
+ viewport = getIntersectionArea(...viewports.filter(Boolean).map(offsetViewport));
82
+
83
+ if (viewportPadding) {
84
+ viewport[start] += viewportPadding;
85
+ viewport[end] -= viewportPadding;
86
+ }
87
+
88
+ if (boundary && !(willFlip || position[prop] > offset(boundary)[prop])) {
89
+ viewport = getIntersectionArea(viewport, offset(boundary));
90
+ }
91
+
82
92
  const isInStartBoundary = position[start] >= viewport[start];
83
93
  const isInEndBoundary = position[end] <= viewport[end];
84
94
 
@@ -110,6 +120,41 @@ function attachToWithFlip(element, target, options) {
110
120
  : 0) -
111
121
  elOffset[i] * 2;
112
122
 
123
+ if (
124
+ !isInScrollArea(
125
+ {
126
+ ...position,
127
+ [start]: position[start] + offsetBy,
128
+ [end]: position[end] + offsetBy,
129
+ },
130
+ scrollElement,
131
+ i
132
+ )
133
+ ) {
134
+ if (isInScrollArea(position, scrollElement, i)) {
135
+ continue;
136
+ }
137
+
138
+ if (options.recursion) {
139
+ return false;
140
+ }
141
+
142
+ const newPos = attachToWithFlip(element, target, {
143
+ ...options,
144
+ attach: {
145
+ element: elAttach.map(flipDir).reverse(),
146
+ target: targetAttach.map(flipDir).reverse(),
147
+ },
148
+ offset: elOffset.reverse(),
149
+ flip: flip === true ? flip : [...flip, dirs[1 - i][1]],
150
+ recursion: true,
151
+ });
152
+
153
+ if (newPos && isInScrollArea(newPos, scrollElement, 1 - i)) {
154
+ return newPos;
155
+ }
156
+ }
157
+
113
158
  // Move
114
159
  } else {
115
160
  offsetBy =
@@ -120,36 +165,47 @@ function attachToWithFlip(element, target, options) {
120
165
  ) - position[start];
121
166
  }
122
167
 
123
- position[start] = position[dir] = position[start] + offsetBy;
124
- position[end] += offsetBy;
168
+ offsetPosition[start] = position[dir] = position[start] + offsetBy;
169
+ offsetPosition[end] += offsetBy;
125
170
  }
126
171
 
127
- return position;
172
+ return offsetPosition;
128
173
  }
129
174
 
130
175
  function moveBy(start, end, dim) {
131
176
  return start === 'center' ? dim / 2 : start === end ? dim : 0;
132
177
  }
133
178
 
134
- function getIntersectionArea(...elements) {
135
- let intersection;
136
- for (const el of elements.filter(Boolean)) {
137
- const rect = offset(el);
138
- if (!intersection) {
139
- intersection = rect;
140
- continue;
141
- }
142
- for (const prop of ['left', 'top']) {
143
- intersection[prop] = Math.max(rect[prop], intersection[prop]);
144
- }
145
- for (const prop of ['right', 'bottom']) {
146
- intersection[prop] = Math.min(rect[prop], intersection[prop]);
179
+ function getIntersectionArea(...rects) {
180
+ let area = {};
181
+ for (const rect of rects) {
182
+ for (const [, , start, end] of dirs) {
183
+ area[start] = Math.max(area[start] || 0, rect[start]);
184
+ area[end] = Math.min(...[area[end], rect[end]].filter(Boolean));
147
185
  }
148
186
  }
149
- return intersection;
187
+ return area;
188
+ }
189
+
190
+ function isInScrollArea(position, scrollElement, dir) {
191
+ const viewport = offsetViewport(scrollElement);
192
+ const [prop, , start, end] = dirs[dir];
193
+ viewport[start] -= scrollElement[`scroll${ucfirst(start)}`];
194
+ viewport[end] = viewport[start] + scrollElement[`scroll${ucfirst(prop)}`];
195
+
196
+ return position[start] >= viewport[start] && position[end] <= viewport[end];
150
197
  }
151
198
 
152
199
  function intersectLine(dimA, dimB, dir) {
153
200
  const [, , start, end] = dirs[dir];
154
201
  return dimA[end] > dimB[start] && dimB[end] > dimA[start];
155
202
  }
203
+
204
+ function flipDir(prop) {
205
+ for (const i in dirs) {
206
+ const index = dirs[i].indexOf(prop);
207
+ if (~index) {
208
+ return dirs[1 - i][(index % 2) + 2];
209
+ }
210
+ }
211
+ }