uikit 3.25.29-dev.7b0f736 → 3.25.29-dev.f3e1c53

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 (57) hide show
  1. package/CHANGELOG.md +19 -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 +3 -3
  13. package/dist/js/components/filter.min.js +1 -1
  14. package/dist/js/components/lightbox-panel.js +14 -10
  15. package/dist/js/components/lightbox-panel.min.js +1 -1
  16. package/dist/js/components/lightbox.js +14 -10
  17. package/dist/js/components/lightbox.min.js +1 -1
  18. package/dist/js/components/notification.js +5 -2
  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 +2 -2
  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 +2 -2
  29. package/dist/js/components/slideshow.min.js +1 -1
  30. package/dist/js/components/sortable.js +2 -2
  31. package/dist/js/components/sortable.min.js +1 -1
  32. package/dist/js/components/tooltip.js +1 -1
  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 +51 -58
  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 +51 -58
  41. package/dist/js/uikit.min.js +1 -1
  42. package/package.json +1 -1
  43. package/src/js/core/alert.js +6 -3
  44. package/src/js/core/dropnav.js +1 -1
  45. package/src/js/core/grid.js +1 -1
  46. package/src/js/core/icon.js +6 -12
  47. package/src/js/core/img.js +3 -3
  48. package/src/js/core/inverse.js +4 -2
  49. package/src/js/core/margin.js +1 -1
  50. package/src/js/core/modal.js +1 -1
  51. package/src/js/core/overflow-fade.js +6 -2
  52. package/src/js/core/switcher.js +1 -0
  53. package/src/js/mixin/event.js +4 -1
  54. package/src/js/util/lang.js +8 -33
  55. package/src/js/util/scroll.js +14 -9
  56. package/tests/alert.html +2 -2
  57. package/tests/overflow-fade.test.mjs +69 -0
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.25.29-dev.7b0f736",
5
+ "version": "3.25.29-dev.f3e1c53",
6
6
  "main": "dist/js/uikit.js",
7
7
  "style": "dist/css/uikit.css",
8
8
  "sideEffects": [
@@ -9,12 +9,11 @@ export default {
9
9
  args: 'animation',
10
10
 
11
11
  props: {
12
- animation: Boolean,
13
12
  close: String,
14
13
  },
15
14
 
16
15
  data: {
17
- animation: true,
16
+ animation: [true],
18
17
  selClose: '.uk-alert-close',
19
18
  duration: 150,
20
19
  },
@@ -32,7 +31,11 @@ export default {
32
31
 
33
32
  methods: {
34
33
  async close() {
35
- await this.toggleElement(this.$el, false, this.animation ? animate : false);
34
+ await this.toggleElement(
35
+ this.$el,
36
+ false,
37
+ this.animation[0] === true || this.animation[0] === 1 ? animate : true,
38
+ );
36
39
  this.$destroy(true);
37
40
  },
38
41
  },
@@ -210,7 +210,7 @@ export default {
210
210
  elements,
211
211
  findIndex(elements, (el) => matches(el, ':focus')),
212
212
  )
213
- ].focus();
213
+ ]?.focus();
214
214
  return;
215
215
  }
216
216
 
@@ -132,7 +132,7 @@ export default {
132
132
  },
133
133
 
