@neovici/cosmoz-utils 6.26.0 → 6.27.0
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/dist/directives/overflow.d.ts +27 -0
- package/dist/directives/overflow.js +121 -0
- package/package.json +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type ElementPart } from 'lit-html';
|
|
2
|
+
import { AsyncDirective } from 'lit-html/async-directive.js';
|
|
3
|
+
/**
|
|
4
|
+
* The directive expects this css. Adopt it on your component, set the
|
|
5
|
+
* class `cz-overflow-band` on the band slot, and give it a `max-height`
|
|
6
|
+
* to match one row.
|
|
7
|
+
*/
|
|
8
|
+
export declare const overflowStyle: CSSStyleSheet;
|
|
9
|
+
/**
|
|
10
|
+
* The directive marks the elements that overflow with "[overflowing]"
|
|
11
|
+
* and reports the full list via `onOverflow`. The effect relies mainly
|
|
12
|
+
* on css flex wrapping, so make sure to use the accompanying stylesheet
|
|
13
|
+
* (or match in your own css).
|
|
14
|
+
*/
|
|
15
|
+
export interface OverflowConfig {
|
|
16
|
+
onOverflow: (overflowing: Set<HTMLElement>) => void;
|
|
17
|
+
}
|
|
18
|
+
declare class OverflowDirective extends AsyncDirective {
|
|
19
|
+
#private;
|
|
20
|
+
_slot?: HTMLSlotElement;
|
|
21
|
+
_onOverflow?: (overflowing: Set<HTMLElement>) => void;
|
|
22
|
+
render(config: OverflowConfig): symbol;
|
|
23
|
+
update(part: ElementPart, [config]: [OverflowConfig]): symbol;
|
|
24
|
+
disconnected(): void;
|
|
25
|
+
}
|
|
26
|
+
export declare const overflow: (config: OverflowConfig) => import("lit-html/directive.js").DirectiveResult<typeof OverflowDirective>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { css } from '@pionjs/pion';
|
|
2
|
+
import { noChange } from 'lit-html';
|
|
3
|
+
import { AsyncDirective, directive } from 'lit-html/async-directive.js';
|
|
4
|
+
import { sheet } from '../sheet.js';
|
|
5
|
+
/**
|
|
6
|
+
* The directive expects this css. Adopt it on your component, set the
|
|
7
|
+
* class `cz-overflow-band` on the band slot, and give it a `max-height`
|
|
8
|
+
* to match one row.
|
|
9
|
+
*/
|
|
10
|
+
export const overflowStyle = sheet(css `
|
|
11
|
+
slot.cz-overflow-band {
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-wrap: wrap;
|
|
14
|
+
align-items: flex-start;
|
|
15
|
+
overflow: clip;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
::slotted([overflowing]) {
|
|
19
|
+
visibility: hidden;
|
|
20
|
+
}
|
|
21
|
+
`);
|
|
22
|
+
const members = (slot) => slot.assignedElements({ flatten: true });
|
|
23
|
+
const stable = (a, b) => a != null &&
|
|
24
|
+
b != null &&
|
|
25
|
+
a.size === b.size &&
|
|
26
|
+
[...b].every((el) => a.has(el));
|
|
27
|
+
class OverflowDirective extends AsyncDirective {
|
|
28
|
+
_slot;
|
|
29
|
+
_onOverflow;
|
|
30
|
+
#clipped = new Map();
|
|
31
|
+
#last;
|
|
32
|
+
#observer;
|
|
33
|
+
#classify = (entries) => {
|
|
34
|
+
entries.forEach((entry) => {
|
|
35
|
+
const member = entry.target;
|
|
36
|
+
this.#clipped.set(member, entry.boundingClientRect.height > 0 &&
|
|
37
|
+
entry.intersectionRect.height === 0);
|
|
38
|
+
});
|
|
39
|
+
this.#flush();
|
|
40
|
+
};
|
|
41
|
+
#observe = (member) => {
|
|
42
|
+
this.#observer?.unobserve(member);
|
|
43
|
+
this.#observer?.observe(member);
|
|
44
|
+
};
|
|
45
|
+
#flush = () => {
|
|
46
|
+
if (!this._slot) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const current = members(this._slot);
|
|
50
|
+
current.forEach((member) => {
|
|
51
|
+
const on = this.#clipped.get(member) === true;
|
|
52
|
+
if (on === member.hasAttribute('overflowing')) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (on) {
|
|
56
|
+
member.setAttribute('overflowing', '');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
member.removeAttribute('overflowing');
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// a member that left the slot: forget it, stop watching it,
|
|
63
|
+
// remove the mark
|
|
64
|
+
this.#clipped.forEach((_, member) => {
|
|
65
|
+
if (current.includes(member)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.#clipped.delete(member);
|
|
69
|
+
this.#observer?.unobserve(member);
|
|
70
|
+
if (member.hasAttribute('overflowing')) {
|
|
71
|
+
member.removeAttribute('overflowing');
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const next = new Set(current.filter((member) => this.#clipped.get(member) === true));
|
|
75
|
+
if (stable(this.#last, next)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.#last = next;
|
|
79
|
+
this._onOverflow?.(next);
|
|
80
|
+
};
|
|
81
|
+
#onSlotChange = () => this.#arm();
|
|
82
|
+
#arm = () => {
|
|
83
|
+
if (!this.#observer || !this._slot) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
for (const member of members(this._slot)) {
|
|
87
|
+
this.#observe(member);
|
|
88
|
+
}
|
|
89
|
+
this.#flush();
|
|
90
|
+
};
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
92
|
+
render(config) {
|
|
93
|
+
return noChange;
|
|
94
|
+
}
|
|
95
|
+
update(part, [config]) {
|
|
96
|
+
this._onOverflow = config.onOverflow;
|
|
97
|
+
const slot = part.element;
|
|
98
|
+
if (this._slot !== slot) {
|
|
99
|
+
this._slot?.removeEventListener('slotchange', this.#onSlotChange);
|
|
100
|
+
this.#observer?.disconnect();
|
|
101
|
+
this.#observer = undefined;
|
|
102
|
+
this._slot = slot;
|
|
103
|
+
slot.addEventListener('slotchange', this.#onSlotChange);
|
|
104
|
+
}
|
|
105
|
+
this.#observer ??= new IntersectionObserver(this.#classify, {
|
|
106
|
+
root: this._slot,
|
|
107
|
+
threshold: [0, 1],
|
|
108
|
+
});
|
|
109
|
+
this.#arm();
|
|
110
|
+
return noChange;
|
|
111
|
+
}
|
|
112
|
+
disconnected() {
|
|
113
|
+
this._slot?.removeEventListener('slotchange', this.#onSlotChange);
|
|
114
|
+
this._slot = undefined;
|
|
115
|
+
this.#observer?.disconnect();
|
|
116
|
+
this.#observer = undefined;
|
|
117
|
+
this.#clipped.clear();
|
|
118
|
+
this.#last = undefined;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export const overflow = directive(OverflowDirective);
|