uikit 3.25.29-dev.3bc1304 → 3.25.29-dev.a0b5ca8
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 +20 -0
- package/dist/css/uikit-core-rtl.css +1 -1
- package/dist/css/uikit-core-rtl.min.css +1 -1
- package/dist/css/uikit-core.css +1 -1
- package/dist/css/uikit-core.min.css +1 -1
- package/dist/css/uikit-rtl.css +1 -1
- package/dist/css/uikit-rtl.min.css +1 -1
- package/dist/css/uikit.css +1 -1
- 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 +2 -2
- package/dist/js/components/filter.min.js +1 -1
- package/dist/js/components/lightbox-panel.js +16 -12
- package/dist/js/components/lightbox-panel.min.js +1 -1
- package/dist/js/components/lightbox.js +16 -12
- 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 +11 -15
- package/dist/js/components/parallax.min.js +1 -1
- package/dist/js/components/slider-parallax.js +11 -15
- package/dist/js/components/slider-parallax.min.js +1 -1
- package/dist/js/components/slider.js +11 -15
- package/dist/js/components/slider.min.js +1 -1
- package/dist/js/components/slideshow-parallax.js +11 -15
- package/dist/js/components/slideshow-parallax.min.js +1 -1
- package/dist/js/components/slideshow.js +11 -15
- 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 +1 -1
- 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 +63 -52
- 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 +66 -55
- package/dist/js/uikit.min.js +1 -1
- package/package.json +1 -1
- package/src/js/components/lightbox-panel.js +3 -3
- package/src/js/core/dropnav.js +1 -1
- package/src/js/core/grid.js +1 -1
- package/src/js/core/icon.js +3 -1
- package/src/js/core/img.js +3 -3
- package/src/js/core/inverse.js +4 -2
- package/src/js/core/margin.js +1 -1
- package/src/js/core/modal.js +1 -1
- package/src/js/core/overflow-fade.js +6 -2
- package/src/js/core/svg.js +5 -1
- package/src/js/core/switcher.js +1 -0
- package/src/js/util/filter.js +6 -1
- package/src/js/util/lang.js +8 -33
- package/src/js/util/scroll.js +14 -9
- package/src/js/util/svg.js +7 -6
- 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.
|
|
5
|
+
"version": "3.25.29-dev.a0b5ca8",
|
|
6
6
|
"main": "dist/js/uikit.js",
|
|
7
7
|
"style": "dist/css/uikit.css",
|
|
8
8
|
"sideEffects": [
|
|
@@ -344,7 +344,7 @@ export default {
|
|
|
344
344
|
try {
|
|
345
345
|
const { height, width } = await (
|
|
346
346
|
await fetch(
|
|
347
|
-
`https://vimeo.com/api/oembed.json?maxwidth=1920&url=${
|
|
347
|
+
`https://vimeo.com/api/oembed.json?maxwidth=1920&url=${encodeURIComponent(
|
|
348
348
|
src,
|
|
349
349
|
)}`,
|
|
350
350
|
{ credentials: 'omit' },
|
|
@@ -463,9 +463,9 @@ function toThumbnavItem(item, videoAutoplay) {
|
|
|
463
463
|
}
|
|
464
464
|
|
|
465
465
|
function isImage(src) {
|
|
466
|
-
return src?.match(/\.(avif|jpe?g|jfif|a?png|gif|svg|webp)(
|
|
466
|
+
return src?.match(/\.(avif|jpe?g|jfif|a?png|gif|svg|webp)($|[?#])/i);
|
|
467
467
|
}
|
|
468
468
|
|
|
469
469
|
function isVideo(src) {
|
|
470
|
-
return src?.match(/\.(mp4|webm|ogv)(
|
|
470
|
+
return src?.match(/\.(mp4|webm|ogv)($|[?#])/i);
|
|
471
471
|
}
|
package/src/js/core/dropnav.js
CHANGED
package/src/js/core/grid.js
CHANGED
package/src/js/core/icon.js
CHANGED
|
@@ -251,7 +251,9 @@ function install(UIkit) {
|
|
|
251
251
|
if (UIkit._initialized) {
|
|
252
252
|
apply(document.body, (el) =>
|
|
253
253
|
each(UIkit.getComponents(el), (cmp) => {
|
|
254
|
-
cmp.$options.isIcon &&
|
|
254
|
+
cmp.$options.isIcon &&
|
|
255
|
+
(aliases[cmp.icon] || cmp.icon) in added &&
|
|
256
|
+
cmp.$reset();
|
|
255
257
|
}),
|
|
256
258
|
);
|
|
257
259
|
}
|
package/src/js/core/img.js
CHANGED
|
@@ -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
|
-
|
|
92
|
-
|
|
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
|
}
|
package/src/js/core/inverse.js
CHANGED
|
@@ -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
|
|
75
|
+
return transitionObserver.observe(e.target);
|
|
75
76
|
}),
|
|
76
77
|
on(document, 'shown hidden transitionend transitioncancel', (e) => {
|
|
77
78
|
handler();
|
|
78
|
-
return
|
|
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
|
};
|
package/src/js/core/margin.js
CHANGED
package/src/js/core/modal.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
117
|
+
once(document, [pointerUp, pointerCancel], end, true);
|
|
114
118
|
|
|
115
119
|
function move(e) {
|
|
116
120
|
let origin = getEventPos(e);
|
package/src/js/core/svg.js
CHANGED
|
@@ -51,7 +51,11 @@ export default {
|
|
|
51
51
|
methods: {
|
|
52
52
|
async getSvg() {
|
|
53
53
|
if (isTag(this.$el, 'img') && !this.$el.complete && this.$el.loading === 'lazy') {
|
|
54
|
-
await new Promise((resolve) =>
|
|
54
|
+
await new Promise((resolve, reject) =>
|
|
55
|
+
once(this.$el, 'load error', (event) =>
|
|
56
|
+
event.type === 'load' ? resolve() : reject(event),
|
|
57
|
+
),
|
|
58
|
+
);
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
return parseSVG(await loadSVG(this.src), this.icon) || Promise.reject('SVG not found.');
|
package/src/js/core/switcher.js
CHANGED
package/src/js/util/filter.js
CHANGED
|
@@ -83,7 +83,12 @@ export function isSameSiteAnchor(el) {
|
|
|
83
83
|
export function getTargetedElement(el) {
|
|
84
84
|
if (isSameSiteAnchor(el)) {
|
|
85
85
|
const { hash, ownerDocument } = toNode(el);
|
|
86
|
-
|
|
86
|
+
let id = hash.slice(1);
|
|
87
|
+
try {
|
|
88
|
+
id = decodeURIComponent(id);
|
|
89
|
+
} catch {
|
|
90
|
+
// Fall back to the literal fragment for malformed encoding.
|
|
91
|
+
}
|
|
87
92
|
return id
|
|
88
93
|
? ownerDocument.getElementById(id) || ownerDocument.getElementsByName(id)[0]
|
|
89
94
|
: ownerDocument.documentElement;
|
package/src/js/util/lang.js
CHANGED
|
@@ -211,44 +211,19 @@ export function pointInRect(point, rect) {
|
|
|
211
211
|
);
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
function
|
|
215
|
-
const
|
|
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
|
-
|
|
219
|
-
|
|
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
|
-
|
|
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);
|
package/src/js/util/scroll.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { css, getEventPos, matches, on, once, resetProps, scrollParents, width } from 'uikit-util';
|
|
2
2
|
|
|
3
|
-
let
|
|
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
|
-
|
|
53
|
+
|
|
54
|
+
if (!scrollLocks++) {
|
|
55
|
+
css(scrollingElement, props);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let released = false;
|
|
59
59
|
return () => {
|
|
60
|
-
|
|
60
|
+
if (released) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
released = true;
|
|
61
64
|
off();
|
|
62
|
-
|
|
65
|
+
if (!--scrollLocks) {
|
|
66
|
+
resetProps(scrollingElement, props);
|
|
67
|
+
}
|
|
63
68
|
};
|
|
64
69
|
}
|
package/src/js/util/svg.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { $$ } from './dom';
|
|
2
|
-
import { isVisible } from './filter.js';
|
|
3
2
|
|
|
4
3
|
export function getMaxPathLength(el) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
try {
|
|
5
|
+
return Math.ceil(
|
|
6
|
+
Math.max(0, ...$$('[stroke]', el).map((stroke) => stroke.getTotalLength?.() || 0)),
|
|
7
|
+
);
|
|
8
|
+
} catch {
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
10
11
|
}
|
|
@@ -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
|
+
});
|