Kaynağa Gözat

Merge pull request #802 from SimoTod/bug/transition-leave-support-in-x-spread

Transition leave support in x spread
Caleb Porzio 4 yıl önce
ebeveyn
işleme
7ec75440c9
3 değiştirilmiş dosya ile 75 ekleme ve 27 silme
  1. 22 15
      dist/alpine.js
  2. 12 12
      src/utils.js
  3. 41 0
      test/spread.spec.js

+ 22 - 15
dist/alpine.js

@@ -381,32 +381,33 @@
     };
     transition(el, stages, type);
   }
-  function transitionClassesIn(el, component, directives, showCallback) {
-    let ensureStringExpression = expression => {
-      return typeof expression === 'function' ? component.evaluateReturnExpression(el, expression) : expression;
-    };
 
+  const ensureStringExpression = (expression, el, component) => {
+    return typeof expression === 'function' ? component.evaluateReturnExpression(el, expression) : expression;
+  };
+
+  function transitionClassesIn(el, component, directives, showCallback) {
     const enter = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter') || {
       expression: ''
-    }).expression));
+    }).expression, el, component));
     const enterStart = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-start') || {
       expression: ''
-    }).expression));
+    }).expression, el, component));
     const enterEnd = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-end') || {
       expression: ''
-    }).expression));
+    }).expression, el, component));
     transitionClasses(el, enter, enterStart, enterEnd, showCallback, () => {}, TRANSITION_TYPE_IN);
   }
   function transitionClassesOut(el, component, directives, hideCallback) {
-    const leave = convertClassStringToArray((directives.find(i => i.value === 'leave') || {
+    const leave = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave') || {
       expression: ''
-    }).expression);
-    const leaveStart = convertClassStringToArray((directives.find(i => i.value === 'leave-start') || {
+    }).expression, el, component));
+    const leaveStart = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave-start') || {
       expression: ''
-    }).expression);
-    const leaveEnd = convertClassStringToArray((directives.find(i => i.value === 'leave-end') || {
+    }).expression, el, component));
+    const leaveEnd = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave-end') || {
       expression: ''
-    }).expression);
+    }).expression, el, component));
     transitionClasses(el, leave, leaveStart, leaveEnd, () => {}, hideCallback, TRANSITION_TYPE_OUT);
   }
   function transitionClasses(el, classesDuring, classesStart, classesEnd, hook1, hook2, type) {
@@ -647,7 +648,7 @@
         // If we are explicitly binding a string to the :value, set the string,
         // If the value is a boolean, leave it alone, it will be set to "on"
         // automatically.
-        if (typeof value !== 'boolean' && ![null, false, undefined].includes(value) && attrType === 'bind') {
+        if (typeof value !== 'boolean' && ![null, undefined].includes(value) && attrType === 'bind') {
           el.value = String(value);
         } else if (attrType !== 'bind') {
           if (Array.isArray(value)) {
@@ -1433,7 +1434,11 @@
       this.unobservedData.$watch = (property, callback) => {
         if (!this.watchers[property]) this.watchers[property] = [];
         this.watchers[property].push(callback);
-      }; // Register custom magic properties.
+      };
+      /* MODERN-ONLY:START */
+      // We remove this piece of code from the legacy build.
+      // In IE11, we have already defined our helpers at this point.
+      // Register custom magic properties.
 
 
       Object.entries(Alpine.magicProperties).forEach(([name, callback]) => {
@@ -1443,6 +1448,8 @@
           }
         });
       });
+      /* MODERN-ONLY:END */
+
       this.showDirectiveStack = [];
       this.showDirectiveLastElement;
       componentForClone || Alpine.onBeforeComponentInitializeds.forEach(callback => callback(this));

+ 12 - 12
src/utils.js

@@ -383,24 +383,24 @@ export function transitionHelper(el, modifiers, hook1, hook2, styleValues, type)
     transition(el, stages, type)
 }
 
