uikit 3.19.5-dev.66a60877b → 3.19.5-dev.74c343fa4

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 (62) hide show
  1. package/CHANGELOG.md +2 -1
  2. package/dist/css/uikit-core-rtl.css +2 -2
  3. package/dist/css/uikit-core-rtl.min.css +1 -1
  4. package/dist/css/uikit-core.css +2 -2
  5. package/dist/css/uikit-core.min.css +1 -1
  6. package/dist/css/uikit-rtl.css +2 -2
  7. package/dist/css/uikit-rtl.min.css +1 -1
  8. package/dist/css/uikit.css +2 -2
  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 +87 -87
  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 +40 -30
  21. package/dist/js/components/parallax.min.js +1 -1
  22. package/dist/js/components/slider-parallax.js +40 -30
  23. package/dist/js/components/slider-parallax.min.js +1 -1
  24. package/dist/js/components/slider.js +40 -30
  25. package/dist/js/components/slider.min.js +1 -1
  26. package/dist/js/components/slideshow-parallax.js +40 -30
  27. package/dist/js/components/slideshow-parallax.min.js +1 -1
  28. package/dist/js/components/slideshow.js +40 -30
  29. package/dist/js/components/slideshow.min.js +1 -1
  30. package/dist/js/components/sortable.js +87 -87
  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 +81 -74
  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 +167 -163
  41. package/dist/js/uikit.min.js +1 -1
  42. package/package.json +1 -1
  43. package/src/js/api/computed.js +20 -26
  44. package/src/js/core/height-placeholder.js +4 -1
  45. package/src/js/core/margin.js +5 -0
  46. package/src/js/core/modal.js +5 -6
  47. package/src/js/core/scrollspy.js +0 -3
  48. package/src/js/core/sticky.js +1 -1
  49. package/src/js/core/switcher.js +4 -1
  50. package/src/js/core/toggle.js +6 -3
  51. package/src/js/mixin/internal/animate-fade.js +2 -7
  52. package/src/js/mixin/internal/animate-slide.js +2 -7
  53. package/src/js/mixin/parallax.js +7 -3
  54. package/src/js/util/fastdom.js +6 -13
  55. package/src/js/util/filter.js +6 -3
  56. package/src/js/util/selector.js +31 -22
  57. package/src/js/util/svg.js +4 -1
  58. package/src/less/components/utility.less +1 -1
  59. package/src/scss/components/utility.scss +1 -1
  60. package/tests/base.html +1 -1
  61. package/tests/js/index.js +12 -10
  62. package/tests/switcher.html +86 -86
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.19.5-dev.66a60877b",
5
+ "version": "3.19.5-dev.74c343fa4",
6
6
  "main": "dist/js/uikit.js",
7
7
  "style": "dist/css/uikit.css",
8
8
  "sideEffects": [
@@ -1,6 +1,6 @@
1
- import { hasOwn, isUndefined } from 'uikit-util';
2
- import { callUpdate, prependUpdate } from './update';
3
- import { runWatches } from './watch';
1
+ import { hasOwn, isUndefined, observeMutation } from 'uikit-util';
2
+ import { callUpdate, prependUpdate } from './update.js';
3
+ import { runWatches } from './watch.js';
4
4
 
5
5
  export function initComputed(instance) {
6
6
  const { computed } = instance.$options;
@@ -13,7 +13,7 @@ export function initComputed(instance) {
13
13
  }
14
14
  }
15
15
  }
