Ensure Transition component completes if nothing is transitioning (#2318)
* make `disposables` consistent Also added a `group` function, this allows us to spawn a _sub_ disposables group that can be disposed on its own, but will also be disposed the moment the "parent" is disposed. * ensure Transition component works when nothing is transitioning * update changelog
This commit is contained in:
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- Nothing yet!
|
||||
### Fixed
|
||||
|
||||
- Ensure `Transition` component completes if nothing is transitioning ([#2318](https://github.com/tailwindlabs/headlessui/pull/2318))
|
||||
|
||||
## [1.7.12] - 2023-02-24
|
||||
|
||||
|
||||
@@ -39,6 +39,23 @@ function waitForTransition(node: HTMLElement, done: () => void) {
|
||||
dispose()
|
||||
}, totalDuration)
|
||||
} else {
|
||||
d.group((d) => {
|
||||
// Mark the transition as done when the timeout is reached. This is a fallback in case the
|
||||
// transitionrun event is not fired.
|
||||
d.setTimeout(() => {
|
||||
done()
|
||||
d.dispose()
|
||||
}, totalDuration)
|
||||
|
||||
// The moment the transitionrun event fires, we should cleanup the timeout fallback, because
|
||||
// then we know that we can use the native transition events because something is
|
||||
// transitioning.
|
||||
d.addEventListener(node, 'transitionrun', (event) => {
|
||||
if (event.target !== event.currentTarget) return
|
||||
d.dispose()
|
||||
})
|
||||
})
|
||||
|
||||
let dispose = d.addEventListener(node, 'transitionend', (event) => {
|
||||
if (event.target !== event.currentTarget) return
|
||||
done()
|
||||
|
||||
@@ -3,7 +3,7 @@ import { microTask } from './micro-task'
|
||||
export type Disposables = ReturnType<typeof disposables>
|
||||
|
||||
export function disposables() {
|
||||
let disposables: Function[] = []
|
||||
let _disposables: Function[] = []
|
||||
|
||||
let api = {
|
||||
addEventListener<TEventName extends keyof WindowEventMap>(
|
||||
@@ -44,23 +44,6 @@ export function disposables() {
|
||||
})
|
||||
},
|
||||
|
||||
add(cb: () => void) {
|
||||
disposables.push(cb)
|
||||
return () => {
|
||||
let idx = disposables.indexOf(cb)
|
||||
if (idx >= 0) {
|
||||
let [dispose] = disposables.splice(idx, 1)
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dispose() {
|
||||
for (let dispose of disposables.splice(0)) {
|
||||
dispose()
|
||||
}
|
||||
},
|
||||
|
||||
style(node: HTMLElement, property: string, value: string) {
|
||||
let previous = node.style.getPropertyValue(property)
|
||||
Object.assign(node.style, { [property]: value })
|
||||
@@ -68,6 +51,30 @@ export function disposables() {
|
||||
Object.assign(node.style, { [property]: previous })
|
||||
})
|
||||
},
|
||||
|
||||
group(cb: (d: typeof this) => void) {
|
||||
let d = disposables()
|
||||
cb(d)
|
||||
return this.add(() => d.dispose())
|
||||
},
|
||||
|
||||
add(cb: () => void) {
|
||||
_disposables.push(cb)
|
||||
return () => {
|
||||
let idx = _disposables.indexOf(cb)
|
||||
if (idx >= 0) {
|
||||
for (let dispose of _disposables.splice(idx, 1)) {
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dispose() {
|
||||
for (let dispose of _disposables.splice(0)) {
|
||||
dispose()
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return api
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export type Disposables = ReturnType<typeof disposables>
|
||||
|
||||
export function disposables() {
|
||||
let disposables: Function[] = []
|
||||
let _disposables: Function[] = []
|
||||
|
||||
let api = {
|
||||
addEventListener<TEventName extends keyof WindowEventMap>(
|
||||
@@ -30,10 +30,6 @@ export function disposables() {
|
||||
api.add(() => clearTimeout(timer))
|
||||
},
|
||||
|
||||
add(cb: () => void) {
|
||||
disposables.push(cb)
|
||||
},
|
||||
|
||||
style(node: HTMLElement, property: string, value: string) {
|
||||
let previous = node.style.getPropertyValue(property)
|
||||
Object.assign(node.style, { [property]: value })
|
||||
@@ -42,8 +38,26 @@ export function disposables() {
|
||||
})
|
||||
},
|
||||
|
||||
group(cb: (d: typeof this) => void) {
|
||||
let d = disposables()
|
||||
cb(d)
|
||||
return this.add(() => d.dispose())
|
||||
},
|
||||
|
||||
add(cb: () => void) {
|
||||
_disposables.push(cb)
|
||||
return () => {
|
||||
let idx = _disposables.indexOf(cb)
|
||||
if (idx >= 0) {
|
||||
for (let dispose of _disposables.splice(idx, 1)) {
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dispose() {
|
||||
for (let dispose of disposables.splice(0)) {
|
||||
for (let dispose of _disposables.splice(0)) {
|
||||
dispose()
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user