uikit 3.25.26 → 3.25.27-dev.9e97c1f

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 (226) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/build/prefix.js +1 -1
  3. package/build/publishDev.js +1 -1
  4. package/build/scope.js +1 -1
  5. package/build/scss.js +1 -1
  6. package/build/util.js +0 -2
  7. package/dist/css/uikit-core-rtl.css +1327 -1204
  8. package/dist/css/uikit-core-rtl.min.css +1 -1
  9. package/dist/css/uikit-core.css +1327 -1204
  10. package/dist/css/uikit-core.min.css +1 -1
  11. package/dist/css/uikit-rtl.css +1339 -1223
  12. package/dist/css/uikit-rtl.min.css +1 -1
  13. package/dist/css/uikit.css +1339 -1223
  14. package/dist/css/uikit.min.css +1 -1
  15. package/dist/js/components/countdown.js +1 -1
  16. package/dist/js/components/countdown.min.js +1 -1
  17. package/dist/js/components/filter.js +1 -1
  18. package/dist/js/components/filter.min.js +1 -1
  19. package/dist/js/components/lightbox-panel.js +149 -146
  20. package/dist/js/components/lightbox-panel.min.js +1 -1
  21. package/dist/js/components/lightbox.js +150 -147
  22. package/dist/js/components/lightbox.min.js +1 -1
  23. package/dist/js/components/marquee.js +215 -0
  24. package/dist/js/components/marquee.min.js +1 -0
  25. package/dist/js/components/notification.js +8 -6
  26. package/dist/js/components/notification.min.js +1 -1
  27. package/dist/js/components/parallax.js +8 -12
  28. package/dist/js/components/parallax.min.js +1 -1
  29. package/dist/js/components/slider-parallax.js +8 -12
  30. package/dist/js/components/slider-parallax.min.js +1 -1
  31. package/dist/js/components/slider.js +65 -26
  32. package/dist/js/components/slider.min.js +1 -1
  33. package/dist/js/components/slideshow-parallax.js +8 -12
  34. package/dist/js/components/slideshow-parallax.min.js +1 -1
  35. package/dist/js/components/slideshow.js +95 -103
  36. package/dist/js/components/slideshow.min.js +1 -1
  37. package/dist/js/components/sortable.js +1 -1
  38. package/dist/js/components/sortable.min.js +1 -1
  39. package/dist/js/components/tooltip.js +15 -17
  40. package/dist/js/components/tooltip.min.js +1 -1
  41. package/dist/js/components/upload.js +1 -1
  42. package/dist/js/components/upload.min.js +1 -1
  43. package/dist/js/uikit-core.js +888 -337
  44. package/dist/js/uikit-core.min.js +1 -1
  45. package/dist/js/uikit-icons.js +1 -1
  46. package/dist/js/uikit-icons.min.js +1 -1
  47. package/dist/js/uikit.js +766 -433
  48. package/dist/js/uikit.min.js +1 -1
  49. package/package.json +1 -1
  50. package/src/js/api/component.js +2 -3
  51. package/src/js/api/observables.js +16 -4
  52. package/src/js/api/options.js +6 -3
  53. package/src/js/api/props.js +1 -3
  54. package/src/js/api/state.js +7 -8
  55. package/src/js/components/index.js +1 -0
  56. package/src/js/components/internal/lightbox-animations.js +7 -26
  57. package/src/js/components/internal/slider-preload.js +1 -0
  58. package/src/js/components/internal/slideshow-animations.js +15 -62
  59. package/src/js/components/lightbox-panel.js +123 -109
  60. package/src/js/components/lightbox.js +5 -8
  61. package/src/js/components/marquee.js +156 -0
  62. package/src/js/components/notification.js +7 -5
  63. package/src/js/core/accordion.js +62 -31
  64. package/src/js/core/alert.js +1 -1
  65. package/src/js/core/drop.js +4 -3
  66. package/src/js/core/dropnav.js +13 -32
  67. package/src/js/core/grid.js +5 -19
  68. package/src/js/core/margin.js +3 -0
  69. package/src/js/core/overflow-auto.js +5 -1
  70. package/src/js/core/sticky.js +1 -1
  71. package/src/js/core/switcher.js +18 -62
  72. package/src/js/core/video.js +236 -21
  73. package/src/js/mixin/connect.js +90 -0
  74. package/src/js/mixin/internal/slideshow-animations.js +5 -13
  75. package/src/js/mixin/internal/slideshow-transitioner.js +2 -2
  76. package/src/js/mixin/parallax.js +1 -4
  77. package/src/js/mixin/position.js +1 -1
  78. package/src/js/mixin/scroll-driven.js +57 -0
  79. package/src/js/mixin/slider-nav.js +2 -12
  80. package/src/js/mixin/slider-parallax.js +9 -38
  81. package/src/js/mixin/togglable.js +13 -14
  82. package/src/js/util/attr.js +7 -7
  83. package/src/js/util/dom.js +3 -4
  84. package/src/js/util/keys.js +14 -0
  85. package/src/js/util/lang.js +2 -2
  86. package/src/js/util/player.js +4 -2
  87. package/src/js/util/style.js +12 -13
  88. package/src/js/util/viewport.js +22 -25
  89. package/src/less/components/_import.less +8 -3
  90. package/src/less/components/animation.less +1 -1
  91. package/src/less/components/base.less +1 -1
  92. package/src/less/components/button.less +1 -1
  93. package/src/less/components/card.less +8 -8
  94. package/src/less/components/dropcap.less +71 -0
  95. package/src/less/components/floating-shadow.less +66 -0
  96. package/src/less/components/form.less +15 -15
  97. package/src/less/components/grid.less +58 -65
  98. package/src/less/components/lightbox.less +2 -8
  99. package/src/less/components/logo.less +94 -0
  100. package/src/less/components/margin.less +155 -124
  101. package/src/less/components/marquee.less +133 -0
  102. package/src/less/components/modal.less +1 -4
  103. package/src/less/components/nav.less +1 -1
  104. package/src/less/components/navbar.less +1 -1
  105. package/src/less/components/padding.less +9 -9
  106. package/src/less/components/position.less +9 -4
  107. package/src/less/components/search.less +1 -1
  108. package/src/less/components/slideshow.less +1 -4
  109. package/src/less/components/switcher.less +5 -2
  110. package/src/less/components/table.less +4 -4
  111. package/src/less/components/text.less +10 -4
  112. package/src/less/components/utility.less +0 -163
  113. package/src/less/components/visibility.less +4 -4
  114. package/src/less/theme/_import.less +6 -2
  115. package/src/less/theme/alert.less +0 -5
  116. package/src/less/theme/dropcap.less +29 -0
  117. package/src/less/theme/floating-shadow.less +20 -0
  118. package/src/less/theme/logo.less +29 -0
  119. package/src/less/theme/marquee.less +14 -0
  120. package/src/less/theme/thumbnav.less +1 -4
  121. package/src/less/theme/utility.less +0 -32
  122. package/src/scss/components/_import.scss +8 -3
  123. package/src/scss/components/animation.scss +1 -1
  124. package/src/scss/components/base.scss +1 -1
  125. package/src/scss/components/button.scss +1 -1
  126. package/src/scss/components/card.scss +8 -8
  127. package/src/scss/components/dropcap.scss +63 -0
  128. package/src/scss/components/floating-shadow.scss +63 -0
  129. package/src/scss/components/form.scss +14 -14
  130. package/src/scss/components/grid.scss +57 -64
  131. package/src/scss/components/lightbox.scss +2 -8
  132. package/src/scss/components/logo.scss +75 -0
  133. package/src/scss/components/margin.scss +155 -124
  134. package/src/scss/components/marquee.scss +136 -0
  135. package/src/scss/components/modal.scss +1 -4
  136. package/src/scss/components/nav.scss +1 -1
  137. package/src/scss/components/navbar.scss +1 -1
  138. package/src/scss/components/padding.scss +9 -9
  139. package/src/scss/components/position.scss +9 -4
  140. package/src/scss/components/search.scss +1 -1
  141. package/src/scss/components/slideshow.scss +1 -4
  142. package/src/scss/components/switcher.scss +5 -2
  143. package/src/scss/components/table.scss +4 -4
  144. package/src/scss/components/text.scss +10 -4
  145. package/src/scss/components/utility.scss +0 -129
  146. package/src/scss/components/visibility.scss +4 -4
  147. package/src/scss/mixins-theme.scss +44 -43
  148. package/src/scss/mixins.scss +40 -31
  149. package/src/scss/variables-theme.scss +14 -14
  150. package/src/scss/variables.scss +14 -14
  151. package/tests/accordion.html +77 -10
  152. package/tests/alert.html +1 -1
  153. package/tests/align.html +5 -5
  154. package/tests/animation.html +4 -4
  155. package/tests/article.html +7 -7
  156. package/tests/background.html +2 -2
  157. package/tests/badge.html +1 -1
  158. package/tests/base.html +2 -2
  159. package/tests/button.html +1 -1
  160. package/tests/card.html +15 -15
  161. package/tests/close.html +2 -2
  162. package/tests/comment.html +9 -9
  163. package/tests/container.html +2 -2
  164. package/tests/countdown.html +21 -21
  165. package/tests/cover.html +3 -3
  166. package/tests/description-list.html +1 -1
  167. package/tests/divider.html +3 -3
  168. package/tests/dotnav.html +1 -1
  169. package/tests/drop.html +7 -7
  170. package/tests/dropbar.html +5 -5
  171. package/tests/dropcap.html +26 -0
  172. package/tests/dropdown.html +1 -1
  173. package/tests/dropnav.html +18 -18
  174. package/tests/filter.html +3 -3
  175. package/tests/floating-shadow.html +44 -0
  176. package/tests/form.html +14 -14
  177. package/tests/grid.html +41 -47
  178. package/tests/heading.html +2 -2
  179. package/tests/height-viewport.html +4 -4
  180. package/tests/height.html +5 -5
  181. package/tests/icon.html +8 -8
  182. package/tests/image.html +6 -6
  183. package/tests/index.html +13 -13
  184. package/tests/js/index.js +1 -1
  185. package/tests/leader.html +5 -5
  186. package/tests/lightbox.html +6 -6
  187. package/tests/link.html +1 -1
  188. package/tests/list.html +4 -4
  189. package/tests/logo.html +84 -0
  190. package/tests/margin.html +59 -7
  191. package/tests/marker.html +3 -3
  192. package/tests/marquee.html +617 -0
  193. package/tests/modal.html +3 -3
  194. package/tests/nav.html +5 -5
  195. package/tests/navbar.html +27 -27
  196. package/tests/notification.html +8 -2
  197. package/tests/offcanvas.html +12 -12
  198. package/tests/overlay.html +3 -3
  199. package/tests/padding.html +1 -1
  200. package/tests/pagination.html +3 -3
  201. package/tests/parallax.html +1 -1
  202. package/tests/position.html +6 -6
  203. package/tests/scrollspy.html +13 -13
  204. package/tests/search.html +5 -5
  205. package/tests/section.html +17 -17
  206. package/tests/slidenav.html +3 -3
  207. package/tests/slider.html +5 -5
  208. package/tests/slideshow.html +33 -3
  209. package/tests/sortable.html +15 -15
  210. package/tests/sticky-navbar.html +4 -4
  211. package/tests/sticky-parallax.html +3 -3
  212. package/tests/sticky.html +3 -3
  213. package/tests/svg.html +3 -2
  214. package/tests/switcher.html +7 -7
  215. package/tests/tab.html +5 -5
  216. package/tests/text.html +9 -3
  217. package/tests/tile.html +4 -4
  218. package/tests/toggle.html +1 -1
  219. package/tests/tooltip.html +3 -3
  220. package/tests/totop.html +2 -2
  221. package/tests/transition.html +1 -1
  222. package/tests/upload.html +5 -5
  223. package/tests/utility.html +16 -116
  224. package/tests/video.html +224 -24
  225. package/tests/visibility.html +4 -4
  226. package/tests/width.html +12 -12
