uikit 3.15.6-dev.fb448ac28 → 3.15.7-dev.3ec9925a1

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 (55) hide show
  1. package/CHANGELOG.md +13 -1
  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 +2 -2
  11. package/dist/js/components/countdown.min.js +1 -1
  12. package/dist/js/components/filter.js +1 -1
  13. package/dist/js/components/filter.min.js +1 -1
  14. package/dist/js/components/lightbox-panel.js +36 -10
  15. package/dist/js/components/lightbox-panel.min.js +1 -1
  16. package/dist/js/components/lightbox.js +36 -10
  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 +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 +7 -6
  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 +7 -6
  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 +3 -4
  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 +121 -104
  37. package/dist/js/uikit-core.min.js +2 -2
  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 +128 -111
  41. package/dist/js/uikit.min.js +2 -2
  42. package/package.json +2 -2
  43. package/src/js/api/boot.js +6 -8
  44. package/src/js/api/component.js +18 -21
  45. package/src/js/api/instance.js +6 -11
  46. package/src/js/api/state.js +11 -11
  47. package/src/js/components/tooltip.js +2 -3
  48. package/src/js/core/accordion.js +41 -33
  49. package/src/js/core/drop.js +10 -4
  50. package/src/js/core/icon.js +1 -1
  51. package/src/js/core/offcanvas.js +0 -14
  52. package/src/js/core/scrollspy-nav.js +2 -1
  53. package/src/js/mixin/class.js +2 -2
  54. package/src/js/mixin/modal.js +25 -0
  55. package/src/js/mixin/slider-drag.js +5 -4
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.15.6-dev.fb448ac28",
5
+ "version": "3.15.7-dev.3ec9925a1",
6
6
  "main": "dist/js/uikit.js",
7
7
  "style": "dist/css/uikit.css",
8
8
  "sideEffects": [
@@ -20,7 +20,7 @@
20
20
  "prefix": "node build/prefix",
21
21
  "scope": "node build/scope",
22
22
  "release": "node build/release",
23
- "watch": "watch-run -i -p '**/*.less' yarn compile-less",
23
+ "watch": "watch-run -i -p \"**/*.less\" -- node build/less",
24
24
  "eslint": "eslint src/js",
25
25
  "eslint-fix": "eslint --fix src/js"
26
26
  },
