Просмотр исходного кода

Fix teleport morphing (#3841)

* Fix teleport morphing

* Make x-trap more friendly with transitions

* wip

* wip

* wip

* wip
Caleb Porzio 1 год назад
Родитель
Сommit
63444046f0
3 измененных файлов с 19 добавлено и 11 удалено
  1. 5 4
      packages/focus/src/index.js
  2. 5 4
      packages/morph/src/morph.js
  3. 9 3
      packages/ui/src/menu.js

+ 5 - 4
packages/focus/src/index.js

@@ -134,12 +134,13 @@ export default function (Alpine) {
 
                 // Start trapping.
                 if (value && ! oldValue) {
-                    setTimeout(() => {
-                        if (modifiers.includes('inert')) undoInert = setInert(el)
-                        if (modifiers.includes('noscroll')) undoDisableScrolling = disableScrolling()
+                    if (modifiers.includes('noscroll')) undoDisableScrolling = disableScrolling()
+                    if (modifiers.includes('inert')) undoInert = setInert(el)
 
+                    // Activate the trap after a generous tick. (Needed to play nice with transitions...)
+                    setTimeout(() => {
                         trap.activate()
-                    });
+                    }, 15)
                 }
 
                 // Stop trapping.

+ 5 - 4
packages/morph/src/morph.js

@@ -120,6 +120,11 @@ export function morph(from, toHtml, options) {
     }
 
     function patchChildren(from, to) {
+        // If we hit a <template x-teleport="body">,
+        // let's use the teleported nodes for this patch...
+        if (from._x_teleport) from = from._x_teleport
+        if (to._x_teleport) to = to._x_teleport
+
         let fromKeys = keyToMap(from.children)
         let fromKeyHoldovers = {}
 
@@ -444,10 +449,6 @@ function getFirstNode(parent) {
 }
 
 function getNextSibling(parent, reference) {
-    if (reference._x_teleport) {
-        return reference._x_teleport
-    }
-
     let next
 
     if (parent instanceof Block) {

+ 9 - 3
packages/ui/src/menu.js

@@ -29,14 +29,20 @@ function handleRoot(el, Alpine) {
                 __itemEls: [],
                 __activeEl: null,
                 __isOpen: false,
-                __open() {
+                __open(activationStrategy) {
+
                     this.__isOpen = true
 
                     // Safari needs more of a "tick" for focusing after x-show for some reason.
                     // Probably because Alpine adds an extra tick when x-showing for @click.outside
                     let nextTick = callback => requestAnimationFrame(() => requestAnimationFrame(callback))
 
-                    nextTick(() => this.$refs.__items.focus({ preventScroll: true }))
+                    nextTick(() => {
+                        this.$refs.__items.focus({ preventScroll: true })
+
+                        // Activate the first item every time the menu is open...
+                        activationStrategy && activationStrategy(Alpine, this.$refs.__items, el => el.__activate())
+                    })
                 },
                 __close(focusAfter = true) {
                     this.__isOpen = false
@@ -67,7 +73,7 @@ function handleButton(el, Alpine) {
         'x-init'() { if (this.$el.tagName.toLowerCase() === 'button' && ! this.$el.hasAttribute('type')) this.$el.type = 'button' },
         '@click'() { this.$data.__open() },
         '@keydown.down.stop.prevent'() { this.$data.__open() },
-        '@keydown.up.stop.prevent'() { this.$data.__open(dom.Alpine, last) },
+        '@keydown.up.stop.prevent'() { this.$data.__open(dom.last) },
         '@keydown.space.stop.prevent'() { this.$data.__open() },
         '@keydown.enter.stop.prevent'() { this.$data.__open() },
     })