uikit 3.13.7 → 3.13.8-dev.2fb6bed58

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 (48) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/css/uikit-core-rtl.css +1 -1
  3. package/dist/css/uikit-core-rtl.min.css +1 -1
  4. package/dist/css/uikit-core.css +1 -1
  5. package/dist/css/uikit-core.min.css +1 -1
  6. package/dist/css/uikit-rtl.css +1 -1
  7. package/dist/css/uikit-rtl.min.css +1 -1
  8. package/dist/css/uikit.css +1 -1
  9. package/dist/css/uikit.min.css +1 -1
  10. package/dist/js/components/countdown.js +1 -1
  11. package/dist/js/components/countdown.min.js +1 -1
  12. package/dist/js/components/filter.js +1 -1
  13. package/dist/js/components/filter.min.js +1 -1
  14. package/dist/js/components/lightbox-panel.js +1 -1
  15. package/dist/js/components/lightbox-panel.min.js +1 -1
  16. package/dist/js/components/lightbox.js +1 -1
  17. package/dist/js/components/lightbox.min.js +1 -1
  18. package/dist/js/components/notification.js +1 -1
  19. package/dist/js/components/notification.min.js +1 -1
  20. package/dist/js/components/parallax.js +1 -1
  21. package/dist/js/components/parallax.min.js +1 -1
  22. package/dist/js/components/slider-parallax.js +1 -1
  23. package/dist/js/components/slider-parallax.min.js +1 -1
  24. package/dist/js/components/slider.js +1 -1
  25. package/dist/js/components/slider.min.js +1 -1
  26. package/dist/js/components/slideshow-parallax.js +1 -1
  27. package/dist/js/components/slideshow-parallax.min.js +1 -1
  28. package/dist/js/components/slideshow.js +1 -1
  29. package/dist/js/components/slideshow.min.js +1 -1
  30. package/dist/js/components/sortable.js +1 -1
  31. package/dist/js/components/sortable.min.js +1 -1
  32. package/dist/js/components/tooltip.js +59 -21
  33. package/dist/js/components/tooltip.min.js +1 -1
  34. package/dist/js/components/upload.js +1 -1
  35. package/dist/js/components/upload.min.js +1 -1
  36. package/dist/js/uikit-core.js +180 -143
  37. package/dist/js/uikit-core.min.js +1 -1
  38. package/dist/js/uikit-icons.js +1 -1
  39. package/dist/js/uikit-icons.min.js +1 -1
  40. package/dist/js/uikit.js +182 -145
  41. package/dist/js/uikit.min.js +1 -1
  42. package/package.json +1 -1
  43. package/src/js/core/drop.js +4 -1
  44. package/src/js/mixin/position.js +56 -19
  45. package/src/js/util/position.js +125 -129
  46. package/tests/drop.html +0 -6
  47. package/tests/dropdown.html +2 -8
  48. package/tests/position.html +38 -39
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.7",
5
+ "version": "3.13.8-dev.2fb6bed58",
6
6
  "main": "dist/js/uikit.js",
7
7
  "style": "dist/css/uikit.css",