@@ -9,27 +9,23 @@ import {
9
9
  getIndex,
10
10
  hasClass,
11
11
  isNumeric,
12
- isTag,
13
12
  matches,
14
13
  queryAll,
15
- toArray,
16
14
  toggleClass,
17
15
  } from 'uikit-util';
18
- import { generateId } from '../api/instance';
19
- import { lazyload, swipe } from '../api/observables';
16
+ import { swipe } from '../api/observables';
17
+ import Connect from '../mixin/connect';
20
18
  import { maybeDefaultPreventClick } from '../mixin/event';
21
- import Togglable from '../mixin/togglable';
22
- import { keyMap } from '../util/keys';
19
+ import { getNavigationIndex, keyMap } from '../util/keys';
23
20
 
24
21
  const selDisabled = '.uk-disabled *, .uk-disabled, [disabled]';
25
22
 
26
23
  export default {
27
- mixins: [Togglable],
24
+ mixins: [Connect],
28
25
 
29
26
  args: 'connect',
30
27
 
31
28
  props: {
32
- connect: String,
33
29
  toggle: String,
34
30
  itemNav: String,
35
31
  active: Number,
@@ -42,7 +38,6 @@ export default {
42
38
  toggle: '> * > :first-child',
43
39
  itemNav: false,
44
40
  active: 0,
45
- cls: 'uk-active',
46
41
  attrItem: 'uk-switcher-item',
47
42
  selVertical: '.uk-nav',
48
43
  followFocus: false,
@@ -50,15 +45,6 @@ export default {
50
45
  },
51
46
 
52
47
  computed: {
53
- connects: {
54
- get: ({ connect }, $el) => queryAll(connect, $el),
55
- observe: ({ connect }) => connect,
56
- },
57
-
58
- connectChildren() {
59
- return this.connects.flatMap((el) => children(el));
60
- },
61
-
62
48
  toggles: ({ toggle }, $el) => $$(toggle, $el),
63
49
 
64
50
  children(_, $el) {
@@ -95,10 +81,7 @@ export default {
95
81
  this.$el.role = 'tablist';
96
82
  },
97
83
 
98
- observe: [
99
- lazyload({ targets: ({ connectChildren }) => connectChildren }),
100
- swipe({ target: ({ connects }) => connects, filter: ({ swiping }) => swiping }),
101
- ],
84
+ observe: swipe({ target: ({ connects }) => connects, filter: ({ swiping }) => swiping }),
102
85
 
103
86
  events: [
104
87
  {
@@ -126,18 +109,11 @@ export default {
126
109
  const { current, keyCode } = e;
127
110
  const isVertical = matches(this.$el, this.selVertical);
128
111
 
129
- let i =
130
- keyCode === keyMap.HOME
131
- ? 0
132
- : keyCode === keyMap.END
133
- ? 'last'
134
- : (keyCode === keyMap.LEFT && !isVertical) ||
135
- (keyCode === keyMap.UP && isVertical)
136
- ? 'previous'
137
- : (keyCode === keyMap.RIGHT && !isVertical) ||
138
- (keyCode === keyMap.DOWN && isVertical)
139
- ? 'next'
140
- : -1;
112
+ const i = getNavigationIndex(
113
+ keyCode,
114
+ isVertical ? keyMap.UP : keyMap.LEFT,
115
+ isVertical ? keyMap.DOWN : keyMap.RIGHT,
116
+ );
141
117
 
142
118
  if (~i) {
143
119
  e.preventDefault();
@@ -180,28 +156,17 @@ export default {
180
156
  ],
181
157
 
182
158
  update() {
183
- for (const el of this.connects) {
184
- if (isTag(el, 'ul')) {
185
- el.role = 'presentation';
186
- }
187
- }
188
159
  attr(children(this.$el), 'role', 'presentation');
189
160
 
190
161
  for (const index in this.toggles) {
191
- const toggle = this.toggles[index];
192
- const item = this.connects[0]?.children[index];
162
+ const controls = this.connects
163
+ .map(({ children }) => children[index]?.id)
164
+ .filter(Boolean);
193
165
 
194
- toggle.role = 'tab';
195
-
196
- if (!item) {
197
- continue;
198
- }
199
-
200
- toggle.id = generateId(this, toggle);
201
- item.id = generateId(this, item);
202
-
203
- attr(toggle, 'aria-controls', item.id);
204
- attr(item, { role: 'tabpanel', 'aria-labelledby': toggle.id });
166
+ attr(this.toggles[index], {
167
+ role: 'tab',
168
+ 'aria-controls': controls.join(' '),
169
+ });
205
170
  }
206
171
  attr(this.$el, 'aria-orientation', matches(this.$el, this.selVertical) ? 'vertical' : null);
207
172
  },
@@ -240,16 +205,7 @@ export default {
240
205
  });
241
206
  });
242
207
 
243
- const animate = prev >= 0 && prev !== next;
244
- this.connects.forEach(async ({ children }) => {
245
- const actives = toArray(children).filter(
246
- (child, i) => i !== next && hasClass(child, this.cls),
247
- );
248
-
249
- if (await this.toggleElement(actives, false, animate)) {
250
- await this.toggleElement(children[next], true, animate);
251
- }
252
- });
208
+ return this.showConnects(next, prev >= 0 && prev !== next);
253
209
  },
254
210
  },
255
211
  };
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  hasAttr,
3
+ isFocusable,
3
4
  isTag,
4
5
  isTouch,
5
6
  mute,
7
+ observeIntersection,
6
8
  parent,
7
9
  pause,
8
10
  play,
@@ -11,27 +13,62 @@ import {
11
13
  query,
12
14
  } from 'uikit-util';
13
15
  import { intersection } from '../api/observables';
16
+ import Media from '../mixin/media';
17
+ import ScrollDriven from '../mixin/scroll-driven';
18
+
19
+ const loopKey = Symbol();
14
20
 
15
21
  export default {
22
+ mixins: [Media, ScrollDriven],
23
+
16
24
  args: 'autoplay',
17
25
 
18
26
  props: {
19
27
  automute: Boolean,
20
28
  autoplay: Boolean,
21
29
  restart: Boolean,
30
+ inviewMargin: String,
31
+ inviewQueued: Number,
22
32
  hoverTarget: Boolean,
33
+ hoverRewind: Number,
34
+ reducedMotionTime: Number,
23
35
  },
24
36
 
25
37
  data: {
26
38
  automute: false,
27
39
  autoplay: true,
28
40
  restart: false,
41
+ inviewMargin: '0px',
42
+ inviewQueued: 0,
29
43
  hoverTarget: false,
44
+ hoverRewind: 0,
45
+ reducedMotionTime: 0,
46
+ media: '(prefers-reduced-motion: reduce)',
30
47
  },
31
48
 
32
49
  beforeConnect() {
33
- const isVideo = isTag(this.$el, 'video');
34
- if (this.autoplay === 'inview' && isVideo && !hasAttr(this.$el, 'preload')) {
50
+ const isVideo = (this.isVideo = isTag(this.$el, 'video'));
51
+
52
+ this.interactionDriven = ['hover', 'parallax'].includes(this.autoplay);
53
+
54
+ if (this.interactionDriven && !isVideo) {
55
+ this.interactionDriven = this.autoplay = false;
56
+ }
57
+
58
+ this.restart = isVideo && this.restart;
59
+ this.parallax = this.autoplay === 'parallax';
60
+ this.inviewQueued = isVideo && this.autoplay === 'inview' && this.inviewQueued;
61
+
62
+ if (this.inviewQueued) {
63
+ this.$el[loopKey] = this.$el.loop;
64
+ this.$el.loop = false;
65
+ }
66
+
67
+ if (
68
+ ['hover', 'inview'].includes(this.autoplay) &&
69
+ isVideo &&
70
+ !hasAttr(this.$el, 'preload')
71
+ ) {
35
72
  this.$el.preload = 'none';
36
73
  }
37
74
 
@@ -40,10 +77,10 @@ export default {
40
77
  }
41
78
 
42
79
  if (this.autoplay === 'hover') {
43
- if (isVideo) {
44
- this.$el.tabIndex = 0;
45
- } else {
46
- this.autoplay = true;
80
+ this.hoverTarget = query(this.hoverTarget, this.$el) || this.$el;
81
+
82
+ if (!isFocusable(this.hoverTarget)) {
83
+ this.hoverTarget.tabIndex = 0;
47
84
  }
48
85
  }
49
86
 
@@ -53,19 +90,44 @@ export default {
53
90
  }
54
91
  },
55
92
 
93
+ connected() {
94
+ if (
95
+ !this.$el.controls &&
96
+ !this.$el.poster &&
97
+ (this.interactionDriven || this.inviewQueued)
98
+ ) {
99
+ this.cancelPreview = preview(this.$el);
100
+ }
101
+ },
102
+
103
+ disconnected() {
104
+ this._reverseAbort?.abort();
105
+
106
+ this.cancelPreview?.();
107
+ this.cancelPreview = null;
108
+
109
+ if (this.$el[loopKey]) {
110
+ this.$el.loop = true;
111
+ }
112
+
113
+ queue.delete(this.$el);
114
+ },
115
+
56
116
  events: [
57
117
  {
58
118
  name: `${pointerEnter} focusin`,
59
119
 
60
- el: ({ hoverTarget, $el }) => query(hoverTarget, $el) || $el,
120
+ el: ({ hoverTarget }) => hoverTarget,
61
121
 
62
122
  filter: ({ autoplay }) => autoplay === 'hover',
63
123
 
64
124
  handler(e) {
125
+ this._reverseAbort?.abort();
126
+
65
127
  if (!isTouch(e) || !isPlaying(this.$el)) {
66
- play(this.$el);
128
+ this.play();
67
129
  } else {
68
- pauseHover(this.$el, this.restart);
130
+ this.pause();
69
131
  }
70
132
  },
71
133
  },
@@ -73,14 +135,34 @@ export default {
73
135
  {
74
136
  name: `${pointerLeave} focusout`,
75
137
 
76
- el: ({ hoverTarget, $el }) => query(hoverTarget, $el) || $el,
138
+ el: ({ hoverTarget }) => hoverTarget,
77
139
 
78
140
  filter: ({ autoplay }) => autoplay === 'hover',
79
141
 
80
142
  handler(e) {
81
- if (!isTouch(e)) {
82
- pauseHover(this.$el, this.restart);
143
+ if (!isTouch(e) && !this.matchMedia) {
144
+ this._reverseAbort?.abort();
145
+ this.pause();
146
+ this._reverseAbort = playReverse(this.$el, this.hoverRewind);
147
+ }
148
+ },
149
+ },
150
+ {
151
+ name: 'loadedmetadata durationchange',
152
+ filter: ({ parallax }) => parallax,
153
+ handler() {
154
+ this.$emit('resize');
155
+ },
156
+ },
157
+ {
158
+ name: 'error pause ended',
159
+ filter: ({ inviewQueued }) => inviewQueued,
160
+ handler(e) {
161
+ if (e.type === 'error' || (e.type === 'ended' && !this.$el[loopKey])) {
162
+ queue.delete(this.$el);
83
163
  }
164
+
165
+ playNextQueued();
84
166
  },
85
167
  },
86
168
  ],
@@ -95,33 +177,166 @@ export default {
95
177
  }),
96
178
 
97
179
  intersection({
98
- filter: ({ $el, autoplay }) => autoplay !== 'hover' && $el.preload !== 'none',
99
- handler([{ isIntersecting, target }]) {
180
+ filter: ({ $el, interactionDriven }) => !interactionDriven && $el.preload !== 'none',
181
+ handler([{ isIntersecting }]) {
100
182
  if (!document.fullscreenElement) {
101
183
  if (isIntersecting) {
102
184
  if (this.autoplay) {
103
- play(target);
185
+ this.play();
104
186
  }
105
187
  } else {
106
- pauseHover(target, this.restart);
188
+ this.pause();
107
189
  }
108
190
  }
109
191
  },
110
192
  args: { intersecting: false },
111
- options: ({ $el, autoplay }) => ({
193
+ options: ({ $el, autoplay, inviewMargin }) => ({
112
194
  root: autoplay === 'inview' ? null : parent($el).closest(':not(a)'),
195
+ rootMargin: autoplay === 'inview' ? inviewMargin : '0px',
113
196
  }),
114
197
  }),
115
198
  ],
199
+
200
+ update: {
201
+ write({ percent }) {
202
+ if (!this.parallax) {
203
+ return;
204
+ }
205
+
206
+ const { duration, seeking } = this.$el;
207
+ if (!isNaN(duration) && !seeking) {
208
+ const value = this.matchMedia ? this.reducedMotionTime : percent * duration;
209
+ setCurrentTime(this.$el, value);
210
+ }
211
+ },
212
+
213
+ events: ['scroll', 'resize'],
214
+ },
215
+
216
+ methods: {
217
+ play() {
218
+ if (this.matchMedia) {
219
+ this.pause();
220
+
221
+ if (this.isVideo) {
222
+ setCurrentTime(this.$el, this.reducedMotionTime);
223
+ }
224
+ } else if (this.inviewQueued) {
225
+ queue.set(this.$el, this.inviewQueued);
226
+ playNextQueued();
227
+ } else {
228
+ this.cancelPreview?.();
229
+ play(this.$el);
230
+ }
231
+ },
232
+
233
+ pause() {
234
+ pause(this.$el);
235
+
236
+ queue.delete(this.$el);
237
+
238
+ if (this.restart) {
239
+ setCurrentTime(this.$el, 0);
240
+ }
241
+ },
242
+ },
116
243
  };
117
244
 
245
+ function setCurrentTime(videoEl, time) {
246
+ if (videoEl.currentTime !== time) {
247
+ videoEl.currentTime = time;
248
+ }
249
+ }
250
+
118
251
  function isPlaying(videoEl) {
119
252
  return !videoEl.paused && !videoEl.ended;
120
253
  }
121
254
 
122
- function pauseHover(el, restart) {
123
- pause(el);
124
- if (restart && isTag(el, 'video')) {
125
- el.currentTime = 0;
255
+ function preview($el) {
256
+ if (!$el.requestVideoFrameCallback) {
257
+ return;
126
258
  }
259
+
260
+ let frame;
261
+ const pausePreview = () => {
262
+ disconnect();
263
+ pause($el);
264
+ };
265
+
266
+ const observer = observeIntersection($el, () => {
267
+ observer.disconnect();
268
+ frame = $el.requestVideoFrameCallback(pausePreview);
269
+ play($el);
270
+ });
271
+
272
+ const disconnect = () => {
273
+ observer.disconnect();
274
+ $el.cancelVideoFrameCallback(frame);
275
+ };
276
+
277
+ return disconnect;
278
+ }
279
+
280
+ const queue = new Map();
281
+ const played = new WeakMap();
282
+
283
+ let frame;
284
+ function playNextQueued() {
285
+ cancelAnimationFrame(frame);
286
+ frame = requestAnimationFrame(() => {
287
+ const getPlayed = (el) => played.get(el) ?? 0;
288
+ const videos = shuffle(queue.keys()).sort((a, b) => getPlayed(a) - getPlayed(b));
289
+ let active = videos.filter(isPlaying).length;
290
+
291
+ for (const el of videos) {
292
+ const maxQueued = queue.get(el);
293
+
294
+ if (isPlaying(el) || active / queue.size >= maxQueued) {
295
+ continue;
296
+ }
297
+
298
+ played.set(el, getPlayed(el) + 1);
299
+ play(el);
300
+ active++;
301
+ }
302
+ });
303
+ }
304
+
305
+ function shuffle(array) {
306
+ array = [...array];
307
+ for (let i = array.length - 1; i > 0; i--) {
308
+ let j = Math.floor(Math.random() * (i + 1));
309
+ [array[i], array[j]] = [array[j], array[i]];
310
+ }
311
+ return array;
312
+ }
313
+
314
+ function playReverse(el, playbackRate) {
315
+ const start = el.currentTime;
316
+
317
+ if (isNaN(start) || !playbackRate) {
318
+ return;
319
+ }
320
+
321
+ playbackRate *= Math.max(1, start / 10 + 0.5);
322
+
323
+ const controller = new AbortController();
324
+ const time = Date.now();
325
+ (function next() {
326
+ requestAnimationFrame(() => {
327
+ if (controller.signal.aborted) {
328
+ return;
329
+ }
330
+
331
+ if (!el.seeking) {
332
+ el.currentTime = Math.max(0, start - ((Date.now() - time) * playbackRate) / 1000);
333
+ }
334
+
335
+ if (el.currentTime > 0) {
336
+ next();
337
+ }
338
+ });
339
+ })();
340
+
341
+ return controller;
127
342
  }
@@ -0,0 +1,90 @@
1
+ import { attr, children, data, hasClass, isTag, queryAll, toArray } from 'uikit-util';
2
+ import App from '../api';
3
+ import { generateId } from '../api/instance';
4
+ import { lazyload } from '../api/observables';
5
+ import Togglable from '../mixin/togglable';
6
+
7
+ const TogglableComponent = App.extend(Togglable);
8
+
9
+ export default {
10
+ mixins: [Togglable],
11
+
12
+ props: {
13
+ connect: String,
14
+ },
15
+
16
+ data: {
17
+ connect: '',
18
+ cls: 'uk-active',
19
+ },
20
+
21
+ computed: {
22
+ connects: {
23
+ get: ({ connect }, $el) => (connect ? queryAll(connect, $el) : []),
24
+ observe: ({ connect }) => connect,
25
+ },
26
+
27
+ connectChildren() {
28
+ return this.connects.flatMap((el) => children(el));
29
+ },
30
+ },
31
+
32
+ watch: {
33
+ connects(connects) {
34
+ for (const el of connects) {
35
+ if (isTag(el, 'ul')) {
36
+ el.role = 'presentation';
37
+ }
38
+ }
39
+ },
40
+ },
41
+
42
+ observe: lazyload({ targets: ({ connectChildren }) => connectChildren }),
43
+
44
+ update() {
45
+ for (const index in this.toggles) {
46
+ const toggle = this.toggles[index];
47
+ if (!toggle) {
48
+ continue;
49
+ }
50
+
51
+ toggle.id = generateId(this, toggle);
52
+
53
+ for (const { children } of this.connects) {
54
+ const item = children[index];
55
+
56
+ if (item) {
57
+ attr(item, {
58
+ id: generateId(this, item),
59
+ role: 'tabpanel',
60
+ 'aria-labelledby': toggle.id,
61
+ });
62
+ }
63
+ }
64
+ }
65
+ },
66
+
67
+ methods: {
68
+ showConnects(index, animate) {
69
+ const toggle = async (el) => {
70
+ const { children } = el;
71
+
72
+ const animation = data(el, 'uk-switcher-animation');
73
+
74
+ let togglable = animation
75
+ ? new TogglableComponent({ data: { ...this.$props, animation } })
76
+ : this;
77
+
78
+ const actives = toArray(children).filter(
79
+ (child, i) => i !== index && hasClass(child, this.cls),
80
+ );
81
+
82
+ if (await togglable.toggleElement(actives, false, animate)) {
83
+ await togglable.toggleElement(children[index], true, animate);
84
+ }
85
+ };
86
+
87
+ return Promise.all(this.connects.map(toggle));
88
+ },
89
+ },
90
+ };
@@ -2,20 +2,12 @@ import { css } from 'uikit-util';
2
2
 
3
3
  export default {
4
4
  slide: {
5
- show(dir) {
6
- return [{ transform: translate(dir * -100) }, { transform: translate() }];
7
- },
5
+ percent: translated,
8
6
 
9
- percent(current) {
10
- return translated(current);
11
- },
12
-
13
- translate(percent, dir) {
14
- return [
15
- { transform: translate(dir * -100 * percent) },
16
- { transform: translate(dir * 100 * (1 - percent)) },
17
- ];
18
- },
7
+ translate: (percent, dir) => [
8
+ { transform: translate(dir * -100 * percent) },
9
+ { transform: translate(dir * 100 * (1 - percent)) },
10
+ ],
19
11
  },
20
12
  };
21
13
 
@@ -1,8 +1,8 @@
1
1
  import { clamp, createEvent, css, noop, resetProps, Transition, trigger } from 'uikit-util';
2
2
 
3
3
  export default function Transitioner(prev, next, dir, { animation, easing }) {
4
- const { percent, translate, show = noop } = animation;
5
- const props = show(dir);
4
+ const { percent, translate } = animation;
5
+ const props = translate(1, dir);
6
6
 
7
7
  const { promise, resolve } = withResolvers();
8
8
 
@@ -382,10 +382,7 @@ function getCssValue(el, prop, value) {
382
382
  }
383
383
 
384
384
  function fillObject(keys, value) {
385
- return keys.reduce((data, prop) => {
386
- data[prop] = value;
387
- return data;
388
- }, {});
385
+ return Object.fromEntries(keys.map((prop) => [prop, value]));
389
386
  }
390
387
 
391
388
  /*
@@ -27,7 +27,7 @@ export default {
27
27
  },
28
28
 
29
29
  connected() {
30
- this.pos = this.$props.pos.split('-').concat('center').slice(0, 2);
30
+ this.pos = [...this.$props.pos.split('-'), 'center'].slice(0, 2);
31
31
  [this.dir, this.align] = this.pos;
32
32
  this.axis = includes(['top', 'bottom'], this.dir) ? 'y' : 'x';
33
33
  },
@@ -0,0 +1,57 @@
1
+ import { query, scrolledOver, toPx } from 'uikit-util';
2
+ import { resize, scroll } from '../api/observables';
3
+ import { ease } from './parallax';
4
+
5
+ export default {
6
+ props: {
7
+ parallaxTarget: Boolean,
8
+ parallaxStart: String,
9
+ parallaxEnd: String,
10
+ parallaxEasing: Number,
11
+ },
12
+
13
+ data: {
14
+ parallaxTarget: false,
15
+ parallaxStart: 0,
16
+ parallaxEnd: 0,
17
+ parallaxEasing: 0,
18
+ },
19
+
20
+ observe: [
21
+ resize({
22
+ target: ({ $el, parallaxTarget }) => [$el, parallaxTarget],
23
+ filter: ({ parallax }) => parallax,
24
+ }),
25
+ scroll({ filter: ({ parallax }) => parallax }),
26
+ ],
27
+
28
+ computed: {
29
+ parallaxTargetFallback: ($props, $el) => $el,
30
+
31
+ parallaxTarget({ parallaxTarget }, $el) {
32
+ return (parallaxTarget && query(parallaxTarget, $el)) || this.parallaxTargetFallback;
33
+ },
34
+ },
35
+
36
+ update: {
37
+ read() {
38
+ if (!this.parallax) {
39
+ return;
40
+ }
41
+
42
+ const target = this.parallaxTarget;
43
+
44
+ if (!target) {
45
+ return;
46
+ }
47
+
48
+ const start = toPx(this.parallaxStart, 'height', target, true);
49
+ const end = toPx(this.parallaxEnd, 'height', target, true);
50
+ const percent = ease(scrolledOver(target, start, end), this.parallaxEasing);
51
+
52
+ return { percent };
53
+ },
54
+
55
+ events: ['scroll', 'resize'],
56
+ },
57
+ };