@@ -9,7 +9,12 @@ import {
99 CUSTOM_CSS_PROPERTIES ,
1010} from './globals.js' ;
1111
12- import { initParentResize , endParentResize } from './resize-parent.js' ;
12+ import {
13+ initParentResize ,
14+ endParentResize ,
15+ setOverflowHidden ,
16+ removeOverflowHidden ,
17+ } from './resize-parent.js' ;
1318
1419import {
1520 removeInlineTransition ,
@@ -32,7 +37,7 @@ const configurations = {
3237 staggerDelay : undefined ,
3338 start : undefined ,
3439 complete : undefined ,
35- keepSpace : false ,
40+ maintainSpace : false ,
3641 dimensionsTransition : true ,
3742 widthTransition : undefined ,
3843 heightTransition : undefined ,
@@ -147,6 +152,12 @@ const TARGETS_STACK = {
147152 stack : { } ,
148153} ;
149154
155+ /**
156+ * Keeps track of the EventListeners associated to a trigger selector
157+ * @type {{[x: String]: EventListener[]} }
158+ */
159+ const LISTENERS = { } ;
160+
150161/**
151162 * Removes the CSS properties customized by the user
152163 * @param {HTMLElement } element - The DOM element with the custom CSS properties
@@ -326,10 +337,12 @@ const isEnabled = element =>
326337 * @returns True if the element has an iteration CSS property set, False otherwise
327338 */
328339const hasIterationProp = element => {
340+ const iterationProperty = element . style . getPropertyValue (
341+ PROPERTY_NAMES . iteration
342+ ) ;
329343 return (
330- element . style
331- . getPropertyValue ( PROPERTY_NAMES . iteration )
332- . match ( / ^ ( i n f i n i t e | \d + ) $ / ) !== null
344+ iterationProperty != '1' &&
345+ iterationProperty . match ( / ^ ( i n f i n i t e | \d + ) $ / ) !== null
333346 ) ;
334347} ;
335348
@@ -343,17 +356,14 @@ const hasIterationProp = element => {
343356 * element: HTMLElement,
344357 * parentMeasures: Object,
345358 * action: string,
346- * dimension: string | undefined,
347- * keepSpace: boolean
359+ * dimension: string | undefined
348360 * }} args - All the necessary arguments
349361 */
350362const handleVisibilityToggle = ( element , args ) => {
351363 setTimeout ( ( ) => {
352364 if ( args . dimension ) setParentMaxMeasures ( args ) ;
353365 if ( args . action === 'show' ) {
354- args . keepSpace
355- ? element . classList . remove ( CLASS_NAMES . hidden )
356- : element . classList . remove ( CLASS_NAMES . collapsed ) ;
366+ element . classList . remove ( CLASS_NAMES . hidden , CLASS_NAMES . collapsed ) ;
357367 }
358368 } , 0 ) ;
359369} ;
@@ -366,12 +376,14 @@ const handleVisibilityToggle = (element, args) => {
366376 */
367377const endVisibilityToggle = ( element , opts ) => {
368378 if ( opts . action === 'hide' ) {
369- opts . keepSpace
379+ opts . maintainSpace
370380 ? element . classList . add ( CLASS_NAMES . hidden )
371381 : element . classList . add ( CLASS_NAMES . collapsed ) ;
372382 }
373383 if ( opts . heightTransition || opts . widthTransition )
374384 endParentResize ( element , opts ) ;
385+ else if ( opts . overflowHidden && element . parentElement )
386+ removeOverflowHidden ( element . parentElement ) ;
375387} ;
376388
377389/**
@@ -414,8 +426,8 @@ const animate = (element, action, id, opts = {}) => {
414426 trigger,
415427 start = CONFIG . start ,
416428 complete = CONFIG . complete ,
417- keepSpace = CONFIG . keepSpace ,
418- dimensionsTransition = keepSpace || isMotion ( animType )
429+ maintainSpace = CONFIG . maintainSpace ,
430+ dimensionsTransition = maintainSpace || isMotion ( animType )
419431 ? false
420432 : CONFIG . dimensionsTransition ,
421433 widthTransition = CONFIG . widthTransition ?? dimensionsTransition ,
@@ -444,7 +456,8 @@ const animate = (element, action, id, opts = {}) => {
444456 heightTransition,
445457 overflowHidden,
446458 } ) ) ;
447- }
459+ } else if ( overflowHidden && element . parentElement )
460+ setOverflowHidden ( element . parentElement ) ;
448461 } ,
449462 motion : ( ) => {
450463 currentTransition = getCurrentTransition ( element ) ;
@@ -459,7 +472,6 @@ const animate = (element, action, id, opts = {}) => {
459472 parentMeasures,
460473 action,
461474 dimension,
462- keepSpace,
463475 } ) ;
464476 } ,
465477 motion : ( ) => {
@@ -473,9 +485,10 @@ const animate = (element, action, id, opts = {}) => {
473485 visibility : ( ) => {
474486 endVisibilityToggle ( element , {
475487 action,
476- keepSpace ,
488+ maintainSpace ,
477489 widthTransition,
478490 heightTransition,
491+ overflowHidden,
479492 } ) ;
480493 if ( ! hasIterationProp ( element ) )
481494 element . classList . remove ( CLASS_NAMES [ action ] [ id ] ) ;
@@ -567,7 +580,7 @@ const preset = (el, args) => {
567580 * @param {HTMLElement } el - The DOM element being animated
568581 * @param {number } animationId - The ID of the animation in the *_ANIMS_ID
569582 * @param {Object } opts - The options passed by the user
570- * @returns A function to be passed to the addEventListener() as a handler
583+ * @returns { EventListener } A function to be passed to the addEventListener() as a handler
571584 * @see {@link module:globals.VISIBILITY_ANIMS_ID }
572585 * @see {@link module:globals.MOTION_ANIMS_ID }
573586 */
@@ -619,24 +632,48 @@ const init = (animationId, opts = {}) => {
619632 btn . setAttribute ( 'target-selector' , targetSelector ) ;
620633 }
621634
635+ if ( ! opts . trigger ) opts . trigger = trigger ;
636+ LISTENERS [ trigger ] = [ ] ;
622637 document
623638 . querySelectorAll ( getTargetSelector ( btn ) )
624639 . forEach ( ( el , i , queryList ) => {
625- btn . addEventListener (
626- eventType ,
627- // @ts -ignore
628- eventHandler ( el , animationId , {
629- ... opts ,
630- totalTargets : queryList . length ,
631- queryIndex : i ,
632- } )
633- ) ;
640+ // @ts -ignore
641+ const listener = eventHandler ( el , animationId , {
642+ ... opts ,
643+ totalTargets : queryList . length ,
644+ queryIndex : i ,
645+ } ) ;
646+
647+ LISTENERS [ trigger ] . push ( listener ) ;
648+ btn . addEventListener ( eventType , listener ) ;
634649 } ) ;
635650 } ) ;
636651} ;
637652
653+ /**
654+ * Removes the event listener of all elements represented by the `triggerSelector`
655+ * @param {String|null } triggerSelector - A valid CSS selector for the trigger Element. If ommited, '.${CLASS_NAMES.trigger}' will be used instead.
656+ * @param {String } eventType - The event name. If ommited, 'click' is the default value.
657+ */
658+ const end = ( triggerSelector = null , eventType = 'click' ) => {
659+ const triggerList =
660+ typeof triggerSelector === 'string'
661+ ? document . querySelectorAll ( triggerSelector )
662+ : document . querySelectorAll ( `.${ CLASS_NAMES . trigger } ` ) ;
663+
664+ triggerList . forEach ( trigger => {
665+ LISTENERS [ triggerSelector ?? `.${ CLASS_NAMES . trigger } ` ] . forEach (
666+ listener => {
667+ trigger . removeEventListener ( eventType , listener ) ;
668+ }
669+ ) ;
670+ } ) ;
671+ delete LISTENERS [ triggerSelector ?? `.${ CLASS_NAMES . trigger } ` ] ;
672+ } ;
673+
638674export {
639675 init ,
676+ end ,
640677 animate ,
641678 preset ,
642679 isEnabled ,
0 commit comments