-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
119 lines (109 loc) · 3.24 KB
/
index.js
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
const doTransition = (elem, trigger, after) => {
let n = 0
let starthandler = () => n++
let endhandler = () => {
if (--n) return
elem.removeEventListener("transitionrun", starthandler)
elem.removeEventListener("transitionend", endhandler)
elem.removeEventListener("transitioncancel", endhandler)
after()
}
elem.addEventListener("transitionrun", starthandler)
elem.addEventListener("transitionend", endhandler)
elem.addEventListener("transitioncancel", endhandler)
requestAnimationFrame(trigger)
}
const offset = elem => {
let rect = elem.getBoundingClientRect()
let dx = elem._tx_rect.x - rect.x
let dy = elem._tx_rect.y - rect.y
elem._tx_rect = rect
if ((dx | dy) === 0) return false
elem.style.translate = `${dx}px ${dy}px`
return true
}
const _HTMLElement = typeof HTMLElement === "undefined" ? Object : HTMLElement
class TransitionGroup extends _HTMLElement {
constructor() {
super()
this._previous = []
this.attachShadow({ mode: "open" })
this.shadowRoot.append(
...[...document.querySelectorAll("style")].map(n => n.cloneNode(true)),
)
this.shadowRoot.append(
...[...document.querySelectorAll("link[rel=stylesheet]")].map(n =>
n.cloneNode(),
),
)
let slot = document.createElement("slot")
slot.addEventListener("slotchange", () => {
this._handleSlotChange()
})
this.shadowRoot.append(slot)
window.addEventListener("resize", () => {
this._handleLayoutChange()
})
window.addEventListener("scroll", () => {
this._handleLayoutChange()
})
}
_handleLayoutChange() {
this._previous.forEach(elem => {
elem._tx_rect = elem.getBoundingClientRect()
})
}
_handleSlotChange() {
let current = [...this.childNodes]
let added = current.filter(node => !this._previous.includes(node))
let removed = this._previous.filter(node => !current.includes(node))
let updated = current.filter(node => !added.includes(node))
added.forEach(elem => this._onadd(elem))
updated.forEach(elem => this._onupdate(elem))
removed.forEach(elem => this._onremove(elem))
this._previous = current
}
_onadd(elem) {
elem._tx_rect = elem.getBoundingClientRect()
let clsentry = this.getAttribute("entry")
if (!clsentry) return
let clsentryPre = clsentry + "-pre"
elem.classList.add(clsentryPre)
doTransition(
elem,
() => elem.classList.replace(clsentryPre, clsentry),
() => elem.classList.remove(clsentry),
)
}
_onupdate(elem) {
let clsslide = this.getAttribute("slide")
if (!clsslide) {
elem._tx_rect = elem.getBoundingClientRect()
return
}
if (!offset(elem)) return
doTransition(
elem,
() => {
elem.classList.add(clsslide)
elem.style.translate = null
},
() => elem.classList.remove(clsslide),
)
}
_onremove(elem) {
let clsremove = this.getAttribute("exit")
if (!clsremove) return
this.shadowRoot.append(elem)
offset(elem)
doTransition(
elem,
() => elem.classList.add(clsremove),
() => elem.parentNode && this.shadowRoot.removeChild(elem),
)
}
}
if (typeof customElements !== "undefined") {
customElements.define("transition-group", TransitionGroup)
}
export {}