Selaa lähdekoodia

Merge branch 'jlb/combobox' into feature/ui/combobox

Simone Todaro 2 vuotta sitten
vanhempi
commit
66de82be33

+ 573 - 40
package-lock.json

@@ -12,12 +12,11 @@
             },
             "devDependencies": {
                 "axios": "^0.21.1",
-                "brotli-size": "^4.0.0",
                 "chalk": "^4.1.1",
                 "cypress": "^7.0.0",
                 "cypress-plugin-tab": "^1.0.5",
                 "dot-json": "^1.2.2",
-                "esbuild": "^0.8.39",
+                "esbuild": "~0.16.17",
                 "jest": "^26.6.3"
             }
         },
@@ -644,6 +643,358 @@
                 "ms": "^2.1.1"
             }
         },
+        "node_modules/@esbuild/android-arm": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz",
+            "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==",
+            "cpu": [
+                "arm"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "android"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/android-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz",
+            "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==",
+            "cpu": [
+                "arm64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "android"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/android-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz",
+            "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "android"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/darwin-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz",
+            "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==",
+            "cpu": [
+                "arm64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "darwin"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/darwin-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz",
+            "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "darwin"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/freebsd-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz",
+            "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==",
+            "cpu": [
+                "arm64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "freebsd"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/freebsd-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz",
+            "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "freebsd"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-arm": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz",
+            "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==",
+            "cpu": [
+                "arm"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz",
+            "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==",
+            "cpu": [
+                "arm64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-ia32": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz",
+            "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==",
+            "cpu": [
+                "ia32"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-loong64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz",
+            "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==",
+            "cpu": [
+                "loong64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-mips64el": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz",
+            "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==",
+            "cpu": [
+                "mips64el"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-ppc64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz",
+            "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==",
+            "cpu": [
+                "ppc64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-riscv64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz",
+            "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==",
+            "cpu": [
+                "riscv64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-s390x": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz",
+            "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==",
+            "cpu": [
+                "s390x"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/linux-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz",
+            "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "linux"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/netbsd-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz",
+            "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "netbsd"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/openbsd-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz",
+            "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "openbsd"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/sunos-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz",
+            "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "sunos"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/win32-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz",
+            "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==",
+            "cpu": [
+                "arm64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "win32"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/win32-ia32": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz",
+            "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==",
+            "cpu": [
+                "ia32"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "win32"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@esbuild/win32-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz",
+            "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==",
+            "cpu": [
+                "x64"
+            ],
+            "dev": true,
+            "optional": true,
+            "os": [
+                "win32"
+            ],
+            "engines": {
+                "node": ">=12"
+            }
+        },
         "node_modules/@istanbuljs/load-nyc-config": {
             "version": "1.1.0",
             "dev": true,
@@ -1486,17 +1837,6 @@
                 "node": ">=8"
             }
         },
-        "node_modules/brotli-size": {
-            "version": "4.0.0",
-            "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "duplexer": "0.1.1"
-            },
-            "engines": {
-                "node": ">= 10.16.0"
-            }
-        },
         "node_modules/browser-process-hrtime": {
             "version": "1.0.0",
             "dev": true,
@@ -2234,10 +2574,6 @@
                 "dot-json": "bin/dot-json.js"
             }
         },
-        "node_modules/duplexer": {
-            "version": "0.1.1",
-            "dev": true
-        },
         "node_modules/ecc-jsbn": {
             "version": "0.1.2",
             "dev": true,
@@ -2296,12 +2632,40 @@
             }
         },
         "node_modules/esbuild": {
-            "version": "0.8.57",
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz",
+            "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==",
             "dev": true,
             "hasInstallScript": true,
-            "license": "MIT",
             "bin": {
                 "esbuild": "bin/esbuild"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "optionalDependencies": {
+                "@esbuild/android-arm": "0.16.17",
+                "@esbuild/android-arm64": "0.16.17",
+                "@esbuild/android-x64": "0.16.17",
+                "@esbuild/darwin-arm64": "0.16.17",
+                "@esbuild/darwin-x64": "0.16.17",
+                "@esbuild/freebsd-arm64": "0.16.17",
+                "@esbuild/freebsd-x64": "0.16.17",
+                "@esbuild/linux-arm": "0.16.17",
+                "@esbuild/linux-arm64": "0.16.17",
+                "@esbuild/linux-ia32": "0.16.17",
+                "@esbuild/linux-loong64": "0.16.17",
+                "@esbuild/linux-mips64el": "0.16.17",
+                "@esbuild/linux-ppc64": "0.16.17",
+                "@esbuild/linux-riscv64": "0.16.17",
+                "@esbuild/linux-s390x": "0.16.17",
+                "@esbuild/linux-x64": "0.16.17",
+                "@esbuild/netbsd-x64": "0.16.17",
+                "@esbuild/openbsd-x64": "0.16.17",
+                "@esbuild/sunos-x64": "0.16.17",
+                "@esbuild/win32-arm64": "0.16.17",
+                "@esbuild/win32-ia32": "0.16.17",
+                "@esbuild/win32-x64": "0.16.17"
             }
         },
         "node_modules/escalade": {
@@ -6682,7 +7046,7 @@
             }
         },
         "packages/alpinejs": {
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT",
             "dependencies": {
                 "@vue/reactivity": "~3.1.1"
@@ -6690,7 +7054,7 @@
         },
         "packages/collapse": {
             "name": "@alpinejs/collapse",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
         },
         "packages/csp": {
@@ -6703,12 +7067,12 @@
         },
         "packages/docs": {
             "name": "@alpinejs/docs",
-            "version": "3.10.5-revision.1",
+            "version": "3.11.1-revision.1",
             "license": "MIT"
         },
         "packages/focus": {
             "name": "@alpinejs/focus",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT",
             "dependencies": {
                 "focus-trap": "^6.6.1"
@@ -6724,17 +7088,17 @@
         },
         "packages/intersect": {
             "name": "@alpinejs/intersect",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
         },
         "packages/mask": {
             "name": "@alpinejs/mask",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
         },
         "packages/morph": {
             "name": "@alpinejs/morph",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
         },
         "packages/navigate": {
@@ -6744,7 +7108,7 @@
         },
         "packages/persist": {
             "name": "@alpinejs/persist",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
         },
         "packages/ui": {
@@ -7186,6 +7550,160 @@
                 }
             }
         },
+        "@esbuild/android-arm": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz",
+            "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/android-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz",
+            "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/android-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz",
+            "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/darwin-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz",
+            "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/darwin-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz",
+            "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/freebsd-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz",
+            "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/freebsd-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz",
+            "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/linux-arm": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz",
+            "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/linux-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz",
+            "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/linux-ia32": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz",
+            "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/linux-loong64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz",
+            "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/linux-mips64el": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz",
+            "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/linux-ppc64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz",
+            "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/linux-riscv64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz",
+            "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/linux-s390x": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz",
+            "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/linux-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz",
+            "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/netbsd-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz",
+            "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/openbsd-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz",
+            "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/sunos-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz",
+            "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/win32-arm64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz",
+            "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/win32-ia32": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz",
+            "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==",
+            "dev": true,
+            "optional": true
+        },
+        "@esbuild/win32-x64": {
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz",
+            "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==",
+            "dev": true,
+            "optional": true
+        },
         "@istanbuljs/load-nyc-config": {
             "version": "1.1.0",
             "dev": true,
@@ -7788,13 +8306,6 @@
                 "fill-range": "^7.0.1"
             }
         },
-        "brotli-size": {
-            "version": "4.0.0",
-            "dev": true,
-            "requires": {
-                "duplexer": "0.1.1"
-            }
-        },
         "browser-process-hrtime": {
             "version": "1.0.0",
             "dev": true
@@ -8288,10 +8799,6 @@
                 "underscore-keypath": "~0.0.22"
             }
         },
-        "duplexer": {
-            "version": "0.1.1",
-            "dev": true
-        },
         "ecc-jsbn": {
             "version": "0.1.2",
             "dev": true,
@@ -8334,8 +8841,34 @@
             }
         },
         "esbuild": {
-            "version": "0.8.57",
-            "dev": true
+            "version": "0.16.17",
+            "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz",
+            "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==",
+            "dev": true,
+            "requires": {
+                "@esbuild/android-arm": "0.16.17",
+                "@esbuild/android-arm64": "0.16.17",
+                "@esbuild/android-x64": "0.16.17",
+                "@esbuild/darwin-arm64": "0.16.17",
+                "@esbuild/darwin-x64": "0.16.17",
+                "@esbuild/freebsd-arm64": "0.16.17",
+                "@esbuild/freebsd-x64": "0.16.17",
+                "@esbuild/linux-arm": "0.16.17",
+                "@esbuild/linux-arm64": "0.16.17",
+                "@esbuild/linux-ia32": "0.16.17",
+                "@esbuild/linux-loong64": "0.16.17",
+                "@esbuild/linux-mips64el": "0.16.17",
+                "@esbuild/linux-ppc64": "0.16.17",
+                "@esbuild/linux-riscv64": "0.16.17",
+                "@esbuild/linux-s390x": "0.16.17",
+                "@esbuild/linux-x64": "0.16.17",
+                "@esbuild/netbsd-x64": "0.16.17",
+                "@esbuild/openbsd-x64": "0.16.17",
+                "@esbuild/sunos-x64": "0.16.17",
+                "@esbuild/win32-arm64": "0.16.17",
+                "@esbuild/win32-ia32": "0.16.17",
+                "@esbuild/win32-x64": "0.16.17"
+            }
         },
         "escalade": {
             "version": "3.1.1",

+ 1 - 2
package.json

@@ -5,12 +5,11 @@
     ],
     "devDependencies": {
         "axios": "^0.21.1",
-        "brotli-size": "^4.0.0",
         "chalk": "^4.1.1",
         "cypress": "^7.0.0",
         "cypress-plugin-tab": "^1.0.5",
         "dot-json": "^1.2.2",
-        "esbuild": "^0.8.39",
+        "esbuild": "~0.16.17",
         "jest": "^26.6.3"
     },
     "scripts": {

+ 1 - 1
packages/alpinejs/package.json

@@ -1,6 +1,6 @@
 {
     "name": "alpinejs",
-    "version": "3.11.1",
+    "version": "3.12.0",
     "description": "The rugged, minimal JavaScript framework",
     "homepage": "https://alpinejs.dev",
     "repository": {

+ 2 - 16
packages/alpinejs/src/directives.js

@@ -27,11 +27,8 @@ export function directive(name, callback) {
                 );
                 return;
             }
-            const pos = directiveOrder.indexOf(directive)
-                ?? directiveOrder.indexOf('DEFAULT');
-            if (pos >= 0) {
-                directiveOrder.splice(pos, 0, name);
-            }
+            const pos = directiveOrder.indexOf(directive);
+            directiveOrder.splice(pos >= 0 ? pos : directiveOrder.indexOf('DEFAULT'), 0, name);
         }
     }
 }
@@ -206,20 +203,9 @@ let directiveOrder = [
     'ref',
     'data',
     'id',
-    // @todo: provide better directive ordering mechanisms so
-    // that I don't have to manually add things like "tabs"
-    // to the order list...
-    'radio',
-    'tabs',
-    'switch',
-    'disclosure',
-    'menu',
-    'listbox',
-    'combobox',
     'bind',
     'init',
     'for',
-    'mask',
     'model',
     'modelable',
     'transition',

+ 4 - 0
packages/alpinejs/src/directives/x-model.js

@@ -47,6 +47,10 @@ directive('model', (el, { modifiers, expression }, { effect, cleanup }) => {
         }
     }
 
+    if (modifiers.includes('fill') && el.hasAttribute('value') && (getValue() === null || getValue() === '')) {
+        setValue(el.value)
+    }
+    
     if (typeof expression === 'string' && el.type === 'radio') {
         // Radio buttons only work properly when they share a name attribute.
         // People might assume we take care of that for them, because

+ 1 - 1
packages/alpinejs/src/utils/on.js

@@ -104,7 +104,7 @@ function isKeyEvent(event) {
 
 function isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers) {
     let keyModifiers = modifiers.filter(i => {
-        return ! ['window', 'document', 'prevent', 'stop', 'once'].includes(i)
+        return ! ['window', 'document', 'prevent', 'stop', 'once', 'capture'].includes(i)
     })
 
     if (keyModifiers.includes('debounce')) {

+ 1 - 1
packages/collapse/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@alpinejs/collapse",
-    "version": "3.11.1",
+    "version": "3.12.0",
     "description": "Collapse and expand elements with robust animations",
     "homepage": "https://alpinejs.dev/plugins/collapse",
     "repository": {

+ 1 - 1
packages/docs/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@alpinejs/docs",
-    "version": "3.11.1-revision.1",
+    "version": "3.12.0-revision.1",
     "description": "The documentation for Alpine",
     "author": "Caleb Porzio",
     "license": "MIT"

+ 5 - 5
packages/docs/src/en/directives/bind.md

@@ -11,7 +11,7 @@ For example, here's a component where we will use `x-bind` to set the placeholde
 
 ```alpine
 <div x-data="{ placeholder: 'Type here...' }">
-  <input type="text" x-bind:placeholder="placeholder">
+    <input type="text" x-bind:placeholder="placeholder">
 </div>
 ```
 
@@ -33,11 +33,11 @@ Here's a simple example of a simple dropdown toggle, but instead of using `x-sho
 
 ```alpine
 <div x-data="{ open: false }">
-  <button x-on:click="open = ! open">Toggle Dropdown</button>
+    <button x-on:click="open = ! open">Toggle Dropdown</button>
 
-  <div :class="open ? '' : 'hidden'">
-    Dropdown Contents...
-  </div>
+    <div :class="open ? '' : 'hidden'">
+        Dropdown Contents...
+    </div>
 </div>
 ```
 

+ 3 - 3
packages/docs/src/en/directives/data.md

@@ -86,9 +86,9 @@ Let's refactor our component to use a getter called `isOpen` instead of accessin
 
 ```alpine
 <div x-data="{
-  open: false,
-  get isOpen() { return this.open },
-  toggle() { this.open = ! this.open },
+    open: false,
+    get isOpen() { return this.open },
+    toggle() { this.open = ! this.open },
 }">
     <button @click="toggle()">Toggle Content</button>
 

+ 11 - 0
packages/docs/src/en/directives/model.md

@@ -337,6 +337,17 @@ The default throttle interval is 250 milliseconds, you can easily customize this
 <input type="text" x-model.throttle.500ms="search">
 ```
 
+<a name="fill"></a>
+### `.fill`
+
+By default, if an input has a value attribute, it is ignored by Alpine and instead, the value of the input is set to the value of the property bound using `x-model`.
+
+But if a bound property is empty, then you can use an input's value attribute to populate the property by adding the `.fill` modifier.
+
+<div x-data="{ message: null }">
+  <input x-model.fill="message" value="This is the default message.">
+</div>
+
 <a name="programmatic access"></a>
 ## Programmatic access
 

+ 15 - 2
packages/docs/src/en/directives/on.md

@@ -100,7 +100,7 @@ Here's an example of a component that dispatches a custom DOM event and listens
 
 ```alpine
 <div x-data @foo="alert('Button Was Clicked!')">
-	<button @click="$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))">...</button>
+    <button @click="$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))">...</button>
 </div>
 ```
 
@@ -112,7 +112,7 @@ Here's the same component re-written with the `$dispatch` magic property.
 
 ```alpine
 <div x-data @foo="alert('Button Was Clicked!')">
-  <button @click="$dispatch('foo')">...</button>
+    <button @click="$dispatch('foo')">...</button>
 </div>
 ```
 
@@ -298,3 +298,16 @@ If you are listening for touch events, it's important to add `.passive` to your
 ```
 
 [→ Read more about passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners)
+
+### .capture
+
+Add this modifier if you want to execute this listener in the event's capturing phase, e.g. before the event bubbles from the target element up the DOM.
+
+```
+<div @click.capture="console.log('I will log first')">
+    <button @click="console.log('I will log second')"></button>
+</div>
+```
+
+[→ Read more about the capturing and bubbling phase of events](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#usecapture)
+

+ 6 - 6
packages/docs/src/en/essentials/installation.md

@@ -19,12 +19,12 @@ This is by far the simplest way to get started with Alpine. Include the followin
 
 ```alpine
 <html>
-  <head>
-    ...
+    <head>
+        ...
 
-    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
-  </head>
-  ...
+        <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
+    </head>
+    ...
 </html>
 ```
 
@@ -33,7 +33,7 @@ This is by far the simplest way to get started with Alpine. Include the followin
 Notice the `@3.x.x` in the provided CDN link. This will pull the latest version of Alpine version 3. For stability in production, it's recommended that you hardcode the latest version in the CDN link.
 
 ```alpine
-<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.11.1/dist/cdn.min.js"></script>
+<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.12.0/dist/cdn.min.js"></script>
 ```
 
 That's it! Alpine is now available for use inside your page.

+ 14 - 1
packages/docs/src/en/plugins/mask.md

@@ -58,7 +58,7 @@ Alpine.plugin(mask)
 <button :aria-expanded="expanded" @click="expanded = ! expanded" class="text-cyan-600 font-medium underline">
     <span x-text="expanded ? 'Hide' : 'Show more'">Show</span> <span x-text="expanded ? '↑' : '↓'">↓</span>
 </button>
- </div>
+</div>
 
 <a name="x-mask"></a>
 
@@ -171,3 +171,16 @@ You may also choose to override the thousands separator by supplying a third opt
     <input type="text" x-mask:dynamic="$money($input, '.', ' ')"  placeholder="3 000.00">
 </div>
 <!-- END_VERBATIM -->
+
+
+You can also override the default precision of 2 digits by using any desired number of digits as the fourth optional argument:
+
+```alpine
+<input x-mask:dynamic="$money($input, '.', ',', 4)">
+```
+
+<!-- START_VERBATIM -->
+<div class="demo" x-data>
+    <input type="text" x-mask:dynamic="$money($input, '.', ',', 4)"  placeholder="0.0001">
+</div>
+<!-- END_VERBATIM -->

+ 1 - 1
packages/focus/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@alpinejs/focus",
-    "version": "3.11.1",
+    "version": "3.12.0",
     "description": "Manage focus within a page",
     "homepage": "https://alpinejs.dev/plugins/focus",
     "repository": {

+ 1 - 1
packages/intersect/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@alpinejs/intersect",
-    "version": "3.11.1",
+    "version": "3.12.0",
     "description": "Trigger JavaScript when an element enters the viewport",
     "homepage": "https://alpinejs.dev/plugins/intersect",
     "repository": {

+ 1 - 1
packages/mask/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@alpinejs/mask",
-    "version": "3.11.1",
+    "version": "3.12.0",
     "description": "An Alpine plugin for input masking",
     "homepage": "https://alpinejs.dev/plugins/mask",
     "repository": {

+ 48 - 38
packages/mask/src/index.js

@@ -4,39 +4,44 @@ export default function (Alpine) {
         let templateFn = () => expression
         let lastInputValue = ''
 
-        if (['function', 'dynamic'].includes(value)) {
-            // This is an x-mask:function directive.
-
-            let evaluator = evaluateLater(expression)
-
-            effect(() => {
-                templateFn = input => {
-                    let result
-
-                    // We need to prevent "auto-evaluation" of functions like
-                    // x-on expressions do so that we can use them as mask functions.
-                    Alpine.dontAutoEvaluateFunctions(() => {
-                        evaluator(value => {
-                            result = typeof value === 'function' ? value(input) : value
-                        }, { scope: {
-                            // These are "magics" we'll make available to the x-mask:function:
-                            '$input': input,
-                            '$money': formatMoney.bind({ el }),
-                        }})
-                    })
-
-                    return result
-                }
-
-                // Run on initialize which serves a dual purpose:
-                // - Initializing the mask on the input if it has an initial value.
-                // - Running the template function to set up reactivity, so that
-                //   when a dependency inside it changes, the input re-masks.
-                processInputValue(el)
-            })
-        } else {
-            processInputValue(el)
-        }
+        queueMicrotask(() => {
+            if (['function', 'dynamic'].includes(value)) {
+                // This is an x-mask:function directive.
+
+                let evaluator = evaluateLater(expression)
+
+                effect(() => {
+                    templateFn = input => {
+                        let result
+
+                        // We need to prevent "auto-evaluation" of functions like
+                        // x-on expressions do so that we can use them as mask functions.
+                        Alpine.dontAutoEvaluateFunctions(() => {
+                            evaluator(value => {
+                                result = typeof value === 'function' ? value(input) : value
+                            }, { scope: {
+                                // These are "magics" we'll make available to the x-mask:function:
+                                '$input': input,
+                                '$money': formatMoney.bind({ el }),
+                            }})
+                        })
+
+                        return result
+                    }
+
+                    // Run on initialize which serves a dual purpose:
+                    // - Initializing the mask on the input if it has an initial value.
+                    // - Running the template function to set up reactivity, so that
+                    //   when a dependency inside it changes, the input re-masks.
+                    processInputValue(el, false)
+                })
+            } else {
+                processInputValue(el, false)
+            }
+
+            // Override x-model's initial value...
+            if (el._x_model) el._x_model.set(el.value)
+        })
 
         el.addEventListener('input', () => processInputValue(el))
         // Don't "restoreCursorPosition" on "blur", because Safari
@@ -56,7 +61,9 @@ export default function (Alpine) {
                 return lastInputValue = el.value
             }
 
-            let setInput = () => { lastInputValue = el.value = formatInput(input, template) }
+            let setInput = () => {
+                lastInputValue = el.value = formatInput(input, template)
+            }
 
             if (shouldRestoreCursor) {
                 // When an input element's value is set, it moves the cursor to the end
@@ -79,7 +86,7 @@ export default function (Alpine) {
 
             return rebuiltInput
         }
-    })
+    }).before('model')
 }
 
 export function restoreCursorPosition(el, template, callback) {
@@ -163,7 +170,8 @@ export function buildUp(template, input) {
     return output
 }
 
-export function formatMoney(input, delimiter = '.', thousands) {
+export function formatMoney(input, delimiter = '.', thousands, precision = 2) {
+    if (input === '-') return '-'
     if (/^\D+$/.test(input)) return '9'
 
     thousands = thousands ?? (delimiter === "," ? "." : ",")
@@ -187,12 +195,14 @@ export function formatMoney(input, delimiter = '.', thousands) {
         return output
     }
 
+    let minus = input.startsWith('-') ? '-' : ''
     let strippedInput = input.replaceAll(new RegExp(`[^0-9\\${delimiter}]`, 'g'), '')
     let template = Array.from({ length: strippedInput.split(delimiter)[0].length }).fill('9').join('')
 
-    template = addThousands(template, thousands)
+    template = `${minus}${addThousands(template, thousands)}`
 
-    if (input.includes(delimiter)) template += `${delimiter}99`
+    if (precision > 0 && input.includes(delimiter)) 
+        template += `${delimiter}` + '9'.repeat(precision)
 
     queueMicrotask(() => {
         if (this.el.value.endsWith(delimiter)) return

+ 1 - 1
packages/morph/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@alpinejs/morph",
-    "version": "3.11.1",
+    "version": "3.12.0",
     "description": "Diff and patch a block of HTML on a page with an HTML template",
     "homepage": "https://alpinejs.dev/plugins/morph",
     "repository": {

+ 1 - 1
packages/persist/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@alpinejs/persist",
-    "version": "3.11.1",
+    "version": "3.12.0",
     "description": "Persist Alpine data across page loads",
     "homepage": "https://alpinejs.dev/plugins/persist",
     "repository": {

+ 1 - 1
packages/ui/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@alpinejs/ui",
-    "version": "3.10.5-beta.8",
+    "version": "3.12.0-beta.0",
     "description": "Headless UI components for Alpine",
     "homepage": "https://alpinejs.dev/components#headless",
     "repository": {

+ 1 - 1
packages/ui/src/combobox.js

@@ -8,7 +8,7 @@ export default function (Alpine) {
         else if (directive.value === 'options')      handleOptions(el, Alpine)
         else if (directive.value === 'option')       handleOption(el, Alpine, directive, evaluate)
         else                                         handleRoot(el, Alpine)
-    })
+    }).before('bind')
 
     Alpine.magic('combobox', el => {
         let data = Alpine.$data(el)

+ 1 - 1
packages/ui/src/disclosure.js

@@ -4,7 +4,7 @@ export default function (Alpine) {
         if      (! directive.value)            handleRoot(el, Alpine)
         else if (directive.value === 'panel')  handlePanel(el, Alpine)
         else if (directive.value === 'button') handleButton(el, Alpine)
-    })
+    }).before('bind')
 
     Alpine.magic('disclosure', el => {
         let $data = Alpine.$data(el)

+ 1 - 1
packages/ui/src/listbox.js

@@ -7,7 +7,7 @@ export default function (Alpine) {
         else if (directive.value === 'button') handleButton(el, Alpine)
         else if (directive.value === 'options') handleOptions(el, Alpine)
         else if (directive.value === 'option') handleOption(el, Alpine)
-    })
+    }).before('bind')
 
     Alpine.magic('listbox', (el) => {
         let data = Alpine.$data(el)

+ 1 - 1
packages/ui/src/menu.js

@@ -4,7 +4,7 @@ export default function (Alpine) {
         else if (directive.value === 'items') handleItems(el, Alpine)
         else if (directive.value === 'item') handleItem(el, Alpine)
         else if (directive.value === 'button') handleButton(el, Alpine)
-    });
+    }).before('bind')
 
     Alpine.magic('menuItem', el => {
         let $data = Alpine.$data(el)

+ 1 - 1
packages/ui/src/radio.js

@@ -5,7 +5,7 @@ export default function (Alpine) {
         else if (directive.value === 'option')      handleOption(el, Alpine)
         else if (directive.value === 'label')       handleLabel(el, Alpine)
         else if (directive.value === 'description') handleDescription(el, Alpine)
-    })
+    }).before('bind')
 
     Alpine.magic('radioOption', el => {
         let $data = Alpine.$data(el)

+ 1 - 1
packages/ui/src/switch.js

@@ -5,7 +5,7 @@ export default function (Alpine) {
         else if (directive.value === 'label')       handleLabel(el, Alpine)
         else if (directive.value === 'description') handleDescription(el, Alpine)
         else                                        handleRoot(el, Alpine)
-    })
+    }).before('bind')
 
     Alpine.magic('switch', el => {
         let $data = Alpine.$data(el)

+ 1 - 1
packages/ui/src/tabs.js

@@ -6,7 +6,7 @@ export default function (Alpine) {
         else if (directive.value === 'tab')        handleTab(el, Alpine)
         else if (directive.value === 'panels')     handlePanels(el, Alpine)
         else if (directive.value === 'panel')      handlePanel(el, Alpine)
-    })
+    }).before('bind')
 
     Alpine.magic('tab', el => {
         let $data = Alpine.$data(el)

+ 6 - 17
scripts/build.js

@@ -1,6 +1,6 @@
+let { writeToPackageDotJson, getFromPackageDotJson } = require('./utils');
 let fs = require('fs');
-let DotJson = require('dot-json');
-let brotliSize = require('brotli-size');
+let zlib = require('zlib');
 
 ([
     // Packages:
@@ -37,7 +37,7 @@ function bundleFile(package, file) {
                 outfile: `packages/${package}/dist/${file}`,
                 bundle: true,
                 platform: 'browser',
-                define: { CDN: true },
+                define: { CDN: 'true' },
             })
 
             // Build a minified version.
@@ -47,7 +47,7 @@ function bundleFile(package, file) {
                 bundle: true,
                 minify: true,
                 platform: 'browser',
-                define: { CDN: true },
+                define: { CDN: 'true' },
             }).then(() => {
                 outputSize(package, `packages/${package}/dist/${file.replace('.js', '.min.js')}`)
             })
@@ -86,26 +86,15 @@ function build(options) {
     options.define['process.env.NODE_ENV'] = process.argv.includes('--watch') ? `'production'` : `'development'`
 
     return require('esbuild').build({
+        logLevel: process.argv.includes('--watch') ? 'info' : 'warning',
         watch: process.argv.includes('--watch'),
         // external: ['alpinejs'],
         ...options,
     }).catch(() => process.exit(1))
 }
 
-function writeToPackageDotJson(package, key, value) {
-    let dotJson = new DotJson(`./packages/${package}/package.json`)
-
-    dotJson.set(key, value).save()
-}
-
-function getFromPackageDotJson(package, key) {
-    let dotJson = new DotJson(`./packages/${package}/package.json`)
-
-    return dotJson.get(key)
-}
-
 function outputSize(package, file) {
-    let size = bytesToSize(brotliSize.sync(fs.readFileSync(file)))
+    let size = bytesToSize(zlib.brotliCompressSync(fs.readFileSync(file)).length)
 
     console.log("\x1b[32m", `${package}: ${size}`)
 }

+ 24 - 0
tests/cypress/integration/directives/x-model.spec.js

@@ -129,3 +129,27 @@ test('x-model updates value when the form is reset',
         get('span').should(haveText(''))
     }
 )
+
+test('x-model with fill modifier takes input value on null or empty string',
+    html`
+    <div x-data="{ a: 123, b: 0, c: '', d: null }">
+      <input x-model.fill="a" value="123456" />
+      <span id="a" x-text="a"></span>
+      <input x-model.fill="b" value="123456" />
+      <span id="b" x-text="b"></span>
+      <input x-model.fill="c" value="123456" />
+      <span id="c" x-text="c"></span>
+      <input x-model.fill="d" value="123456" />
+      <span id="d" x-text="d"></span>
+    </div>
+    `,
+    ({ get }) => {
+        get('#a').should(haveText('123'))
+        get('#b').should(haveText('0'))
+        get('#c').should(haveText('123456'))
+        get('#d').should(haveText('123456'))
+    }
+)
+
+
+

+ 35 - 2
tests/cypress/integration/directives/x-on.spec.js

@@ -99,8 +99,8 @@ test('.stop modifier',
 
 test('.capture modifier',
     html`
-        <div x-data="{ foo: 'bar' }">
-            <button @click.capture="foo = 'baz'">
+        <div x-data="{ foo: 'bar', count: 0 }">
+            <button @click.capture="count = count + 1; foo = 'baz'">
                 <h1>h1</h1>
                 <h2 @click="foo = 'bob'">h2</h2>
             </button>
@@ -110,6 +110,39 @@ test('.capture modifier',
         get('div').should(haveData('foo', 'bar'))
         get('h2').click()
         get('div').should(haveData('foo', 'bob'))
+        get('div').should(haveData('count', 1))
+    }
+)
+
+test('.capture modifier with @keyup',
+    html`
+        <div x-data="{ foo: 'bar', count: 0 }">
+            <span @keyup.capture="count = count + 1; foo = 'span'">
+                <input type="text" @keyup="foo = 'input'">
+            </span>
+        </div>
+    `,
+    ({ get }) => {
+        get('div').should(haveData('foo', 'bar'))
+        get('input').type('f')
+        get('div').should(haveData('foo', 'input'))
+        get('div').should(haveData('count', 1))
+    }
+)
+
+test('.capture modifier with @keyup and specified key',
+    html`
+        <div x-data="{ foo: 'bar', count: 0 }">
+            <span @keyup.enter.capture="count = count + 1; foo = 'span'">
+                <input type="text" @keyup.enter="foo = 'input'">
+            </span>
+        </div>
+    `,
+    ({ get }) => {
+        get('div').should(haveData('foo', 'bar'))
+        get('input').type('{enter}')
+        get('div').should(haveData('foo', 'input'))
+        get('div').should(haveData('count', 1))
     }
 )
 

+ 45 - 0
tests/cypress/integration/plugins/mask.spec.js

@@ -60,6 +60,19 @@ test('x-mask with x-model',
     },
 )
 
+test('x-mask with x-model with initial value',
+    [html`
+        <div x-data="{ value: '1234567890' }">
+            <input x-mask="(999) 999-9999" x-model="value" id="1">
+            <input id="2" x-model="value">
+        </div>
+    `],
+    ({ get }) => {
+        get('#1').should(haveValue('(123) 456-7890'))
+        get('#2').should(haveValue('(123) 456-7890'))
+    },
+)
+
 test('x-mask with a falsy input',
     [html`<input x-data x-mask="">`],
     ({ get }) => {
@@ -178,3 +191,35 @@ test('$money mask should remove letters or non numeric characters',
         get('input').type('40').should(haveValue('40'))
     }
 )
+
+test('$money mask negative values',
+    [html`
+        <input id="1" x-data x-mask:dynamic="$money($input)" value="-1234.50" />
+        <input id="2" x-data x-mask:dynamic="$money($input)" />
+    `],
+    ({ get }) => {
+        get('#1').should(haveValue('-1,234.50'))
+        get('#2').type('-12.509').should(haveValue('-12.50'))
+        get('#2').type('{leftArrow}{leftArrow}{leftArrow}-').should(haveValue('-12.50'))
+        get('#2').type('{leftArrow}{leftArrow}{backspace}').should(haveValue('12.50'))
+        get('#2').type('{rightArrow}-').should(haveValue('12.50'))
+        get('#2').type('{rightArrow}-').should(haveValue('12.50'))
+        get('#2').type('{rightArrow}{rightArrow}{rightArrow}-').should(haveValue('12.50'))
+        get('#2').type('{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}-').should(haveValue('-12.50'))
+    }
+)
+
+test('$money with custom decimal precision',
+    [html`
+        <input id="0" x-data x-mask:dynamic="$money($input, '.', ',', 0)" />
+        <input id="1" x-data x-mask:dynamic="$money($input, '.', ',', 1)" />
+        <input id="2" x-data x-mask:dynamic="$money($input, '.', ',', 2)" />
+        <input id="3" x-data x-mask:dynamic="$money($input, '.', ',', 3)" />
+    `],
+    ({ get }) => {
+        get('#0').type('1234.5678').should(haveValue('12,345,678'))
+        get('#1').type('1234.5678').should(haveValue('1,234.5'))
+        get('#2').type('1234.5678').should(haveValue('1,234.56'))
+        get('#3').type('1234.5678').should(haveValue('1,234.567'))
+    }
+)

+ 1 - 1
tests/cypress/integration/plugins/ui/popover.spec.js

@@ -156,7 +156,7 @@ test('focusing away doesnt close panel if focusing inside a group',
     },
 )
 
-test('focusing away still closes panel inside a group if the focus attribute is present',
+test.retry(5)('focusing away still closes panel inside a group if the focus attribute is present',
     [html`
         <div x-data>
             <div x-popover:group>