1
0
Эх сурвалжийг харах

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

Simone Todaro 2 жил өмнө
parent
commit
66de82be33

+ 573 - 40
package-lock.json

@@ -12,12 +12,11 @@
             },
             },
             "devDependencies": {
             "devDependencies": {
                 "axios": "^0.21.1",
                 "axios": "^0.21.1",
-                "brotli-size": "^4.0.0",
                 "chalk": "^4.1.1",
                 "chalk": "^4.1.1",
                 "cypress": "^7.0.0",
                 "cypress": "^7.0.0",
                 "cypress-plugin-tab": "^1.0.5",
                 "cypress-plugin-tab": "^1.0.5",
                 "dot-json": "^1.2.2",
                 "dot-json": "^1.2.2",
-                "esbuild": "^0.8.39",
+                "esbuild": "~0.16.17",
                 "jest": "^26.6.3"
                 "jest": "^26.6.3"
             }
             }
         },
         },
@@ -644,6 +643,358 @@
                 "ms": "^2.1.1"
                 "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": {
         "node_modules/@istanbuljs/load-nyc-config": {
             "version": "1.1.0",
             "version": "1.1.0",
             "dev": true,
             "dev": true,
@@ -1486,17 +1837,6 @@
                 "node": ">=8"
                 "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": {
         "node_modules/browser-process-hrtime": {
             "version": "1.0.0",
             "version": "1.0.0",
             "dev": true,
             "dev": true,
@@ -2234,10 +2574,6 @@
                 "dot-json": "bin/dot-json.js"
                 "dot-json": "bin/dot-json.js"
             }
             }
         },
         },