@@ -45,15 +45,13 @@ export default function (UIkit) {
45
45
  function applyAttributeMutation({ target, attributeName }) {
46
46
  const name = getComponentName(attributeName);
47
47
 
48
- if (!name || !(name in UIkit)) {
49
- return;
50
- }
48
+ if (name) {
49
+ if (hasAttr(target, attributeName)) {
50
+ UIkit[name](target);
51
+ return;
52
+ }
51
53
 
52
- if (hasAttr(target, attributeName)) {
53
- UIkit[name](target);
54
- return;
54
+ UIkit.getComponent(target, name)?.$destroy();
55
55
  }
56
-
57
- UIkit.getComponent(target, name)?.$destroy();
58
56
  }
59
57
  }
@@ -1,23 +1,23 @@
1
- import { $$, camelize, hyphenate, isPlainObject, memoize, startsWith } from 'uikit-util';
1
+ import { $$, camelize, hyphenate, isPlainObject } from 'uikit-util';
2
2
 
3
+ const components = {};
3
4
  export default function (UIkit) {
4
- const DATA = UIkit.data;
5
-
6
- const components = {};
5
+ const { data: DATA, prefix: PREFIX } = UIkit;
7
6
 
8
7
  UIkit.component = function (name, options) {
9
- const id = hyphenate(name);
10
-
11
- name = camelize(id);
8
+ name = hyphenate(name);
9
+ const id = PREFIX + name;
12
10
 
13
11
  if (!options) {
14
- if (isPlainObject(components[name])) {
15
- components[name] = UIkit.extend(components[name]);
12
+ if (isPlainObject(components[id])) {
13
+ components[id] = components[`data-${id}`] = UIkit.extend(components[id]);
16
14
  }
17
15
 
18
- return components[name];
16
+ return components[id];
19
17
  }
20
18
 
19
+ name = camelize(name);
20
+
21
21
  UIkit[name] = function (element, data) {
22
22
  const component = UIkit.component(name);
23
23
 
@@ -44,15 +44,16 @@ export default function (UIkit) {
44
44
 
45
45
  const opt = isPlainObject(options) ? { ...options } : options.options;
46
46
 
47
+ opt.id = id;
47
48
  opt.name = name;
48
49
 
49
50
  opt.install?.(UIkit, opt, name);
50
51
 
51
52
  if (UIkit._initialized && !opt.functional) {
52
- requestAnimationFrame(() => UIkit[name](`[uk-${id}],[data-uk-${id}]`));
53
+ requestAnimationFrame(() => UIkit[name](`[${id}],[data-${id}]`));
53
54
  }
54
55
 
55
- return (components[name] = isPlainObject(options) ? opt : options);
56
+ return (components[id] = components[`data-${id}`] = isPlainObject(options) ? opt : options);
56
57
  };
57
58
 
58
59
  UIkit.getComponents = (element) => element?.[DATA] || {};
@@ -67,10 +68,7 @@ export default function (UIkit) {
67
68
 
68
69
  for (const attribute of node.attributes) {
69
70
  const name = getComponentName(attribute.name);
70
-
71
- if (name && name in components) {
72
- UIkit[name](node);
73
- }
71
+ name && UIkit[name](node);
74
72
  }
75
73
  };
76
74
 
@@ -81,8 +79,7 @@ export default function (UIkit) {
81
79
  };
82
80
  }
83
81
 
84
- export const getComponentName = memoize((attribute) => {
85
- return startsWith(attribute, 'uk-') || startsWith(attribute, 'data-uk-')
86
- ? camelize(attribute.replace('data-uk-', '').replace('uk-', ''))
87
- : false;
88
- });
82
+ export function getComponentName(attribute) {
83
+ const cmp = components[attribute];
84
+ return cmp && (isPlainObject(cmp) ? cmp : cmp.options).name;
85
+ }
@@ -1,4 +1,4 @@
1
- import { hyphenate, isEmpty, memoize, remove, within } from 'uikit-util';
1
+ import { isEmpty, remove, within } from 'uikit-util';
2
2
 
3
3
  export default function (UIkit) {
4
4
  const DATA = UIkit.data;
@@ -66,14 +66,9 @@ export default function (UIkit) {
66
66
 
67
67
  UIkit.prototype.$getComponent = UIkit.getComponent;
68
68
 
69
- const componentName = memoize((name) => UIkit.prefix + hyphenate(name));
70
- Object.defineProperties(UIkit.prototype, {
71
- $container: Object.getOwnPropertyDescriptor(UIkit, 'container'),
72
-
73
- $name: {
74
- get() {
75
- return componentName(this.$options.name);
76
- },
77
- },
78
- });
69
+ Object.defineProperty(
70
+ UIkit.prototype,
71
+ '$container',
72
+ Object.getOwnPropertyDescriptor(UIkit, 'container')
73
+ );
79
74
  }
@@ -73,7 +73,7 @@ export default function (UIkit) {
73
73
  UIkit.prototype._initProps = function (props) {
74
74
  let key;
75
75
 
76
- props = props || getProps(this.$options, this.$name);
76
+ props = props || getProps(this.$options);
77
77
 
78
78
  for (key in props) {
79
79
  if (!isUndefined(props[key])) {
@@ -124,9 +124,9 @@ export default function (UIkit) {
124
124
  };
125
125
  }
126
126
 
127
- function getProps(opts, name) {
127
+ function getProps(opts) {
128
128
  const data = {};
129
- const { args = [], props = {}, el } = opts;
129
+ const { args = [], props = {}, el, id } = opts;
130
130
 
131
131
  if (!props) {
132
132
  return data;
@@ -149,7 +149,7 @@ function getProps(opts, name) {
149
149
  data[key] = value;
150
150
  }
151
151
 
152
- const options = parseOptions(getData(el, name), args);
152
+ const options = parseOptions(getData(el, id), args);
153
153
 
154
154
  for (const key in options) {
155
155
  const prop = camelize(key);
@@ -277,24 +277,24 @@ function initChildListObserver(component) {
277
277
  }
278
278
 
279
279
  function initPropsObserver(component) {
280
- const { $name, $options, $props } = component;
281
- const { attrs, props, el } = $options;
280
+ const { $options, $props } = component;
281
+ const { id, attrs, props, el } = $options;
282
282
 
283
283
  if (!props || attrs === false) {
284
284
  return;
285
285
  }
286
286
 
287
287
  const attributes = isArray(attrs) ? attrs : Object.keys(props);
288
- const filter = attributes.map((key) => hyphenate(key)).concat($name);
288
+ const filter = attributes.map((key) => hyphenate(key)).concat(id);
289
289
 
290
290
  const observer = new MutationObserver((records) => {
291
- const data = getProps($options, $name);
291
+ const data = getProps($options);
292
292
  if (
293
293
  records.some(({ attributeName }) => {
294
294
  const prop = attributeName.replace('data-', '');
295
- return (
296
- prop === $name ? attributes : [camelize(prop), camelize(attributeName)]
297
- ).some((prop) => !isUndefined(data[prop]) && data[prop] !== $props[prop]);
295
+ return (prop === id ? attributes : [camelize(prop), camelize(attributeName)]).some(
296
+ (prop) => !isUndefined(data[prop]) && data[prop] !== $props[prop]
297
+ );
298
298
  })
299
299
  ) {
300
300
  component.$reset();
@@ -59,13 +59,12 @@ export default {
59
59
 
60
60
  this._unbind = once(
61
61
  document,
62
- `show keydown ${pointerDown}`,
62
+ `keydown ${pointerDown}`,
63
63
  this.hide,
64
64
  false,
65
65
  (e) =>
66
66
  (e.type === pointerDown && !within(e.target, this.$el)) ||
67
- (e.type === 'keydown' && e.keyCode === 27) ||
68
- (e.type === 'show' && e.detail[0] !== this && e.detail[0].$name === this.$name)
67
+ (e.type === 'keydown' && e.keyCode === 27)
69
68
  );
70
69
 
71
70
  clearTimeout(this.showTimer);
@@ -11,9 +11,7 @@ import {
11
11
  hasClass,
12
12
  includes,
13
13
  index,
14
- isInView,
15
- noop,
16
- scrollIntoView,
14
+ scrollParents,
17
15
  toFloat,
18
16
  toggleClass,
19
17
  Transition,
@@ -108,52 +106,46 @@ export default {
108
106
  return `${this.targets} ${this.$props.toggle}`;
109
107
  },
110
108
 
111
- handler(e) {
109
+ async handler(e) {
112
110
  e.preventDefault();
113
- this.toggle(index(this.toggles, e.current));
111
+
112
+ this._off?.();
113
+ this._off = keepScrollPosition(e.target);
114
+ await this.toggle(index(this.toggles, e.current));
115
+ this._off();
114
116
  },
115
117
  },
116
118
  ],
117
119
 
118
120
  methods: {
119
- toggle(item, animate) {
120
- let items = [this.items[getIndex(item, this.items)]];
121
+ async toggle(item, animate) {
122
+ item = this.items[getIndex(item, this.items)];
123
+ let items = [item];
121
124
  const activeItems = filter(this.items, `.${this.clsOpen}`);
122
125
 
123
126
  if (!this.multiple && !includes(activeItems, items[0])) {
124
127
  items = items.concat(activeItems);
125
128
  }
126
129
 
127
- if (
128
- !this.collapsible &&
129
- activeItems.length < 2 &&
130
- !filter(items, `:not(.${this.clsOpen})`).length
131
- ) {
130
+ if (!this.collapsible && activeItems.length < 2 && includes(activeItems, item)) {
132
131
  return;
133
132
  }
134
133
 
135
- for (const el of items) {
136
- this.toggleElement(el, !hasClass(el, this.clsOpen), (el, show) => {
137
- toggleClass(el, this.clsOpen, show);
138
- attr($(this.$props.toggle, el), 'aria-expanded', show);
139
-
140
- if (animate === false || !this.animation) {
141
- hide($(this.content, el), !show);
142
- return;
143
- }
144
-
145
- return transition(el, show, this).then(() => {
146
- if (show) {
147
- const toggle = $(this.$props.toggle, el);
148
- requestAnimationFrame(() => {
149
- if (!isInView(toggle)) {
150
- scrollIntoView(toggle, { offset: this.offset });
151
- }
152
- });
134
+ await Promise.all(
135
+ items.map((el) =>
136
+ this.toggleElement(el, !includes(activeItems, el), (el, show) => {
137
+ toggleClass(el, this.clsOpen, show);
138
+ attr($(this.$props.toggle, el), 'aria-expanded', show);
139
+
140
+ if (animate === false || !this.animation) {
141
+ hide($(this.content, el), !show);
142
+ return;
153
143
  }
154
- }, noop);
155
- });
156
- }
144
+
145
+ return transition(el, show, this);
146
+ })
147
+ )
148
+ );
157
149
  },
158
150
  },
159
151
  };
@@ -193,3 +185,19 @@ async function transition(el, show, { content, duration, velocity, transition })
193
185
  hide(content, true);
194
186
  }
195
187
  }
188
+
189
+ function keepScrollPosition(el) {
190
+ const scrollParent = scrollParents(el)[0];
191
+ let frame;
192
+ (function scroll() {
193
+ frame = requestAnimationFrame(() => {
194
+ const { top } = el.getBoundingClientRect();
195
+ if (top < 0) {
196
+ scrollParent.scrollTop += top;
197
+ }
198
+ scroll();
199
+ });
200
+ })();
201
+
202
+ return () => requestAnimationFrame(() => cancelAnimationFrame(frame));
203
+ }
@@ -30,7 +30,7 @@ import {
30
30
  scrollParents,
31
31
  within,
32
32
  } from 'uikit-util';
33
- import { preventBackgroundScroll, preventOverscroll } from '../mixin/modal';
33
+ import { isSameSiteAnchor, preventBackgroundScroll, preventOverscroll } from '../mixin/modal';
34
34
 
35
35
  export let active;
36
36
 
@@ -143,11 +143,17 @@ export default {
143
143
  name: 'click',
144
144
 
145
145
  delegate() {
146
- return 'a[href^="#"]';
146
+ return 'a[href*="#"]';
147
147
  },
148
148
 
149
- handler({ defaultPrevented, current: { hash } }) {
150
- if (!defaultPrevented && hash && !within(hash, this.$el)) {
149
+ handler({ defaultPrevented, current }) {
150
+ const { hash } = current;
151
+ if (
152
+ !defaultPrevented &&
153
+ hash &&
154
+ isSameSiteAnchor(current) &&
155
+ !within(hash, this.$el)
156
+ ) {
151
157
  this.hide(false);
152
158
  }
153
159
  },
@@ -99,7 +99,7 @@ export const IconComponent = {
99
99
  }),
100
100
 
101
101
  beforeConnect() {
102
- addClass(this.$el, this.$name);
102
+ addClass(this.$el, this.$options.id);
103
103
  },
104
104
  };
105
105
 
@@ -79,20 +79,6 @@ export default {
79
79
  },
80
80
 
81
81
  events: [
82
- {
83
- name: 'click',
84
-
85
- delegate() {
86
- return 'a[href^="#"]';
87
- },
88
-
89
- handler({ current: { hash }, defaultPrevented }) {
90
- if (!defaultPrevented && hash && $(hash, document.body)) {
91
- this.hide();
92
- }
93
- },
94
- },
95
-
96
82
  {
97
83
  name: 'touchmove',
98
84
 
@@ -11,6 +11,7 @@ import {
11
11
  trigger,
12
12
  } from 'uikit-util';
13
13
  import { getTargetElement } from './scroll';
14
+ import { isSameSiteAnchor } from '../mixin/modal';
14
15
 
15
16
  export default {
16
17
  mixins: [Scroll],
@@ -34,7 +35,7 @@ export default {
34
35
  computed: {
35
36
  links: {
36
37
  get(_, $el) {
37
- return $$('a[href^="#"]', $el).filter((el) => el.hash);
38
+ return $$('a[href*="#"]', $el).filter((el) => el.hash && isSameSiteAnchor(el));
38
39
  },
39
40
 
40
41
  watch(links) {
@@ -1,7 +1,7 @@
1
- import { addClass, hasClass } from 'uikit-util';
1
+ import { addClass } from 'uikit-util';
2
2
 
3
3
  export default {
4
4
  connected() {
5
- !hasClass(this.$el, this.$name) && addClass(this.$el, this.$name);
5
+ addClass(this.$el, this.$options.id);
6
6
  },
7
7
  };
@@ -81,6 +81,27 @@ export default {
81
81
  },
82
82
  },
83
83
 
84
+ {
85
+ name: 'click',
86
+
87
+ delegate() {
88
+ return 'a[href*="#"]';
89
+ },
90
+
91
+ handler({ current, defaultPrevented }) {
92
+ const { hash } = current;
93
+ if (
94
+ !defaultPrevented &&
95
+ hash &&
96
+ isSameSiteAnchor(current) &&
97
+ !within(hash, this.$el) &&
98
+ $(hash, document.body)
99
+ ) {
100
+ this.hide();
101
+ }
102
+ },
103
+ },
104
+
84
105
  {
85
106
  name: 'toggle',
86
107
 
@@ -361,3 +382,7 @@ function filterChildren(el, fn) {
361
382
  });
362
383
  return children;
363
384
  }
385
+
386
+ export function isSameSiteAnchor(a) {
387
+ return ['origin', 'pathname', 'search'].every((part) => a[part] === location[part]);
388
+ }
@@ -14,9 +14,10 @@ import {
14
14
  } from 'uikit-util';
15
15
 
16
16
  const pointerOptions = { passive: false, capture: true };
17
+ const pointerUpOptions = { passive: true, capture: true };
17
18
  const pointerDown = 'touchstart mousedown';
18
19
  const pointerMove = 'touchmove mousemove';
19
- const pointerUp = 'touchend touchcancel mouseup click input';
20
+ const pointerUp = 'touchend touchcancel mouseup click input scroll';
20
21
 
21
22
  export default {
22
23
  props: {
@@ -75,7 +76,7 @@ export default {
75
76
 
76
77
  {
77
78
  // iOS workaround for slider stopping if swiping fast
78
- name: `${pointerMove} ${pointerUp}`,
79
+ name: pointerMove,
79
80
  el() {
80
81
  return this.list;
81
82
  },
@@ -105,7 +106,7 @@ export default {
105
106
  on(document, pointerMove, this.move, pointerOptions);
106
107
 
107
108
  // 'input' event is triggered by video controls
108
- on(document, pointerUp, this.end, pointerOptions);
109
+ on(document, pointerUp, this.end, pointerUpOptions);
109
110
 
110
111
  css(this.list, 'userSelect', 'none');
111
112
  },
@@ -186,7 +187,7 @@ export default {
186
187
 
187
188
  end() {
188
189
  off(document, pointerMove, this.move, pointerOptions);
189
- off(document, pointerUp, this.end, pointerOptions);
190
+ off(document, pointerUp, this.end, pointerUpOptions);
190
191
 
191
192
  if (this.dragging) {
192
193
  this.dragging = null;