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.
- package/CHANGELOG.md +33 -3
- package/build/build.js +4 -1
- package/dist/css/uikit-core-rtl.css +11 -2
- package/dist/css/uikit-core-rtl.min.css +1 -1
- package/dist/css/uikit-core.css +11 -2
- package/dist/css/uikit-core.min.css +1 -1
- package/dist/css/uikit-rtl.css +11 -2
- package/dist/css/uikit-rtl.min.css +1 -1
- package/dist/css/uikit.css +11 -2
- package/dist/css/uikit.min.css +1 -1
- package/dist/js/components/countdown.js +1 -1
- package/dist/js/components/countdown.min.js +1 -1
- package/dist/js/components/filter.js +1 -1
- package/dist/js/components/filter.min.js +1 -1
- package/dist/js/components/lightbox-panel.js +7 -3
- package/dist/js/components/lightbox-panel.min.js +1 -1
- package/dist/js/components/lightbox.js +7 -3
- package/dist/js/components/lightbox.min.js +1 -1
- package/dist/js/components/notification.js +1 -1
- package/dist/js/components/notification.min.js +1 -1
- package/dist/js/components/parallax.js +6 -2
- package/dist/js/components/parallax.min.js +1 -1
- package/dist/js/components/slider-parallax.js +6 -2
- package/dist/js/components/slider-parallax.min.js +1 -1
- package/dist/js/components/slider.js +1 -1
- package/dist/js/components/slider.min.js +1 -1
- package/dist/js/components/slideshow-parallax.js +6 -2
- package/dist/js/components/slideshow-parallax.min.js +1 -1
- package/dist/js/components/slideshow.js +1 -1
- package/dist/js/components/slideshow.min.js +1 -1
- package/dist/js/components/sortable.js +2 -2
- package/dist/js/components/sortable.min.js +1 -1
- package/dist/js/components/tooltip.js +4 -2
- package/dist/js/components/tooltip.min.js +1 -1
- package/dist/js/components/upload.js +1 -1
- package/dist/js/components/upload.min.js +1 -1
- package/dist/js/uikit-core.js +203 -134
- package/dist/js/uikit-core.min.js +1 -1
- package/dist/js/uikit-icons.js +1 -1
- package/dist/js/uikit-icons.min.js +1 -1
- package/dist/js/uikit.js +209 -136
- package/dist/js/uikit.min.js +1 -1
- package/package.json +1 -1
- package/src/js/components/sortable.js +2 -3
- package/src/js/core/drop.js +19 -12
- package/src/js/core/height-match.js +1 -2
- package/src/js/core/margin.js +1 -1
- package/src/js/core/navbar.js +17 -7
- package/src/js/core/scrollspy-nav.js +4 -9
- package/src/js/core/sticky.js +26 -13
- package/src/js/core/toggle.js +8 -8
- package/src/js/mixin/modal.js +6 -2
- package/src/js/mixin/parallax.js +5 -1
- package/src/js/mixin/position.js +2 -0
- package/src/js/uikit-core.js +0 -4
- package/src/js/util/lang.js +0 -4
- package/src/js/util/position.js +80 -24
- package/src/js/util/viewport.js +42 -22
- package/src/less/components/drop.less +0 -1
- package/src/less/components/navbar.less +11 -0
- package/src/less/components/search.less +2 -0
- package/src/less/theme/search.less +6 -0
- package/src/scss/components/drop.scss +0 -1
- package/src/scss/components/navbar.scss +11 -0
- package/src/scss/components/search.scss +2 -0
- package/src/scss/mixins-theme.scss +1 -0
- package/src/scss/mixins.scss +1 -0
- package/src/scss/theme/search.scss +6 -0
- package/tests/animation.html +216 -214
- package/tests/navbar.html +37 -0
- package/tests/sticky-parallax.html +16 -0
- package/tests/sticky.html +212 -36
- 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.
|
|
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
|
-
|
|
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 } =
|
|
326
|
+
const { top, bottom, height } = offsetViewport(scrollEl);
|
|
328
327
|
|
|
329
328
|
if (top < y && top + 35 > y) {
|
|
330
329
|
scroll -= dist;
|
package/src/js/core/drop.js
CHANGED
|
@@ -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(
|
|
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
|
|
363
|
-
const
|
|
364
|
-
const
|
|
365
|
-
const
|
|
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,
|
|
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 >
|
|
374
|
+
} else if (this.$el.offsetWidth > maxWidth) {
|
|
372
375
|
addClass(this.$el, `${this.clsDrop}-stack`);
|
|
373
376
|
}
|
|
374
377
|
|
|
375
|
-
css(this.$el,
|
|
378
|
+
css(this.$el, 'maxWidth', maxWidth);
|
|
376
379
|
|
|
377
|
-
this.positionAt(
|
|
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: {
|
package/src/js/core/margin.js
CHANGED
package/src/js/core/navbar.js
CHANGED
|
@@ -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:
|
|
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
|
|
140
|
-
|
|
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
|
|
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;
|
package/src/js/core/sticky.js
CHANGED
|
@@ -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:
|
|
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:
|
|
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
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const end =
|
|
177
|
-
|
|
178
|
-
|
|
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(
|
|
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 (
|
package/src/js/core/toggle.js
CHANGED
|
@@ -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
|
},
|
package/src/js/mixin/modal.js
CHANGED
|
@@ -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
|
|
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
|
+
}
|
package/src/js/mixin/parallax.js
CHANGED
|
@@ -79,12 +79,16 @@ export default {
|
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
function transformFn(prop, el, stops) {
|
|
82
|
-
|
|
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) {
|
package/src/js/mixin/position.js
CHANGED
|
@@ -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
|
},
|
package/src/js/uikit-core.js
CHANGED
|
@@ -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;
|
package/src/js/util/lang.js
CHANGED
|
@@ -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 ||
|
package/src/js/util/position.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { offset } from './dimensions';
|
|
2
|
-
import { clamp, includes } from './lang';
|
|
3
|
-
import {
|
|
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)
|
|
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
|
-
|
|
80
|
-
|
|
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
|
-
|
|
124
|
-
|
|
168
|
+
offsetPosition[start] = position[dir] = position[start] + offsetBy;
|
|
169
|
+
offsetPosition[end] += offsetBy;
|
|
125
170
|
}
|
|
126
171
|
|
|
127
|
-
return
|
|
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(...
|
|
135
|
-
let
|
|
136
|
-
for (const
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
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
|
|
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
|
+
}
|