-        "node_modules/duplexer": {
-            "version": "0.1.1",
-            "dev": true
-        },
         "node_modules/ecc-jsbn": {
         "node_modules/ecc-jsbn": {
             "version": "0.1.2",
             "version": "0.1.2",
             "dev": true,
             "dev": true,
@@ -2296,12 +2632,40 @@
             }
             }
         },
         },
         "node_modules/esbuild": {
         "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,
             "dev": true,
             "hasInstallScript": true,
             "hasInstallScript": true,
-            "license": "MIT",
             "bin": {
             "bin": {
                 "esbuild": "bin/esbuild"
                 "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": {
         "node_modules/escalade": {
@@ -6682,7 +7046,7 @@
             }
             }
         },
         },
         "packages/alpinejs": {
         "packages/alpinejs": {
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT",
             "license": "MIT",
             "dependencies": {
             "dependencies": {
                 "@vue/reactivity": "~3.1.1"
                 "@vue/reactivity": "~3.1.1"
@@ -6690,7 +7054,7 @@
         },
         },
         "packages/collapse": {
         "packages/collapse": {
             "name": "@alpinejs/collapse",
             "name": "@alpinejs/collapse",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
             "license": "MIT"
         },
         },
         "packages/csp": {
         "packages/csp": {
@@ -6703,12 +7067,12 @@
         },
         },
         "packages/docs": {
         "packages/docs": {
             "name": "@alpinejs/docs",
             "name": "@alpinejs/docs",
-            "version": "3.10.5-revision.1",
+            "version": "3.11.1-revision.1",
             "license": "MIT"
             "license": "MIT"
         },
         },
         "packages/focus": {
         "packages/focus": {
             "name": "@alpinejs/focus",
             "name": "@alpinejs/focus",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT",
             "license": "MIT",
             "dependencies": {
             "dependencies": {
                 "focus-trap": "^6.6.1"
                 "focus-trap": "^6.6.1"
@@ -6724,17 +7088,17 @@
         },
         },
         "packages/intersect": {
         "packages/intersect": {
             "name": "@alpinejs/intersect",
             "name": "@alpinejs/intersect",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
             "license": "MIT"
         },
         },
         "packages/mask": {
         "packages/mask": {
             "name": "@alpinejs/mask",
             "name": "@alpinejs/mask",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
             "license": "MIT"
         },
         },
         "packages/morph": {
         "packages/morph": {
             "name": "@alpinejs/morph",
             "name": "@alpinejs/morph",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
             "license": "MIT"
         },
         },
         "packages/navigate": {
         "packages/navigate": {
@@ -6744,7 +7108,7 @@
         },
         },
         "packages/persist": {
         "packages/persist": {
             "name": "@alpinejs/persist",
             "name": "@alpinejs/persist",
-            "version": "3.10.5",
+            "version": "3.11.1",
             "license": "MIT"
             "license": "MIT"
         },
         },
         "packages/ui": {
         "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": {
         "@istanbuljs/load-nyc-config": {
             "version": "1.1.0",
             "version": "1.1.0",
             "dev": true,
             "dev": true,
@@ -7788,13 +8306,6 @@
                 "fill-range": "^7.0.1"
                 "fill-range": "^7.0.1"
             }
             }
         },
         },
-        "brotli-size": {
-            "version": "4.0.0",
-            "dev": true,
-            "requires": {
-                "duplexer": "0.1.1"
-            }
-        },
         "browser-process-hrtime": {
         "browser-process-hrtime": {
             "version": "1.0.0",
             "version": "1.0.0",
             "dev": true
             "dev": true
@@ -8288,10 +8799,6 @@
                 "underscore-keypath": "~0.0.22"
                 "underscore-keypath": "~0.0.22"
             }
             }
         },
         },
-        "duplexer": {
-            "version": "0.1.1",
-            "dev": true
-        },
         "ecc-jsbn": {
         "ecc-jsbn": {
             "version": "0.1.2",
             "version": "0.1.2",
             "dev": true,
             "dev": true,
@@ -8334,8 +8841,34 @@
             }
             }
         },
         },
         "esbuild": {
         "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": {
         "escalade": {
             "version": "3.1.1",
             "version": "3.1.1",

+ 1 - 2
package.json

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

+ 1 - 1
packages/alpinejs/package.json

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

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

@@ -27,11 +27,8 @@ export function directive(name, callback) {
                 );
                 );
                 return;
                 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',
     'ref',
     'data',
     'data',
     'id',
     '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',
     'bind',
     'init',
     'init',
     'for',
     'for',
-    'mask',
     'model',
     'model',
     'modelable',
     'modelable',
     'transition',
     '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') {
     if (typeof expression === 'string' && el.type === 'radio') {
         // Radio buttons only work properly when they share a name attribute.
         // Radio buttons only work properly when they share a name attribute.
         // People might assume we take care of that for them, because
         // 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) {
 function isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers) {
     let keyModifiers = modifiers.filter(i => {
     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')) {
     if (keyModifiers.includes('debounce')) {

+ 1 - 1
packages/collapse/package.json

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

+ 1 - 1
packages/docs/package.json

@@ -1,6 +1,6 @@
 {
 {
     "name": "@alpinejs/docs",
     "name": "@alpinejs/docs",
-    "version": "3.11.1-revision.1",
+    "version": "3.12.0-revision.1",
     "description": "The documentation for Alpine",
     "description": "The documentation for Alpine",
     "author": "Caleb Porzio",
     "author": "Caleb Porzio",
     "license": "MIT"
     "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
 ```alpine
 <div x-data="{ placeholder: 'Type here...' }">
 <div x-data="{ placeholder: 'Type here...' }">
-  <input type="text" x-bind:placeholder="placeholder">
+    <input type="text" x-bind:placeholder="placeholder">
 </div>
 </div>
 ```
 ```
 
 
@@ -33,11 +33,11 @@ Here's a simple example of a simple dropdown toggle, but instead of using `x-sho
 
 
 ```alpine
 ```alpine
 <div x-data="{ open: false }">
 <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>
 </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
 ```alpine
 <div x-data="{
 <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>
     <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">
 <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>
 <a name="programmatic access"></a>
 ## Programmatic access
 ## 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
 ```alpine
 <div x-data @foo="alert('Button Was Clicked!')">
 <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>
 </div>
 ```
 ```
 
 
@@ -112,7 +112,7 @@ Here's the same component re-written with the `$dispatch` magic property.
 
 
 ```alpine
 ```alpine
 <div x-data @foo="alert('Button Was Clicked!')">
 <div x-data @foo="alert('Button Was Clicked!')">
-  <button @click="$dispatch('foo')">...</button>
+    <button @click="$dispatch('foo')">...</button>
 </div>
 </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)
 [→ 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
 ```alpine
 <html>
 <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>
 </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.
 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
 ```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.
 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">
 <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>
     <span x-text="expanded ? 'Hide' : 'Show more'">Show</span> <span x-text="expanded ? '↑' : '↓'">↓</span>
 </button>
 </button>
- </div>
+</div>
 
 
 <a name="x-mask"></a>
 <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">
     <input type="text" x-mask:dynamic="$money($input, '.', ' ')"  placeholder="3 000.00">
 </div>
 </div>
 <!-- END_VERBATIM -->
 <!-- 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",
     "name": "@alpinejs/focus",
-    "version": "3.11.1",
+    "version": "3.12.0",
     "description": "Manage focus within a page",
     "description": "Manage focus within a page",
     "homepage": "https://alpinejs.dev/plugins/focus",
     "homepage": "https://alpinejs.dev/plugins/focus",
     "repository": {
     "repository": {

+ 1 - 1
packages/intersect/package.json

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

+ 1 - 1
packages/mask/package.json

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

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

@@ -4,39 +4,44 @@ export default function (Alpine) {
         let templateFn = () => expression
         let templateFn = () => expression
         let lastInputValue = ''
         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))
         el.addEventListener('input', () => processInputValue(el))
         // Don't "restoreCursorPosition" on "blur", because Safari
         // Don't "restoreCursorPosition" on "blur", because Safari
@@ -56,7 +61,9 @@ export default function (Alpine) {
                 return lastInputValue = el.value
                 return lastInputValue = el.value
             }
             }
 
 
-            let setInput = () => { lastInputValue = el.value = formatInput(input, template) }
+            let setInput = () => {
+                lastInputValue = el.value = formatInput(input, template)
+            }
 
 
             if (shouldRestoreCursor) {
             if (shouldRestoreCursor) {
                 // When an input element's value is set, it moves the cursor to the end
                 // 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
             return rebuiltInput
         }
         }
-    })
+    }).before('model')
 }
 }
 
 
 export function restoreCursorPosition(el, template, callback) {
 export function restoreCursorPosition(el, template, callback) {
@@ -163,7 +170,8 @@ export function buildUp(template, input) {
     return output
     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'
     if (/^\D+$/.test(input)) return '9'
 
 
     thousands = thousands ?? (delimiter === "," ? "." : ",")
     thousands = thousands ?? (delimiter === "," ? "." : ",")
@@ -187,12 +195,14 @@ export function formatMoney(input, delimiter = '.', thousands) {
         return output
         return output
     }
     }
 
 
+    let minus = input.startsWith('-') ? '-' : ''
     let strippedInput = input.replaceAll(new RegExp(`[^0-9\\${delimiter}]`, 'g'), '')
     let strippedInput = input.replaceAll(new RegExp(`[^0-9\\${delimiter}]`, 'g'), '')
     let template = Array.from({ length: strippedInput.split(delimiter)[0].length }).fill('9').join('')
     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(() => {
     queueMicrotask(() => {
         if (this.el.value.endsWith(delimiter)) return
         if (this.el.value.endsWith(delimiter)) return

+ 1 - 1
packages/morph/package.json

@@ -1,6 +1,6 @@
 {
 {
     "name": "@alpinejs/morph",
     "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",
     "description": "Diff and patch a block of HTML on a page with an HTML template",
     "homepage": "https://alpinejs.dev/plugins/morph",
     "homepage": "https://alpinejs.dev/plugins/morph",
     "repository": {
     "repository": {

+ 1 - 1
packages/persist/package.json

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

+ 1 - 1
packages/ui/package.json

@@ -1,6 +1,6 @@
 {
 {
     "name": "@alpinejs/ui",
     "name": "@alpinejs/ui",
-    "version": "3.10.5-beta.8",
+    "version": "3.12.0-beta.0",
     "description": "Headless UI components for Alpine",
     "description": "Headless UI components for Alpine",
     "homepage": "https://alpinejs.dev/components#headless",
     "homepage": "https://alpinejs.dev/components#headless",
     "repository": {
     "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 === 'options')      handleOptions(el, Alpine)
         else if (directive.value === 'option')       handleOption(el, Alpine, directive, evaluate)
         else if (directive.value === 'option')       handleOption(el, Alpine, directive, evaluate)
         else                                         handleRoot(el, Alpine)
         else                                         handleRoot(el, Alpine)
-    })
+    }).before('bind')
 
 
     Alpine.magic('combobox', el => {
     Alpine.magic('combobox', el => {
         let data = Alpine.$data(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)
         if      (! directive.value)            handleRoot(el, Alpine)
         else if (directive.value === 'panel')  handlePanel(el, Alpine)
         else if (directive.value === 'panel')  handlePanel(el, Alpine)
         else if (directive.value === 'button') handleButton(el, Alpine)
         else if (directive.value === 'button') handleButton(el, Alpine)
-    })
+    }).before('bind')
 
 
     Alpine.magic('disclosure', el => {
     Alpine.magic('disclosure', el => {
         let $data = Alpine.$data(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 === 'button') handleButton(el, Alpine)
         else if (directive.value === 'options') handleOptions(el, Alpine)
         else if (directive.value === 'options') handleOptions(el, Alpine)
         else if (directive.value === 'option') handleOption(el, Alpine)
         else if (directive.value === 'option') handleOption(el, Alpine)
-    })
+    }).before('bind')
 
 
     Alpine.magic('listbox', (el) => {
     Alpine.magic('listbox', (el) => {
         let data = Alpine.$data(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 === 'items') handleItems(el, Alpine)
         else if (directive.value === 'item') handleItem(el, Alpine)
         else if (directive.value === 'item') handleItem(el, Alpine)
         else if (directive.value === 'button') handleButton(el, Alpine)
         else if (directive.value === 'button') handleButton(el, Alpine)
-    });
+    }).before('bind')
 
 
     Alpine.magic('menuItem', el => {
     Alpine.magic('menuItem', el => {
         let $data = Alpine.$data(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 === 'option')      handleOption(el, Alpine)
         else if (directive.value === 'label')       handleLabel(el, Alpine)
         else if (directive.value === 'label')       handleLabel(el, Alpine)
         else if (directive.value === 'description') handleDescription(el, Alpine)
         else if (directive.value === 'description') handleDescription(el, Alpine)
-    })
+    }).before('bind')
 
 
     Alpine.magic('radioOption', el => {
     Alpine.magic('radioOption', el => {
         let $data = Alpine.$data(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 === 'label')       handleLabel(el, Alpine)
         else if (directive.value === 'description') handleDescription(el, Alpine)
         else if (directive.value === 'description') handleDescription(el, Alpine)
         else                                        handleRoot(el, Alpine)
         else                                        handleRoot(el, Alpine)
-    })
+    }).before('bind')
 
 
     Alpine.magic('switch', el => {
     Alpine.magic('switch', el => {
         let $data = Alpine.$data(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 === 'tab')        handleTab(el, Alpine)
         else if (directive.value === 'panels')     handlePanels(el, Alpine)
         else if (directive.value === 'panels')     handlePanels(el, Alpine)
         else if (directive.value === 'panel')      handlePanel(el, Alpine)
         else if (directive.value === 'panel')      handlePanel(el, Alpine)
-    })
+    }).before('bind')
 
 
     Alpine.magic('tab', el => {
     Alpine.magic('tab', el => {
         let $data = Alpine.$data(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 fs = require('fs');
-let DotJson = require('dot-json');
-let brotliSize = require('brotli-size');
+let zlib = require('zlib');
 
 
 ([
 ([
     // Packages:
     // Packages:
@@ -37,7 +37,7 @@ function bundleFile(package, file) {
                 outfile: `packages/${package}/dist/${file}`,
                 outfile: `packages/${package}/dist/${file}`,
                 bundle: true,
                 bundle: true,
                 platform: 'browser',
                 platform: 'browser',
-                define: { CDN: true },
+                define: { CDN: 'true' },
             })
             })
 
 
             // Build a minified version.
             // Build a minified version.
@@ -47,7 +47,7 @@ function bundleFile(package, file) {
                 bundle: true,
                 bundle: true,
                 minify: true,
                 minify: true,
                 platform: 'browser',
                 platform: 'browser',
-                define: { CDN: true },
+                define: { CDN: 'true' },
             }).then(() => {
             }).then(() => {
                 outputSize(package, `packages/${package}/dist/${file.replace('.js', '.min.js')}`)
                 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'`
     options.define['process.env.NODE_ENV'] = process.argv.includes('--watch') ? `'production'` : `'development'`
 
 
     return require('esbuild').build({
     return require('esbuild').build({
+        logLevel: process.argv.includes('--watch') ? 'info' : 'warning',
         watch: process.argv.includes('--watch'),
         watch: process.argv.includes('--watch'),
         // external: ['alpinejs'],
         // external: ['alpinejs'],
         ...options,
         ...options,
     }).catch(() => process.exit(1))
     }).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) {
 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}`)
     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(''))
         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',
 test('.capture modifier',
     html`
     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>
                 <h1>h1</h1>
                 <h2 @click="foo = 'bob'">h2</h2>
                 <h2 @click="foo = 'bob'">h2</h2>
             </button>
             </button>
@@ -110,6 +110,39 @@ test('.capture modifier',
         get('div').should(haveData('foo', 'bar'))
         get('div').should(haveData('foo', 'bar'))
         get('h2').click()
         get('h2').click()
         get('div').should(haveData('foo', 'bob'))
         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',
 test('x-mask with a falsy input',
     [html`<input x-data x-mask="">`],
     [html`<input x-data x-mask="">`],
     ({ get }) => {
     ({ get }) => {
@@ -178,3 +191,35 @@ test('$money mask should remove letters or non numeric characters',
         get('input').type('40').should(haveValue('40'))
         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`
     [html`
         <div x-data>
         <div x-data>
             <div x-popover:group>
             <div x-popover:group>