16
-
16
+ const mutationOptions = { subtree: true, childList: true };
17
17
  export function registerComputed(instance, key, cb) {
18
18
  instance._hasComputed = true;
19
19
  Object.defineProperty(instance, key, {
@@ -24,6 +24,15 @@ export function registerComputed(instance, key, cb) {
24
24
 
25
25
  if (!hasOwn(_computed, key)) {
26
26
  _computed[key] = (cb.get || cb).call(instance, $props, $el);
27
+ if (cb.observe && instance._computedObserver) {
28
+ const selector = cb.observe.call(instance, $props);
29
+ instance._computedObserver.observe(
30
+ ['~', '+', '-'].includes(selector[0])
31
+ ? $el.parentElement
32
+ : $el.getRootNode(),
33
+ mutationOptions,
34
+ );
35
+ }
27
36
  }
28
37
 
29
38
  return _computed[key];
@@ -51,12 +60,16 @@ export function initComputedUpdates(instance) {
51
60
  events: ['resize', 'computed'],
52
61
  });
53
62
 
54
- registerComputedObserver();
55
- instances.add(instance);
63
+ instance._computedObserver = observeMutation(
64
+ instance.$el,
65
+ () => callUpdate(instance, 'computed'),
66
+ mutationOptions,
67
+ );
56
68
  }
57
69
 
58
70
  export function disconnectComputedUpdates(instance) {
59
- instances?.delete(instance);
71
+ instance._computedObserver?.disconnect();
72
+ delete instance._computedObserver;
60
73
  resetComputed(instance);
61
74
  }
62
75
 
@@ -65,22 +78,3 @@ function resetComputed(instance) {
65
78
  instance._computed = {};
66
79
  return values;
67
80
  }
68
-
69
- let observer;
70
- let instances;
71
- function registerComputedObserver() {
72
- if (observer) {
73
- return;
74
- }
75
-
76
- instances = new Set();
77
- observer = new MutationObserver(() => {
78
- for (const instance of instances) {
79
- callUpdate(instance, 'computed');
80
- }
81
- });
82
- observer.observe(document, {
83
- subtree: true,
84
- childList: true,
85
- });
86
- }
@@ -13,7 +13,10 @@ export default {
13
13
  },
14
14
 
15
15
  computed: {
16
- target: ({ target }, $el) => query(target, $el),
16
+ target: {
17
+ get: ({ target }, $el) => query(target, $el),
18
+ observe: ({ target }) => target,
19
+ },
17
20
  },
18
21
 
19
22
  observe: resize({ target: ({ target }) => target }),
@@ -13,6 +13,11 @@ export default {
13
13
  },
14
14
 
15
15
  observe: [
16
+ mutation({
17
+ options: {
18
+ childList: true,
19
+ },
20
+ }),
16
21
  mutation({
17
22
  options: {
18
23
  attributes: true,
@@ -70,12 +70,11 @@ export default {
70
70
 
71
71
  function install({ modal }) {
72
72
  modal.dialog = function (content, options) {
73
- const dialog = modal(
74
- `<div class="uk-modal">
75
- <div class="uk-modal-dialog">${content}</div>
76
- </div>`,
77
- { stack: true, role: 'alertdialog', ...options },
78
- );
73
+ const dialog = modal($(`<div><div class="uk-modal-dialog">${content}</div></div>`), {
74
+ stack: true,
75
+ role: 'alertdialog',
76
+ ...options,
77
+ });
79
78
 
80
79
  dialog.show();
81
80
 
@@ -135,9 +135,6 @@ export default {
135
135
  trigger(el, inview ? 'inview' : 'outview');
136
136
 
137
137
  state.inview = inview;
138
-
139
- // change to `visibility: hidden` does not trigger observers
140
- this.$update(el);
141
138
  },
142
139
  },
143
140
  };
@@ -109,7 +109,7 @@ export default {
109
109
  target: () => document.scrollingElement,
110
110
  options: { box: 'content-box' },
111
111
  }),
112
- resize({ target: ({ $el }) => $el }),
112
+ resize(),
113
113
  ],
114
114
 
115
115
  events: [
@@ -50,7 +50,10 @@ export default {
50
50
  },
51
51
 
52
52
  computed: {
53
- connects: ({ connect }, $el) => queryAll(connect, $el),
53
+ connects: {
54
+ get: ({ connect }, $el) => queryAll(connect, $el),
55
+ observe: ({ connect }) => connect,
56
+ },
54
57
 
55
58
  connectChildren() {
56
59
  return this.connects.map((el) => children(el)).flat();
@@ -41,9 +41,12 @@ export default {
41
41
  },
42
42
 
43
43
  computed: {
44
- target({ target }, $el) {
45
- target = queryAll(target || $el.hash, $el);
46
- return target.length ? target : [$el];
44
+ target: {
45
+ get: ({ target }, $el) => {
46
+ target = queryAll(target || $el.hash, $el);
47
+ return target.length ? target : [$el];
48
+ },
49
+ observe: ({ target }) => target,
47
50
  },
48
51
  },
49
52
 
@@ -11,6 +11,7 @@ import {
11
11
  Transition,
12
12
  } from 'uikit-util';
13
13
  import { getRows } from '../../core/margin';
14
+ import { awaitFrame } from './animate-slide.js';
14
15
 
15
16
  const clsLeave = 'uk-transition-leave';
16
17
  const clsEnter = 'uk-transition-enter';
@@ -117,13 +118,7 @@ function waitTransitionend(target) {
117
118
  }
118
119
 
119
120
  function getTransitionNodes(target) {
120
- return getRows(children(target))
121
- .flat()
122
- .filter((node) => isVisible(node));
123
- }
124
-
125
- function awaitFrame() {
126
- return new Promise((resolve) => requestAnimationFrame(resolve));
121
+ return getRows(children(target)).flat().filter(isVisible);
127
122
  }
128
123
 
129
124
  function awaitTimeout(timeout) {
@@ -2,7 +2,6 @@ import {
2
2
  attr,
3
3
  children,
4
4
  css,
5
- fastdom,
6
5
  includes,
7
6
  index,
8
7
  isVisible,
@@ -26,7 +25,7 @@ export default async function (action, target, duration) {
26
25
  await Promise.all(nodes.concat(target).map(Transition.cancel));
27
26
 
28
27
  // Adding, sorting, removing nodes
29
- action();
28
+ await action();
30
29
 
31
30
  // Find new nodes
32
31
  nodes = nodes.concat(children(target).filter((el) => !includes(nodes, el)));
@@ -34,9 +33,6 @@ export default async function (action, target, duration) {
34
33
  // Wait for update to propagate
35
34
  await Promise.resolve();
36
35
 
37
- // Force update
38
- fastdom.flush();
39
-
40
36
  // Get new state
41
37
  const targetStyle = attr(target, 'style');
42
38
  const targetPropsTo = css(target, ['height', 'padding']);
@@ -49,7 +45,6 @@ export default async function (action, target, duration) {
49
45
 
50
46
  // Trigger update in e.g. parallax component
51
47
  trigger(target, 'scroll');
52
- fastdom.flush();
53
48
 
54
49
  // Start transitions on next frame
55
50
  await awaitFrame();
@@ -142,6 +137,6 @@ function getPositionWithMargin(el) {
142
137
  };
143
138
  }
144
139
 
145
- function awaitFrame() {
140
+ export function awaitFrame() {
146
141
  return new Promise((resolve) => requestAnimationFrame(resolve));
147
142
  }
@@ -7,6 +7,7 @@ import {
7
7
  isString,
8
8
  isUndefined,
9
9
  noop,
10
+ once,
10
11
  propName,
11
12
  toFloat,
12
13
  toPx,
@@ -271,6 +272,7 @@ function setBackgroundPosFn(bgProps, positions, props) {
271
272
  };
272
273
  }
273
274
 
275
+ const loading = {};
274
276
  const dimensions = {};
275
277
  function getBackgroundImageDimensions(el) {
276
278
  const src = css(el, 'backgroundImage').replace(/^none|url\(["']?(.+?)["']?\)$/, '$1');
@@ -283,11 +285,13 @@ function getBackgroundImageDimensions(el) {
283
285
  if (src) {
284
286
  image.src = src;
285
287
 
286
- if (!image.naturalWidth) {
287
- image.onload = () => {
288
+ if (!image.naturalWidth && !loading[src]) {
289
+ once(image, 'error load', () => {
288
290
  dimensions[src] = toDimensions(image);
289
291
  trigger(el, createEvent('load', false));
290
- };
292
+ });
293
+ loading[src] = true;
294
+
291
295
  return toDimensions(image);
292
296
  }
293
297
  }
@@ -28,28 +28,21 @@ export const fastdom = {
28
28
  flush,
29
29
  };
30
30
 
31
- function flush(recursion) {
31
+ function flush() {
32
32
  runTasks(fastdom.reads);
33
33
  runTasks(fastdom.writes.splice(0));
34
34
 
35
35
  fastdom.scheduled = false;
36
36
 
37
37
  if (fastdom.reads.length || fastdom.writes.length) {
38
- scheduleFlush(recursion + 1);
38
+ scheduleFlush();
39
39
  }
40
40
  }
41
41
 
42
- const RECURSION_LIMIT = 4;
43
- function scheduleFlush(recursion) {
44
- if (fastdom.scheduled) {
45
- return;
46
- }
47
-
48
- fastdom.scheduled = true;
49
- if (recursion && recursion < RECURSION_LIMIT) {
50
- Promise.resolve().then(() => flush(recursion));
51
- } else {
52
- requestAnimationFrame(() => flush(1));
42
+ function scheduleFlush() {
43
+ if (!fastdom.scheduled) {
44
+ fastdom.scheduled = true;
45
+ queueMicrotask(flush);
53
46
  }
54
47
  }
55
48
 
@@ -21,10 +21,13 @@ export function isVoidElement(element) {
21
21
  return toNodes(element).some((element) => voidElements[element.tagName.toLowerCase()]);
22
22
  }
23
23
 
24
+ const isVisibleFn =
25
+ Element.prototype.checkVisibility ||
26
+ function () {
27
+ return this.offsetWidth || this.offsetHeight || this.getClientRects().length;
28
+ };
24
29
  export function isVisible(element) {
25
- return toNodes(element).some(
26
- (element) => element.offsetWidth || element.offsetHeight || element.getClientRects().length,
27
- );
30
+ return toNodes(element).some((element) => isVisibleFn.call(element));
28
31
  }
29
32
 
30
33
  export const selInput = 'input,select,textarea,button';
@@ -35,10 +35,7 @@ const parseSelector = memoize((selector) => {
35
35
  const selectors = [];
36
36
  for (let sel of selector.match(splitSelectorRe) ?? []) {
37
37
  sel = sel.replace(trailingCommaRe, '').trim();
38
- if (sel[0] === '>') {
39
- sel = `:scope ${sel}`;
40
- }
41
- isContextSelector ||= ['!', '+', '~', '-'].includes(sel[0]);
38
+ isContextSelector ||= ['!', '+', '~', '-', '>'].includes(sel[0]);
42
39
  selectors.push(sel);
43
40
  }
44
41
 
@@ -49,6 +46,12 @@ const parseSelector = memoize((selector) => {
49
46
  };
50
47
  });
51
48
 
49
+ const parsePositionSelector = memoize((selector) => {
50
+ selector = selector.substr(1).trim();
51
+ const index = selector.indexOf(' ');
52
+ return ~index ? [selector.substring(0, index), selector.substring(index + 1)] : [selector, ''];
53
+ });
54
+
52
55
  function _query(selector, context = document, queryFn) {
53
56
  if (!selector || !isString(selector)) {
54
57
  return selector;
@@ -63,36 +66,42 @@ function _query(selector, context = document, queryFn) {
63
66
  selector = '';
64
67
  const isSingle = parsed.selectors.length === 1;
65
68
  for (let sel of parsed.selectors) {
69
+ let positionSel;
66
70
  let ctx = context;
67
71
 
68
72
  if (sel[0] === '!') {
69
- const selectors = sel.substr(1).trim().split(' ');
70
- ctx = context.parentElement.closest(selectors[0]);
71
- sel = selectors.slice(1).join(' ').trim();
72
- if (!sel.length && isSingle) {
73
+ [positionSel, sel] = parsePositionSelector(sel);
74
+ ctx = context.parentElement.closest(positionSel);
75
+ if (!sel && isSingle) {
73
76
  return ctx;
74
77
  }
75
78
  }
76
79
 
77
- if (sel[0] === '-') {
78
- const selectors = sel.substr(1).trim().split(' ');
79
- const prev = (ctx || context).previousElementSibling;
80
- ctx = matches(prev, sel.substr(1)) ? prev : null;
81
- sel = selectors.slice(1).join(' ');
82
- if (!sel.length && isSingle) {
80
+ if (ctx && sel[0] === '-') {
81
+ [positionSel, sel] = parsePositionSelector(sel);
82
+ ctx = ctx.previousElementSibling;
83
+ ctx = matches(ctx, positionSel) ? ctx : null;
84
+ if (!sel && isSingle) {
83
85
  return ctx;
84
86
  }
85
- } else if (sel[0] === '~' || (sel[0] === '+' && isSingle)) {
86
- return _doQuery(
87
- ctx.parentElement,
88
- queryFn,
89
- `:scope :nth-child(${index(ctx) + 1}) ${sel}`,
90
- );
91
87
  }
92
88
 
93
- if (ctx) {
94
- selector += `${selector ? ',' : ''}${domPath(ctx)} ${sel}`;
89
+ if (!ctx) {
90
+ continue;
91
+ }
92
+
93
+ if (isSingle) {
94
+ if (sel[0] === '~' || sel[0] === '+') {
95
+ sel = `:scope :nth-child(${index(ctx) + 1}) ${sel}`;
96
+ ctx = ctx.parentElement;
97
+ } else if (sel[0] === '>') {
98
+ sel = `:scope ${sel}`;
99
+ }
100
+
101
+ return _doQuery(ctx, queryFn, sel);
95
102
  }
103
+
104
+ selector += `${selector ? ',' : ''}${domPath(ctx)} ${sel}`;
96
105
  }
97
106
 
98
107
  if (!isDocument(context)) {
@@ -1,5 +1,8 @@
1
1
  import { $$ } from './dom';
2
+ import { isVisible } from './filter.js';
2
3
 
3
4
  export function getMaxPathLength(el) {
4
- return Math.ceil(Math.max(0, ...$$('[stroke]', el).map((stroke) => stroke.getTotalLength?.())));
5
+ return isVisible(el)
6
+ ? Math.ceil(Math.max(0, ...$$('[stroke]', el).map((stroke) => stroke.getTotalLength())))
7
+ : 0;
5
8
  }
@@ -129,7 +129,7 @@
129
129
  [class*="uk-float-"] { max-width: 100%; }
130
130
 
131
131
 
132
- /* Overfow
132
+ /* Overflow
133
133
  ========================================================================== */
134
134
 
135
135
  .uk-overflow-hidden { overflow: hidden; }
@@ -111,7 +111,7 @@
111
111
  [class*="uk-float-"] { max-width: 100%; }
112
112
 
113
113
 
114
- /* Overfow
114
+ /* Overflow
115
115
  ========================================================================== */
116
116
 
117
117
  .uk-overflow-hidden { overflow: hidden; }
package/tests/base.html CHANGED
@@ -233,7 +233,7 @@
233
233
 
234
234
  <h3>Audio</h3>
235
235
 
236
- <audio controls src="https://interactive-examples.mdn.mozilla.net/media/examples/t-rex-roar.mp3"></audio>
236
+ <audio controls src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"></audio>
237
237
 
238
238
  </div>
239
239
  </div>
package/tests/js/index.js CHANGED
@@ -5,7 +5,6 @@ const tests = TESTS;
5
5
  const storage = window.sessionStorage;
6
6
  const key = '_uikit_style';
7
7
  const keyinverse = '_uikit_inverse';
8
- const docEl = document.documentElement;
9
8
 
10
9
  // try to load themes.json
11
10
  const request = new XMLHttpRequest();
@@ -39,7 +38,7 @@ storage[keyinverse] = storage[keyinverse] || '';
39
38
  const dir = storage._uikit_dir || 'ltr';
40
39
 
41
40
  // set dir
42
- docEl.dir = dir;
41
+ document.documentElement.dir = dir;
43
42
 
44
43
  const style = styles[storage[key]] || styles.theme;
45
44
 
@@ -50,6 +49,10 @@ document.writeln(
50
49
  }">`,
51
50
  );
52
51
 
52
+ document.writeln(
53
+ `<style>html:not(:has(body :first-child [aria-label="Component switcher"])) {padding-top: 80px}</style>`,
54
+ );
55
+
53
56
  // add javascript
54
57
  document.writeln('<script src="../dist/js/uikit.js"></script>');
55
58
  document.writeln(
@@ -60,9 +63,8 @@ on(window, 'load', () =>
60
63
  setTimeout(
61
64
  () =>
62
65
  requestAnimationFrame(() => {
63
- const $body = document.body;
64
66
  const $container = prepend(
65
- $body,
67
+ document.body,
66
68
  `
67
69
  <div class="uk-container">
68
70
  <select class="uk-select uk-form-width-small" style="margin: 20px 20px 20px 0" aria-label="Component switcher">
@@ -144,8 +146,12 @@ on(window, 'load', () =>
144
146
 
145
147
  addClass($$('.uk-navbar-container'), 'uk-navbar-transparent');
146
148
 
147
- css(docEl, 'background', $inverse.value === 'dark' ? '#fff' : '#222');
148
- addClass($body, `uk-${$inverse.value}`);
149
+ css(
150
+ document.documentElement,
151
+ 'background',
152
+ $inverse.value === 'dark' ? '#fff' : '#222',
153
+ );
154
+ addClass(document.body, `uk-${$inverse.value}`);
149
155
  }
150
156
 
151
157
  on($inverse, 'change', () => {
@@ -161,15 +167,11 @@ on(window, 'load', () =>
161
167
  location.reload();
162
168
  });
163
169
  $rtl.firstElementChild.checked = dir === 'rtl';
164
-
165
- css(docEl, 'paddingTop', '');
166
170
  }),
167
171
  100,
168
172
  ),
169
173
  );
170
174
 
171
- css(docEl, 'paddingTop', '80px');
172
-
173
175
  function getParam(name) {
174
176
  const match = new RegExp(`[?&]${name}=([^&]*)`).exec(window.location.search);
175
177
  return match && decodeURIComponent(match[1].replace(/\+/g, ' '));