Преглед изворни кода

Merge branch 'main' into wip

Caleb Porzio пре 3 година
родитељ
комит
b2a02fbe40

+ 1 - 1
README.md

@@ -30,7 +30,7 @@ Here's a brief look at each package in this repo:
 Package | Description
 --- | ---
 [alpinejs](packages/alpinejs) | The main Alpine repo with all of Alpine's core
-[collapse](packages/collpase) | A plugin for expanding and collapsing elements using smooth animations
+[collapse](packages/collapse) | A plugin for expanding and collapsing elements using smooth animations
 [csp](packages/csp) | A repo to provide a "CSP safe" build of Alpine
 [docs](packages/docs) | The Alpine documentation
 [focus](packages/focus) | A plugin that allows you to manage focus inside an element

+ 3 - 2
packages/alpinejs/src/directives/x-transition.js

@@ -131,7 +131,8 @@ window.Element.prototype._x_toggleAndCascadeWithTransitions = function (el, valu
     // it keeps running in background. setTimeout has a lower priority in the
     // event loop so it would skip nested transitions but when the tab is
     // hidden, it's not relevant.
-    let clickAwayCompatibleShow = () => {document.visibilityState === 'visible' ? requestAnimationFrame(show) : setTimeout(show)}
+    const nextTick = document.visibilityState === 'visible' ? requestAnimationFrame : setTimeout;
+    let clickAwayCompatibleShow = () => nextTick(show);
 
     if (value) {
         if (el._x_transition && (el._x_transition.enter || el._x_transition.leave)) {
@@ -167,7 +168,7 @@ window.Element.prototype._x_toggleAndCascadeWithTransitions = function (el, valu
 
             closest._x_hideChildren.push(el)
         } else {
-            queueMicrotask(() => {
+            nextTick(() => {
                 let hideAfterChildren = el => {
                     let carry = Promise.all([
                         el._x_hidePromise,

+ 1 - 1
packages/docs/src/en/directives/on.md

@@ -13,7 +13,7 @@ Here's an example of simple button that shows an alert when clicked.
 <button x-on:click="alert('Hello World!')">Say Hi</button>
 ```
 
-> `x-on` can only listen for events with lower case names, as HTML attributes are case-insensitive. Writing `x-on:CLICK` will listen for an event named `click`. If you need to listen for a custom event with a camelCase name, you can use the [`.camel` helper](#camel) to work around this limitation. Alternatively, you can use  [`x-bind`](/directives/bind.md#bind-directives) to attach an `x-on` directive to an element in javascript code (where case will be preserved).
+> `x-on` can only listen for events with lower case names, as HTML attributes are case-insensitive. Writing `x-on:CLICK` will listen for an event named `click`. If you need to listen for a custom event with a camelCase name, you can use the [`.camel` helper](#camel) to work around this limitation. Alternatively, you can use  [`x-bind`](/directives/bind#bind-directives) to attach an `x-on` directive to an element in javascript code (where case will be preserved).
 
 <a name="shorthand-syntax"></a>
 ## Shorthand syntax

+ 1 - 0
packages/focus/src/index.js

@@ -106,6 +106,7 @@ export default function (Alpine) {
                 escapeDeactivates: false,
                 allowOutsideClick: true,
                 fallbackFocus: () => el,
+                initialFocus: el.querySelector('[autofocus]')
             })
 
             let undoInert = () => {}

+ 3 - 0
packages/mask/src/index.js

@@ -48,6 +48,9 @@ export default function (Alpine) {
 
             let template = templateFn(input)
 
+            // If a template value is `falsy`, then don't process the input value
+            if(!template || template === 'false') return false
+
             // If they hit backspace, don't process input.
             if (lastInputValue.length - el.value.length === 1) {
                 return lastInputValue = el.value

+ 16 - 0
tests/cypress/integration/directives/x-show.spec.js

@@ -143,3 +143,19 @@ test('x-show takes precedence over style bindings for display property',
         get('span:nth-of-type(2)').should(haveAttribute('style', 'color: red; display: none;'))
     }
 )
+
+test('x-show executes consecutive state changes in correct order',
+    html`
+        <div
+            x-data="{ isEnabled: false }"
+            x-init="$watch('isEnabled', () => { if (isEnabled) isEnabled = false })"
+        >
+            <button id="enable" x-show="!isEnabled" @click="isEnabled = true"></button>
+            <button id="disable" x-show="isEnabled" @click="isEnabled = false"></button>
+        </div>
+    `,
+    ({ get }) => {
+        get('button#enable').should(beVisible())
+        get('button#disable').should(beHidden())
+    }
+)

+ 26 - 0
tests/cypress/integration/plugins/focus.spec.js

@@ -307,3 +307,29 @@ test('$focus.last',
         get('#1').should(haveText('3'))
     },
 )
+
+test('focuses element with autofocus',
+    [html`
+        <div x-data="{ open: false }">
+            <input type="text" id="1">
+            <button id="2" @click="open = true">open</button>
+            <div>
+                <div x-trap="open">
+                    <input type="text" id="3">
+                    <input autofocus type="text" id="4">
+                    <button @click="open = false" id="5">close</button>
+                </div>
+            </div>
+        </div>
+    `],
+    ({ get }) => {
+        get('#1').click()
+        get('#1').should(haveFocus())
+        get('#2').click()
+        get('#4').should(haveFocus())
+        cy.focused().tab()
+        get('#5').should(haveFocus())
+        cy.focused().tab()
+        get('#3').should(haveFocus())
+    }
+)

+ 25 - 1
tests/cypress/integration/plugins/mask.spec.js

@@ -60,6 +60,30 @@ test('x-mask with x-model',
     },
 )
 
+test('x-mask with a falsy input',
+    [html`<input x-data x-mask="">`],
+    ({ get }) => {
+	    get('input').type('1').should(haveValue('1'))
+	    get('input').type('2').should(haveValue('12'))
+	    get('input').type('ua').should(haveValue('12ua'))
+	    get('input').type('/').should(haveValue('12ua/'))
+	    get('input').type('cs').should(haveValue('12ua/cs'))
+	    get('input').type('  3').should(haveValue('12ua/cs  3'))
+    }
+)
+
+test('x-mask with a falsy string input',
+    [html`<input x-data x-mask="false">`],
+    ({ get }) => {
+	    get('input').type('1').should(haveValue('1'))
+	    get('input').type('2').should(haveValue('12'))
+	    get('input').type('ua').should(haveValue('12ua'))
+	    get('input').type('/').should(haveValue('12ua/'))
+	    get('input').type('cs').should(haveValue('12ua/cs'))
+	    get('input').type('  3').should(haveValue('12ua/cs  3'))
+    }
+)
+
 test('x-mask with non wildcard alpha-numeric characters (b)',
     [html`<input x-data x-mask="ba9*b">`],
     ({ get }) => {
@@ -68,7 +92,7 @@ test('x-mask with non wildcard alpha-numeric characters (b)',
         get('input').type('3').should(haveValue('ba3'))
         get('input').type('z').should(haveValue('ba3zb'))
         get('input').type('{backspace}{backspace}4').should(haveValue('ba34b'))
-    },
+    }
 )
 
 test('x-mask:dynamic',