uikit 3.11.2-dev.3dfa2c50b → 3.11.2-dev.45194f70c

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 (147) hide show
  1. package/CHANGELOG.md +40 -19
  2. package/dist/css/uikit-core-rtl.css +86 -185
  3. package/dist/css/uikit-core-rtl.min.css +1 -1
  4. package/dist/css/uikit-core.css +86 -185
  5. package/dist/css/uikit-core.min.css +1 -1
  6. package/dist/css/uikit-rtl.css +88 -191
  7. package/dist/css/uikit-rtl.min.css +1 -1
  8. package/dist/css/uikit.css +88 -191
  9. package/dist/css/uikit.min.css +1 -1
  10. package/dist/js/components/countdown.js +3 -3
  11. package/dist/js/components/countdown.min.js +1 -1
  12. package/dist/js/components/filter.js +6 -8
  13. package/dist/js/components/filter.min.js +1 -1
  14. package/dist/js/components/lightbox-panel.js +29 -68
  15. package/dist/js/components/lightbox-panel.min.js +1 -1
  16. package/dist/js/components/lightbox.js +30 -70
  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 +115 -78
  21. package/dist/js/components/parallax.min.js +1 -1
  22. package/dist/js/components/slider-parallax.js +115 -78
  23. package/dist/js/components/slider-parallax.min.js +1 -1
  24. package/dist/js/components/slider.js +79 -58
  25. package/dist/js/components/slider.min.js +1 -1
  26. package/dist/js/components/slideshow-parallax.js +115 -78
  27. package/dist/js/components/slideshow-parallax.min.js +1 -1
  28. package/dist/js/components/slideshow.js +35 -29
  29. package/dist/js/components/slideshow.min.js +1 -1
  30. package/dist/js/components/sortable.js +5 -7
  31. package/dist/js/components/sortable.min.js +1 -1
  32. package/dist/js/components/tooltip.js +2 -2
  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 +408 -326
  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 +646 -528
  41. package/dist/js/uikit.min.js +1 -1
  42. package/package.json +1 -1
  43. package/src/js/api/component.js +2 -11
  44. package/src/js/api/hooks.js +3 -3
  45. package/src/js/api/state.js +34 -1
  46. package/src/js/components/countdown.js +2 -2
  47. package/src/js/components/filter.js +2 -3
  48. package/src/js/components/internal/lightbox-animations.js +4 -3
  49. package/src/js/components/internal/slider-preload.js +18 -0
  50. package/src/js/components/internal/slideshow-animations.js +4 -3
  51. package/src/js/components/lightbox-panel.js +34 -58
  52. package/src/js/components/lightbox.js +1 -2
  53. package/src/js/components/slider.js +60 -43
  54. package/src/js/components/slideshow.js +8 -1
  55. package/src/js/components/sortable.js +1 -1
  56. package/src/js/core/accordion.js +6 -1
  57. package/src/js/core/alert.js +1 -2
  58. package/src/js/core/core.js +2 -21
  59. package/src/js/core/cover.js +5 -1
  60. package/src/js/core/drop.js +3 -1
  61. package/src/js/core/form-custom.js +2 -2
  62. package/src/js/core/height-viewport.js +3 -0
  63. package/src/js/core/icon.js +13 -6
  64. package/src/js/core/img.js +131 -122
  65. package/src/js/core/modal.js +1 -2
  66. package/src/js/core/navbar.js +3 -3
  67. package/src/js/core/sticky.js +51 -57
  68. package/src/js/core/svg.js +10 -6
  69. package/src/js/core/switcher.js +6 -1
  70. package/src/js/core/toggle.js +5 -2
  71. package/src/js/core/video.js +13 -1
  72. package/src/js/mixin/internal/animate-slide.js +9 -12
  73. package/src/js/mixin/lazyload.js +16 -0
  74. package/src/js/mixin/parallax.js +116 -79
  75. package/src/js/mixin/slider.js +8 -22
  76. package/src/js/mixin/slideshow.js +2 -6
  77. package/src/js/mixin/togglable.js +1 -2
  78. package/src/js/util/ajax.js +15 -14
  79. package/src/js/util/animation.js +7 -12
  80. package/src/js/util/dimensions.js +4 -4
  81. package/src/js/util/dom.js +37 -31
  82. package/src/js/util/index.js +1 -0
  83. package/src/js/util/lang.js +7 -6
  84. package/src/js/util/observer.js +36 -0
  85. package/src/js/util/options.js +2 -11
  86. package/src/js/util/player.js +5 -4
  87. package/src/js/util/selector.js +12 -18
  88. package/src/js/util/style.js +4 -4
  89. package/src/less/components/base.less +10 -33
  90. package/src/less/components/form-range.less +48 -95
  91. package/src/less/components/form.less +0 -1
  92. package/src/less/components/height.less +3 -0
  93. package/src/less/components/leader.less +0 -1
  94. package/src/less/components/lightbox.less +0 -1
  95. package/src/less/components/modal.less +3 -7
  96. package/src/less/components/progress.less +14 -36
  97. package/src/less/components/slider.less +0 -3
  98. package/src/less/components/slideshow.less +0 -3
  99. package/src/less/components/text.less +16 -32
  100. package/src/scss/components/base.scss +10 -33
  101. package/src/scss/components/form-range.scss +48 -95
  102. package/src/scss/components/form.scss +0 -1
  103. package/src/scss/components/height.scss +3 -0
  104. package/src/scss/components/leader.scss +0 -1
  105. package/src/scss/components/lightbox.scss +0 -1
  106. package/src/scss/components/modal.scss +3 -7
  107. package/src/scss/components/progress.scss +14 -36
  108. package/src/scss/components/slider.scss +0 -3
  109. package/src/scss/components/slideshow.scss +0 -3
  110. package/src/scss/components/text.scss +16 -32
  111. package/src/scss/mixins-theme.scss +1 -1
  112. package/src/scss/mixins.scss +1 -1
  113. package/src/scss/variables-theme.scss +3 -3
  114. package/src/scss/variables.scss +3 -3
  115. package/tests/align.html +10 -10
  116. package/tests/animation.html +2 -2
  117. package/tests/article.html +2 -2
  118. package/tests/base.html +3 -3
  119. package/tests/card.html +10 -10
  120. package/tests/column.html +3 -3
  121. package/tests/comment.html +9 -9
  122. package/tests/dotnav.html +3 -3
  123. package/tests/image.html +296 -64
  124. package/tests/images/image-type.avif +0 -0
  125. package/tests/images/image-type.jpeg +0 -0
  126. package/tests/images/image-type.webp +0 -0
  127. package/tests/index.html +8 -8
  128. package/tests/lightbox.html +10 -10
  129. package/tests/marker.html +2 -2
  130. package/tests/modal.html +8 -9
  131. package/tests/navbar.html +2 -2
  132. package/tests/overlay.html +7 -7
  133. package/tests/parallax.html +16 -7
  134. package/tests/position.html +12 -12
  135. package/tests/slidenav.html +12 -12
  136. package/tests/slider.html +20 -20
  137. package/tests/sortable.html +1 -1
  138. package/tests/sticky-parallax.html +56 -71
  139. package/tests/svg.html +6 -6
  140. package/tests/table.html +11 -11
  141. package/tests/thumbnav.html +12 -12
  142. package/tests/transition.html +30 -30
  143. package/tests/utility.html +50 -33
  144. package/tests/video.html +1 -1
  145. package/tests/width.html +1 -1
  146. package/src/js/util/promise.js +0 -0
  147. package/tests/images/animated.gif +0 -0
