u2ui 1.5.20 → 1.7.5
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/attr/disableif/README.md +21 -0
- package/attr/disableif/disableif.js +72 -45
- package/el/calendar/README.md +6 -6
- package/el/calendar/calendar.css +2 -2
- package/el/calendar/calendar.js +15 -11
- package/el/calendar/ext/drag.js +1 -1
- package/el/calendar/ext/keyNavigation.js +1 -1
- package/el/calendar/manifest.json +2 -2
- package/el/{carousel-nav → carouselnav}/README.md +7 -7
- package/el/{carousel-nav/carousel-nav.js → carouselnav/carouselnav.js} +5 -5
- package/el/{carousel-nav → carouselnav}/manifest.json +4 -4
- package/el/{parallax-bg → parallaxbg}/README.md +14 -14
- package/el/{parallax-bg → parallaxbg}/manifest.json +5 -5
- package/el/{parallax-bg/parallax-bg.css → parallaxbg/parallaxbg.css} +2 -2
- package/el/{parallax-bg/parallax-bg.js → parallaxbg/parallaxbg.js} +5 -5
- package/el/system/demoHtml.html +5 -5
- package/package.json +1 -1
- package/u2/enhance.js +2 -1
- package/u2/projects.json +17 -17
package/attr/disableif/README.md
CHANGED
|
@@ -19,6 +19,26 @@ Disable form-elements (like inputs, buttons, fieldsets) based on a condition
|
|
|
19
19
|
}
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
## Conditions
|
|
23
|
+
|
|
24
|
+
| condition | disabled while |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `name` | a value of `name` is not empty |
|
|
27
|
+
| `!name` | no value of `name` is not empty |
|
|
28
|
+
| `name=v` | a value equals `v` |
|
|
29
|
+
| `name!=v` | no value equals `v` |
|
|
30
|
+
| `name>n`, `name<n` | a value is a number greater / less than `n` |
|
|
31
|
+
|
|
32
|
+
A field's values are what the form would send under its name (`FormData`): none for an unchecked
|
|
33
|
+
checkbox or a disabled field, several for same-named fields or a `select multiple`, a file by its name.
|
|
34
|
+
So a field disabled by its own condition counts as empty for the conditions that depend on it, and
|
|
35
|
+
chains settle in one go. Each check builds the `FormData`, which fires the form's `formdata` event.
|
|
36
|
+
A field that is not in the form counts as empty, with a warning (a typo?).
|
|
37
|
+
|
|
38
|
+
Typing applies at once; fields and conditions added, removed or changed in the form apply on the
|
|
39
|
+
next microtask. A value set by script (`input.value = …`) is only seen with an `input` event.
|
|
40
|
+
Removing the attribute leaves the element as it is.
|
|
41
|
+
|
|
22
42
|
## Install
|
|
23
43
|
|
|
24
44
|
```html
|
|
@@ -29,6 +49,7 @@ Disable form-elements (like inputs, buttons, fieldsets) based on a condition
|
|
|
29
49
|
|
|
30
50
|
[test.html](http://gcdn.li/u2ui/u2@main/attr/disableif/tests/test.html)
|
|
31
51
|
[minimal.html](http://gcdn.li/u2ui/u2@main/attr/disableif/tests/minimal.html)
|
|
52
|
+
[disableif.test.html](http://gcdn.li/u2ui/u2@main/attr/disableif/tests/disableif.test.html) (tests)
|
|
32
53
|
|
|
33
54
|
## About
|
|
34
55
|
|
|
@@ -1,59 +1,86 @@
|
|
|
1
1
|
import { SelectorObserver } from '../../js/SelectorObserver/SelectorObserver.js';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (operator) console.warn(`u2-disableif: "!" operator is not supported with other operators`, { el, field, operator, value });
|
|
11
|
-
operator = '=';
|
|
12
|
-
}
|
|
13
|
-
const target = el.form.elements[field];
|
|
14
|
-
if (!target) {
|
|
15
|
-
console.warn(`u2-disableif: field "${field}" not found`, { el, field, operator, value });
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
let stringTargetValue = target.value;
|
|
19
|
-
if (target.type === 'checkbox') stringTargetValue = target.checked ? target.value : '';
|
|
3
|
+
/** Once per element and problem, not on every update. */
|
|
4
|
+
const warned = new WeakMap();
|
|
5
|
+
function warn(el, problem) {
|
|
6
|
+
if (warned.get(el) === problem) return;
|
|
7
|
+
warned.set(el, problem);
|
|
8
|
+
console.warn('u2-disableif: ' + problem, el);
|
|
9
|
+
}
|
|
20
10
|
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Whether the element's condition holds. A field's values are what the form would send under its
|
|
13
|
+
* name (FormData): none for an unchecked box or a disabled field, several for same-named fields or
|
|
14
|
+
* a select multiple; a file counts by its name. undefined: no valid condition (yet).
|
|
15
|
+
*/
|
|
16
|
+
function holds(el, data) {
|
|
17
|
+
const match = el.getAttribute('u2-disableif').match(/^(!?)([^=!<>]*)(=|!=|>|<)?([^=!<>]*)$/);
|
|
18
|
+
if (!match) return;
|
|
19
|
+
const [, not, field, operator, value] = match;
|
|
20
|
+
const form = el.form;
|
|
21
|
+
// a custom element that is not defined yet is no form field yet: check again once it is
|
|
22
|
+
const pending = !form.elements[field] && form.querySelector(`:not(:defined)[name="${CSS.escape(field)}"]`);
|
|
23
|
+
if (pending) { customElements.whenDefined(pending.localName).then(() => schedule(form)); return; }
|
|
24
|
+
if (not && operator) { warn(el, `"!" cannot be combined with "${operator}"`); return; }
|
|
25
|
+
if (!form.elements[field]) warn(el, `field "${field}" not found, so it is empty`); // a typo?
|
|
26
|
+
const values = data.getAll(field).map(v => typeof v === 'string' ? v : v.name);
|
|
27
|
+
switch (operator) {
|
|
28
|
+
case '=': return values.includes(value);
|
|
29
|
+
case '!=': return !values.includes(value);
|
|
30
|
+
case '>': return values.some(v => parseFloat(v) > parseFloat(value));
|
|
31
|
+
case '<': return values.some(v => parseFloat(v) < parseFloat(value));
|
|
32
|
+
}
|
|
33
|
+
return values.some(Boolean) !== !!not;
|
|
34
|
+
}
|
|
23
35
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
conditionMet = numericTargetValue > numericConditionValue;
|
|
37
|
-
break;
|
|
38
|
-
case '<':
|
|
39
|
-
conditionMet = numericTargetValue < numericConditionValue;
|
|
40
|
-
break;
|
|
36
|
+
/** Applies all conditions of the form, again until nothing changes: disabling a field empties it for
|
|
37
|
+
* the conditions that depend on it. A cycle stops after as many passes as there are conditions. */
|
|
38
|
+
function update(form) {
|
|
39
|
+
const els = [...form.elements].filter(el => el.hasAttribute('u2-disableif'));
|
|
40
|
+
for (let pass = 0; pass <= els.length; pass++) {
|
|
41
|
+
const data = new FormData(form); // fires "formdata", once per pass
|
|
42
|
+
let changed = false;
|
|
43
|
+
for (const el of els) {
|
|
44
|
+
const disabled = holds(el, data);
|
|
45
|
+
if (disabled === undefined || disabled === el.disabled) continue;
|
|
46
|
+
el.disabled = disabled;
|
|
47
|
+
changed = true;
|
|
41
48
|
}
|
|
42
|
-
|
|
49
|
+
if (!changed) return;
|
|
43
50
|
}
|
|
44
51
|
}
|
|
45
52
|
|
|
53
|
+
/** One update per form and `wait` (microtask, frame), however many changes ask for it. */
|
|
54
|
+
const scheduled = new Map();
|
|
55
|
+
function schedule(form, wait = queueMicrotask) {
|
|
56
|
+
const forms = scheduled.get(wait) ?? scheduled.set(wait, new WeakSet()).get(wait);
|
|
57
|
+
if (!form || forms.has(form)) return;
|
|
58
|
+
forms.add(form);
|
|
59
|
+
wait(() => { forms.delete(form); update(form); });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Typing applies at once. Fields and conditions that are added, removed or changed in the form
|
|
63
|
+
* apply on the next microtask; one that changes its form also updates the new one. */
|
|
64
|
+
const ATTRIBUTES = ['u2-disableif', 'name', 'form', 'value', 'checked', 'selected', 'multiple', 'type'];
|
|
65
|
+
const watched = new WeakSet();
|
|
66
|
+
function watch(form) {
|
|
67
|
+
if (!form || watched.has(form)) return;
|
|
68
|
+
watched.add(form);
|
|
69
|
+
form.addEventListener('input', () => update(form));
|
|
70
|
+
form.addEventListener('reset', () => setTimeout(() => update(form))); // the values change after the event
|
|
71
|
+
new MutationObserver(records => {
|
|
72
|
+
schedule(form);
|
|
73
|
+
for (const { target } of records) if (target.form !== form) { watch(target.form); schedule(target.form); }
|
|
74
|
+
}).observe(form, { subtree: true, childList: true, attributes: true, attributeFilter: ATTRIBUTES });
|
|
75
|
+
}
|
|
46
76
|
|
|
47
77
|
new SelectorObserver({
|
|
48
78
|
on: (el) => {
|
|
49
|
-
|
|
79
|
+
watch(el.form);
|
|
80
|
+
schedule(el.form);
|
|
50
81
|
// wait for custom-element-inputs
|
|
51
|
-
// queueMicrotask(()=>
|
|
52
|
-
|
|
53
|
-
//setTimeout(()=>
|
|
54
|
-
const form = el.form;
|
|
55
|
-
el.form.addEventListener('input', () => checkCondition(el));
|
|
82
|
+
// queueMicrotask(() => schedule(el.form));
|
|
83
|
+
schedule(el.form, requestAnimationFrame);
|
|
84
|
+
// setTimeout(() => schedule(el.form));
|
|
56
85
|
},
|
|
57
|
-
off: (el) => {
|
|
58
|
-
}
|
|
59
86
|
}).observe('[u2-disableif]');
|
package/el/calendar/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# <u2-calendar> - element (BETA)
|
|
2
|
-
Calendar / month view component, use `<u2-
|
|
2
|
+
Calendar / month view component, use `<u2-calendar-item>` as children
|
|
3
3
|
|
|
4
4
|
> Status: BETA — experimental. API and markup may change.
|
|
5
5
|
|
|
6
6
|
## Features
|
|
7
7
|
|
|
8
|
-
- month view
|
|
8
|
+
- month view, always six weeks: every month has the same height
|
|
9
9
|
- lightweight layout and styling
|
|
10
|
-
- supports `u2-
|
|
10
|
+
- supports `u2-calendar-item` children with `start` and `end` attributes
|
|
11
11
|
- events rendered as colored bars spanning multiple days
|
|
12
12
|
- performat and responsive using css grid
|
|
13
13
|
|
|
@@ -21,8 +21,8 @@ u2Calendaritem2.addEventListener('click',()=>{
|
|
|
21
21
|
|
|
22
22
|
```html
|
|
23
23
|
<u2-calendar date="2025-10-01">
|
|
24
|
-
<u2-
|
|
25
|
-
<u2-
|
|
24
|
+
<u2-calendar-item start="2025-10-09">Demo</u2-calendar-item>
|
|
25
|
+
<u2-calendar-item start="2025-10-19" end="2025-10-23" id="u2Calendaritem2">Demo 2</u2-calendar-item>
|
|
26
26
|
</u2-calendar>
|
|
27
27
|
|
|
28
28
|
```
|
|
@@ -31,7 +31,7 @@ u2Calendaritem2.addEventListener('click',()=>{
|
|
|
31
31
|
u2-calendar {
|
|
32
32
|
font-size:10px;
|
|
33
33
|
}
|
|
34
|
-
u2-
|
|
34
|
+
u2-calendar-item {
|
|
35
35
|
background-color:var(--color, orange);
|
|
36
36
|
&:hover {
|
|
37
37
|
background-color:var(--color-dark, red);
|
package/el/calendar/calendar.css
CHANGED
|
@@ -6,7 +6,7 @@ u2-calendar {
|
|
|
6
6
|
z-index: 1;
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
-
u2-
|
|
9
|
+
u2-calendar-item {
|
|
10
10
|
&[draggable="true"] {
|
|
11
11
|
cursor: move;
|
|
12
12
|
}
|
|
@@ -20,7 +20,7 @@ u2-calendaritem {
|
|
|
20
20
|
u2-calendar:not(:defined) {
|
|
21
21
|
display:block;
|
|
22
22
|
}
|
|
23
|
-
u2-
|
|
23
|
+
u2-calendar-item:not(:defined) {
|
|
24
24
|
display:block;
|
|
25
25
|
padding:.2em .9em;
|
|
26
26
|
margin:.2em 0;
|
package/el/calendar/calendar.js
CHANGED
|
@@ -62,19 +62,25 @@ export default class U2Calendar extends U2Element {
|
|
|
62
62
|
</style>
|
|
63
63
|
<div class=navigation>
|
|
64
64
|
<h2></h2>
|
|
65
|
-
<button
|
|
65
|
+
<button name=today style="padding-inline:.5rem">
|
|
66
66
|
Today
|
|
67
67
|
</button>
|
|
68
|
-
<button
|
|
68
|
+
<button name=prev>
|
|
69
69
|
<u2-ico icon="chevron-left"><</u2-ico>
|
|
70
70
|
</button>
|
|
71
|
-
<button
|
|
71
|
+
<button name=next>
|
|
72
72
|
<u2-ico icon="chevron-right">></u2-ico>
|
|
73
73
|
</button>
|
|
74
74
|
</div>
|
|
75
75
|
<div class=header></div>
|
|
76
76
|
<div class=grid role=grid><slot></slot></div>
|
|
77
77
|
`;
|
|
78
|
+
// no inline handlers: a CSP without 'unsafe-inline' would block them
|
|
79
|
+
this.shadowRoot.querySelector('.navigation').addEventListener('click', (e) => {
|
|
80
|
+
const name = e.target.closest('button')?.name;
|
|
81
|
+
if (name === 'today') this.date = new Date();
|
|
82
|
+
else if (name) this[name]();
|
|
83
|
+
});
|
|
78
84
|
}
|
|
79
85
|
|
|
80
86
|
_setLocale(localeStr) {
|
|
@@ -154,10 +160,9 @@ export default class U2Calendar extends U2Element {
|
|
|
154
160
|
const firstOfMonth = new Date(Date.UTC(year, month, 1));
|
|
155
161
|
const startOffset = (firstOfMonth.getUTCDay() - this._weekStart + 7) % 7;
|
|
156
162
|
|
|
157
|
-
for (let i = 0; i < 42; i++) { // 6
|
|
163
|
+
for (let i = 0; i < 42; i++) { // always 6 weeks, so every month has the same height
|
|
158
164
|
const date = new Date(Date.UTC(year, month, 1 - startOffset + i));
|
|
159
165
|
const isOtherMonth = date.getUTCMonth() !== month;
|
|
160
|
-
if (isOtherMonth && i === 35) break; // stop, if other month and last row
|
|
161
166
|
const isToday = date.toDateString() === today.toDateString();
|
|
162
167
|
grid.appendChild(this.createDayCell(date, i, isOtherMonth, isToday));
|
|
163
168
|
}
|
|
@@ -190,7 +195,7 @@ export default class U2Calendar extends U2Element {
|
|
|
190
195
|
});
|
|
191
196
|
}
|
|
192
197
|
_updateLayout() {
|
|
193
|
-
const items = Array.from(this.querySelectorAll('u2-
|
|
198
|
+
const items = Array.from(this.querySelectorAll('u2-calendar-item'));
|
|
194
199
|
|
|
195
200
|
// Berechne Wochen-Segmente für alle Items
|
|
196
201
|
const itemWeeks = items.map(item => ({
|
|
@@ -235,14 +240,11 @@ export default class U2Calendar extends U2Element {
|
|
|
235
240
|
splitIntoWeeks(start, end, year, month) {
|
|
236
241
|
const weeks = [];
|
|
237
242
|
const firstDay = new Date(Date.UTC(year, month, 1));
|
|
238
|
-
const monthEnd = new Date(Date.UTC(year, month + 1, 0));
|
|
239
243
|
const startOffset = (firstDay.getUTCDay() - this._weekStart + 7) % 7;
|
|
240
244
|
|
|
241
245
|
// Calculate the first and last day of the visible calendar view
|
|
242
246
|
const viewStart = new Date(Date.UTC(year, month, 1 - startOffset));
|
|
243
|
-
const
|
|
244
|
-
const totalDays = Math.ceil((daysInMonth + startOffset) / 7) * 7;
|
|
245
|
-
const viewEnd = new Date(Date.UTC(year, month, 1 - startOffset + totalDays - 1));
|
|
247
|
+
const viewEnd = new Date(Date.UTC(year, month, 1 - startOffset + 41)); // 6 weeks, as rendered
|
|
246
248
|
|
|
247
249
|
// Parse input dates and normalize to start of day
|
|
248
250
|
const eventStart = new Date(start);
|
|
@@ -387,4 +389,6 @@ function getTimeFormatter(localeTag, options = { hour: '2-digit', minute: '2-dig
|
|
|
387
389
|
|
|
388
390
|
|
|
389
391
|
customElements.get('u2-calendar') || customElements.define('u2-calendar', U2Calendar);
|
|
390
|
-
customElements.get('u2-
|
|
392
|
+
customElements.get('u2-calendar-item') || customElements.define('u2-calendar-item', U2CalendarItem);
|
|
393
|
+
|
|
394
|
+
export const extraElements = { 'u2-calendar-item': U2CalendarItem };
|
package/el/calendar/ext/drag.js
CHANGED
|
@@ -17,7 +17,7 @@ function removePart(el, partName) {
|
|
|
17
17
|
document.addEventListener('dragstart', (e) => {
|
|
18
18
|
const item = e.target.closest('[draggable="true"]');
|
|
19
19
|
if (!item) return;
|
|
20
|
-
if (item.tagName.toLowerCase() !== 'u2-
|
|
20
|
+
if (item.tagName.toLowerCase() !== 'u2-calendar-item') return;
|
|
21
21
|
draggedItem = item;
|
|
22
22
|
e.dataTransfer.effectAllowed = 'move';
|
|
23
23
|
e.dataTransfer.setData('text/plain', '');
|
|
@@ -76,7 +76,7 @@ document.addEventListener('wheel', e => {
|
|
|
76
76
|
|
|
77
77
|
// move event by one day left or right
|
|
78
78
|
document.addEventListener('keydown', e => {
|
|
79
|
-
const item = e.target.closest('u2-
|
|
79
|
+
const item = e.target.closest('u2-calendar-item');
|
|
80
80
|
if (!item) return;
|
|
81
81
|
if (!item.draggable) return;
|
|
82
82
|
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"cssProperties": [],
|
|
48
48
|
"cssParts": [],
|
|
49
49
|
"superclass": { "name": "HTMLElement" },
|
|
50
|
-
"tagName": "u2-
|
|
50
|
+
"tagName": "u2-calendar-item",
|
|
51
51
|
"customElement": true
|
|
52
52
|
}],
|
|
53
53
|
"exports": [{
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
}
|
|
60
60
|
},{
|
|
61
61
|
"kind": "custom-element-definition",
|
|
62
|
-
"name": "u2-
|
|
62
|
+
"name": "u2-calendar-item",
|
|
63
63
|
"declaration": {
|
|
64
64
|
"name": "U2CalendarItem",
|
|
65
65
|
"module": "calendar.js"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# <u2-
|
|
1
|
+
# <u2-carouselnav> - element
|
|
2
2
|
Carousel navigation element for u2-carousel. (beta)
|
|
3
3
|
|
|
4
4
|
## Usage
|
|
5
5
|
|
|
6
6
|
```html
|
|
7
|
-
<u2-
|
|
7
|
+
<u2-carouselnav></u2-carouselnav>
|
|
8
8
|
<u2-carousel>
|
|
9
9
|
<div>Item 1</div>
|
|
10
10
|
<div>Item 2</div>
|
|
@@ -13,10 +13,10 @@ Carousel navigation element for u2-carousel. (beta)
|
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
```css
|
|
16
|
-
u2-
|
|
16
|
+
u2-carouselnav > * {
|
|
17
17
|
transition:.3s;
|
|
18
18
|
}
|
|
19
|
-
u2-
|
|
19
|
+
u2-carouselnav > .-active {
|
|
20
20
|
transform:scale(1.2);
|
|
21
21
|
}
|
|
22
22
|
```
|
|
@@ -24,13 +24,13 @@ u2-carousel-nav > .-active {
|
|
|
24
24
|
## Install
|
|
25
25
|
|
|
26
26
|
```html
|
|
27
|
-
<script src="https://cdn.jsdelivr.net/gh/u2ui/u2@main/el/
|
|
27
|
+
<script src="https://cdn.jsdelivr.net/gh/u2ui/u2@main/el/carouselnav/carouselnav.js" type=module async></script>
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
## Demos
|
|
31
31
|
|
|
32
|
-
[test.html](http://gcdn.li/u2ui/u2@main/el/
|
|
33
|
-
[minimal.html](http://gcdn.li/u2ui/u2@main/el/
|
|
32
|
+
[test.html](http://gcdn.li/u2ui/u2@main/el/carouselnav/tests/test.html)
|
|
33
|
+
[minimal.html](http://gcdn.li/u2ui/u2@main/el/carouselnav/tests/minimal.html)
|
|
34
34
|
|
|
35
35
|
## About
|
|
36
36
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
|
|
2
2
|
const style = document.createElement('style');
|
|
3
3
|
style.innerHTML = `
|
|
4
|
-
u2-
|
|
4
|
+
u2-carouselnav {
|
|
5
5
|
display:flex;
|
|
6
6
|
justify-content:center;
|
|
7
7
|
margin:.5rem;
|
|
8
8
|
gap:.5rem;
|
|
9
9
|
}
|
|
10
|
-
u2-
|
|
10
|
+
u2-carouselnav > * {
|
|
11
11
|
width:1.2rem;
|
|
12
12
|
height:1.2rem;
|
|
13
13
|
border-radius:99rem;
|
|
@@ -22,10 +22,10 @@ u2-carousel-nav > * {
|
|
|
22
22
|
align-items:center;
|
|
23
23
|
opacity:.3;
|
|
24
24
|
}
|
|
25
|
-
u2-
|
|
25
|
+
u2-carouselnav > :hover {
|
|
26
26
|
opacity:.6;
|
|
27
27
|
}
|
|
28
|
-
u2-
|
|
28
|
+
u2-carouselnav > .-active {
|
|
29
29
|
opacity:1;
|
|
30
30
|
}
|
|
31
31
|
`
|
|
@@ -71,4 +71,4 @@ export default class U2CarouselNav extends HTMLElement {
|
|
|
71
71
|
})
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
customElements.get('u2-
|
|
74
|
+
customElements.get('u2-carouselnav') || customElements.define('u2-carouselnav', U2CarouselNav)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"readme": "README.md",
|
|
4
4
|
"modules": [{
|
|
5
5
|
"kind": "javascript-module",
|
|
6
|
-
"path": "
|
|
6
|
+
"path": "carouselnav.js",
|
|
7
7
|
"declarations": [{
|
|
8
8
|
"kind": "class",
|
|
9
9
|
"description": "Carousel navigation element for u2-carousel. (beta)",
|
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
}],
|
|
17
17
|
"cssProperties": [],
|
|
18
18
|
"superclass": { "name": "HTMLElement" },
|
|
19
|
-
"tagName": "u2-
|
|
19
|
+
"tagName": "u2-carouselnav",
|
|
20
20
|
"customElement": true
|
|
21
21
|
}],
|
|
22
22
|
"exports": [{
|
|
23
23
|
"kind": "custom-element-definition",
|
|
24
|
-
"name": "u2-
|
|
24
|
+
"name": "u2-carouselnav",
|
|
25
25
|
"declaration": {
|
|
26
26
|
"name": "U2CarouselNav",
|
|
27
|
-
"module": "
|
|
27
|
+
"module": "carouselnav.js"
|
|
28
28
|
}
|
|
29
29
|
}]
|
|
30
30
|
}]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# <u2-
|
|
1
|
+
# <u2-parallaxbg> - element
|
|
2
2
|
Scroll-driven parallax background-layer with dynamic container sizing for full content visibility
|
|
3
3
|
|
|
4
4
|
## Features
|
|
@@ -13,18 +13,18 @@ Scroll-driven parallax background-layer with dynamic container sizing for full c
|
|
|
13
13
|
## Usage
|
|
14
14
|
|
|
15
15
|
```html
|
|
16
|
-
<div class=u2-
|
|
17
|
-
<u2-
|
|
18
|
-
<img src="https://raw.githubusercontent.com/u2ui/u2/main/el/
|
|
19
|
-
</u2-
|
|
16
|
+
<div class=u2-parallaxbg-stage style="height:100%">
|
|
17
|
+
<u2-parallaxbg>
|
|
18
|
+
<img src="https://raw.githubusercontent.com/u2ui/u2/main/el/parallaxbg/tests/bg.jpg" alt="parallaxbg demo">
|
|
19
|
+
</u2-parallaxbg>
|
|
20
20
|
</div>
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
```css
|
|
24
|
-
u2-
|
|
25
|
-
--
|
|
24
|
+
u2-parallaxbg {
|
|
25
|
+
--parallaxbg-speed:.7
|
|
26
26
|
}
|
|
27
|
-
u2-
|
|
27
|
+
u2-parallaxbg div {
|
|
28
28
|
display:grid;
|
|
29
29
|
place-items: center;
|
|
30
30
|
}
|
|
@@ -33,16 +33,16 @@ u2-parallax-bg div {
|
|
|
33
33
|
## Install
|
|
34
34
|
|
|
35
35
|
```html
|
|
36
|
-
<link href="https://cdn.jsdelivr.net/gh/u2ui/u2@main/el/
|
|
37
|
-
<script src="https://cdn.jsdelivr.net/gh/u2ui/u2@main/el/
|
|
36
|
+
<link href="https://cdn.jsdelivr.net/gh/u2ui/u2@main/el/parallaxbg/parallaxbg.css" rel=stylesheet>
|
|
37
|
+
<script src="https://cdn.jsdelivr.net/gh/u2ui/u2@main/el/parallaxbg/parallaxbg.js" type=module async></script>
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
## Demos
|
|
41
41
|
|
|
42
|
-
[test.html](http://gcdn.li/u2ui/u2@main/el/
|
|
43
|
-
[visible.html](http://gcdn.li/u2ui/u2@main/el/
|
|
44
|
-
[minimal.html](http://gcdn.li/u2ui/u2@main/el/
|
|
45
|
-
[demo.html](http://gcdn.li/u2ui/u2@main/el/
|
|
42
|
+
[test.html](http://gcdn.li/u2ui/u2@main/el/parallaxbg/tests/test.html)
|
|
43
|
+
[visible.html](http://gcdn.li/u2ui/u2@main/el/parallaxbg/tests/visible.html)
|
|
44
|
+
[minimal.html](http://gcdn.li/u2ui/u2@main/el/parallaxbg/tests/minimal.html)
|
|
45
|
+
[demo.html](http://gcdn.li/u2ui/u2@main/el/parallaxbg/tests/demo.html)
|
|
46
46
|
|
|
47
47
|
## Also interesting
|
|
48
48
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"readme": "README.md",
|
|
4
4
|
"modules": [{
|
|
5
5
|
"kind": "javascript-module",
|
|
6
|
-
"path": "
|
|
6
|
+
"path": "parallaxbg.js",
|
|
7
7
|
"declarations": [{
|
|
8
8
|
"kind": "class",
|
|
9
9
|
"description": "Scroll-driven parallax background layer with dynamic container sizing",
|
|
@@ -12,20 +12,20 @@
|
|
|
12
12
|
"events": [],
|
|
13
13
|
"attributes": [],
|
|
14
14
|
"cssProperties": [{
|
|
15
|
-
"name": "--
|
|
15
|
+
"name": "--parallaxbg-speed",
|
|
16
16
|
"description": "Parallax speed factor (1 = normal scroll speed)",
|
|
17
17
|
"syntax": "<number>"
|
|
18
18
|
}],
|
|
19
19
|
"superclass": { "name": "HTMLElement" },
|
|
20
|
-
"tagName": "u2-
|
|
20
|
+
"tagName": "u2-parallaxbg",
|
|
21
21
|
"customElement": true
|
|
22
22
|
}],
|
|
23
23
|
"exports": [{
|
|
24
24
|
"kind": "custom-element-definition",
|
|
25
|
-
"name": "u2-
|
|
25
|
+
"name": "u2-parallaxbg",
|
|
26
26
|
"declaration": {
|
|
27
27
|
"name": "U2ParallaxBg",
|
|
28
|
-
"module": "
|
|
28
|
+
"module": "parallaxbg.js"
|
|
29
29
|
}
|
|
30
30
|
}]
|
|
31
31
|
}]
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
.u2-
|
|
1
|
+
.u2-parallaxbg-stage {
|
|
2
2
|
position:relative;
|
|
3
3
|
display: flow-root; /* prevent margin collapse on inner element */
|
|
4
4
|
z-index:0; /* needed? else the parallax-element will go behinde everithing with a stackingcontext? */
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
u2-
|
|
7
|
+
u2-parallaxbg {
|
|
8
8
|
position:absolute;
|
|
9
9
|
inset: -.4px; /* ugly strange 1px space see demo */
|
|
10
10
|
z-index:-1;
|
|
@@ -107,7 +107,7 @@ export default class U2ParallaxBg extends HTMLElement {
|
|
|
107
107
|
this.visible = this.shadowRoot.querySelector('.visible');
|
|
108
108
|
|
|
109
109
|
const style = getComputedStyle(this);
|
|
110
|
-
const speed = style.getPropertyValue('--
|
|
110
|
+
const speed = style.getPropertyValue('--parallaxbg-speed');
|
|
111
111
|
this.speed = speed === '' ? .5 : parseFloat(speed);
|
|
112
112
|
}
|
|
113
113
|
connectedCallback() {
|
|
@@ -149,13 +149,13 @@ export default class U2ParallaxBg extends HTMLElement {
|
|
|
149
149
|
this.mover.style.bottom = -offset + 'px';
|
|
150
150
|
|
|
151
151
|
// if the element cannot go further down or up
|
|
152
|
-
// the [
|
|
152
|
+
// the [parallaxbg-visible] element
|
|
153
153
|
// the most complicated part of the lib, seems to work well, but it was born by trial and error
|
|
154
154
|
if (this.speed < 0) {
|
|
155
|
-
console.warn('
|
|
155
|
+
console.warn('parallaxbg: parallaxbg-visible attribute is not implemented for speed < 0');
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
|
-
//const visibleEl = this.querySelector('[
|
|
158
|
+
//const visibleEl = this.querySelector('[parallaxbg-visible]');
|
|
159
159
|
const visibleEl = this.visible;
|
|
160
160
|
if (visibleEl) {
|
|
161
161
|
let top = 0;
|
|
@@ -194,4 +194,4 @@ export default class U2ParallaxBg extends HTMLElement {
|
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
customElements.get('u2-
|
|
197
|
+
customElements.get('u2-parallaxbg') || customElements.define('u2-parallaxbg', U2ParallaxBg)
|
package/el/system/demoHtml.html
CHANGED
|
@@ -449,7 +449,7 @@ Line 3</pre>
|
|
|
449
449
|
<img src="https://picsum.photos/id/20/400/200" alt="Slide 2">
|
|
450
450
|
<img src="https://picsum.photos/id/30/400/200" alt="Slide 3">
|
|
451
451
|
</u2-carousel>
|
|
452
|
-
<u2-
|
|
452
|
+
<u2-carouselnav for="myCarousel"></u2-carouselnav>
|
|
453
453
|
|
|
454
454
|
<hr>
|
|
455
455
|
|
|
@@ -468,8 +468,8 @@ Line 3</pre>
|
|
|
468
468
|
<hr>
|
|
469
469
|
|
|
470
470
|
<u2-calendar>
|
|
471
|
-
<u2-
|
|
472
|
-
<u2-
|
|
471
|
+
<u2-calendar-item date="2025-12-24">Christmas Eve</u2-calendar-item>
|
|
472
|
+
<u2-calendar-item date="2025-12-31">New Year's Eve</u2-calendar-item>
|
|
473
473
|
</u2-calendar>
|
|
474
474
|
|
|
475
475
|
<hr>
|
|
@@ -568,9 +568,9 @@ Line 3</pre>
|
|
|
568
568
|
<hr>
|
|
569
569
|
|
|
570
570
|
<div style="height: 300px; position: relative; overflow: hidden;">
|
|
571
|
-
<u2-
|
|
571
|
+
<u2-parallaxbg>
|
|
572
572
|
<img src="https://picsum.photos/id/50/800/600" alt="Parallax">
|
|
573
|
-
</u2-
|
|
573
|
+
</u2-parallaxbg>
|
|
574
574
|
<h2 style="position: relative; color: white;">Content on Top</h2>
|
|
575
575
|
</div>
|
|
576
576
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "u2ui",
|
|
3
|
-
"version": "1.5
|
|
3
|
+
"version": "1.7.5",
|
|
4
4
|
"description": "HTML Advanced: More Capabilities, Same Feel, Same Simplicity",
|
|
5
5
|
"keywords": ["web-components","pattern-library","component-library","ui-toolkit","design-system"],
|
|
6
6
|
"author": "Tobias Buschor",
|
package/u2/enhance.js
CHANGED
|
@@ -98,7 +98,8 @@ export function enhance(root, { registry = root.customElementRegistry ?? customE
|
|
|
98
98
|
// neither a DOMTokenList nor a NamedNodeMap iterator is allocated per element.
|
|
99
99
|
function visit(el) {
|
|
100
100
|
const tag = el.tagName;
|
|
101
|
-
|
|
101
|
+
// the project is the part up to the first hyphen: u2-calendar-item comes with el/calendar
|
|
102
|
+
if (tag.startsWith('U2-')) load('el', tag.slice(3).toLowerCase().replace(/-.*/, ''));
|
|
102
103
|
|
|
103
104
|
const cls = el.className; // string on html elements, SVGAnimatedString on svg
|
|
104
105
|
if (typeof cls === 'string' && cls.includes('u2-')) {
|
package/u2/projects.json
CHANGED
|
@@ -246,15 +246,7 @@
|
|
|
246
246
|
},
|
|
247
247
|
"calendar": {
|
|
248
248
|
"name": "calendar",
|
|
249
|
-
"description": "Calendar / month view component, use `<u2-
|
|
250
|
-
"beta": false,
|
|
251
|
-
"deprecated": false,
|
|
252
|
-
"css": true,
|
|
253
|
-
"js": true
|
|
254
|
-
},
|
|
255
|
-
"parallax-bg": {
|
|
256
|
-
"name": "parallax-bg",
|
|
257
|
-
"description": "Scroll-driven parallax background-layer with dynamic container sizing for full content visibility",
|
|
249
|
+
"description": "Calendar / month view component, use `<u2-calendar-item>` as children",
|
|
258
250
|
"beta": false,
|
|
259
251
|
"deprecated": false,
|
|
260
252
|
"css": true,
|
|
@@ -284,6 +276,14 @@
|
|
|
284
276
|
"css": true,
|
|
285
277
|
"js": true
|
|
286
278
|
},
|
|
279
|
+
"carouselnav": {
|
|
280
|
+
"name": "carouselnav",
|
|
281
|
+
"description": "Carousel navigation element for u2-carousel. (beta)",
|
|
282
|
+
"beta": true,
|
|
283
|
+
"deprecated": false,
|
|
284
|
+
"css": false,
|
|
285
|
+
"js": true
|
|
286
|
+
},
|
|
287
287
|
"fields": {
|
|
288
288
|
"name": "fields",
|
|
289
289
|
"description": "Every content before a form element is considered as label",
|
|
@@ -332,6 +332,14 @@
|
|
|
332
332
|
"css": true,
|
|
333
333
|
"js": true
|
|
334
334
|
},
|
|
335
|
+
"parallaxbg": {
|
|
336
|
+
"name": "parallaxbg",
|
|
337
|
+
"description": "Scroll-driven parallax background-layer with dynamic container sizing for full content visibility",
|
|
338
|
+
"beta": false,
|
|
339
|
+
"deprecated": false,
|
|
340
|
+
"css": true,
|
|
341
|
+
"js": true
|
|
342
|
+
},
|
|
335
343
|
"carousel": {
|
|
336
344
|
"name": "carousel",
|
|
337
345
|
"description": "Simple carousel component",
|
|
@@ -492,14 +500,6 @@
|
|
|
492
500
|
"css": true,
|
|
493
501
|
"js": true
|
|
494
502
|
},
|
|
495
|
-
"carousel-nav": {
|
|
496
|
-
"name": "carousel-nav",
|
|
497
|
-
"description": "Carousel navigation element for u2-carousel. (beta)",
|
|
498
|
-
"beta": true,
|
|
499
|
-
"deprecated": false,
|
|
500
|
-
"css": false,
|
|
501
|
-
"js": true
|
|
502
|
-
},
|
|
503
503
|
"accordion": {
|
|
504
504
|
"name": "accordion",
|
|
505
505
|
"description": "Turns HTML structures with headings into an accordion, using the content between headings as each panel’s content.",
|