diff --git a/core/src/components/item-sliding/animations/item-sliding-options.ts b/core/src/components/item-sliding/animations/item-sliding-options.ts index df4c28f7c5..30d920fdb6 100644 --- a/core/src/components/item-sliding/animations/item-sliding-options.ts +++ b/core/src/components/item-sliding/animations/item-sliding-options.ts @@ -6,6 +6,7 @@ import { createAnimation } from '@utils/animation/animation'; * @param viewportOffset The offset of the element on the x-axis to locate it off-screen. * @param progress The progress of the animation (0 - 1). * @param isFinal Whether the animation is in its final state (collapsed or expanded). + * @param isReset Whether to reset the element to its initial state. * @param zIndex _Optional_ The z-index to apply to the element. */ export const slidingItemAnimation = ( @@ -13,11 +14,12 @@ export const slidingItemAnimation = ( viewportOffset: number, progress: number, isFinal: boolean, + isReset: boolean, zIndex: number | undefined ) => { const styles = zIndex !== undefined ? { zIndex: `${zIndex}` } : {}; - const animation = createAnimation() + const swipeAnimation = createAnimation() .addElement(el) /** * The specific value here does not actually @@ -32,12 +34,28 @@ export const slidingItemAnimation = ( { offset: 1, transform: `translate3d(0,0,0)`, ...styles }, ]); - if (!isFinal) { - animation.progressStart(true, progress); - } else { - animation.destroy(); + if (isReset) { + swipeAnimation.destroy(); - const toggleAnimation = createAnimation() + const leaveAnimation = createAnimation() + .addElement(el) + .duration(300) + .easing('ease-out') + .beforeStyles({ + zIndex: zIndex, + }) + .fromTo('transform', el.style.transform, `translate3d(${viewportOffset}px,0,0)`) + .afterClearStyles(['z-index']); + + leaveAnimation.play().then(() => leaveAnimation.destroy()); + } + + if (!isFinal) { + swipeAnimation.progressStart(true, progress); + } else { + swipeAnimation.destroy(); + + const expandAnimation = createAnimation() .addElement(el) .duration(300) .easing('ease-out') @@ -48,6 +66,6 @@ export const slidingItemAnimation = ( .fromTo('transform', el.style.transform, `translate3d(0,0,0)`) .afterClearStyles(['z-index']); - toggleAnimation.play(); + expandAnimation.play(); } }; diff --git a/core/src/components/item-sliding/item-sliding.tsx b/core/src/components/item-sliding/item-sliding.tsx index 8bc4e2317c..7b664a9c29 100644 --- a/core/src/components/item-sliding/item-sliding.tsx +++ b/core/src/components/item-sliding/item-sliding.tsx @@ -454,7 +454,7 @@ export class ItemSliding implements ComponentInterface { return; } - const { el, optsWidthRightSide, optsWidthLeftSide } = this; + const { el, optsWidthRightSide, optsWidthLeftSide, animationType } = this; const rtl = isRTL(el); @@ -501,44 +501,16 @@ export class ItemSliding implements ComponentInterface { openSlidingItem = undefined; style.transform = ''; + + if (animationType === 'modern') { + this.animateSlidingItemOptions(0, rtl); + } return; } style.transform = `translate3d(${-openAmount}px,0,0)`; - if (this.animationType === 'modern') { - /** - * The total width of the 'processed' options. - * Used to calculate the offset to move each option off the - * screen, on top of each other. - */ - let optionWidthOffset = 0; - - const side = this.state === SlidingState.Start ? 'start' : 'end'; - - const options = Array.from(this.getOptions(side)?.querySelectorAll('ion-item-option') || []); - const optsWidth = this.getOptionsWidth(side); - - const progress = Math.abs(openAmount / optsWidth); - - options.forEach((option, index) => { - let isFinal = false; - let zIndex: number | undefined; - let viewportOffset = 0; - - if (side === 'start') { - viewportOffset = rtl ? -1 * (optsWidth - optionWidthOffset) : -1 * (option.clientWidth + optionWidthOffset); - isFinal = openAmount <= -optsWidth; - zIndex = rtl ? undefined : options.length - index; - } else { - viewportOffset = rtl ? optionWidthOffset + option.clientWidth : optsWidth - optionWidthOffset; - isFinal = openAmount >= optsWidth; - zIndex = rtl ? options.length - index : undefined; - } - - slidingItemAnimation(option, viewportOffset, progress, isFinal, zIndex); - - optionWidthOffset += option.clientWidth; - }); + if (animationType === 'modern') { + this.animateSlidingItemOptions(openAmount, rtl); } this.ionDrag.emit({ @@ -547,6 +519,44 @@ export class ItemSliding implements ComponentInterface { }); } + private animateSlidingItemOptions(openAmount: number, isRTL: boolean) { + /** + * The total width of the 'processed' options. + * Used to calculate the offset to move each option off the + * screen, on top of each other. + */ + let optionWidthOffset = 0; + + const side = this.state === SlidingState.Start ? 'start' : 'end'; + + const options = Array.from(this.getOptions(side)?.querySelectorAll('ion-item-option') || []); + const optsWidth = this.getOptionsWidth(side); + + const progress = Math.abs(openAmount / optsWidth); + + options.forEach((option, index) => { + let isFinal = false; + let zIndex: number | undefined; + let viewportOffset = 0; + + const isReset = openAmount === 0; + + if (side === 'start') { + viewportOffset = isRTL ? -1 * (optsWidth - optionWidthOffset) : -1 * (option.clientWidth + optionWidthOffset); + isFinal = openAmount <= -optsWidth; + zIndex = isRTL ? undefined : options.length - index; + } else { + viewportOffset = isRTL ? optionWidthOffset + option.clientWidth : optsWidth - optionWidthOffset; + isFinal = openAmount >= optsWidth; + zIndex = isRTL ? options.length - index : undefined; + } + + slidingItemAnimation(option, viewportOffset, progress, isFinal, isReset, zIndex); + + optionWidthOffset += option.clientWidth; + }); + } + private getSlidingRatioSync(): number { if (this.openAmount > 0) { return this.openAmount / this.optsWidthRightSide;