@zag-js/collapsible
Advanced tools
Comparing version 0.0.0-dev-20240424101351 to 0.0.0-dev-20240424190747
@@ -57,3 +57,3 @@ "use strict"; | ||
const disabled = !!state.context.disabled; | ||
const skipMountAnimation = state.context.isMountAnimationPrevented && open; | ||
const skip = !state.context.initial && open; | ||
return { | ||
@@ -76,3 +76,3 @@ disabled, | ||
...parts.content.attrs, | ||
"data-state": skipMountAnimation ? void 0 : open ? "open" : "closed", | ||
"data-state": skip ? void 0 : open ? "open" : "closed", | ||
id: dom.getContentId(state.context), | ||
@@ -95,3 +95,5 @@ "data-disabled": (0, import_dom_query2.dataAttr)(disabled), | ||
"aria-expanded": visible || false, | ||
onClick() { | ||
onClick(event) { | ||
if (event.defaultPrevented) | ||
return; | ||
if (disabled) | ||
@@ -119,18 +121,15 @@ return; | ||
width: 0, | ||
isMountAnimationPrevented: !!ctx.open, | ||
stylesRef: null | ||
initial: false, | ||
stylesRef: null, | ||
unmountAnimationName: null | ||
}, | ||
watch: { | ||
open: ["allowAnimation", "toggleVisibility"] | ||
open: ["setInitial", "computeSize", "toggleVisibility"] | ||
}, | ||
entry: ["computeSize"], | ||
exit: ["clearInitial"], | ||
states: { | ||
closed: { | ||
tags: ["closed"], | ||
entry: ["computeSize"], | ||
on: { | ||
"CONTROLLED.OPEN": { | ||
target: "open", | ||
actions: ["computeSize"] | ||
}, | ||
"CONTROLLED.OPEN": "open", | ||
OPEN: [ | ||
@@ -143,3 +142,3 @@ { | ||
target: "open", | ||
actions: ["allowAnimation", "invokeOnOpen", "computeSize"] | ||
actions: ["setInitial", "computeSize", "invokeOnOpen"] | ||
} | ||
@@ -153,6 +152,3 @@ ] | ||
on: { | ||
"CONTROLLED.CLOSE": { | ||
target: "closed", | ||
actions: ["invokeOnExitComplete"] | ||
}, | ||
"CONTROLLED.CLOSE": "closed", | ||
"CONTROLLED.OPEN": "open", | ||
@@ -166,3 +162,3 @@ OPEN: [ | ||
target: "open", | ||
actions: ["allowAnimation", "invokeOnOpen"] | ||
actions: ["setInitial", "invokeOnOpen"] | ||
} | ||
@@ -173,7 +169,7 @@ ], | ||
guard: "isOpenControlled", | ||
actions: ["invokeOnClose"] | ||
actions: ["invokeOnExitComplete"] | ||
}, | ||
{ | ||
target: "closed", | ||
actions: ["allowAnimation", "computeSize", "invokeOnExitComplete"] | ||
actions: ["setInitial", "computeSize", "invokeOnExitComplete"] | ||
} | ||
@@ -190,6 +186,3 @@ ], | ||
on: { | ||
"CONTROLLED.CLOSE": { | ||
target: "closing", | ||
actions: ["computeSize"] | ||
}, | ||
"CONTROLLED.CLOSE": "closing", | ||
CLOSE: [ | ||
@@ -202,3 +195,3 @@ { | ||
target: "closing", | ||
actions: ["allowAnimation", "computeSize"] | ||
actions: ["setInitial", "computeSize", "invokeOnClose"] | ||
} | ||
@@ -228,11 +221,11 @@ ] | ||
const onEnd = (event) => { | ||
if (event.target !== contentEl) | ||
return; | ||
send({ type: "ANIMATION.END" }); | ||
const win = contentEl.ownerDocument.defaultView || window; | ||
const animationName2 = win.getComputedStyle(contentEl).animationName; | ||
if (event.target === contentEl && animationName2 === ctx2.unmountAnimationName) { | ||
send({ type: "ANIMATION.END" }); | ||
} | ||
}; | ||
contentEl.addEventListener("animationend", onEnd); | ||
contentEl.addEventListener("animationcancel", onEnd); | ||
cleanup = () => { | ||
contentEl.removeEventListener("animationend", onEnd); | ||
contentEl.removeEventListener("animationcancel", onEnd); | ||
}; | ||
@@ -247,7 +240,11 @@ }); | ||
actions: { | ||
allowAnimation(ctx2) { | ||
ctx2.isMountAnimationPrevented = false; | ||
setInitial(ctx2) { | ||
ctx2.initial = true; | ||
}, | ||
computeSize: (ctx2) => { | ||
(0, import_dom_query3.raf)(() => { | ||
clearInitial(ctx2) { | ||
ctx2.initial = false; | ||
}, | ||
computeSize(ctx2, evt) { | ||
ctx2._rafCleanup?.(); | ||
ctx2._rafCleanup = (0, import_dom_query3.raf)(() => { | ||
const contentEl = dom.getContentEl(ctx2); | ||
@@ -260,2 +257,6 @@ if (!contentEl) | ||
})); | ||
if (evt.type === "CLOSE" || !ctx2.open) { | ||
const win = contentEl.ownerDocument.defaultView || window; | ||
ctx2.unmountAnimationName = win.getComputedStyle(contentEl).animationName; | ||
} | ||
const hidden = contentEl.hidden; | ||
@@ -268,3 +269,3 @@ contentEl.style.animationName = "none"; | ||
ctx2.width = rect.width; | ||
if (!ctx2.isMountAnimationPrevented) { | ||
if (ctx2.initial) { | ||
contentEl.style.animationName = ctx2.stylesRef.animationName; | ||
@@ -271,0 +272,0 @@ contentEl.style.animationDuration = ctx2.stylesRef.animationDuration; |
{ | ||
"name": "@zag-js/collapsible", | ||
"version": "0.0.0-dev-20240424101351", | ||
"version": "0.0.0-dev-20240424190747", | ||
"description": "Core logic for the collapsible widget implemented as a state machine", | ||
@@ -31,7 +31,7 @@ "keywords": [ | ||
"dependencies": { | ||
"@zag-js/anatomy": "0.0.0-dev-20240424101351", | ||
"@zag-js/core": "0.0.0-dev-20240424101351", | ||
"@zag-js/dom-query": "0.0.0-dev-20240424101351", | ||
"@zag-js/utils": "0.0.0-dev-20240424101351", | ||
"@zag-js/types": "0.0.0-dev-20240424101351" | ||
"@zag-js/anatomy": "0.0.0-dev-20240424190747", | ||
"@zag-js/core": "0.0.0-dev-20240424190747", | ||
"@zag-js/dom-query": "0.0.0-dev-20240424190747", | ||
"@zag-js/utils": "0.0.0-dev-20240424190747", | ||
"@zag-js/types": "0.0.0-dev-20240424190747" | ||
}, | ||
@@ -38,0 +38,0 @@ "devDependencies": { |
@@ -15,3 +15,3 @@ import { dataAttr } from "@zag-js/dom-query" | ||
const skipMountAnimation = state.context.isMountAnimationPrevented && open | ||
const skip = !state.context.initial && open | ||
@@ -36,3 +36,3 @@ return { | ||
...parts.content.attrs, | ||
"data-state": skipMountAnimation ? undefined : open ? "open" : "closed", | ||
"data-state": skip ? undefined : open ? "open" : "closed", | ||
id: dom.getContentId(state.context), | ||
@@ -56,3 +56,4 @@ "data-disabled": dataAttr(disabled), | ||
"aria-expanded": visible || false, | ||
onClick() { | ||
onClick(event) { | ||
if (event.defaultPrevented) return | ||
if (disabled) return | ||
@@ -59,0 +60,0 @@ send({ type: open ? "CLOSE" : "OPEN", src: "trigger.click" }) |
@@ -18,11 +18,12 @@ import { createMachine, ref } from "@zag-js/core" | ||
width: 0, | ||
isMountAnimationPrevented: !!ctx.open, | ||
initial: false, | ||
stylesRef: null, | ||
unmountAnimationName: null, | ||
}, | ||
watch: { | ||
open: ["allowAnimation", "toggleVisibility"], | ||
open: ["setInitial", "computeSize", "toggleVisibility"], | ||
}, | ||
entry: ["computeSize"], | ||
exit: ["clearInitial"], | ||
@@ -32,8 +33,4 @@ states: { | ||
tags: ["closed"], | ||
entry: ["computeSize"], | ||
on: { | ||
"CONTROLLED.OPEN": { | ||
target: "open", | ||
actions: ["computeSize"], | ||
}, | ||
"CONTROLLED.OPEN": "open", | ||
OPEN: [ | ||
@@ -46,3 +43,3 @@ { | ||
target: "open", | ||
actions: ["allowAnimation", "invokeOnOpen", "computeSize"], | ||
actions: ["setInitial", "computeSize", "invokeOnOpen"], | ||
}, | ||
@@ -57,6 +54,3 @@ ], | ||
on: { | ||
"CONTROLLED.CLOSE": { | ||
target: "closed", | ||
actions: ["invokeOnExitComplete"], | ||
}, | ||
"CONTROLLED.CLOSE": "closed", | ||
"CONTROLLED.OPEN": "open", | ||
@@ -70,3 +64,3 @@ OPEN: [ | ||
target: "open", | ||
actions: ["allowAnimation", "invokeOnOpen"], | ||
actions: ["setInitial", "invokeOnOpen"], | ||
}, | ||
@@ -77,7 +71,7 @@ ], | ||
guard: "isOpenControlled", | ||
actions: ["invokeOnClose"], | ||
actions: ["invokeOnExitComplete"], | ||
}, | ||
{ | ||
target: "closed", | ||
actions: ["allowAnimation", "computeSize", "invokeOnExitComplete"], | ||
actions: ["setInitial", "computeSize", "invokeOnExitComplete"], | ||
}, | ||
@@ -91,9 +85,7 @@ ], | ||
}, | ||
open: { | ||
tags: ["open"], | ||
on: { | ||
"CONTROLLED.CLOSE": { | ||
target: "closing", | ||
actions: ["computeSize"], | ||
}, | ||
"CONTROLLED.CLOSE": "closing", | ||
CLOSE: [ | ||
@@ -106,3 +98,3 @@ { | ||
target: "closing", | ||
actions: ["allowAnimation", "computeSize"], | ||
actions: ["setInitial", "computeSize", "invokeOnClose"], | ||
}, | ||
@@ -129,2 +121,3 @@ ], | ||
const hasNoAnimation = !animationName || animationName === "none" | ||
if (hasNoAnimation) { | ||
@@ -136,12 +129,12 @@ send({ type: "ANIMATION.END" }) | ||
const onEnd = (event: AnimationEvent) => { | ||
if (event.target !== contentEl) return | ||
send({ type: "ANIMATION.END" }) | ||
const win = contentEl.ownerDocument.defaultView || window | ||
const animationName = win.getComputedStyle(contentEl).animationName | ||
if (event.target === contentEl && animationName === ctx.unmountAnimationName) { | ||
send({ type: "ANIMATION.END" }) | ||
} | ||
} | ||
contentEl.addEventListener("animationend", onEnd) | ||
contentEl.addEventListener("animationcancel", onEnd) | ||
cleanup = () => { | ||
contentEl.removeEventListener("animationend", onEnd) | ||
contentEl.removeEventListener("animationcancel", onEnd) | ||
} | ||
@@ -157,7 +150,12 @@ }) | ||
actions: { | ||
allowAnimation(ctx) { | ||
ctx.isMountAnimationPrevented = false | ||
setInitial(ctx) { | ||
ctx.initial = true | ||
}, | ||
computeSize: (ctx) => { | ||
raf(() => { | ||
clearInitial(ctx) { | ||
ctx.initial = false | ||
}, | ||
computeSize(ctx, evt) { | ||
ctx._rafCleanup?.() | ||
ctx._rafCleanup = raf(() => { | ||
const contentEl = dom.getContentEl(ctx) | ||
@@ -171,2 +169,7 @@ if (!contentEl) return | ||
if (evt.type === "CLOSE" || !ctx.open) { | ||
const win = contentEl.ownerDocument.defaultView || window | ||
ctx.unmountAnimationName = win.getComputedStyle(contentEl).animationName | ||
} | ||
const hidden = contentEl.hidden | ||
@@ -184,3 +187,3 @@ | ||
// kick off any animations/transitions that were originally set up if it isn't the initial mount | ||
if (!ctx.isMountAnimationPrevented) { | ||
if (ctx.initial) { | ||
contentEl.style.animationName = ctx.stylesRef.animationName | ||
@@ -187,0 +190,0 @@ contentEl.style.animationDuration = ctx.stylesRef.animationDuration |
@@ -69,5 +69,15 @@ import type { StateMachine as S } from "@zag-js/core" | ||
* @internal | ||
* Whether the mount animation is prevented | ||
* Whether the initial animation is allowed | ||
*/ | ||
isMountAnimationPrevented: boolean | ||
initial: boolean | ||
/** | ||
* @internal | ||
* The requestAnimationFrame id | ||
*/ | ||
_rafCleanup?: VoidFunction | ||
/** | ||
* @internal | ||
* The unmount animation name | ||
*/ | ||
unmountAnimationName: string | null | ||
} | ||
@@ -74,0 +84,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
69583
1012
+ Added@zag-js/anatomy@0.0.0-dev-20240424190747(transitive)
+ Added@zag-js/core@0.0.0-dev-20240424190747(transitive)
+ Added@zag-js/dom-query@0.0.0-dev-20240424190747(transitive)
+ Added@zag-js/store@0.0.0-dev-20240424190747(transitive)
+ Added@zag-js/types@0.0.0-dev-20240424190747(transitive)
+ Added@zag-js/utils@0.0.0-dev-20240424190747(transitive)
- Removed@zag-js/anatomy@0.0.0-dev-20240424101351(transitive)
- Removed@zag-js/core@0.0.0-dev-20240424101351(transitive)
- Removed@zag-js/dom-query@0.0.0-dev-20240424101351(transitive)
- Removed@zag-js/store@0.0.0-dev-20240424101351(transitive)
- Removed@zag-js/types@0.0.0-dev-20240424101351(transitive)
- Removed@zag-js/utils@0.0.0-dev-20240424101351(transitive)