134
134
  write({ columns, scrolled, scrollColumns, translates }) {
135
- if (!scrolled && !translates) {
135
+ if (scrolled === false && !translates) {
136
136
  return;
137
137
  }
138
138
 
@@ -140,17 +140,9 @@ export const Search = {
140
140
  ? 'search-medium'
141
141
  : this.$props.icon;
142
142
 
143
- if (hasAttr(this.$el, 'aria-label')) {
144
- return;
145
- }
146
-
147
- if (isToggle) {
148
- this.$el.ariaLabel = this.t('toggle');
149
- } else {
150
- const button = this.$el.closest('a,button');
151
- if (button) {
152
- button.ariaLabel = this.t('submit');
153
- }
143
+ const target = isToggle ? this.$el : this.$el.closest('a,button');
144
+ if (target && !hasAttr(target, 'aria-label')) {
145
+ target.ariaLabel = this.t(isToggle ? 'toggle' : 'submit');
154
146
  }
155
147
  },
156
148
  };
@@ -259,7 +251,9 @@ function install(UIkit) {
259
251
  if (UIkit._initialized) {
260
252
  apply(document.body, (el) =>
261
253
  each(UIkit.getComponents(el), (cmp) => {
262
- cmp.$options.isIcon && cmp.icon in added && cmp.$reset();
254
+ cmp.$options.isIcon &&
255
+ (aliases[cmp.icon] || cmp.icon) in added &&
256
+ cmp.$reset();
263
257
  }),
264
258
  );
265
259
  }
@@ -7,7 +7,6 @@ import {
7
7
  data,
8
8
  escape,
9
9
  fragment,
10
- includes,
11
10
  isArray,
12
11
  isEmpty,
13
12
  isTag,
@@ -88,8 +87,9 @@ function setSrcAttrs(el, src) {
88
87
  const elements = isTag(parentNode, 'picture') ? children(parentNode) : [el];
89
88
  elements.forEach((el) => setSourceProps(el, el));
90
89
  } else if (src) {
91
- if (!includes(el.style.backgroundImage, src)) {
92
- css(el, 'backgroundImage', `url(${escape(src)})`);
90
+ const previousBackground = el.style.backgroundImage;
91
+ css(el, 'backgroundImage', `url(${escape(src)})`);
92
+ if (el.style.backgroundImage !== previousBackground) {
93
93
  trigger(el, createEvent('load', false));
94
94
  }
95
95
  }
@@ -64,6 +64,7 @@ export default {
64
64
  [...toNodes(target), document.documentElement],
65
65
  handler,
66
66
  );
67
+ const transitionObserver = observeResize([], handler);
67
68
  const listener = [
68
69
  on(document, 'scroll itemshown itemhidden', handler, {
69
70
  passive: true,
@@ -71,11 +72,11 @@ export default {
71
72
  }),
72
73
  on(document, 'show hide transitionstart', (e) => {
73
74
  handler();
74
- return observer.observe(e.target);
75
+ return transitionObserver.observe(e.target);
75
76
  }),
76
77
  on(document, 'shown hidden transitionend transitioncancel', (e) => {
77
78
  handler();
78
- return observer.unobserve(e.target);
79
+ return transitionObserver.unobserve(e.target);
79
80
  }),
80
81
  ];
81
82
 
@@ -84,6 +85,7 @@ export default {
84
85
  unobserve: observer.unobserve.bind(observer),
85
86
  disconnect() {
86
87
  observer.disconnect();
88
+ transitionObserver.disconnect();
87
89
  listener.forEach((off) => off());
88
90
  },
89
91
  };
@@ -85,7 +85,7 @@ export function getRows(elements) {
85
85
  const offsetCurrent = getOffset(current[0], withOffset);
86
86
 
87
87
  if (offset.top >= offsetCurrent.bottom - 1 && offset.top !== offsetCurrent.top) {
88
- sorted.push([el]);
88
+ sorted.splice(i + 1, 0, [el]);
89
89
  break;
90
90
  }
91
91
 
@@ -164,7 +164,7 @@ function install({ modal }) {
164
164
 
165
165
  return assign(
166
166
  new Promise((resolve) => {
167
- const off = on(dialog.$el, 'hide', () => resolve(hideFn()));
167
+ const off = on(dialog.$el, 'hide', () => resolve(hideFn()), { self: true });
168
168
 
169
169
  on(dialog.$el, 'submit', 'form', (e) => {
170
170
  e.preventDefault();
@@ -5,8 +5,10 @@ import {
5
5
  getEventPos,
6
6
  hasClass,
7
7
  isInput,
8
+ isRtl,
8
9
  isTouch,
9
10
  on,
11
+ once,
10
12
  pointerCancel,
11
13
  pointerDown,
12
14
  pointerMove,
@@ -73,7 +75,9 @@ export default {
73
75
 
74
76
  if (!overflow[i - 1]) {
75
77
  const dir = i ? 'Top' : 'Left';
76
- const percent = overflow[i] ? this.$el[`scroll${dir}`] / overflow[i] : 0;
78
+ // The horizontal mask runs left to right, even in RTL.
79
+ const position = this.$el[`scroll${dir}`] + (!i && isRtl ? overflow[i] : 0);
80
+ const percent = overflow[i] ? position / overflow[i] : 0;
77
81
 
78
82
  const toValue = (value) =>
79
83
  overflow[i] ? clamp((this.fadeDuration - value) / this.fadeDuration) : 1;
@@ -110,7 +114,7 @@ function handleMouseDrag(e) {
110
114
  let started;
111
115
 
112
116
  const off = on(document, pointerMove, move(e), pointerOptions);
113
- on(document, [pointerUp, pointerCancel], end, { capture: true, once: true });
117
+ once(document, [pointerUp, pointerCancel], end, true);
114
118
 
115
119
  function move(e) {
116
120
  let origin = getEventPos(e);
@@ -108,6 +108,7 @@ export default {
108
108
 
109
109
  handler(e) {
110
110
  if (
111
+ !e.defaultPrevented &&
111
112
  !matches(e.current, selDisabled) &&
112
113
  (e.type === 'click' || e.keyCode === keyMap.SPACE)
113
114
  ) {
@@ -3,7 +3,10 @@ import { on, once } from '../util/event';
3
3
  import { keyMap } from '../util/keys';
4
4
 
5
5
  export function maybeDefaultPreventClick(e) {
6
- if (e.target.closest('a[href="#"],a[href=""]')) {
6
+ if (
7
+ (e.type === 'keydown' && e.keyCode === keyMap.SPACE) ||
8
+ e.target.closest('a[href="#"],a[href=""]')
9
+ ) {
7
10
  e.preventDefault();
8
11
  }
9
12
  }
@@ -211,44 +211,19 @@ export function pointInRect(point, rect) {
211
211
  );
212
212
  }
213
213
 
214
- function ratio(dimensions, prop, value) {
215
- const aProp = prop === 'width' ? 'height' : 'width';
214
+ function cover(dimensions, maxDimensions) {
215
+ const scale = Math.max(
216
+ dimensions.width ? maxDimensions.width / dimensions.width : 0,
217
+ dimensions.height ? maxDimensions.height / dimensions.height : 0,
218
+ );
216
219
 
217
220
  return {
218
- [aProp]: dimensions[prop]
219
- ? Math.round((value * dimensions[aProp]) / dimensions[prop])
220
- : dimensions[aProp],
221
- [prop]: value,
221
+ width: Math.round(dimensions.width * scale),
222
+ height: Math.round(dimensions.height * scale),
222
223
  };
223
224
  }
224
225
 
225
- function contain(dimensions, maxDimensions) {
226
- dimensions = { ...dimensions };
227
-
228
- for (const prop in dimensions) {
229
- dimensions =
230
- dimensions[prop] > maxDimensions[prop]
231
- ? ratio(dimensions, prop, maxDimensions[prop])
232
- : dimensions;
233
- }
234
-
235
- return dimensions;
236
- }
237
-
238
- function cover(dimensions, maxDimensions) {
239
- dimensions = contain(dimensions, maxDimensions);
240
-
241
- for (const prop in dimensions) {
242
- dimensions =
243
- dimensions[prop] < maxDimensions[prop]
244
- ? ratio(dimensions, prop, maxDimensions[prop])
245
- : dimensions;
246
- }
247
-
248
- return dimensions;
249
- }
250
-
251
- export const Dimensions = { ratio, contain, cover };
226
+ export const Dimensions = { cover };
252
227
 
253
228
  export function getIndex(i, elements, current = 0, finite = false) {
254
229
  elements = toNodes(elements);
@@ -1,6 +1,6 @@
1
1
  import { css, getEventPos, matches, on, once, resetProps, scrollParents, width } from 'uikit-util';
2
2
 
3
- let prevented;
3
+ let scrollLocks = 0;
4
4
  export function preventBackgroundScroll(el) {
5
5
  // 'overscroll-behavior: contain' only works consistently if el overflows (Safari)
6
6
  const off = on(
@@ -44,21 +44,26 @@ export function preventBackgroundScroll(el) {
44
44
  { passive: true },
45
45
  );
46
46
 
47
- if (prevented) {
48
- return off;
49
- }
50
- prevented = true;
51
-
52
47
  const { scrollingElement } = document;
53
48
  const props = {
54
49
  overflowY: CSS.supports('overflow', 'clip') ? 'clip' : 'hidden',
55
50
  touchAction: 'none',
56
51
  scrollbarGutter: width(window) - scrollingElement.clientWidth ? 'stable' : '',
57
52
  };
58
- css(scrollingElement, props);
53
+
54
+ if (!scrollLocks++) {
55
+ css(scrollingElement, props);
56
+ }
57
+
58
+ let released = false;
59
59
  return () => {
60
- prevented = false;
60
+ if (released) {
61
+ return;
62
+ }
63
+ released = true;
61
64
  off();
62
- resetProps(scrollingElement, props);
65
+ if (!--scrollLocks) {
66
+ resetProps(scrollingElement, props);
67
+ }
63
68
  };
64
69
  }
package/tests/alert.html CHANGED
@@ -98,9 +98,9 @@
98
98
  <tbody>
99
99
  <tr>
100
100
  <td><code>animation</code></td>
101
- <td>Boolean</td>
101
+ <td>Boolean, String</td>
102
102
  <td>true</td>
103
- <td>On close fade out.</td>
103
+ <td>On close fade out. Set to false to disable animation or specify an animation class.</td>
104
104
  </tr>
105
105
  <tr>
106
106
  <td><code>duration</code></td>
@@ -0,0 +1,69 @@
1
+ import assert from 'node:assert/strict';
2
+ import { readFile } from 'node:fs/promises';
3
+ import test from 'node:test';
4
+ import vm from 'node:vm';
5
+
6
+ const source = await readFile(new URL('../src/js/core/overflow-fade.js', import.meta.url), 'utf8');
7
+ function loadComponent(direction) {
8
+ return vm.runInNewContext(
9
+ source.replace(/^import[\s\S]*?from '[^']+';\s*/gm, '').replace('export default', 'component ='),
10
+ {
11
+ clamp: (value) => Math.min(1, Math.max(0, value)),
12
+ isRtl: direction === 'rtl',
13
+ css: (el, value) => (typeof value === 'string' ? el[value] : Object.assign(el.style, value)),
14
+ mutation: () => ({}),
15
+ resize: () => ({}),
16
+ toggleClass: () => {},
17
+ pointerDown: 'pointerdown',
18
+ },
19
+ );
20
+ }
21
+
22
+ function getOpacities(direction, scrollLeft, scrollTop = 0, horizontal = 200, vertical = 0) {
23
+ const component = loadComponent(direction);
24
+ const context = {
25
+ $el: {
26
+ direction,
27
+ scrollLeft,
28
+ scrollTop,
29
+ scrollWidth: 100 + horizontal,
30
+ clientWidth: 100,
31
+ scrollHeight: 100 + vertical,
32
+ clientHeight: 100,
33
+ style: {},
34
+ },
35
+ $options: { id: 'uk-overflow-fade' },
36
+ ...component.data,
37
+ };
38
+ component.update.write.call(context, component.update.read.call(context));
39
+ return [
40
+ context.$el.style['--uk-overflow-fade-start-opacity'],
41
+ context.$el.style['--uk-overflow-fade-end-opacity'],
42
+ ];
43
+ }
44
+
45
+ test('RTL horizontal fades follow physical left and right edges', () => {
46
+ assert.deepEqual(getOpacities('rtl', 0), [0, 1]);
47
+ assert.deepEqual(getOpacities('rtl', -100), [0, 0]);
48
+ assert.deepEqual(getOpacities('rtl', -200), [1, 0]);
49
+ });
50
+
51
+ test('LTR horizontal fades are unchanged', () => {
52
+ assert.deepEqual(getOpacities('ltr', 0), [1, 0]);
53
+ assert.deepEqual(getOpacities('ltr', 100), [0, 0]);
54
+ assert.deepEqual(getOpacities('ltr', 200), [0, 1]);
55
+ });
56
+
57
+ test('vertical fades are independent of direction', () => {
58
+ for (const direction of ['ltr', 'rtl']) {
59
+ assert.deepEqual(getOpacities(direction, 0, 0, 0, 200), [1, 0]);
60
+ assert.deepEqual(getOpacities(direction, 0, 100, 0, 200), [0, 0]);
61
+ assert.deepEqual(getOpacities(direction, 0, 200, 0, 200), [0, 1]);
62
+ }
63
+ });
64
+
65
+ test('elements without overflow remain opaque', () => {
66
+ for (const direction of ['ltr', 'rtl']) {
67
+ assert.deepEqual(getOpacities(direction, 0, 0, 0), [1, 1]);
68
+ }
69
+ });