@@ -1,4 +1,5 @@
1
1
  import Container from '../mixin/container';
2
+ import Lazyload from '../mixin/lazyload';
2
3
  import Position from '../mixin/position';
3
4
  import Togglable from '../mixin/togglable';
4
5
  import {
@@ -30,7 +31,7 @@ import {
30
31
  export let active;
31
32
 
32
33
  export default {
33
- mixins: [Container, Position, Togglable],
34
+ mixins: [Container, Lazyload, Position, Togglable],
34
35
 
35
36
  args: 'pos',
36
37
 
@@ -84,6 +85,7 @@ export default {
84
85
  mode: this.mode,
85
86
  }).$el;
86
87
  attr(this.target, 'aria-haspopup', true);
88
+ this.lazyload(this.target);
87
89
  }
88
90
  },
89
91
 
@@ -60,7 +60,7 @@ export default {
60
60
  name: 'change',
61
61
 
62
62
  handler() {
63
- this.$update();
63
+ this.$emit();
64
64
  },
65
65
  },
66
66
 
@@ -72,7 +72,7 @@ export default {
72
72
  },
73
73
 
74
74
  handler() {
75
- this.$update();
75
+ this.$emit();
76
76
  },
77
77
  },
78
78
  ],
@@ -1,3 +1,4 @@
1
+ import Class from '../mixin/class';
1
2
  import {
2
3
  boxModelAdjust,
3
4
  css,
@@ -14,6 +15,8 @@ import {
14
15
  } from 'uikit-util';
15
16
 
16
17
  export default {
18
+ mixins: [Class],
19
+
17
20
  props: {
18
21
  expand: Boolean,
19
22
  offsetTop: Boolean,
@@ -68,14 +68,14 @@ const Icon = {
68
68
  },
69
69
 
70
70
  methods: {
71
- getSvg() {
71
+ async getSvg() {
72
72
  const icon = getIcon(this.icon);
73
73
 
74
74
  if (!icon) {
75
- return Promise.reject('Icon not found.');
75
+ throw 'Icon not found.';
76
76
  }
77
77
 
78
- return Promise.resolve(icon);
78
+ return icon;
79
79
  },
80
80
  },
81
81
  };
@@ -137,9 +137,16 @@ export const Close = {
137
137
  export const Spinner = {
138
138
  extends: IconComponent,
139
139
 
140
- async connected() {
141
- const svg = await this.svg;
142
- svg && this.ratio !== 1 && css($('circle', svg), 'strokeWidth', 1 / this.ratio);
140
+ methods: {
141
+ async getSvg() {
142
+ const icon = await Icon.methods.getSvg.call(this);
143
+
144
+ if (this.ratio !== 1) {
145
+ css($('circle', icon), 'strokeWidth', 1 / this.ratio);
146
+ }
147
+
148
+ return icon;
149
+ },
143
150
  },
144
151
  };
145
152
 
@@ -1,132 +1,116 @@
1
1
  import {
2
+ append,
3
+ attr,
4
+ children,
2
5
  createEvent,
3
6
  css,
4
- Dimensions,
7
+ data,
5
8
  escape,
6
- getImage,
9
+ fragment,
10
+ hasAttr,
11
+ hasIntersectionObserver,
7
12
  includes,
8
- isUndefined,
13
+ isArray,
14
+ isEmpty,
15
+ isTag,
16
+ observeIntersection,
17
+ parent,
18
+ parseOptions,
9
19
  queryAll,
20
+ removeAttr,
10
21
  startsWith,
11
22
  toFloat,
12
23
  toPx,
13
24
  trigger,
14
25
  } from 'uikit-util';
15
26
 
27
+ const nativeLazyLoad = 'loading' in HTMLImageElement.prototype;
28
+
16
29
  export default {
17
30
  args: 'dataSrc',
18
31
 
19
32
  props: {
20
33
  dataSrc: String,
21
- dataSrcset: Boolean,
22
- sizes: String,
23
- width: Number,
24
- height: Number,
34
+ sources: String,
25
35
  offsetTop: String,
26
36
  offsetLeft: String,
27
37
  target: String,
38
+ loading: String,
28
39
  },
29
40
 
30
41
  data: {
31
42
  dataSrc: '',
32
- dataSrcset: false,
33
- sizes: false,
34
- width: false,
35
- height: false,
43
+ sources: false,
36
44
  offsetTop: '50vh',
37
45
  offsetLeft: '50vw',
38
46
  target: false,
47
+ loading: 'lazy',
39
48
  },
40
49
 
41
50
  computed: {
42
- cacheKey({ dataSrc }) {
43
- return `${this.$name}.${dataSrc}`;
44
- },
45
-
46
- width({ width, dataWidth }) {
47
- return width || dataWidth;
48
- },
49
-
50
- height({ height, dataHeight }) {
51
- return height || dataHeight;
52
- },
53
-
54
- sizes({ sizes, dataSizes }) {
55
- return sizes || dataSizes;
56
- },
57
-
58
- isImg(_, $el) {
59
- return isImg($el);
60
- },
61
-
62
51
  target: {
63
52
  get({ target }) {
64
53
  return [this.$el, ...queryAll(target, this.$el)];
65
54
  },
66
55
 
67
56
  watch() {
68
- this.observe();
57
+ this.$reset();
69
58
  },
70
59
  },
71
-
72
- offsetTop({ offsetTop }) {
73
- return toPx(offsetTop, 'height');
74
- },
75
-
76
- offsetLeft({ offsetLeft }) {
77
- return toPx(offsetLeft, 'width');
78
- },
79
60
  },
80
61
 
81
62
  connected() {
82
- if (!window.IntersectionObserver) {
83
- setSrcAttrs(this.$el, this.dataSrc, this.dataSrcset, this.sizes);
63
+ if (this.loading !== 'lazy' || !hasIntersectionObserver) {
64
+ this.load();
84
65
  return;
85
66
  }
86
67
 
87
- if (storage[this.cacheKey]) {
88
- setSrcAttrs(this.$el, storage[this.cacheKey], this.dataSrcset, this.sizes);
89
- } else if (this.isImg && this.width && this.height) {
90
- setSrcAttrs(this.$el, getPlaceholderImage(this.width, this.height, this.sizes));
68
+ if (nativeLazyLoad && isImg(this.$el)) {
69
+ this.$el.loading = 'lazy';
70
+ setSrcAttrs(this.$el);
71
+
72
+ if (this.target.length === 1) {
73
+ return;
74
+ }
91
75
  }
92
76
 
93
- this.observer = new IntersectionObserver(this.load, {
94
- rootMargin: `${this.offsetTop}px ${this.offsetLeft}px`,
95
- });
77
+ ensureSrcAttribute(this.$el);
96
78
 
97
- requestAnimationFrame(this.observe);
79
+ this.registerObserver(
80
+ observeIntersection(
81
+ this.target,
82
+ (entries, observer) => {
83
+ this.load();
84
+ observer.disconnect();
85
+ },
86
+ {
87
+ rootMargin: `${toPx(this.offsetTop, 'height')}px ${toPx(
88
+ this.offsetLeft,
89
+ 'width'
90
+ )}px`,
91
+ }
92
+ )
93
+ );
98
94
  },
99
95
 
100
96
  disconnected() {
101
- this.observer && this.observer.disconnect();
97
+ if (this._data.image) {
98
+ this._data.image.onload = '';
99
+ }
102
100
  },
103
101
 
104
102
  update: {
105
- read({ image }) {
106
- if (!this.observer) {
103
+ write(store) {
104
+ if (!this.observer || isImg(this.$el)) {
107
105
  return false;
108
106
  }
109
107
 
110
- if (!image && document.readyState === 'complete') {
111
- this.load(this.observer.takeRecords());
112
- }
113
-
114
- if (this.isImg) {
115
- return false;
116
- }
117
-
118
- image &&
119
- image.then(
120
- (img) => img && img.currentSrc !== '' && setSrcAttrs(this.$el, currentSrc(img))
121
- );
122
- },
123
-
124
- write(data) {
125
- if (this.dataSrcset && window.devicePixelRatio !== 1) {
108
+ const srcset = data(this.$el, 'data-srcset');
109
+ if (srcset && window.devicePixelRatio !== 1) {
126
110
  const bgSize = css(this.$el, 'backgroundSize');
127
- if (bgSize.match(/^(auto\s?)+$/) || toFloat(bgSize) === data.bgSize) {
128
- data.bgSize = getSourceSize(this.dataSrcset, this.sizes);
129
- css(this.$el, 'backgroundSize', `${data.bgSize}px`);
111
+ if (bgSize.match(/^(auto\s?)+$/) || toFloat(bgSize) === store.bgSize) {
112
+ store.bgSize = getSourceSize(srcset, data(this.$el, 'sizes'));
113
+ css(this.$el, 'backgroundSize', `${store.bgSize}px`);
130
114
  }
131
115
  }
132
116
  },
@@ -135,42 +119,27 @@ export default {
135
119
  },
136
120
 
137
121
  methods: {
138
- load(entries) {
139
- // Old chromium based browsers (UC Browser) did not implement `isIntersecting`
140
- if (
141
- !entries.some((entry) => isUndefined(entry.isIntersecting) || entry.isIntersecting)
142
- ) {
143
- return;
122
+ load() {
123
+ if (this._data.image) {
124
+ return this._data.image;
144
125
  }
145
126
 
146
- this._data.image = getImage(this.dataSrc, this.dataSrcset, this.sizes).then(
147
- (img) => {
148
- setSrcAttrs(this.$el, currentSrc(img), img.srcset, img.sizes);
149
- storage[this.cacheKey] = currentSrc(img);
150
- return img;
151
- },
152
- (e) => trigger(this.$el, new e.constructor(e.type, e))
153
- );
127
+ const image = isImg(this.$el)
128
+ ? this.$el
129
+ : getImageFromElement(this.$el, this.dataSrc, this.sources);
154
130
 
155
- this.observer.disconnect();
156
- },
157
-
158
- observe() {
159
- if (this._connected && !this._data.image) {
160
- for (const el of this.target) {
161
- this.observer.observe(el);
162
- }
163
- }
131
+ removeAttr(image, 'loading');
132
+ setSrcAttrs(this.$el, image.currentSrc);
133
+ return (this._data.image = image);
164
134
  },
165
135
  },
166
136
  };
167
137
 
168
- function setSrcAttrs(el, src, srcset, sizes) {
138
+ function setSrcAttrs(el, src) {
169
139
  if (isImg(el)) {
170
- const set = (prop, val) => val && val !== el[prop] && (el[prop] = val);
171
- set('sizes', sizes);
172
- set('srcset', srcset);
173
- set('src', src);
140
+ const parentNode = parent(el);
141
+ const elements = isPicture(parentNode) ? children(parentNode) : [el];
142
+ elements.forEach((el) => setSourceProps(el, el));
174
143
  } else if (src) {
175
144
  const change = !includes(el.style.backgroundImage, src);
176
145
  if (change) {
@@ -180,16 +149,62 @@ function setSrcAttrs(el, src, srcset, sizes) {
180
149
  }
181
150
  }
182
151
 
183
- function getPlaceholderImage(width, height, sizes) {
184
- if (sizes) {
185
- ({ width, height } = Dimensions.ratio(
186
- { width, height },
187
- 'width',
188
- toPx(sizesToPixel(sizes))
189
- ));
152
+ const srcProps = ['data-src', 'data-srcset', 'sizes'];
153
+ function setSourceProps(sourceEl, targetEl) {
154
+ srcProps.forEach((prop) => {
155
+ const value = data(sourceEl, prop);
156
+ if (value) {
157
+ attr(targetEl, prop.replace(/^(data-)+/, ''), value);
158
+ }
159
+ });
160
+ }
161
+
162
+ function getImageFromElement(el, src, sources) {
163
+ const img = new Image();
164
+
165
+ wrapInPicture(img, sources);
166
+ setSourceProps(el, img);
167
+ img.onload = () => {
168
+ setSrcAttrs(el, img.currentSrc);
169
+ };
170
+ attr(img, 'src', src);
171
+ return img;
172
+ }
173
+
174
+ function wrapInPicture(img, sources) {
175
+ sources = parseSources(sources);
176
+
177
+ if (sources.length) {
178
+ const picture = fragment('<picture>');
179
+ for (const attrs of sources) {
180
+ const source = fragment('<source>');
181
+ attr(source, attrs);
182
+ append(picture, source);
183
+ }
184
+ append(picture, img);
185
+ }
186
+ }
187
+
188
+ function parseSources(sources) {
189
+ if (!sources) {
190
+ return [];
191
+ }
192
+
193
+ if (startsWith(sources, '[')) {
194
+ try {
195
+ sources = JSON.parse(sources);
196
+ } catch (e) {
197
+ sources = [];
198
+ }
199
+ } else {
200
+ sources = parseOptions(sources);
190
201
  }
191
202
 
192
- return `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"></svg>`;
203
+ if (!isArray(sources)) {
204
+ sources = [sources];
205
+ }
206
+
207
+ return sources.filter((source) => !isEmpty(source));
193
208
  }
194
209
 
195
210
  const sizesRe = /\s*(.*?)\s*(\w+|calc\(.*?\))\s*(?:,|$)/g;
@@ -229,22 +244,16 @@ function getSourceSize(srcset, sizes) {
229
244
  return descriptors.filter((size) => size >= srcSize)[0] || descriptors.pop() || '';
230
245
  }
231
246
 
232
- function isImg(el) {
233
- return el.tagName === 'IMG';
247
+ function ensureSrcAttribute(el) {
248
+ if (isImg(el) && !hasAttr(el, 'src')) {
249
+ attr(el, 'src', 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"></svg>');
250
+ }
234
251
  }
235
252
 
236
- function currentSrc(el) {
237
- return el.currentSrc || el.src;
253
+ function isPicture(el) {
254
+ return isTag(el, 'picture');
238
255
  }
239
256
 
240
- const key = '__test__';
241
- let storage;
242
-
243
- // workaround for Safari's private browsing mode and accessing sessionStorage in Blink
244
- try {
245
- storage = window.sessionStorage || {};
246
- storage[key] = 1;
247
- delete storage[key];
248
- } catch (e) {
249
- storage = {};
257
+ function isImg(el) {
258
+ return isTag(el, 'img');
250
259
  }
@@ -2,7 +2,6 @@ import Modal from '../mixin/modal';
2
2
  import {
3
3
  $,
4
4
  addClass,
5
- assign,
6
5
  css,
7
6
  Deferred,
8
7
  hasClass,
@@ -136,7 +135,7 @@ function install({ modal }) {
136
135
  };
137
136
 
138
137
  function openDialog(tmpl, options, hideFn, submitFn) {
139
- options = assign({ bgClose: false, escClose: true, labels: modal.labels }, options);
138
+ options = { bgClose: false, escClose: true, labels: modal.labels, ...options };
140
139
 
141
140
  const dialog = modal.dialog(tmpl(options), options);
142
141
  const deferred = new Deferred();
@@ -6,7 +6,6 @@ import {
6
6
  $$,
7
7
  addClass,
8
8
  after,
9
- assign,
10
9
  css,
11
10
  findIndex,
12
11
  hasAttr,
@@ -126,11 +125,12 @@ export default {
126
125
  this.$create(
127
126
  'drop',
128
127
  dropdowns.filter((el) => !this.getDropdown(el)),
129
- assign({}, this.$props, {
128
+ {
129
+ ...this.$props,
130
130
  boundary: this.boundary,
131
131
  pos: this.pos,
132
132
  offset: this.dropbar || this.offset,
133
- })
133
+ }
134
134
  );
135
135
  },
136
136