-export function transitionClassesIn(el, component, directives, showCallback) {
-    let ensureStringExpression = (expression) => {
-        return typeof expression === 'function'
-            ? component.evaluateReturnExpression(el, expression)
-            : expression
-    }
+const ensureStringExpression = (expression, el, component) => {
+    return typeof expression === 'function'
+        ? component.evaluateReturnExpression(el, expression)
+        : expression
+}
 
-    const enter = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter') || { expression: '' }).expression))
-    const enterStart = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-start') || { expression: '' }).expression))
-    const enterEnd = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-end') || { expression: '' }).expression))
+export function transitionClassesIn(el, component, directives, showCallback) {
+    const enter = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter') || { expression: '' }).expression, el, component))
+    const enterStart = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-start') || { expression: '' }).expression, el, component))
+    const enterEnd = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-end') || { expression: '' }).expression, el, component))
 
     transitionClasses(el, enter, enterStart, enterEnd, showCallback, () => {}, TRANSITION_TYPE_IN)
 }
 
 export function transitionClassesOut(el, component, directives, hideCallback) {
-    const leave = convertClassStringToArray((directives.find(i => i.value === 'leave') || { expression: '' }).expression)
-    const leaveStart = convertClassStringToArray((directives.find(i => i.value === 'leave-start') || { expression: '' }).expression)
-    const leaveEnd = convertClassStringToArray((directives.find(i => i.value === 'leave-end') || { expression: '' }).expression)
+    const leave = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave') || { expression: '' }).expression, el, component))
+    const leaveStart = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave-start') || { expression: '' }).expression, el, component))
+    const leaveEnd = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave-end') || { expression: '' }).expression, el, component))
 
     transitionClasses(el, leave, leaveStart, leaveEnd, () => {}, hideCallback, TRANSITION_TYPE_OUT)
 }

+ 41 - 0
test/spread.spec.js

@@ -92,6 +92,9 @@ test('x-spread syntax supports x-transition', async () => {
                 ['x-transition:enter']() { return 'enter' },
                 ['x-transition:enter-start']() { return 'enter-start' },
                 ['x-transition:enter-end']() { return 'enter-end' },
+                ['x-transition:leave']() { return 'leave' },
+                ['x-transition:leave-start']() { return 'leave-start' },
+                ['x-transition:leave-end']() { return 'leave-end' },
             },
         }
     }
@@ -145,6 +148,44 @@ test('x-spread syntax supports x-transition', async () => {
             resolve();
         }, 10)
     )
+
+    document.querySelector('button').click()
+
+    // Wait out the intial Alpine refresh debounce.
+    await new Promise((resolve) =>
+        setTimeout(() => {
+            resolve();
+        }, 5)
+    )
+
+    expect(document.querySelector('span').classList.contains('leave')).toEqual(true)
+    expect(document.querySelector('span').classList.contains('leave-start')).toEqual(true)
+    expect(document.querySelector('span').classList.contains('leave-end')).toEqual(false)
+    expect(document.querySelector('span').getAttribute('style')).toEqual(null)
+
+    frameStack.pop()()
+
+    expect(document.querySelector('span').classList.contains('leave')).toEqual(true)
+    expect(document.querySelector('span').classList.contains('leave-start')).toEqual(true)
+    expect(document.querySelector('span').classList.contains('leave-end')).toEqual(false)
+    expect(document.querySelector('span').getAttribute('style')).toEqual(null)
+
+    frameStack.pop()()
+
+    expect(document.querySelector('span').classList.contains('leave')).toEqual(true)
+    expect(document.querySelector('span').classList.contains('leave-start')).toEqual(false)
+    expect(document.querySelector('span').classList.contains('leave-end')).toEqual(true)
+    expect(document.querySelector('span').getAttribute('style')).toEqual(null)
+
+    await new Promise((resolve) =>
+        setTimeout(() => {
+            expect(document.querySelector('span').classList.contains('leave')).toEqual(false)
+            expect(document.querySelector('span').classList.contains('leave-start')).toEqual(false)
+            expect(document.querySelector('span').classList.contains('leave-end')).toEqual(false)
+            expect(document.querySelector('span').getAttribute('style')).toEqual('display: none;')
+            resolve();
+        }, 10)
+    )
 })