-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsmooth-height.component.ts
More file actions
68 lines (60 loc) · 1.87 KB
/
smooth-height.component.ts
File metadata and controls
68 lines (60 loc) · 1.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import {
afterNextRender,
booleanAttribute,
Component,
DestroyRef,
effect,
ElementRef,
inject,
input,
signal,
untracked,
} from '@angular/core'
/**
* Standalone Component to smoothly animate height changes.
* Animates the height property when the content of sc-smooth-height changes
* use the {@link trigger} input to provide the essential value changes to trigger a resize
*/
@Component({
selector: 'sc-smooth-height',
standalone: true,
template: `<ng-content />`,
styleUrls: ['./smooth-height.component.scss'],
})
export class SmoothHeightComponent {
readonly withInitialAnimation = input(false, { transform: booleanAttribute })
readonly animationOptions = input<Pick<EffectTiming, 'duration' | 'easing'>>({ duration: 300, easing: 'ease-in-out' })
// we do not use initial
private readonly height = signal<number | null>(null)
private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef)
constructor() {
const destroyRef = inject(DestroyRef)
afterNextRender(() => {
const obs = new MutationObserver(this.updateElementHeight.bind(this))
obs.observe(this.elementRef.nativeElement, { attributes: true, subtree: true, characterData: true })
this.updateElementHeight()
destroyRef.onDestroy(() => obs?.disconnect())
})
let prevHeight: number | null = null
effect(() => {
let height = this.height()
if (height === null) {
if (untracked(this.withInitialAnimation)) {
height = 0
} else {
return
}
}
if (prevHeight !== null) {
this.elementRef.nativeElement.animate(
[{ height: `${prevHeight}px` }, { height: `${height}px` }],
untracked(this.animationOptions),
)
}
prevHeight = height
})
}
private updateElementHeight() {
this.height.set(this.elementRef.nativeElement.clientHeight)
}
}