8
8
  "sideEffects": [
@@ -62,8 +62,11 @@ export default {
62
62
  this.tracker = new MouseTracker();
63
63
  },
64
64
 
65
- connected() {
65
+ beforeConnect() {
66
66
  this.clsDrop = this.$props.clsDrop || `uk-${this.$options.name}`;
67
+ },
68
+
69
+ connected() {
67
70
  addClass(this.$el, this.clsDrop);
68
71
 
69
72
  if (this.toggle && !this.target) {
@@ -3,6 +3,7 @@ import {
3
3
  flipPosition,
4
4
  getCssVar,
5
5
  offset as getOffset,
6
+ includes,
6
7
  isNumeric,
7
8
  isRtl,
8
9
  positionAt,
@@ -30,9 +31,8 @@ export default {
30
31
 
31
32
  methods: {
32
33
  positionAt(element, target, boundary) {
33
- const axis = this.getAxis();
34
- const dir = this.pos[0];
35
- const align = this.pos[1];
34
+ const [dir, align] = this.pos;
35
+ const axis = this.getAxis(dir);
36
36
 
37
37
  let { offset } = this;
38
38
  if (!isNumeric(offset)) {
@@ -43,26 +43,63 @@ export default {
43
43
  : 0;
44
44
  }
45
45
  offset = toPx(offset) + toPx(getCssVar('position-offset', element));
46
+ offset = [includes(['left', 'top'], dir) ? -offset : +offset, 0];
46
47
 
47
- const { x, y } = positionAt(
48
- element,
49
- target,
50
- axis === 'x' ? `${flipPosition(dir)} ${align}` : `${align} ${flipPosition(dir)}`,
51
- axis === 'x' ? `${dir} ${align}` : `${align} ${dir}`,
52
- axis === 'x'
53
- ? `${dir === 'left' ? -offset : offset}`
54
- : ` ${dir === 'top' ? -offset : offset}`,
55
- null,
56
- this.flip,
57
- boundary
58
- ).target;
48
+ const attach = {
49
+ element: [flipPosition(dir), align],
50
+ target: [dir, align],
51
+ };
59
52
 
60
- this.dir = axis === 'x' ? x : y;
61
- this.align = axis === 'x' ? y : x;
53
+ if (axis === 'y') {
54
+ for (const prop in attach) {
55
+ attach[prop] = attach[prop].reverse();
56
+ }
57
+ offset = offset.reverse();
58
+ }
59
+
60
+ positionAt(element, target, {
61
+ attach,
62
+ offset,
63
+ boundary,
64
+ flip: this.flip,
65
+ });
66
+
67
+ [this.dir, this.align] = getAlignment(element, target, this.pos);
62
68
  },
63
69
 
64
- getAxis() {
65
- return this.dir === 'top' || this.dir === 'bottom' ? 'y' : 'x';
70
+ getAxis(dir = this.dir) {
71
+ return includes(['top', 'bottom'], dir) ? 'y' : 'x';
66
72
  },
67
73
  },
68
74
  };
75
+
76
+ function getAlignment(el, target, [dir, align]) {
77
+ const elOffset = getOffset(el);
78
+ const targetOffset = getOffset(target);
79
+ const properties = [
80
+ ['left', 'right'],
81
+ ['top', 'bottom'],
82
+ ];
83
+
84
+ for (const props of properties) {
85
+ if (elOffset[props[0]] >= targetOffset[props[1]]) {
86
+ dir = props[1];
87
+ break;
88
+ }
89
+ if (elOffset[props[1]] <= targetOffset[props[0]]) {
90
+ dir = props[0];
91
+ break;
92
+ }
93
+ }
94
+
95
+ const props = includes(properties[0], dir) ? properties[1] : properties[0];
96
+ if (elOffset[props[0]] === targetOffset[props[0]]) {
97
+ align = props[0];
98
+ } else if (elOffset[props[1]] === targetOffset[props[1]]) {
99
+ align = props[1];
100
+ } else {
101
+ align = 'center';
102
+ }
103
+
104
+ return [dir, align];
105
+ }
@@ -1,156 +1,152 @@
1
1
  import { offset } from './dimensions';
2
- import { each, endsWith, includes, toFloat } from './lang';
2
+ import { clamp, includes } from './lang';
3
3
  import { getViewport, scrollParents } from './viewport';
4
4
 
5
- const dirs = {
6
- width: ['x', 'left', 'right'],
7
- height: ['y', 'top', 'bottom'],
8
- };
9
-
10
- export function positionAt(
11
- element,
12
- target,
13
- elAttach,
14
- targetAttach,
15
- elOffset,
16
- targetOffset,
17
- flip,
18
- boundary
19
- ) {
20
- elAttach = getPos(elAttach);
21
- targetAttach = getPos(targetAttach);
22
-
23
- const flipped = { element: elAttach, target: targetAttach };
24
-
25
- if (!element || !target) {
26
- return flipped;
5
+ const dirs = [
6
+ ['width', 'x', 'left', 'right'],
7
+ ['height', 'y', 'top', 'bottom'],
8
+ ];
9
+
10
+ export function positionAt(element, target, options) {
11
+ options = {
12
+ attach: {
13
+ element: ['left', 'top'],
14
+ target: ['left', 'top'],
15
+ ...options.attach,
16
+ },
17
+ offset: [0, 0],
18
+ ...options,
19
+ };
20
+
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 in dirs) {
42
+ const [prop, dir, start, end] = dirs[i];
43
+ position[start] = position[dir] =
44
+ targetOffset[start] +
45
+ moveBy(attach.target[i], end, targetOffset[prop]) -
46
+ moveBy(attach.element[i], end, position[prop]) +
47
+ +offsetBy[i];
48
+ position[end] = position[start] + position[prop];
27
49
  }
50
+ return position;
51
+ }
28
52
 
29
- const dim = offset(element);
53
+ function attachToWithFlip(element, target, options) {
54
+ const position = attachTo(element, target, options);
30
55
  const targetDim = offset(target);
31
- const position = targetDim;
56
+ const viewports = scrollParents(element).map(getViewport);
57
+
58
+ let {
59
+ flip,
60
+ attach: { element: elAttach, target: targetAttach },
61
+ offset: elOffset,
62
+ boundary,
63
+ viewport,
64
+ } = options;
32
65
 
33
- moveTo(position, elAttach, dim, -1);
34
- moveTo(position, targetAttach, targetDim, 1);
66
+ viewports.push(viewport);
35
67
 
36
- elOffset = getOffsets(elOffset, dim.width, dim.height);
37
- targetOffset = getOffsets(targetOffset, targetDim.width, targetDim.height);
68
+ for (const i in dirs) {
69
+ const [prop, dir, start, end] = dirs[i];
38
70
 
39
- elOffset['x'] += targetOffset['x'];
40
- elOffset['y'] += targetOffset['y'];
71
+ if (flip !== true && !includes(flip, dir)) {
72
+ continue;
73
+ }
41
74
 
42
- position.left += elOffset['x'];
43
- position.top += elOffset['y'];
75
+ const willFlip =
76
+ !intersectLine(position, targetDim, i) && intersectLine(position, targetDim, 1 - i);
44
77
 
45
- if (flip) {
46
- let boundaries = scrollParents(element).map(getViewport);
78
+ viewport = getIntersectionArea(...viewports, willFlip ? null : boundary);
79
+ const isInStartBoundary = position[start] >= viewport[start];
80
+ const isInEndBoundary = position[end] <= viewport[end];
47
81
 
48
- if (boundary && !includes(boundaries, boundary)) {
49
- boundaries.unshift(boundary);
82
+ if (isInStartBoundary && isInEndBoundary) {
83
+ continue;
50
84
  }
51
85
 
52
- boundaries = boundaries.map((el) => offset(el));
86
+ let offsetBy;
53
87
 
54
- each(dirs, ([dir, align, alignFlip], prop) => {
55
- if (!(flip === true || includes(flip, dir))) {
56
- return;
88
+ // Flip
89
+ if (willFlip) {
90
+ if (
91
+ (elAttach[i] === end && isInStartBoundary) ||
92
+ (elAttach[i] === start && isInEndBoundary)
93
+ ) {
94
+ continue;
57
95
  }
58
96
 
59
- boundaries.some((boundary) => {
60
- const elemOffset =
61
- elAttach[dir] === align
62
- ? -dim[prop]
63
- : elAttach[dir] === alignFlip
64
- ? dim[prop]
65
- : 0;
66
-
67
- const targetOffset =
68
- targetAttach[dir] === align
69
- ? targetDim[prop]
70
- : targetAttach[dir] === alignFlip
71
- ? -targetDim[prop]
72
- : 0;
73
-
74
- if (
75
- position[align] < boundary[align] ||
76
- position[align] + dim[prop] > boundary[alignFlip]
77
- ) {
78
- const centerOffset = dim[prop] / 2;
79
- const centerTargetOffset =
80
- targetAttach[dir] === 'center' ? -targetDim[prop] / 2 : 0;
81
-
82
- return (
83
- (elAttach[dir] === 'center' &&
84
- (apply(centerOffset, centerTargetOffset) ||
85
- apply(-centerOffset, -centerTargetOffset))) ||
86
- apply(elemOffset, targetOffset)
87
- );
88
- }
89
-
90
- function apply(elemOffset, targetOffset) {
91
- const newVal = toFloat(
92
- (position[align] + elemOffset + targetOffset - elOffset[dir] * 2).toFixed(4)
93
- );
94
-
95
- if (newVal >= boundary[align] && newVal + dim[prop] <= boundary[alignFlip]) {
96
- position[align] = newVal;
97
-
98
- for (const el of ['element', 'target']) {
99
- if (elemOffset) {
100
- flipped[el][dir] =
101
- flipped[el][dir] === dirs[prop][1]
102
- ? dirs[prop][2]
103
- : dirs[prop][1];
104
- }
105
- }
106
-
107
- return true;
108
- }
109
- }
110
- });
111
- });
112
- }
97
+ offsetBy =
98
+ (elAttach[i] === start
99
+ ? -position[prop]
100
+ : elAttach[i] === end
101
+ ? position[prop]
102
+ : 0) +
103
+ (targetAttach[i] === start
104
+ ? targetDim[prop]
105
+ : targetAttach[i] === end
106
+ ? -targetDim[prop]
107
+ : 0) -
108
+ elOffset[i] * 2;
109
+
110
+ // Move
111
+ } else {
112
+ offsetBy =
113
+ clamp(
114
+ clamp(position[start], viewport[start], viewport[end] - position[prop]),
115
+ targetDim[start] - position[prop] + elOffset[i],
116
+ targetDim[end] - elOffset[i]
117
+ ) - position[start];
118
+ }
113
119
 
114
- offset(element, position);
120
+ position[start] = position[dir] = position[start] + offsetBy;
121
+ position[end] += offsetBy;
122
+ }
115
123
 
116
- return flipped;
124
+ return position;
117
125
  }
118
126
 
119
- function moveTo(position, attach, dim, factor) {
120
- each(dirs, ([dir, align, alignFlip], prop) => {
121
- if (attach[dir] === alignFlip) {
122
- position[align] += dim[prop] * factor;
123
- } else if (attach[dir] === 'center') {
124
- position[align] += (dim[prop] * factor) / 2;
125
- }
126
- });
127
+ function moveBy(start, end, dim) {
128
+ return start === 'center' ? dim / 2 : start === end ? dim : 0;
127
129
  }
128
130
 
129
- function getPos(pos) {
130
- const x = /left|center|right/;
131
- const y = /top|center|bottom/;
132
-
133
- pos = (pos || '').split(' ');
134
-
135
- if (pos.length === 1) {
136
- pos = x.test(pos[0])
137
- ? pos.concat('center')
138
- : y.test(pos[0])
139
- ? ['center'].concat(pos)
140
- : ['center', 'center'];
131
+ function getIntersectionArea(...elements) {
132
+ let intersection;
133
+ for (const el of elements.filter(Boolean)) {
134
+ const rect = offset(el);
135
+ if (!intersection) {
136
+ intersection = rect;
137
+ continue;
138
+ }
139
+ for (const prop of ['left', 'top']) {
140
+ intersection[prop] = Math.max(rect[prop], intersection[prop]);
141
+ }
142
+ for (const prop of ['right', 'bottom']) {
143
+ intersection[prop] = Math.min(rect[prop], intersection[prop]);
144
+ }
141
145
  }
142
-
143
- return {
144
- x: x.test(pos[0]) ? pos[0] : 'center',
145
- y: y.test(pos[1]) ? pos[1] : 'center',
146
- };
146
+ return intersection;
147
147
  }
148
148
 
149
- function getOffsets(offsets, width, height) {
150
- const [x, y] = (offsets || '').split(' ');
151
-
152
- return {
153
- x: x ? toFloat(x) * (endsWith(x, '%') ? width / 100 : 1) : 0,
154
- y: y ? toFloat(y) * (endsWith(y, '%') ? height / 100 : 1) : 0,
155
- };
149
+ function intersectLine(dimA, dimB, dir) {
150
+ const [, , start, end] = dirs[dir];
151
+ return dimA[end] > dimB[start] && dimB[end] > dimA[start];
156
152
  }
package/tests/drop.html CHANGED
@@ -395,12 +395,6 @@
395
395
  <td>true</td>
396
396
  <td>Automatic Drop flip.</td>
397
397
  </tr>
398
- <tr>
399
- <td><code>cls</code></td>
400
- <td>String</td>
401
- <td>'uk-drop'</td>
402
- <td>The Drop container class.</td>
403
- </tr>
404
398
  <tr>
405
399
  <td><code>offset</code></td>
406
400
  <td>Number</td>
@@ -384,8 +384,8 @@
384
384
  <tr>
385
385
  <td><code>boundary</code></td>
386
386
  <td>CSS selector</td>
387
- <td>window</td>
388
- <td>Referenced element to keep Dropdown's visibility.</td>
387
+ <td>true</td>
388
+ <td>The area that the element will be checked for overflow, causing the Drop to flip. By default, it's the scrolling containers of the Drop's element.</td>
389
389
  </tr>
390
390
  <tr>
391
391
  <td><code>boundary-align</code></td>
@@ -399,12 +399,6 @@
399
399
  <td>true</td>
400
400
  <td>Automatic Dropdown flip.</td>
401
401
  </tr>
402
- <tr>
403
- <td><code>cls</code></td>
404
- <td>String</td>
405
- <td>'uk-dropdown'</td>
406
- <td>The Dropdown container class.</td>
407
- </tr>
408
402
  <tr>
409
403
  <td><code>offset</code></td>
410
404
  <td>Number</td>
@@ -9,7 +9,7 @@
9
9
  <style>
10
10
 
11
11
  /* JavaScript */
12
- #js-boundary {
12
+ #js-viewport {
13
13
  height: 300px;
14
14
  outline: 1px solid rgba(0,0,0,0.1);
15
15
  position: relative;
@@ -26,7 +26,6 @@
26
26
 
27
27
  #js-element {
28
28
  position: absolute;
29
- display: none;
30
29
  width: 75px;
31
30
  height: 75px;
32
31
  background: rgba(0,0,0,0.1);
@@ -238,13 +237,13 @@
238
237
 
239
238
  <h2>JavaScript</h2>
240
239
 
241
- <div id="js-boundary" class="uk-margin">
240
+ <div id="js-viewport" class="uk-margin">
242
241
  <div id="js-target" class="uk-flex uk-flex-center uk-flex-middle" draggable="true">Drag me!</div>
243
242
  </div>
244
243
 
245
244
  <div id="js-element"></div>
246
245
 
247
- <div class="uk-grid uk-child-width-auto uk-form-stacked">
246
+ <div class="uk-grid uk-child-width-auto uk-form-stacked" style="margin-bottom: 100vh">
248
247
  <div>
249
248
 
250
249
  <div class="uk-margin">
@@ -327,27 +326,26 @@
327
326
 
328
327
  <script>
329
328
 
330
- var util = UIkit.util,
331
- $ = util.$,
332
- on = util.on,
333
- offset = util.offset,
334
- ticking,
335
- element = $('#js-element'),
336
- boundary = $('#js-boundary'),
337
- target = $('#js-target'),
338
- offsetX,
339
- offsetY;
329
+ const {$, $$, css, getEventPos, on, offset, positionAt} = UIkit.util;
330
+ let viewport = $('#js-viewport');
331
+ let element = $('#js-element');
332
+ let target = $('#js-target');
333
+ let offsetX;
334
+ let offsetY;
340
335
 
341
336
  function position() {
342
- util.positionAt(
337
+ positionAt(
343
338
  element,
344
339
  target,
345
- $('#js-element_x').value + ' ' + $('#js-element_y').value,
346
- $('#js-target_x').value + ' ' + $('#js-target_y').value,
347
- $('#js-offset_x').value + ' ' + $('#js-offset_y').value,
348
- null,
349
- $('#js-flip_x').value + $('#js-flip_y').value,
350
- boundary
340
+ {
341
+ viewport,
342
+ attach:{
343
+ element: [$('#js-element_x').value, $('#js-element_y').value],
344
+ target: [$('#js-target_x').value, $('#js-target_y').value]
345
+ },
346
+ offset: [$('#js-offset_x').value, $('#js-offset_y').value],
347
+ flip: [$('#js-flip_x').value, $('#js-flip_y').value]
348
+ }
351
349
  );
352
350
  }
353
351
 
@@ -359,33 +357,34 @@
359
357
 
360
358
  });
361
359
 
360
+ let lastPos;
362
361
  on(window, 'dragover', function (e) {
363
362
 
364
- e.preventDefault();
365
-
366
- if (!ticking) {
367
- requestAnimationFrame(function () {
363
+ const pos = getEventPos(e);
368
364
 
369
- util.positionAt(
370
- target,
371
- boundary,
372
- 'left top',
373
- 'left top',
374
- (e.pageX - offset(boundary).left - offsetX) + ' ' + (e.pageY - offset(boundary).top - offsetY)
375
- );
365
+ if (lastPos?.x === pos.x && lastPos?.y === pos.y) {
366
+ return;
367
+ }
368
+ lastPos = pos;
376
369
 
377
- position();
370
+ e.preventDefault();
378
371
 
379
- ticking = false;
380
- });
381
- ticking = true;
382
- }
372
+ // positions target at mouse cursor
373
+ positionAt(
374
+ target,
375
+ viewport,
376
+ {
377
+ offset: [e.pageX - offset(viewport).left - offsetX, e.pageY - offset(viewport).top - offsetY]
378
+ }
379
+ );
383
380
 
381
+ // positions element at target
382
+ position();
384
383
  });
385
384
 
386
- util.$$('select,input').forEach(el => on(el, 'change', position));
385
+ on($$('select,input'), 'change', position);
386
+ on(window, 'scroll', position);
387
387
 
388
- util.css(element, 'display', 'block');
389
388
  position();
390
389
 
391
390
  </script>