diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 65fc1f75891b4d43652b6ff749339626688ed2c5..8944e612c6ca61353e8899677e4e0b2a1949dcd4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,7 +24,6 @@ check: - tags only: - merge_requests - - /^release\/.+$/ - main script: task check @@ -34,7 +33,6 @@ test: - tags only: - merge_requests - - /^release\/.+$/ - main script: task test @@ -48,30 +46,22 @@ a11y: except: - tags only: - - /^release\/.+$/ - main script: task a11y -merge_release_preview: - stage: merge - only: - - merge_requests - script: task release:preview - publish-dev: stage: publish + when: manual only: - - /^release\/.+$/ + - merge_requests script: - git config user.email "gitlab@s-v.de" - git config user.name "CI" - git remote set-url origin https://oauth2:$GIT_PUSH_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git - - git checkout "$CI_COMMIT_REF_NAME" - - git reset --hard origin/"$CI_COMMIT_REF_NAME" - - git fetch --prune --prune-tags -f - bun x npm config set //gitlab.s-v.de/api/v4/projects/1560/packages/npm/:_authToken="$CI_JOB_TOKEN" - bun x npm config list - task prerelease + - git push origin -o ci.skip origin $CI_COMMIT_REF_NAME && git push --tags publish: stage: publish @@ -83,12 +73,10 @@ publish: - git config user.email "gitlab@s-v.de" - git config user.name "CI" - git remote set-url origin https://oauth2:$GIT_PUSH_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git - - git checkout "$CI_COMMIT_REF_NAME" - - git reset --hard origin/"$CI_COMMIT_REF_NAME" - - git fetch --prune --prune-tags -f - bun x npm config set //gitlab.s-v.de/api/v4/projects/1560/packages/npm/:_authToken="$CI_JOB_TOKEN" - bun x npm config list - task release + - git push origin -o ci.skip origin $CI_COMMIT_REF_NAME && git push --tags pages: stage: docs diff --git a/bun.lock b/bun.lock index 845b0acd7b9f7cd8435708b99f1d8f5ae472a040..bb4d956f4fc6c3612082e61134a04fbfe9ed73aa 100644 --- a/bun.lock +++ b/bun.lock @@ -11,7 +11,7 @@ "@types/web": "^0.0.123", "fast-glob": "^3.3.2", "npm": "^10.7.0", - "tsup": "^8.1.0", + "tsup": "^8.4.0", "turbo": "^2.0.1", }, }, @@ -61,7 +61,7 @@ }, "packages/components": { "name": "@sv/components", - "version": "1.7.3", + "version": "1.8.1", "bin": "./bin/cli.js", "dependencies": { "chalk": "^5.3.0", @@ -77,7 +77,7 @@ }, "packages/elements": { "name": "@sv/elements", - "version": "2.2.0", + "version": "2.4.2-dev.1", "dependencies": { "lit": "^3.1.3", }, @@ -321,55 +321,55 @@ "@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.0", "", { "os": "android", "cpu": "arm" }, "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.0", "", { "os": "android", "cpu": "arm64" }, "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.0", "", { "os": "android", "cpu": "x64" }, "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.0", "", { "os": "linux", "cpu": "arm" }, "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.0", "", { "os": "linux", "cpu": "none" }, "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.0", "", { "os": "linux", "cpu": "x64" }, "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.0", "", { "os": "none", "cpu": "arm64" }, "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.0", "", { "os": "none", "cpu": "x64" }, "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.0", "", { "os": "sunos", "cpu": "x64" }, "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.0", "", { "os": "win32", "cpu": "x64" }, "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ=="], "@expressive-code/core": ["@expressive-code/core@0.40.2", "", { "dependencies": { "@ctrl/tinycolor": "^4.0.4", "hast-util-select": "^6.0.2", "hast-util-to-html": "^9.0.1", "hast-util-to-text": "^4.0.1", "hastscript": "^9.0.0", "postcss": "^8.4.38", "postcss-nested": "^6.0.1", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1" } }, "sha512-gXY3v7jbgz6nWKvRpoDxK4AHUPkZRuJsM79vHX/5uhV9/qX6Qnctp/U/dMHog/LCVXcuOps+5nRmf1uxQVPb3w=="], @@ -1161,7 +1161,7 @@ "esast-util-from-js": ["esast-util-from-js@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "acorn": "^8.0.0", "esast-util-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw=="], - "esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + "esbuild": ["esbuild@0.25.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.0", "@esbuild/android-arm": "0.25.0", "@esbuild/android-arm64": "0.25.0", "@esbuild/android-x64": "0.25.0", "@esbuild/darwin-arm64": "0.25.0", "@esbuild/darwin-x64": "0.25.0", "@esbuild/freebsd-arm64": "0.25.0", "@esbuild/freebsd-x64": "0.25.0", "@esbuild/linux-arm": "0.25.0", "@esbuild/linux-arm64": "0.25.0", "@esbuild/linux-ia32": "0.25.0", "@esbuild/linux-loong64": "0.25.0", "@esbuild/linux-mips64el": "0.25.0", "@esbuild/linux-ppc64": "0.25.0", "@esbuild/linux-riscv64": "0.25.0", "@esbuild/linux-s390x": "0.25.0", "@esbuild/linux-x64": "0.25.0", "@esbuild/netbsd-arm64": "0.25.0", "@esbuild/netbsd-x64": "0.25.0", "@esbuild/openbsd-arm64": "0.25.0", "@esbuild/openbsd-x64": "0.25.0", "@esbuild/sunos-x64": "0.25.0", "@esbuild/win32-arm64": "0.25.0", "@esbuild/win32-ia32": "0.25.0", "@esbuild/win32-x64": "0.25.0" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -2193,7 +2193,7 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "tsup": ["tsup@8.3.6", "", { "dependencies": { "bundle-require": "^5.0.0", "cac": "^6.7.14", "chokidar": "^4.0.1", "consola": "^3.2.3", "debug": "^4.3.7", "esbuild": "^0.24.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.24.0", "source-map": "0.8.0-beta.0", "sucrase": "^3.35.0", "tinyexec": "^0.3.1", "tinyglobby": "^0.2.9", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-XkVtlDV/58S9Ye0JxUUTcrQk4S+EqlOHKzg6Roa62rdjL1nGWNUstG0xgI4vanHdfIpjP448J8vlN0oK6XOJ5g=="], + "tsup": ["tsup@8.4.0", "", { "dependencies": { "bundle-require": "^5.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", "esbuild": "^0.25.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", "source-map": "0.8.0-beta.0", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-b+eZbPCjz10fRryaAA7C8xlIHnf8VnsaRqydheLIqwG/Mcpfk8Z5zp3HayX7GaTygkigHl5cBUs+IhcySiIexQ=="], "tsutils": ["tsutils@3.21.0", "", { "dependencies": { "tslib": "^1.8.1" }, "peerDependencies": { "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA=="], @@ -2479,6 +2479,8 @@ "@vue/devtools-core/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "astro/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + "astro/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], "astro/vite": ["vite@6.1.1", "", { "dependencies": { "esbuild": "^0.24.2", "postcss": "^8.5.2", "rollup": "^4.30.1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA=="], @@ -2995,6 +2997,10 @@ "yaml-language-server/yaml": ["yaml@2.2.2", "", {}, "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA=="], + "@astrojs/react/vite/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + + "@astrojs/solid-js/vite/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + "@astrojs/starlight-tailwind/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "@astrojs/starlight-tailwind/tailwindcss/glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], @@ -3005,6 +3011,8 @@ "@astrojs/tailwind/tailwindcss/glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + "@astrojs/vue/vite/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], @@ -3021,6 +3029,62 @@ "@sv/svg-sprites/tsup/rollup": ["rollup@3.29.5", "", { "optionalDependencies": { "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w=="], + "@tailwindcss/vite/vite/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + + "@vitejs/plugin-vue/vite/esbuild": ["esbuild@0.24.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.24.2", "@esbuild/android-arm": "0.24.2", "@esbuild/android-arm64": "0.24.2", "@esbuild/android-x64": "0.24.2", "@esbuild/darwin-arm64": "0.24.2", "@esbuild/darwin-x64": "0.24.2", "@esbuild/freebsd-arm64": "0.24.2", "@esbuild/freebsd-x64": "0.24.2", "@esbuild/linux-arm": "0.24.2", "@esbuild/linux-arm64": "0.24.2", "@esbuild/linux-ia32": "0.24.2", "@esbuild/linux-loong64": "0.24.2", "@esbuild/linux-mips64el": "0.24.2", "@esbuild/linux-ppc64": "0.24.2", "@esbuild/linux-riscv64": "0.24.2", "@esbuild/linux-s390x": "0.24.2", "@esbuild/linux-x64": "0.24.2", "@esbuild/netbsd-arm64": "0.24.2", "@esbuild/netbsd-x64": "0.24.2", "@esbuild/openbsd-arm64": "0.24.2", "@esbuild/openbsd-x64": "0.24.2", "@esbuild/sunos-x64": "0.24.2", "@esbuild/win32-arm64": "0.24.2", "@esbuild/win32-ia32": "0.24.2", "@esbuild/win32-x64": "0.24.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA=="], + + "astro/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], + + "astro/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], + + "astro/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], + + "astro/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], + + "astro/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], + + "astro/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], + + "astro/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], + + "astro/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], + + "astro/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], + + "astro/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], + + "astro/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], + + "astro/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], + + "astro/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], + + "astro/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], + + "astro/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], + + "astro/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], + + "astro/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], + + "astro/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], + + "astro/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], + + "astro/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], + + "astro/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], + + "astro/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], + + "astro/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], + + "astro/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], + + "astro/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], + "boxen/string-width/emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="], "boxen/string-width/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], @@ -4779,6 +4843,106 @@ "yaml-language-server/vscode-languageserver/vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.16.0", "", { "dependencies": { "vscode-jsonrpc": "6.0.0", "vscode-languageserver-types": "3.16.0" } }, "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A=="], + "@astrojs/react/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], + + "@astrojs/react/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], + + "@astrojs/react/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], + + "@astrojs/react/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], + + "@astrojs/react/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], + + "@astrojs/react/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], + + "@astrojs/react/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], + + "@astrojs/react/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], + + "@astrojs/react/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], + + "@astrojs/react/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], + + "@astrojs/react/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], + + "@astrojs/react/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], + + "@astrojs/react/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], + + "@astrojs/react/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], + + "@astrojs/react/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], + + "@astrojs/react/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], + + "@astrojs/react/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], + + "@astrojs/react/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], + + "@astrojs/react/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], + + "@astrojs/react/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], + + "@astrojs/react/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], + + "@astrojs/react/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], + + "@astrojs/react/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], + + "@astrojs/react/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], + + "@astrojs/react/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], + + "@astrojs/solid-js/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], + "@astrojs/starlight-tailwind/tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "@astrojs/starlight-tailwind/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], @@ -4787,6 +4951,56 @@ "@astrojs/tailwind/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + "@astrojs/vue/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], + + "@astrojs/vue/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], + + "@astrojs/vue/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], + + "@astrojs/vue/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], + + "@astrojs/vue/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], + + "@astrojs/vue/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], + + "@astrojs/vue/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], + + "@astrojs/vue/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], + + "@astrojs/vue/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], + + "@astrojs/vue/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], + + "@astrojs/vue/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], + + "@astrojs/vue/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], + + "@astrojs/vue/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], + + "@astrojs/vue/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], + + "@astrojs/vue/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], + + "@astrojs/vue/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], + + "@astrojs/vue/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], + + "@astrojs/vue/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], + + "@astrojs/vue/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], + + "@astrojs/vue/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], + + "@astrojs/vue/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], + + "@astrojs/vue/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], + + "@astrojs/vue/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], + + "@astrojs/vue/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], + + "@astrojs/vue/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], + "@sv/svg-sprites/tsup/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "@sv/svg-sprites/tsup/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.17.19", "", { "os": "android", "cpu": "arm" }, "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A=="], @@ -4837,6 +5051,156 @@ "@sv/svg-sprites/tsup/postcss-load-config/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], + "@tailwindcss/vite/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], + + "@tailwindcss/vite/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], + + "@vitejs/plugin-vue-jsx/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.24.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.24.2", "", { "os": "android", "cpu": "arm" }, "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.24.2", "", { "os": "android", "cpu": "arm64" }, "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.24.2", "", { "os": "android", "cpu": "x64" }, "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.24.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.24.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.24.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.24.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.24.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.24.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.24.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.24.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.24.2", "", { "os": "linux", "cpu": "none" }, "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.24.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.24.2", "", { "os": "linux", "cpu": "x64" }, "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.24.2", "", { "os": "none", "cpu": "arm64" }, "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.24.2", "", { "os": "none", "cpu": "x64" }, "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.24.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.24.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.24.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.24.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.24.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA=="], + + "@vitejs/plugin-vue/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.24.2", "", { "os": "win32", "cpu": "x64" }, "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg=="], + "boxen/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], "colorspace/color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], diff --git a/docs/src/content/docs/elements/a-track.mdx b/docs/src/content/docs/elements/a-track.mdx index 965592e9e4ec80fcd26dbaeb44de881c307562d3..fc56023f891e4c64c0e2ac38d514bbead4896876 100644 --- a/docs/src/content/docs/elements/a-track.mdx +++ b/docs/src/content/docs/elements/a-track.mdx @@ -65,7 +65,6 @@ Implemented with [Slider](/atrium/components/slider) and [Drawer](/atrium/compon <TypeDoc source="../packages/elements/packages/track" symbol="Track" /> <TypeDoc source="../packages/elements/packages/track" symbol="Trait" /> -<TypeDoc source="../packages/elements/packages/track" symbol="PointerTrait" /> <TypeDoc source="../packages/elements/packages/track" symbol="SnapTrait" /> Different example confugrations of tracks. @@ -73,7 +72,7 @@ Different example confugrations of tracks. ### Free scroll <div class="not-content box"> - <a-track overflowscroll class="flex"> + <a-track class="flex overflow-visible"> <a href="#" class="block flex-none pr-4"> <canvas width="260" height="280" class="bg-slate-500" /> </a> @@ -110,7 +109,7 @@ Different example confugrations of tracks. ### Snap scroll <div class="not-content box"> - <a-track snap class="flex"> + <a-track snap class="flex overflow-visible"> <a href="#" class="block flex-none pr-4"> <canvas width="260" height="280" class="bg-slate-500" /> </a> @@ -159,7 +158,7 @@ Different example confugrations of tracks. ### Align center <div class="not-content box"> - <a-track align="center" snap class="flex"> + <a-track align="center" snap class="flex overflow-visible"> <a href="#" class="block flex-none pr-4"> <canvas width="260" height="280" class="bg-slate-500" /> </a> @@ -237,31 +236,31 @@ Different example confugrations of tracks. class="flex h-[450px] w-[250px] flex-col overflow-hidden" vertical align="center"> <div class="flex-none py-2 font-bold"> - <canvas width="200" height="80" class="bg-slate-500" /> + <canvas width="200" height="200" class="bg-slate-500" /> </div> <div class="flex-none py-2 font-bold"> - <canvas width="200" height="80" class="bg-slate-500" /> + <canvas width="200" height="200" class="bg-slate-500" /> </div> <div class="flex-none py-2 font-bold"> - <canvas width="200" height="80" class="bg-slate-500" /> + <canvas width="200" height="200" class="bg-slate-500" /> </div> <div class="flex-none py-2 font-bold"> - <canvas width="200" height="80" class="bg-slate-500" /> + <canvas width="200" height="200" class="bg-slate-500" /> </div> <div class="flex-none py-2 font-bold"> - <canvas width="200" height="80" class="bg-slate-500" /> + <canvas width="200" height="200" class="bg-slate-500" /> </div> <div class="flex-none py-2 font-bold"> - <canvas width="200" height="80" class="bg-slate-500" /> + <canvas width="200" height="200" class="bg-slate-500" /> </div> <div class="flex-none py-2 font-bold"> - <canvas width="200" height="80" class="bg-slate-500" /> + <canvas width="200" height="200" class="bg-slate-500" /> </div> <div class="flex-none py-2 font-bold"> - <canvas width="200" height="80" class="bg-slate-500" /> + <canvas width="200" height="200" class="bg-slate-500" /> </div> <div class="flex-none py-2 font-bold"> - <canvas width="200" height="80" class="bg-slate-500" /> + <canvas width="200" height="200" class="bg-slate-500" /> </div> </a-track> </div> @@ -291,33 +290,33 @@ track.addEventListener("format", e => { <canvas width="260" height="280" class="bg-slate-500" /> </div> <div class="flex-none pr-4"> - <a-track vertical snap class="flex h-[280px] flex-col overflow-hidden"> + <a-track align="center" vertical snap class="flex h-[280px] flex-col overflow-hidden"> <div class="flex-none pb-2 font-bold"> - <canvas width="200" height="64" class="bg-slate-500" /> + <canvas width="200" height="180" class="bg-slate-500" /> </div> <div class="flex-none pb-2 font-bold"> - <canvas width="200" height="64" class="bg-slate-500" /> + <canvas width="200" height="180" class="bg-slate-500" /> </div> <div class="flex-none pb-2 font-bold"> - <canvas width="200" height="64" class="bg-slate-500" /> + <canvas width="200" height="180" class="bg-slate-500" /> </div> <div class="flex-none pb-2 font-bold"> - <canvas width="200" height="64" class="bg-slate-500" /> + <canvas width="200" height="180" class="bg-slate-500" /> </div> <div class="flex-none pb-2 font-bold"> - <canvas width="200" height="64" class="bg-slate-500" /> + <canvas width="200" height="180" class="bg-slate-500" /> </div> <div class="flex-none pb-2 font-bold"> - <canvas width="200" height="64" class="bg-slate-500" /> + <canvas width="200" height="180" class="bg-slate-500" /> </div> <div class="flex-none pb-2 font-bold"> - <canvas width="200" height="64" class="bg-slate-500" /> + <canvas width="200" height="180" class="bg-slate-500" /> </div> <div class="flex-none pb-2 font-bold"> - <canvas width="200" height="64" class="bg-slate-500" /> + <canvas width="200" height="180" class="bg-slate-500" /> </div> <div class="flex-none pb-2 font-bold"> - <canvas width="200" height="64" class="bg-slate-500" /> + <canvas width="200" height="180" class="bg-slate-500" /> </div> </a-track> </div> diff --git a/docs/src/content/docs/elements/a-track/Track.tsx b/docs/src/content/docs/elements/a-track/Track.tsx index 79acbf19bdf2fa221a94657b57b3f4eff60b26c7..ac9692e1a62cb76beddec47988eb747ae6f4549e 100644 --- a/docs/src/content/docs/elements/a-track/Track.tsx +++ b/docs/src/content/docs/elements/a-track/Track.tsx @@ -52,7 +52,7 @@ export const VariableTrack = defineComponent(() => { /> </div> </div> - <a-track ref={track} overflowscroll snap class="flex max-w-[100vw]" debug> + <a-track ref={track} snap class="flex max-w-[100vw] overflow-visible" debug> {new Array(count.value || 1).fill(1).map((_, i) => { return ( <div class="counted flex-none pr-2" key={i}> diff --git a/docs/src/custom.css b/docs/src/custom.css index 4548f2a514270fe365602614edf4dad7661dc02b..a912e564312b1e9106e25a40161ef665ea31f45a 100644 --- a/docs/src/custom.css +++ b/docs/src/custom.css @@ -82,6 +82,7 @@ table { .not-content { counter-reset: content-counter; + overflow: hidden; } .counted { diff --git a/knope.toml b/knope.toml index 6e879236b436c368b802af81dd3a915323bcd7b0..31bfa316257f22ad071741c1b0786a24be2ce2b5 100644 --- a/knope.toml +++ b/knope.toml @@ -48,11 +48,6 @@ type = "Command" command = "task publish-packages" shell = true -[[workflows.steps]] -type = "Command" -command = "git push origin -o ci.skip && git push --tags" -shell = true - [[workflows]] name = "document-change" diff --git a/package.json b/package.json index 556691958836e6a8a3fb477c8c8f3c93a81fc559..600774d823bb88f5bd60cb6c43ac36c7a8dc2d82 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "@types/web": "^0.0.123", "fast-glob": "^3.3.2", "npm": "^10.7.0", - "tsup": "^8.1.0", + "tsup": "^8.4.0", "turbo": "^2.0.1" }, "packageManager": "bun@1.1.12", diff --git a/packages/components/src/vue/Drawer.tsx b/packages/components/src/vue/Drawer.tsx index 0dc84ac5633522d787fb4a923caac99865964cb2..89f106a83ad360b65c33d3a67d089d47bc7665cc 100644 --- a/packages/components/src/vue/Drawer.tsx +++ b/packages/components/src/vue/Drawer.tsx @@ -1,12 +1,6 @@ /* @jsxImportSource vue */ import { defineComponent, ref, onMounted, effect, nextTick } from "vue"; -import { - PointerTrait, - Track, - type InputState, - type Easing, - type Trait, -} from "@sv/elements/track"; +import { Track, type InputState, type Easing, type Trait } from "@sv/elements/track"; import { Button } from "./Button"; import { Icon } from "./Icon"; @@ -121,7 +115,6 @@ export const Drawer = defineComponent( export class DrawerTrack extends Track { public traits: Trait[] = [ - new PointerTrait(), { id: "drawer", input(track: DrawerTrack, inputState: InputState) { @@ -139,7 +132,7 @@ export class DrawerTrack extends Track { if (track.deltaVelocity.y >= 0) return; if (track.isStatic) return; - const vel = Math.round(track.lastVelocity[track.currentAxis] * 10) / 10; + const vel = Math.round(track.velocity[track.currentAxis] * 10) / 10; const power = Math.round(vel / 15); if (power < 0) { diff --git a/packages/components/src/vue/Tabs.tsx b/packages/components/src/vue/Tabs.tsx index 94631e248c34fcfd89efbfcedec75834facebbe0..800e659053a7e8d828e6af84981c768054022caf 100644 --- a/packages/components/src/vue/Tabs.tsx +++ b/packages/components/src/vue/Tabs.tsx @@ -20,7 +20,7 @@ export const Tabs = defineComponent( return () => ( <div class="w-full p-1"> - <a-track overflowscroll> + <a-track> <ul class="flex list-none gap-1 p-0"> {slots.default?.()?.map((item, i) => { return ( diff --git a/packages/elements/CHANGELOG.md b/packages/elements/CHANGELOG.md index 035d321656356461b390aef49262d131713280a8..dac9795ed10c4fc317650ddd35900ad5862bb280 100644 --- a/packages/elements/CHANGELOG.md +++ b/packages/elements/CHANGELOG.md @@ -1,5 +1,63 @@ # @sv/elements +## 0.0.1-dev.3 (2025-03-09) + +### Fixes + +- package version + +## 0.0.1-dev.2 (2025-03-09) + +### Fixes + +- Grab wont allow clicking on items + +## 0.0.1-dev.1 (2025-03-09) + +### Fixes + +- Grab wont allow clicking on items + +## 0.0.1-dev.0 (2025-03-09) + +### Fixes + +- Grab wont allow clicking on items + +## 2.4.2-dev.3 (2025-03-08) + +### Fixes + +- Improve track behaviour on different variable hardware +- Fix check +- Bug whre snap with align center did not snap to the last item +- Grab wont allow clicking on items + +## 2.4.2-dev.2 (2025-03-08) + +### Fixes + +- Improve track behaviour on different variable hardware +- Fix check +- Bug whre snap with align center did not snap to the last item +- Grab wont allow clicking on items + +## 2.4.2-dev.1 (2025-03-08) + +### Fixes + +- Improve track behaviour on different variable hardware +- Fix check +- Bug whre snap with align center did not snap to the last item + +## 2.4.2-dev.0 (2025-03-08) + +### Fixes + +- Improve track behaviour on different variable hardware +- Fix check +- Bug whre snap with align center did not snap to the last item + ## 2.4.1 (2025-03-04) ### Fixes diff --git a/packages/elements/package.json b/packages/elements/package.json index 1425f81f47dc952add4df1914704da9881204730..1398670110aebe79f1f432cc862efe498c841113 100644 --- a/packages/elements/package.json +++ b/packages/elements/package.json @@ -4,12 +4,12 @@ "contributors": [ "luckydye" ], - "version": "2.4.1", + "version": "2.4.2-dev.4", "description": "Atrium Elements", "type": "module", "scripts": { "check": "tsc --pretty", - "test": "bun test --rerun-each 5", + "test": "bun test --rerun-each 3 --coverage", "publish-package": "task publish" }, "files": [ @@ -132,4 +132,4 @@ "types": "./packages/box/src/index.ts" } } -} \ No newline at end of file +} diff --git a/packages/elements/packages/track/src/Track.ts b/packages/elements/packages/track/src/Track.ts index dba6ca729230a8dccdcb18fa851a3e9d975c47f9..d70b47886a93dde2aec791a4fcd2079a3a754150 100644 --- a/packages/elements/packages/track/src/Track.ts +++ b/packages/elements/packages/track/src/Track.ts @@ -1,6 +1,51 @@ import { LitElement, type PropertyValues, css, html } from "lit"; import { property } from "lit/decorators/property.js"; -import { Vec2 } from "./Vec.js"; +// import { DebugTrait } from "./debug.js"; + +const PI2 = Math.PI * 2; + +export class MoveEvent extends CustomEvent<{ + delta: Vec2; + direction: Vec2; + velocity: Vec2; + position: Vec2; +}> { + constructor(track: Track, delta: Vec2) { + super("move", { + cancelable: true, + detail: { + delta: delta, + direction: track.direction.clone(), + velocity: track.deltaPosition.clone(), + position: track.position.clone(), + }, + }); + } +} + +export type InputState = { + grab: { + value: boolean; + }; + scroll: { + value: boolean; + }; + move: { + value: Vec2; + }; + release: { + value: boolean; + }; + format: { + value: boolean; + }; + leave: { + value: boolean; + }; + enter: { + value: boolean; + }; +}; /** * The Track implements a trait system, which can be used to add new behaviours to the track. @@ -10,11 +55,10 @@ import { Vec2 } from "./Vec.js"; * Or the Track class can be extended to override add new behaviours entirely. * @example * ```js - * import { type InputState, PointerTrait, Track, type Trait } from "@sv/elements/track"; + * import { type InputState, Track, type Trait } from "@sv/elements/track"; * * export class CustomTrack extends Track { * public traits: Trait[] = [ - * new PointerTrait(), * // satefies the "Trait" interface * { * id: "custom-trait", @@ -48,149 +92,9 @@ export interface Trait<T extends Track = Track> { /** update tick (fixed tickrate) */ update?(track: T): void; -} - -/** - * The PointerTrait addes the ability to move the track with the mouse or touch inputs by dragging. - * - * @example - * ```js - * new PointerTrait({ - * borderBounce?: number; - * borderResistance?: number; - * }) - * ``` - */ -export class PointerTrait implements Trait { - id = "pointer"; - - grabbing = false; - grabbedStart = new Vec2(); - grabDelta = new Vec2(); - - borderBounce = 0.1; - borderResistance = 0.3; - - moveDrag = 0.5; - - constructor( - options: { - borderBounce?: number; - borderResistance?: number; - } = {}, - ) { - this.borderBounce = options.borderBounce ?? this.borderBounce; - this.borderResistance = options.borderResistance ?? this.borderResistance; - } - - moveVelocity = new Vec2(); - - input(track: Track, inputState: InputState) { - if (inputState.grab.value && !this.grabbing) { - this.grabbing = true; - this.grabbedStart.set(track.mousePos); - track.dispatchEvent(new Event("pointer:grab")); - track.setTarget(undefined); - } - - if (track.mousePos.abs()) { - this.grabDelta.set(track.mousePos).sub(this.grabbedStart); - } - - // TODO: might want to give every trait a "inputForce", so I dont have to mutate the tracks fields. - if (this.grabbing) { - if (inputState.move.value.abs()) { - this.moveVelocity.add(inputState.move.value); - track.inputForce.set(inputState.move.value.clone().mul(-1)); - } else { - track.inputForce.mul(0); - } - } - - if (inputState.release.value) { - this.grabbing = false; - track.dispatchEvent(new Event("pointer:release")); - - track.inputForce.set(this.moveVelocity.clone().mul(-1)); - } - - // prevent moving in wrong direction - if (track.vertical) { - track.inputForce.x = 0; - } else { - track.inputForce.y = 0; - } - - if (track.slotElement) { - track.slotElement.inert = this.grabbing; - } - if (!isTouch()) track.style.cursor = this.grabbing ? "grabbing" : ""; - } - - update(track: Track) { - this.moveVelocity.mul(this.moveDrag); - - if (this.grabbing) { - track.drag = 0; - } else { - track.drag = 0.95; - } - - // clamp input force - const pos = Vec2.add(track.position, track.inputForce); - const clamped = this.getClapmedPosition(track, pos); - const diff = Vec2.sub(pos, clamped); - - if (!track.loop && diff.abs() && this.grabbing) { - const resitance = this.borderResistance * (1 - diff.abs() / 200); - - if (track.vertical) { - track.inputForce.mul(resitance); - } else { - track.inputForce.mul(resitance); - } - } - - const bounce = this.borderBounce; - if (!track.loop && bounce && diff.abs() && !this.grabbing) { - if ((track.vertical && Math.abs(diff.y)) || Math.abs(diff.x)) { - track.inputForce.sub(diff.mul(bounce)); - track.acceleration.mul(0); - } - } - } - - getClapmedPosition(e: Track, pos: Vec2) { - let clampedPos = pos; - - const bounds = e.scrollBounds; - - switch (e.align) { - case "center": - clampedPos = new Vec2( - Math.min(bounds.right, clampedPos.x), - Math.min(bounds.bottom, clampedPos.y), - ); - clampedPos = new Vec2( - Math.max(bounds.left, clampedPos.x), - Math.max(bounds.top, clampedPos.y), - ); - break; - default: - clampedPos = new Vec2( - Math.min(bounds.right, clampedPos.x), - Math.min(bounds.bottom, clampedPos.y), - ); - clampedPos = new Vec2( - Math.max(bounds.left, clampedPos.x), - Math.max(bounds.top, clampedPos.y), - ); - break; - } - - return clampedPos; - } + /** draw (variable tickrate) */ + draw?(track: T): void; } /** @@ -215,10 +119,11 @@ export class SnapTrait implements Trait { } input(track: Track) { - if (track.grabbing || track.target) return; + if (track.interacting || track.target) return; - // Only when decelerating - if (track.deltaVelocity[track.currentAxis] > 0) return; + // only when decelerating, but also when not moving + const movement = track.velocity.clone().precision(0.1).abs(); + if (movement !== 0 && movement < 0.1) return; switch (track.align) { case "center": @@ -235,24 +140,31 @@ export class SnapTrait implements Trait { } // Project the current velocity to determine the target item. - // This checks lastVelocity, because I don't know why velocity is 0,0 at random points. - const vel = Math.round(track.lastVelocity[track.currentAxis] * 10) / 10; + const vel = Math.round(track.velocity[track.currentAxis] * 10) / 10; const dir = Math.sign(vel); - const power = Math.max(Math.round(track.lastVelocity.abs() / 40), 1) * dir; + const power = Math.max(Math.round(track.velocity.abs() / 40), 1) * dir; if (!track.loop) { // disable snap when past maxIndex - if (track.maxIndex && power > 0 && track.currentIndex + power >= track.maxIndex) + if (track.maxIndex && power > 0 && track.currentIndex + power > track.maxIndex) { + // instead, snap to the end + track.setTarget(track.getToItemPosition(track.itemCount - 1), "linear"); return; + } } if (Math.abs(vel) > 8) { + // apply inertia to snap target track.acceleration.mul(0.25); track.inputForce.mul(0.125); track.setTarget(track.getToItemPosition(track.currentItem + power), "linear"); } else { track.setTarget(track.getToItemPosition(track.currentItem), "linear"); } + + if (!track.target) { + throw new Error("Track target not set, but snap"); + } } } @@ -298,24 +210,24 @@ function getCSSChildren(element: Element) { * */ export class Track extends LitElement { - static Vec2 = Vec2; - static get styles() { return css` :host { display: flex; outline: none; overflow: hidden; + touch-action: pan-y; + overscroll-behavior: none; + scrollbar-width: none; } - - .debug { - position: absolute; - z-index: 100; - background: rgba(0, 0, 0, 0.5); - backdrop-filter: blur(4px); + :host([vertical]) { + flex-direction: column; + } + :host([vertical]) { + touch-action: pan-x; } - slot { + will-change: transform; display: inherit; flex-direction: inherit; flex-flow: inherit; @@ -324,33 +236,84 @@ export class Track extends LitElement { will-change: transform; min-width: 100%; } - - :host([vertical]) { - flex-direction: column; - } - - :host { - touch-action: pan-y; - } - - :host([vertical]) { - touch-action: pan-x; - } - - :host { - overscroll-behavior: none; - scrollbar-width: none; - } - ::-webkit-scrollbar { width: 0px; height: 0px; background: transparent; display: none; } + .debug { + position: absolute; + z-index: 10; + pointer-events: none; + } `; } + constructor() { + super(); + + // TODO: put this in a trait so it can be disabled + // TODO: sync it to screen? + this.addEventListener("wheel", this.onWheel, { passive: false }); + + this.addEventListener("focusin", this.onFocusIn); + + this.addEventListener("keydown", this.onKeyDown); + + this.addEventListener("pointerdown", this.onPointerDown); + + this.addEventListener("pointerleave", () => { + this.inputState.leave.value = true; + }); + + this.addEventListener("pointerenter", () => { + this.inputState.enter.value = true; + }); + } + + connectedCallback(): void { + super.connectedCallback(); + + this.updateItems(); + + this.ariaRoleDescription = "carousel"; + this.role = "region"; + + this.listener(window, "pointermove", this.onPointerMove); + this.listener(window, ["pointerup", "pointercancel"], this.onPointerUpOrCancel); + + const intersectionObserver = new IntersectionObserver((intersections) => { + for (const entry of intersections) { + if (entry.isIntersecting) { + this.startAnimate(); + } else { + this.stopAnimate(); + } + } + }); + + this.addController({ + hostConnected: () => intersectionObserver.observe(this), + hostDisconnected: () => intersectionObserver.disconnect(), + }); + + // TODO: diff the container size and appliy to position of track + this.resizeObserver = new ResizeObserver(debounce(() => this.onFormat())); + + this.addController({ + hostConnected: () => this.resizeObserver?.observe(this), + hostDisconnected: () => this.resizeObserver?.disconnect(), + }); + + this.computeCurrentItem(); + } + + disconnectedCallback(): void { + this.stopAnimate(); + super.disconnectedCallback(); + } + render() { return html` <slot @slotchange=${this.onSlotChange}></slot> @@ -362,7 +325,9 @@ export class Track extends LitElement { return this.shadowRoot?.children?.[0] as HTMLSlotElement | undefined; } - public traits: Trait[] = [new PointerTrait()]; + public traits: Trait[] = [ + // new DebugTrait() + ]; protected updated(_changedProperties: PropertyValues): void { if (_changedProperties.has("current") && this.current !== undefined) { @@ -379,7 +344,7 @@ export class Track extends LitElement { } if (_changedProperties.has("align")) { - this.format(); + this.onFormat(); } } @@ -391,7 +356,7 @@ export class Track extends LitElement { private updateItems() { this._children = getCSSChildren(this); - this.format(); + this.onFormat(); } public get itemCount() { @@ -408,29 +373,6 @@ export class Track extends LitElement { .map((_, i) => new Vec2(this.itemWidths[i], this.itemHeights[i])); } - /** - * Get the absolute position of the closest item to the current position. - * @argument offset - offset the position by a number - */ - public getClosestItemPosition(offset = 0) { - const posPrev = this.getToItemPosition(this.currentItem + -offset); - const posCurr = this.getToItemPosition(this.currentItem + offset); - const posNext = this.getToItemPosition(this.currentItem + (offset + 1)); - - const prev = posPrev.clone().sub(this.position).abs(); - const curr = posCurr.clone().sub(this.position).abs(); - const next = posNext.clone().sub(this.position).abs(); - - switch (Math.min(curr, next, prev)) { - case prev: - return posPrev; - case next: - return posNext; - default: - return posCurr; - } - } - private _widths: number[] | undefined = undefined; private get itemWidths() { if (!this._widths) { @@ -500,8 +442,6 @@ export class Track extends LitElement { return this.overflowWidth > 0 || this.overflowHeight > 0; } - public currentItem = 0; - public get currentIndex() { return this.currentItem % this.itemCount; } @@ -511,6 +451,10 @@ export class Track extends LitElement { } public get maxIndex() { + if (this.overflow === "ignore") { + return this.itemCount - 1; + } + if (this.align === "start") { // get index of item at the end of the track if (this.vertical) { @@ -535,6 +479,24 @@ export class Track extends LitElement { return 0; } + public get trackSize() { + return this.vertical ? this.trackHeight : this.trackWidth; + } + + public get currentAngle() { + return (this.currentPosition / this.trackSize) * Math.PI * 2; + } + + public get originAngle() { + return (this.origin[this.currentAxis] / this.trackSize || 0) * PI2; + } + + public get targetAngle() { + return this.target ? (this.target.x / this.trackSize) * PI2 : undefined; + } + + public itemAngles: number[] = []; + private getScrollBounds() { let stopTop = 0; let stopLeft = 0; @@ -572,39 +534,91 @@ export class Track extends LitElement { }; } - scrollBounds = { - top: 0, - left: 0, - bottom: 0, - right: 0, - }; + private toClapmedPosition(pos: Vec2) { + let clampedPos = pos; + + const bounds = this.scrollBounds; + + switch (this.align) { + case "center": + clampedPos = new Vec2( + Math.min(bounds.right, clampedPos.x), + Math.min(bounds.bottom, clampedPos.y), + ); + clampedPos = new Vec2( + Math.max(bounds.left, clampedPos.x), + Math.max(bounds.top, clampedPos.y), + ); + break; + default: + clampedPos = new Vec2( + Math.min(bounds.right, clampedPos.x), + Math.min(bounds.bottom, clampedPos.y), + ); + clampedPos = new Vec2( + Math.max(bounds.left, clampedPos.x), + Math.max(bounds.top, clampedPos.y), + ); + break; + } + + return clampedPos; + } + + private scrollBounds = { + top: 0, + left: 0, + bottom: 0, + right: 0, + }; private animation: number | undefined; - private tickRate = 1000 / 144; + private tickRate = 1000 / 120; private lastTick = 0; private accumulator = 0; + public currentItem = 0; + public grabbing = false; + public mouseDown = false; public mousePos = new Vec2(); + + // Force applied to the acceleration every frame public inputForce = new Vec2(); public drag = 0.95; public origin = new Vec2(); public position = new Vec2(); + + public moveDrag = 0.5; + + public borderBounce = 0.1; + public borderResistance = 0.3; + + public moveVelocity = new Vec2(); + + // Delta of position compared to the last frame + public deltaPosition = new Vec2(); + + // Average velocity over multiple frames public velocity = new Vec2(); + + // Delta of velocity compared to the last frame + public deltaVelocity = new Vec2(); + + // Direction of the inputForce public direction = new Vec2(); + + // Acceleration that is applied to the position every frame public acceleration = new Vec2(); - public lastVelocity = new Vec2(); - private lastPosition = new Vec2(); public target?: Vec2; public targetEasing: Easing = "linear"; private targetForce = new Vec2(); private targetStart = new Vec2(); - public transitionTime = 350; - + public transitionTime = 420; private transitionAt = 0; private transition = 0; @@ -632,6 +646,30 @@ export class Track extends LitElement { }, }; + /** The index of the current item. */ + @property({ type: Number, reflect: true }) public current: number | undefined; + + /** Whether the track should scroll vertically, instead of horizontally. */ + @property({ type: Boolean, reflect: true }) public vertical = false; + + /** Whether the track should loop back to the start when reaching the end. */ + @property({ type: Boolean, reflect: true }) public loop = false; + + /** Whether the track should snap to the closest child element. */ + @property({ type: Boolean, reflect: true }) public snap = false; + + /** Item alignment in the track. "start" (left/top) or "center" */ + @property({ type: String }) public align: "start" | "center" = "start"; + + /** Change the overflow behavior. + * - "auto" - Only scrollable when necessary. + * - "scroll" - Always scrollable. + * - "ignore" - Ignore any overflow. + */ + @property({ type: String }) public overflow: "auto" | "scroll" | "ignore" = "auto"; + + @property({ type: Boolean }) public debug = false; + private trait(callback: (t: Trait) => void) { for (const t of this.traits) { try { @@ -662,29 +700,6 @@ export class Track extends LitElement { return undefined; } - /** The index of the current item. */ - @property({ type: Number, reflect: true }) current: number | undefined; - - /** Whether the track should scroll vertically, instead of horizontally. */ - @property({ type: Boolean, reflect: true }) vertical = false; - - /** Whether the track should loop back to the start when reaching the end. */ - @property({ type: Boolean, reflect: true }) loop = false; - - /** Whether the track should snap to the closest child element. */ - @property({ type: Boolean, reflect: true }) snap = false; - - /** Item alignment in the track. "start" (left/top) or "center" */ - @property({ type: String }) align: "start" | "center" = "start"; - - /** Change the overflow behavior. - * - "auto" - Only scrollable when necessary. - * - "scroll" - Always scrollable. - */ - @property({ type: String }) overflow: "auto" | "scroll" = "auto"; - - @property({ type: Boolean }) debug = false; - private observedChildren = new Set<Node>(); private onSlotChange = () => { @@ -709,43 +724,28 @@ export class Track extends LitElement { } }; - private format = () => { - this.inputState.format.value = true; - this._width = undefined; - this._height = undefined; - this._widths = undefined; - this._heights = undefined; - - // apply align prop - switch (this.align) { - case "start": - this.origin.set([0, 0]); - break; - case "center": - if (this.vertical) { - this.origin.set([0, -this.height / 2]); - } else { - this.origin.set([-this.width / 2, 0]); - } - break; - } - - this.scrollBounds = this.getScrollBounds(); - - const formatEvent = new CustomEvent("format", { - bubbles: true, - cancelable: true, - }); - this.dispatchEvent(formatEvent); + /** + * Get the absolute position of the closest item to the current position. + * @argument offset - offset the position by a number + */ + public getClosestItemPosition(offset = 0) { + const posPrev = this.getToItemPosition(this.currentItem + -offset); + const posCurr = this.getToItemPosition(this.currentItem + offset); + const posNext = this.getToItemPosition(this.currentItem + (offset + 1)); - if (!formatEvent.defaultPrevented) { - this.trait((t) => t.format?.(this)); + const prev = posPrev.clone().sub(this.position).abs(); + const curr = posCurr.clone().sub(this.position).abs(); + const next = posNext.clone().sub(this.position).abs(); - if (this.position.x > this.overflowWidth || this.position.y > this.overflowHeight) { - this.setTarget(undefined); - } + switch (Math.min(curr, next, prev)) { + case prev: + return posPrev; + case next: + return posNext; + default: + return posCurr; } - }; + } /** * Get the index of the item that contains given element. Returns -1 if it is not in any item. @@ -871,12 +871,11 @@ export class Track extends LitElement { const deltaTick = ms - this.lastTick; this.lastTick = ms; - this.accumulator += deltaTick; - const lastPosition = this.position.clone(); + this.trait((t) => t.draw?.(this)); - this.updateInputs(); + const lastPosition = this.position.clone(); let ticks = 0; const maxTicks = 10; @@ -887,6 +886,8 @@ export class Track extends LitElement { this.updateTick(); } + this.updateInputs(); + const deltaPosition = Vec2.sub(this.position, lastPosition); const currItem = this.getCurrentItem(); @@ -928,30 +929,102 @@ export class Track extends LitElement { private updateInputs() { this.trait((t) => t.input?.(this, this.inputState)); + if (this.inputState.grab.value === true) { + // grab change + this.grabbing = true; + this.dispatchEvent(new Event("pointer:grab")); + this.setTarget(undefined); + } + + if (this.grabbing) { + if (this.inputState.move.value.abs()) { + this.moveVelocity.add(this.inputState.move.value); + this.inputForce.set(this.inputState.move.value.clone().mul(-1)); + } else { + this.inputForce.mul(0); + } + } + + if (this.inputState.release.value) { + this.grabbing = false; + this.dispatchEvent(new Event("pointer:release")); + + this.inputForce.set(this.moveVelocity.clone().mul(-1)); + } + + // prevent moving in wrong direction + if (this.vertical) { + this.inputForce.x = 0; + } else { + this.inputForce.y = 0; + } + + if (this.slotElement) { + this.slotElement.inert = this.grabbing; + } + if (!isTouch()) this.style.cursor = this.grabbing ? "grabbing" : ""; + this.direction.add(this.inputForce).sign(); // clear const state = this.inputState; state.move.value.mul(0); state.grab.value = false; + state.scroll.value = false; state.format.value = false; state.leave.value = false; state.enter.value = false; state.release.value = false; } - public get deltaVelocity() { - return Vec2.sub(this.velocity.abs(), this.lastVelocity.abs()); + public get interacting() { + return this.inputForce.abs() > 0.5 || this.mouseDown; } private updateTick() { - this.lastPosition = this.position.clone(); - this.lastVelocity = this.velocity.clone(); + const lastPosition = this.position.clone(); + const lastVelocity = this.velocity.clone(); - this.acceleration.mul(this.drag); + this.velocity = Vec2.add(this.velocity.clone().mul(0.5), this.deltaPosition); + this.deltaVelocity = Vec2.sub(this.velocity, lastVelocity); this.trait((t) => t.update?.(this)); + const interacting = this.target || this.interacting; + + this.moveVelocity.mul(this.moveDrag); + + // clamp input force + const pos = Vec2.add(this.position, this.inputForce); + const clamped = this.toClapmedPosition(pos); + const diff = Vec2.sub(pos, clamped); + + if (interacting) { + this.drag = 0; + + if (!this.loop && diff.abs()) { + const resitance = this.borderResistance * (1 - diff.abs() / 200); + + if (this.vertical) { + this.inputForce.mul(resitance); + } else { + this.inputForce.mul(resitance); + } + } + } else { + this.drag = 0.95; + + const bounce = this.borderBounce; + if (!this.loop && bounce && diff.abs()) { + if ((this.vertical && Math.abs(diff.y)) || Math.abs(diff.x)) { + this.inputForce.sub(diff.mul(bounce)); + this.acceleration.mul(0); + } + } + } + + this.acceleration.mul(this.drag); + this.acceleration.add(this.inputForce); this.inputForce.mul(0); @@ -1029,34 +1102,21 @@ export class Track extends LitElement { this.position.add(this.targetForce); this.targetForce.set(0); - this.velocity = Vec2.sub(this.position, this.lastPosition); + this.deltaPosition = Vec2.sub(this.position, lastPosition); } - debugCanvas = document.createElement("canvas"); + public debugCanvas = document.createElement("canvas"); private getCurrentItem() { - let ctx: CanvasRenderingContext2D | null = null; - if (this.debug) { - ctx = this.debugCanvas.getContext("2d"); - ctx?.translate(0.5, 0.5); - this.debugCanvas.width = 200; - this.debugCanvas.height = 200; - this.debugCanvas.style.width = "100px"; - this.debugCanvas.style.height = "100px"; - } - - const trackSize = this.vertical ? this.trackHeight : this.trackWidth; - const currentAngle = (this.currentPosition / trackSize) * Math.PI * 2; + const trackSize = this.trackSize; + const currentAngle = this.currentAngle; let minDist = Number.POSITIVE_INFINITY; - let closestAngle = 0; let closestIndex = 0; const rects = this.getItemRects(); - const PI2 = Math.PI * 2; - - const originAngle = (this.origin[this.currentAxis] / trackSize || 0) * PI2; + const originAngle = this.originAngle; const axes = this.vertical ? 1 : 0; // all items angles @@ -1065,6 +1125,8 @@ export class Track extends LitElement { return acc; }, [] as number[]); + this.itemAngles = []; + for (let i = -1; i < this.itemCount + 1; i++) { const itemIndex = i % this.itemCount; const rect = rects[itemIndex]; @@ -1087,15 +1149,7 @@ export class Track extends LitElement { itemAngle += (angles[Math.min(lastIndex + 1, this.currentIndex)] || 0) / 2; } - if (this.debug && ctx) { - // draw a line from the center to the current position with angle - ctx.strokeStyle = `hsl(0, 0%, ${(i / this.itemCount) * 100}%)`; - ctx.beginPath(); - ctx.moveTo(100, 100); - ctx.lineTo(100 + Math.cos(itemAngle) * 69, 100 + Math.sin(itemAngle) * 69); - ctx.lineWidth = 3; - ctx.stroke(); - } + this.itemAngles[itemIndex] = itemAngle; const deltaAngle = angleDist(itemAngle, currentAngle); @@ -1107,79 +1161,9 @@ export class Track extends LitElement { if (currentAngle > PI2 / 2) { closestIndex += offset; } - - closestAngle = itemAngle; } } - if (this.debug && ctx) { - // draw a line from the center to the current position with angle - ctx.fillStyle = "rgba(255, 0, 0, 0.5)"; - ctx.beginPath(); - ctx.moveTo(100, 100); - ctx.lineTo( - 100 + Math.cos(currentAngle + originAngle) * 69, - 100 + Math.sin(currentAngle + originAngle) * 69, - ); - ctx.arc( - 100, - 100, - 69, - currentAngle + originAngle, - currentAngle + originAngle + (this.width / trackSize) * PI2, - ); - ctx.lineTo(100, 100); - ctx.fill(); - - // print current position - ctx.font = "24px sans-serif"; - ctx.fillStyle = "#fff"; - ctx.textAlign = "left"; - ctx.textBaseline = "middle"; - ctx.fillText( - `${this.currentPosition.toFixed(1)} / ${trackSize.toFixed(1)}`, - 42, - 18, - ); - - // print current position index - ctx.font = "24px sans-serif"; - ctx.fillStyle = "#fff"; - ctx.textAlign = "left"; - ctx.textBaseline = "middle"; - ctx.fillText(closestIndex.toString(), 6, 18); - - // draw a line from the center to the current position with angle - ctx.strokeStyle = "yellow"; - ctx.beginPath(); - ctx.moveTo(100, 100); - ctx.lineTo(100 + Math.cos(closestAngle) * 69, 100 + Math.sin(closestAngle) * 69); - ctx.lineWidth = 3; - ctx.stroke(); - - const targetAngle = this.target ? (this.target.x / trackSize) * PI2 : undefined; - - if (targetAngle) { - // draw a line from the center to the current position with angle - ctx.strokeStyle = "blue"; - ctx.beginPath(); - ctx.moveTo(100, 100); - ctx.lineTo(100 + Math.cos(closestAngle) * 50, 100 + Math.sin(closestAngle) * 50); - ctx.lineWidth = 3; - ctx.stroke(); - } - } - - if (this.debug && ctx) { - // draw a line from the center to the current position with angle - ctx.strokeStyle = "lime"; - ctx.beginPath(); - ctx.moveTo(100, 100); - ctx.lineTo(100 + Math.cos(originAngle) * 69, 100 + Math.sin(originAngle) * 69); - ctx.lineWidth = 3; - ctx.stroke(); - } - return closestIndex; } @@ -1281,6 +1265,15 @@ export class Track extends LitElement { private resizeObserver?: ResizeObserver; + private canMove(delta: Vec2) { + if (this.overflow === "auto" && !this.hasOverflow) { + // respect overflowscroll + return false; + } + + return this.dispatchEvent(new MoveEvent(this, delta)); + } + listener<T extends Event>( host: HTMLElement | typeof globalThis, events: string | string[], @@ -1298,247 +1291,184 @@ export class Track extends LitElement { } } - private canMove(delta: Vec2) { - if (this.overflow === "auto" && !this.hasOverflow) { - // respect overflowscroll - return false; - } - - return this.dispatchEvent(new MoveEvent(this, delta)); - } - - connectedCallback(): void { - super.connectedCallback(); - - this.updateItems(); - - this.ariaRoleDescription = "carousel"; - this.role = "region"; + private onFormat = () => { + this.inputState.format.value = true; + this._width = undefined; + this._height = undefined; + this._widths = undefined; + this._heights = undefined; - this.listener(this, "focusin", (e: FocusEvent) => { - const item = this.elementItemIndex(e.target as HTMLElement); - const dist = Vec2.dist2(this.getToItemPosition(item), this.position); - const rect = this.getItemRects()[item]; + // apply align prop + switch (this.align) { + case "start": + this.origin.set([0, 0]); + break; + case "center": + if (this.vertical) { + this.origin.set([0, -this.height / 2]); + } else { + this.origin.set([-this.width / 2, 0]); + } + break; + } - if (!rect) return; + this.scrollBounds = this.getScrollBounds(); - if ( - dist.x + rect.x > this.width || - dist.x < 0 || - dist.y + rect.y > this.height || - dist.y < 0 - ) { - this.moveTo(item); - } + const formatEvent = new CustomEvent("format", { + bubbles: true, + cancelable: true, }); + this.dispatchEvent(formatEvent); - this.listener(this, "keydown", (e: KeyboardEvent) => { - const Key = { - prev: this.vertical ? "ArrowUp" : "ArrowLeft", - next: this.vertical ? "ArrowDown" : "ArrowRight", - }; + if (!formatEvent.defaultPrevented) { + this.trait((t) => t.format?.(this)); - if (e.key === Key.prev) { - this.moveBy(-1, "linear"); - e.preventDefault(); - } - if (e.key === Key.next) { - this.moveBy(1, "linear"); - e.preventDefault(); + if (this.position.x > this.overflowWidth || this.position.y > this.overflowHeight) { + this.setTarget(undefined); } - }); + } + }; - this.listener(this, "pointerdown", (e: PointerEvent) => { - if (e.button !== 0) return; // only left click + public scrollDebounce?: Timer; - // Try to focus this element when clicked on for arrow key navigation, - // will only work when tabindex=0. - this.focus(); + private onWheel = (wheelEvent: WheelEvent) => { + // TODO: if there is a tick without a scroll event, it will jitter + if (wheelEvent.ctrlKey === true) { + // its a pinch zoom gesture + return; + } - this.mousePos.x = e.x; - this.mousePos.y = e.y; + const delta = new Vec2(wheelEvent.deltaX, wheelEvent.deltaY); - this.setTarget(undefined); - this.acceleration.set(0); + if (!this.canMove(delta)) return; - e.preventDefault(); - e.stopPropagation(); - }); + const deltaThreshold = Vec2.abs(delta); + const axisThreshold = this.vertical + ? Math.abs(delta.x) < Math.abs(delta.y) + : Math.abs(delta.x) > Math.abs(delta.y); - this.listener(this, "pointerleave", () => { - this.inputState.leave.value = true; - }); + if (axisThreshold) { + wheelEvent.preventDefault(); + } - this.listener(this, "pointerenter", () => { - this.inputState.enter.value = true; - }); + if (axisThreshold && deltaThreshold > 2) { + this.setTarget(undefined); - this.listener(window, "pointermove", (pointerEvent: PointerEvent) => { - const pos = new Vec2(pointerEvent.x, pointerEvent.y); - const delta = Vec2.sub(pos, this.mousePos); + this.inputState.scroll.value = true; - if (!this.canMove(delta)) return; + if ( + this.position.x < this.scrollBounds.left - 20 || + this.position.y < this.scrollBounds.top - 20 || + this.position.x > this.scrollBounds.right + 20 || + this.position.y > this.scrollBounds.bottom + 20 || + this.scrollDebounce + ) { + clearTimeout(this.scrollDebounce); + this.scrollDebounce = setTimeout(() => { + this.scrollDebounce = undefined; + }, 32); - if (!this.grabbing && delta.abs() > 3) { - if (this.vertical && this.mousePos.y && Math.abs(delta.x) < Math.abs(delta.y)) { - this.grabbing = true; - this.inputState.grab.value = true; - } else if (this.mousePos.x && Math.abs(delta.y) < Math.abs(delta.x)) { - this.grabbing = true; - this.inputState.grab.value = true; - } + return; } - if (this.grabbing) { - this.inputState.move.value.add(delta.clone()); - this.mousePos.set(pos); - - pointerEvent.preventDefault(); - pointerEvent.stopPropagation(); + if (this.vertical) { + this.inputForce.y = delta.y; + } else { + this.inputForce.x = delta.x; } - }); - - // TODO: put this in a trait so it can be disabled - this.listener( - this, - "wheel", - (wheelEvent: WheelEvent) => { - if (wheelEvent.ctrlKey === true) { - // its a pinch zoom gesture - return; - } - - const delta = new Vec2(wheelEvent.deltaX, wheelEvent.deltaY); - - if (!this.canMove(delta)) return; - - const deltaThreshold = Vec2.abs(delta); - const axisThreshold = this.vertical - ? Math.abs(delta.x) < Math.abs(delta.y) - : Math.abs(delta.x) > Math.abs(delta.y); + } + }; - if (axisThreshold) { - wheelEvent.preventDefault(); - } + private onKeyDown = (e: KeyboardEvent) => { + const Key = { + prev: this.vertical ? "ArrowUp" : "ArrowLeft", + next: this.vertical ? "ArrowDown" : "ArrowRight", + }; - if (axisThreshold && deltaThreshold > 2) { - this.setTarget(undefined); + if (e.key === Key.prev) { + this.moveBy(-1, "linear"); + e.preventDefault(); + } + if (e.key === Key.next) { + this.moveBy(1, "linear"); + e.preventDefault(); + } + }; - this.grabbing = true; - this.inputState.scroll.value = true; + private onFocusIn = (e: FocusEvent) => { + const item = this.elementItemIndex(e.target as HTMLElement); + const dist = Vec2.dist2(this.getToItemPosition(item), this.position); + const rect = this.getItemRects()[item]; - this.acceleration.mul(0); + if (!rect) return; - if (this.vertical) { - this.inputForce.y = wheelEvent.deltaY; - } else { - this.inputForce.x = wheelEvent.deltaX; - } - } else { - this.grabbing = false; - } - }, - { passive: false }, - ); + if ( + dist.x + rect.x > this.width || + dist.x < 0 || + dist.y + rect.y > this.height || + dist.y < 0 + ) { + this.moveTo(item); + } + }; - this.listener(window, ["pointerup", "pointercancel"], (e: PointerEvent) => { - this.mousePos.mul(0); + private onPointerDown = (pointerEvent: PointerEvent) => { + if (pointerEvent.button !== 0) return; // only left click - if (this.grabbing) { - this.grabbing = false; - e.preventDefault(); - e.stopPropagation(); + // Try to focus this element when clicked on for arrow key navigation, + // will only work when tabindex=0. + this.focus(); - this.inputState.release.value = true; - } - }); + this.mouseDown = true; + this.mousePos.x = pointerEvent.x; + this.mousePos.y = pointerEvent.y; - const intersectionObserver = new IntersectionObserver((intersections) => { - for (const entry of intersections) { - if (entry.isIntersecting) { - this.startAnimate(); - } else { - this.stopAnimate(); - } - } - }); + // stop moving when grabbing + this.setTarget(undefined); + this.acceleration.set(0); - this.addController({ - hostConnected: () => intersectionObserver.observe(this), - hostDisconnected: () => intersectionObserver.disconnect(), - }); + pointerEvent.preventDefault(); + pointerEvent.stopPropagation(); + }; - // TODO: diff the container size and appliy to position of track - this.resizeObserver = new ResizeObserver(debounce(() => this.format())); + private onPointerUpOrCancel = (pointerEvent: PointerEvent) => { + this.mouseDown = false; + this.mousePos.mul(0); - this.addController({ - hostConnected: () => this.resizeObserver?.observe(this), - hostDisconnected: () => this.resizeObserver?.disconnect(), - }); + if (this.grabbing) { + this.grabbing = false; + this.inputState.release.value = true; - this.computeCurrentItem(); - } + pointerEvent.preventDefault(); + pointerEvent.stopPropagation(); + } + }; - disconnectedCallback(): void { - this.stopAnimate(); - super.disconnectedCallback(); - } -} + private onPointerMove = (pointerEvent: PointerEvent) => { + const pos = new Vec2(pointerEvent.x, pointerEvent.y); + const delta = Vec2.sub(pos, this.mousePos); -export class MoveEvent extends CustomEvent<{ - delta: Vec2; - direction: Vec2; - velocity: Vec2; - position: Vec2; -}> { - constructor(track: Track, delta: Vec2) { - super("move", { - cancelable: true, - detail: { - delta: delta, - direction: track.direction.clone(), - velocity: track.velocity.clone(), - position: track.position.clone(), - }, - }); - } -} + if (!this.canMove(delta)) return; -function mod(a: number, n: number) { - return a - Math.floor(a / n) * n; -} - -function angleDist(a: number, b: number) { - return mod(b - a + 180, 360) - 180; -} + if (!this.grabbing && delta.abs() > 3) { + if (this.vertical && this.mousePos.y && Math.abs(delta.x) < Math.abs(delta.y)) { + this.grabbing = true; + this.inputState.grab.value = true; + } else if (this.mousePos.x && Math.abs(delta.y) < Math.abs(delta.x)) { + this.grabbing = true; + this.inputState.grab.value = true; + } + } -export function timer(start: number, time: number) { - return Math.min((Date.now() - start) / time, 1); -} + if (this.grabbing) { + this.inputState.move.value.add(delta.clone()); + this.mousePos.set(pos); -export type InputState = { - grab: { - value: boolean; - }; - scroll: { - value: boolean; - }; - move: { - value: Vec2; - }; - release: { - value: boolean; - }; - format: { - value: boolean; - }; - leave: { - value: boolean; - }; - enter: { - value: boolean; + pointerEvent.preventDefault(); + pointerEvent.stopPropagation(); + } }; -}; +} export type Easing = "ease" | "linear" | "none"; @@ -1555,7 +1485,7 @@ export function isTouch() { return !!navigator.maxTouchPoints || "ontouchstart" in window; } -function debounce<T>(callback: (arg: T) => void) { +export function debounce<T>(callback: (arg: T) => void) { let timeout: Timer; return (arg: T) => { @@ -1563,3 +1493,180 @@ function debounce<T>(callback: (arg: T) => void) { timeout = setTimeout(() => callback(arg), 80); }; } + +function mod(a: number, n: number) { + return a - Math.floor(a / n) * n; +} + +export function angleDist(a: number, b: number) { + return mod(b - a + 180, 360) - 180; +} + +export function timer(start: number, time: number) { + return Math.min((Date.now() - start) / time, 1); +} + +type VecOrNumber = Vec2 | number[] | number; + +export class Vec2 extends Array { + constructor(x: VecOrNumber = 0, y = 0) { + super(); + + if (Vec2.isVec(x)) { + this[0] = x[0]; + this[1] = x[1]; + } else { + this[0] = x; + this[1] = y; + } + } + + get x() { + return this[0]; + } + + set x(x: number) { + this[0] = x; + } + + get y() { + return this[1]; + } + + set y(y: number) { + this[1] = y; + } + + get xy() { + return [this[0], this[1]]; + } + + set xy(xy: number[]) { + this[0] = xy[0]; + this[1] = xy[1]; + } + + add(vec: VecOrNumber) { + if (Vec2.isVec(vec)) { + this[0] += vec[0]; + this[1] += vec[1]; + } else { + this[0] += vec; + this[1] += vec; + } + return this; + } + + sub(vec: VecOrNumber) { + if (Vec2.isVec(vec)) { + this[0] -= vec[0]; + this[1] -= vec[1]; + } else { + this[0] -= vec; + this[1] -= vec; + } + return this; + } + + mul(vec: VecOrNumber) { + if (Vec2.isVec(vec)) { + this[0] *= vec[0]; + this[1] *= vec[1]; + } else { + this[0] *= vec; + this[1] *= vec; + } + return this; + } + + set(vec: VecOrNumber) { + if (Vec2.isVec(vec)) { + this[0] = vec[0]; + this[1] = vec[1]; + } else { + this[0] = vec; + this[1] = vec; + } + return this; + } + + mod(vec: VecOrNumber) { + if (Vec2.isVec(vec)) { + this[0] = this[0] % vec[0]; + this[1] = this[1] % vec[1]; + } else { + this[0] = this[0] % vec; + this[1] = this[1] % vec; + } + return this; + } + + sign() { + this[0] = Math.sign(this[0]); + this[1] = Math.sign(this[1]); + return this; + } + + dist(vec: Vec2) { + return Math.sqrt((vec[0] - this[0]) ** 2 + (vec[1] - this[1]) ** 2); + } + + abs() { + return Math.sqrt(this[0] ** 2 + this[1] ** 2); + } + + precision(precision: number) { + this[0] = Math.floor(this[0] / precision) * precision; + this[1] = Math.floor(this[1] / precision) * precision; + return this; + } + + floor() { + this[0] = Math.floor(this[0]); + this[1] = Math.floor(this[1]); + return this; + } + + clone() { + return new Vec2(this); + } + + isNaN() { + return Number.isNaN(this[0]) || Number.isNaN(this[1]); + } + + toString(): string { + return `Vec{${this.map((v) => v.toFixed(2)).join(",")}}`; + } + + static add(vec1: VecOrNumber, vec2: VecOrNumber) { + if (Vec2.isVec(vec1)) { + return new Vec2(vec1[0], vec1[1]).add(vec2); + } + return new Vec2(vec1, vec1).add(vec2); + } + + static sub(vec1: VecOrNumber, vec2: VecOrNumber) { + if (Vec2.isVec(vec1)) { + return new Vec2(vec1[0], vec1[1]).sub(vec2); + } + return new Vec2(vec1, vec1).sub(vec2); + } + + static mul(vec1: VecOrNumber, vec2: VecOrNumber) { + if (Vec2.isVec(vec1)) { + return new Vec2(vec1[0], vec1[1]).mul(vec2); + } + return new Vec2(vec1, vec1).mul(vec2); + } + + static abs(vec: Vec2) { + return new Vec2(vec.x, vec.y).abs(); + } + + static dist2(vec1: Vec2, vec2: Vec2) { + return new Vec2(vec1[0] - vec2[0], vec1[1] - vec2[1]); + } + + static isVec = Array.isArray; +} diff --git a/packages/elements/packages/track/src/Vec.ts b/packages/elements/packages/track/src/Vec.ts deleted file mode 100644 index 521769793c712fca92a7d0263a9382f04192ee0c..0000000000000000000000000000000000000000 --- a/packages/elements/packages/track/src/Vec.ts +++ /dev/null @@ -1,169 +0,0 @@ -type VecOrNumber = Vec2 | number[] | number; - -export class Vec2 extends Array { - constructor(x: VecOrNumber = 0, y = 0) { - super(); - - if (Vec2.isVec(x)) { - this[0] = x[0]; - this[1] = x[1]; - } else { - this[0] = x; - this[1] = y; - } - } - - get x() { - return this[0]; - } - - set x(x: number) { - this[0] = x; - } - - get y() { - return this[1]; - } - - set y(y: number) { - this[1] = y; - } - - get xy() { - return [this[0], this[1]]; - } - - set xy(xy: number[]) { - this[0] = xy[0]; - this[1] = xy[1]; - } - - add(vec: VecOrNumber) { - if (Vec2.isVec(vec)) { - this[0] += vec[0]; - this[1] += vec[1]; - } else { - this[0] += vec; - this[1] += vec; - } - return this; - } - - sub(vec: VecOrNumber) { - if (Vec2.isVec(vec)) { - this[0] -= vec[0]; - this[1] -= vec[1]; - } else { - this[0] -= vec; - this[1] -= vec; - } - return this; - } - - mul(vec: VecOrNumber) { - if (Vec2.isVec(vec)) { - this[0] *= vec[0]; - this[1] *= vec[1]; - } else { - this[0] *= vec; - this[1] *= vec; - } - return this; - } - - set(vec: VecOrNumber) { - if (Vec2.isVec(vec)) { - this[0] = vec[0]; - this[1] = vec[1]; - } else { - this[0] = vec; - this[1] = vec; - } - return this; - } - - mod(vec: VecOrNumber) { - if (Vec2.isVec(vec)) { - this[0] = this[0] % vec[0]; - this[1] = this[1] % vec[1]; - } else { - this[0] = this[0] % vec; - this[1] = this[1] % vec; - } - return this; - } - - sign() { - this[0] = Math.sign(this[0]); - this[1] = Math.sign(this[1]); - return this; - } - - dist(vec: Vec2) { - return Math.sqrt((vec[0] - this[0]) ** 2 + (vec[1] - this[1]) ** 2); - } - - abs() { - return Math.sqrt(this[0] ** 2 + this[1] ** 2); - } - - abs2() { - this[0] = Math.abs(this[0]); - this[1] = Math.abs(this[1]); - return this; - } - - precision(precision: number) { - this[0] = Math.floor(this[0] / precision) * precision; - this[1] = Math.floor(this[1] / precision) * precision; - } - - floor() { - this[0] = Math.floor(this[0]); - this[1] = Math.floor(this[1]); - return this; - } - - clone() { - return new Vec2(this); - } - - isNaN() { - return Number.isNaN(this[0]) || Number.isNaN(this[1]); - } - - toString(): string { - return `Vec{${this.join(",")}}`; - } - - static add(vec1: VecOrNumber, vec2: VecOrNumber) { - if (Vec2.isVec(vec1)) { - return new Vec2(vec1[0], vec1[1]).add(vec2); - } - return new Vec2(vec1, vec1).add(vec2); - } - - static sub(vec1: VecOrNumber, vec2: VecOrNumber) { - if (Vec2.isVec(vec1)) { - return new Vec2(vec1[0], vec1[1]).sub(vec2); - } - return new Vec2(vec1, vec1).sub(vec2); - } - - static mul(vec1: VecOrNumber, vec2: VecOrNumber) { - if (Vec2.isVec(vec1)) { - return new Vec2(vec1[0], vec1[1]).mul(vec2); - } - return new Vec2(vec1, vec1).mul(vec2); - } - - static abs(vec: Vec2) { - return new Vec2(vec.x, vec.y).abs(); - } - - static dist2(vec1: Vec2, vec2: Vec2) { - return new Vec2(vec1[0] - vec2[0], vec1[1] - vec2[1]); - } - - static isVec = Array.isArray; -} diff --git a/packages/elements/packages/track/src/debug.ts b/packages/elements/packages/track/src/debug.ts new file mode 100644 index 0000000000000000000000000000000000000000..cb9ede44b584dd44d584e99e04833ba22e76022f --- /dev/null +++ b/packages/elements/packages/track/src/debug.ts @@ -0,0 +1,119 @@ +import type { Track, Trait } from "./Track"; + +const PI2 = Math.PI * 2; + +/** + * Debug trait for debugging hud. + */ +export class DebugTrait implements Trait { + id = "debug"; + + update(track: Track): void { + if (!track.debug) return; + + const meta = { + mouseDown: track.mouseDown, + grabbing: track.grabbing, + acceleration: track.acceleration, + velocity: track.velocity, + drag: track.drag, + moveVelocity: track.moveVelocity, + inputForce: track.inputForce, + scrollDebounce: track.scrollDebounce, + mousePos: track.mousePos, + target: track.target, + }; + + const trackSize = track.trackSize; + const currentAngle = track.currentAngle; + + const canvas = track.debugCanvas; + const ctx = canvas.getContext("2d"); + if (!ctx) return; + + ctx.translate(0.5, 0.5); + canvas.width = track.width * 2; + canvas.height = track.height * 2; + canvas.style.width = `${track.width}px`; + canvas.style.height = `${track.height}px`; + + ctx.fillStyle = "rgba(0, 0, 0, 0.5)"; + ctx.fillRect(0, 0, 400, 600); + + const originAngle = track.originAngle; + + for (let i = -1; i < track.itemCount + 1; i++) { + const itemAngle = track.itemAngles[i] || 0; + + // draw a line from the center to the current position with angle + ctx.strokeStyle = `hsl(0, 0%, ${(i / track.itemCount) * 100}%)`; + ctx.beginPath(); + ctx.moveTo(100, 100); + ctx.lineTo(100 + Math.cos(itemAngle) * 69, 100 + Math.sin(itemAngle) * 69); + ctx.lineWidth = 3; + ctx.stroke(); + } + + // draw a line from the center to the current position with angle + ctx.fillStyle = "rgba(255, 0, 0, 0.5)"; + ctx.beginPath(); + ctx.moveTo(100, 100); + ctx.lineTo( + 100 + Math.cos(currentAngle + originAngle) * 69, + 100 + Math.sin(currentAngle + originAngle) * 69, + ); + ctx.arc( + 100, + 100, + 69, + currentAngle + originAngle, + currentAngle + originAngle + (track.width / trackSize) * PI2, + ); + ctx.lineTo(100, 100); + ctx.fill(); + + // print current position + ctx.font = "24px sans-serif"; + ctx.fillStyle = "#fff"; + ctx.textAlign = "left"; + ctx.textBaseline = "middle"; + ctx.fillText(`${track.currentPosition.toFixed(1)} / ${trackSize.toFixed(1)}`, 42, 18); + + // print current position index + ctx.font = "24px sans-serif"; + ctx.fillStyle = "#fff"; + ctx.textAlign = "left"; + ctx.textBaseline = "middle"; + ctx.fillText(track.currentItem.toString(), 6, 18); + + if (track.targetAngle) { + // draw a line from the center to the current position with angle + ctx.strokeStyle = "blue"; + ctx.beginPath(); + ctx.moveTo(100, 100); + ctx.lineTo( + 100 + Math.cos(track.targetAngle) * 50, + 100 + Math.sin(track.targetAngle) * 50, + ); + ctx.lineWidth = 3; + ctx.stroke(); + } + + // draw a line from the center to the current position with angle + ctx.strokeStyle = "lime"; + ctx.beginPath(); + ctx.moveTo(100, 100); + ctx.lineTo(100 + Math.cos(originAngle) * 69, 100 + Math.sin(originAngle) * 69); + ctx.lineWidth = 3; + ctx.stroke(); + + let line = 6; + ctx.font = "24px sans-serif"; + ctx.fillStyle = "#fff"; + ctx.textAlign = "left"; + for (const key in meta) { + ctx.fillText(`${key}: ${meta[key]}`, 6, 24 * 1.5 * line); + line++; + } + } +} diff --git a/packages/elements/packages/track/tests/test-utils.ts b/packages/elements/packages/track/tests/test-utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..76c4583072faf5126150f2d24e5720511bd04ac0 --- /dev/null +++ b/packages/elements/packages/track/tests/test-utils.ts @@ -0,0 +1,155 @@ +import Rand from "rand-seed"; +import { expect } from "bun:test"; +import type { Vec2 } from "../src"; +import type { Track as TrackElement } from "../src/Track"; + +export function enviroment() { + globalThis.seed = process.env.TEST_SEED || crypto.randomUUID(); +} + +export function setup() { + globalThis.rand = new Rand(globalThis.seed); +} + +export function random() { + return globalThis.rand.next(); +} + +export function label(str: string) { + return `[TEST_SEED=${globalThis.seed} bun test track -t "${str}"]`; +} + +export function press(ele: Element, key: string) { + ele.dispatchEvent( + new KeyboardEvent("keydown", { + key: key, + }), + ); +} + +export async function fixElementSizes(ele: Element, width: number, height: number) { + Object.defineProperty(ele, "offsetWidth", { + writable: true, + }); + Object.defineProperty(ele, "offsetHeight", { + writable: true, + }); + + // @ts-ignore + ele.offsetWidth = width; + // @ts-ignore + ele.offsetHeight = height; +} + +export async function sleep(ms = 16) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export class FakePointerEvent extends PointerEvent { + constructor( + type: string, + public x: number, + public y: number, + init?: PointerEventInit, + ) { + super(type, { + button: 0, + bubbles: true, + ...init, + }); + } +} + +export async function drag< + T extends HTMLElement & { + position: Vec2; + target?: Vec2; + }, +>(track: T, dist: [number, number]) { + const multiplier = 1 + random(); + const pos = [10, 10] as [number, number]; + const start = [...track.position]; + const step = [ + Math.abs(dist[0]) > 0 ? multiplier * dist[0] : 0, + Math.abs(dist[1]) > 0 ? multiplier * dist[1] : 0, + ] as [number, number]; + + console.info("drag", multiplier, "dist", dist, "step", step, "start", start); + + // start moving + track.dispatchEvent(new FakePointerEvent("pointerdown", ...pos)); + console.info("down"); + + await sleep(); + + expect(track.target).toBeUndefined(); + + for (let i = 0; i < 10; i++) { + window.dispatchEvent(new FakePointerEvent("pointermove", ...pos)); + + await sleep(); + + pos[0] -= step[0]; + pos[1] -= step[1]; + } + // has moved at all? + expect(track.position[0] !== start[0] || track.position[1] !== start[1]).toBeTrue(); + + window.dispatchEvent(new FakePointerEvent("pointerup", ...pos)); + console.info("up"); + + await sleep(); +} + +export async function trackWithChildren( + itemCount = 10, + attributes: Record<string, string | boolean | number> = {}, +) { + await import("../src/index.js"); + + const widths = new Array<number>(itemCount) + .fill(0) + .map(() => Math.floor(random() * 500 + 150)); + + console.info("items", widths); + + const div = document.createElement("div"); + const markup = ` + <a-track ${Object.entries(attributes) + .map(([key, value]) => `${key}="${value}"`) + .join(" ")}> + ${widths.map((w) => `<canvas width="${w}" height="800"></canvas>`).join("")} + </a-track> + `; + div.innerHTML = markup; + + const track = div.children[0] as TrackElement; + fixElementSizes(track, random() * 1000 + 200, random() * 800 + 200); + + // increase animation speed for testing + track.transitionTime = 100; + + for (let i = 0; i < itemCount; i++) { + const child = track.children[i] as HTMLCanvasElement; + fixElementSizes( + child, + Number.parseInt(child.getAttribute("width") || "0"), + Number.parseInt(child.getAttribute("height") || "0"), + ); + } + + document.body.append(div); + + if (track.vertical) { + track.position.y = random() * track.overflowWidth; + } else { + track.position.x = random() * track.overflowWidth; + } + + console.info("track", track.width, track.height, track.trackWidth, track.position); + + // @ts-ignore + track.onFormat(); + + return track; +} diff --git a/packages/elements/packages/track/tests/track.spec.ts b/packages/elements/packages/track/tests/track.spec.ts index 32d2507af9d1c142b21308523446b2a47e9fd497..fa59875695b725fd96ceeba7a2f787f7bd2e118a 100644 --- a/packages/elements/packages/track/tests/track.spec.ts +++ b/packages/elements/packages/track/tests/track.spec.ts @@ -1,292 +1,353 @@ -import { test, expect } from "bun:test"; -import type { MoveEvent } from "../src/Track"; -import type { Track as TrackElement } from "../src/Track"; -import Rand from "rand-seed"; +import { beforeEach, test, expect, afterEach, describe } from "bun:test"; +import type { MoveEvent, Track } from "../src/Track"; +import { + drag, + enviroment, + FakePointerEvent, + label, + press, + setup, + sleep, + trackWithChildren, +} from "./test-utils"; + +let int: Timer; +function logRun(track: Track) { + int = setInterval(() => { + console.info(track.position, track.velocity, track.target); + }, 16); +} -const seed = process.env.TEST_SEED || crypto.randomUUID(); -const rand = new Rand(seed); +window.requestAnimationFrame = (callback: () => void) => { + const timer = setTimeout(() => callback(Date.now()), 16.6666666667); + return timer; +}; +window.cancelAnimationFrame = (timer: Timer) => { + clearTimeout(timer); +}; -function random() { - return rand.next(); -} +describe("Track", () => { + enviroment(); -console.info("\nTest run seed:", seed, "\n"); + afterEach(() => { + clearInterval(int); + }); -const NODE_NAME = "a-track"; + beforeEach(() => { + setup(); + }); -test("import track element", async () => { - const { Track } = await import("@sv/elements/track"); - expect(Track).toBeDefined(); + test(label("import track element"), async () => { + const { Track } = await import("@sv/elements/track"); + expect(Track).toBeDefined(); - // is defined in custom element registry - expect(customElements.get(NODE_NAME)).toBeDefined(); -}); + // is defined in custom element registry + expect(customElements.get("a-track")).toBeDefined(); + }); -test("construct track element", async () => { - const { Track } = await import("@sv/elements/track"); + test("construct track element", async () => { + const { Track } = await import("@sv/elements/track"); - // is constructable - expect(new Track()).toBeInstanceOf(Track); + // is constructable + expect(new Track()).toBeInstanceOf(Track); - const html = `<${NODE_NAME} />`; - const ele = document.createElement("div"); - ele.innerHTML = html; + const html = "<a-track></a-track>"; + const ele = document.createElement("div"); + ele.innerHTML = html; - expect(ele.children[0]).toBeInstanceOf(Track); -}); + expect(ele.children[0]).toBeInstanceOf(Track); + }); -test("deconstruct track element", async () => { - const track = await trackWithChildren(); - track.remove(); - // @ts-ignore - expect(track.animation).toBeUndefined(); -}); + test(label("deconstruct track element"), async () => { + const track = await trackWithChildren(); + track.remove(); + // @ts-ignore + expect(track.animation).toBeUndefined(); + }); -test("check default traits", async () => { - const track = await trackWithChildren(); - expect(track.findTrait("pointer")).toBeDefined(); -}); + test(label("item count"), async () => { + const track = await trackWithChildren(10); + expect(track.itemCount).toBe(10); + }); -test("item count", async () => { - const track = await trackWithChildren(10); - expect(track.itemCount).toBe(10); -}); + test(label("custom trait"), async () => { + const track = await trackWithChildren(); + + let input = false; + let update = false; + let format = false; + let start = false; + let stop = false; + + track.addTrait({ + id: "test", -test("custom trait", async () => { - const track = await trackWithChildren(); + input() { + input = true; + }, - let input = false; - let update = false; - let format = false; - let start = false; - let stop = false; + update() { + update = true; + }, - track.addTrait({ - id: "test", + stop() { + stop = true; + }, - input() { - input = true; - }, + start() { + start = true; + }, - update() { - update = true; - }, + format() { + format = true; + }, + }); - stop() { - stop = true; - }, + // @ts-ignore + track.onFormat(); + track.startAnimate(); + // @ts-ignore Force update tick + track.updateTick(); + + expect(start).toBeTrue(); + expect(input).toBeTrue(); + expect(update).toBeTrue(); + expect(format).toBeTrue(); - start() { - start = true; - }, + track.remove(); - format() { - format = true; - }, + expect(stop).toBeTrue(); }); - // @ts-ignore - track.format(); - track.startAnimate(); - // @ts-ignore Force update tick - track.updateTick(); + test(label("check snap trait"), async () => { + const track = await trackWithChildren(); + track.snap = true; + await track.updateComplete; + expect(track.findTrait("snap")).toBeDefined(); + }); - expect(start).toBeTrue(); - expect(input).toBeTrue(); - expect(update).toBeTrue(); - expect(format).toBeTrue(); + test(label("arrow key navigation"), async () => { + const track = await trackWithChildren(); + track.tabIndex = 0; + track.focus(); - track.remove(); + press(track, "ArrowRight"); - expect(stop).toBeTrue(); -}); + await sleep(track.transitionTime + 100); -test("check snap trait", async () => { - const track = await trackWithChildren(); - track.snap = true; - await track.updateComplete; - expect(track.findTrait("snap")).toBeDefined(); -}); + expect(document.activeElement).toBe(track); + expect(track.currentItem).toBe(1); + }); -test("arrow key navigation", async () => { - const track = await trackWithChildren(); - track.tabIndex = 0; - track.focus(); + test(label("move event details"), async () => { + const track = await trackWithChildren(); + track.addEventListener("move", ((e: MoveEvent) => { + expect(e.detail.direction).toBeDefined(); + expect(e.detail.velocity).toBeDefined(); + expect(e.detail.position).toBeDefined(); - press(track, "ArrowRight"); + e.preventDefault(); + }) as EventListener); + + // @ts-ignore + expect(track.canMove()).toBeFalse(); + }); - await sleep(track.transitionTime + 100); + test(label("moveBy"), async () => { + const track = await trackWithChildren(); - expect(document.activeElement).toBe(track); - expect(track.currentItem).toBe(1); -}); + track.moveBy(2); -test("move event details", async () => { - const track = await trackWithChildren(); - track.addEventListener("move", ((e: MoveEvent) => { - expect(e.detail.direction).toBeDefined(); - expect(e.detail.velocity).toBeDefined(); - expect(e.detail.position).toBeDefined(); + const positions: Array<number> = []; - e.preventDefault(); - }) as EventListener); + const int = setInterval(() => { + positions.push(track.currentPosition); + }, track.transitionTime / 10); - // @ts-ignore - expect(track.canMove()).toBeFalse(); -}); + await sleep(track.transitionTime + 100); -test("moveBy", async () => { - const track = await trackWithChildren(); + expect(track.currentItem).toBe(2); - track.moveBy(2); + clearInterval(int); - const positions: Array<number> = []; + expect(positions.length > 5).toBeTrue(); + }); - const int = setInterval(() => { - positions.push(track.currentPosition); - }, track.transitionTime / 10); + test(label("centered index 1"), async () => { + const track = await trackWithChildren(10, { + align: "center", + }); + logRun(track); - await sleep(track.transitionTime + 100); + expect(track.align).toBe("center"); - expect(track.currentItem).toBe(2); + track.moveTo(1); + await sleep(300); - clearInterval(int); + expect(track.currentItem).toBe(1); + expect(Math.abs(track.currentPosition)).toBeGreaterThan(0); - expect(positions.length > 5).toBeTrue(); -}); + let offset = 0; + for (let i = 0; i < track.currentItem; i++) { + // @ts-ignore + offset += track.itemWidths[i]; + } + // @ts-ignore + offset += track.itemWidths[track.currentItem] / 2; -test("centered index 1", async () => { - const track = await trackWithChildren(10, { - align: "center", + expect(track.currentPosition).toBeCloseTo(offset - track.width / 2); }); - expect(track.align).toBe("center"); + test(label("centered index 0"), async () => { + const track = await trackWithChildren(10, { + align: "center", + }); + + expect(track.align).toBe("center"); + + track.moveTo(0); + await sleep(track.transitionTime + 100); - track.moveTo(1); - await sleep(track.transitionTime + 100); + expect(track.currentItem).toBe(0); - expect(track.currentItem).toBe(1); - expect(track.currentPosition !== 0).toBeTrue(); + // @ts-ignore + const offset = track.itemWidths[track.currentItem] / 2; + expect(track.currentPosition).toBeCloseTo(offset - track.width / 2); + }); + + test(label("snap"), async () => { + const track = await trackWithChildren(10, { snap: true }); + + expect(track.snap).toBe(true); - let offset = 0; - for (let i = 0; i < track.currentItem; i++) { // @ts-ignore - offset += track.itemWidths[i]; - } - // @ts-ignore - offset += track.itemWidths[track.currentItem] / 2; + const widths = track.itemWidths; - expect(track.currentPosition).toBe(offset - track.width / 2); -}); + track.setTarget([widths[0] + widths[1] + 10, 0]); + await sleep(track.transitionTime + 100); + track.setTarget(undefined); + await sleep(track.transitionTime + 100); + + expect(Math.floor(track.currentPosition)).toBeGreaterThanOrEqual( + widths[0] + widths[1], + ); -test("centered index 0", async () => { - const track = await trackWithChildren(10, { - align: "center", + expect(track.currentIndex).toBeGreaterThanOrEqual(2); }); - expect(track.align).toBe("center"); + test(label("drag with snap"), async () => { + const track = await trackWithChildren(10, { snap: true, current: 2 }); + logRun(track); - track.moveTo(0); - await sleep(track.transitionTime + 100); + track.moveTo(4, "none"); + await sleep(200); - expect(track.currentItem).toBe(0); + console.info(track.position, track.overflowWidth, track.target); - // @ts-ignore - const offset = track.itemWidths[track.currentItem] / 2; - expect(track.currentPosition).toBe(offset - track.width / 2); -}); + await drag(track, [200, 0]); + await sleep(300); -test("snap", async () => { - const track = await trackWithChildren(10, { snap: true }); + // target should be set by snap + expect(track.target).toBeDefined(); + expect(track.position[0]).toBeCloseTo(track.target?.[0], -2); + }); + + test(label("drag with snap negative"), async () => { + const track = await trackWithChildren(10, { snap: true, current: 2 }); + logRun(track); - expect(track.snap).toBe(true); + track.moveTo(6, "linear"); + await sleep(300); - // @ts-ignore - const widths = track.itemWidths; + await drag(track, [-100, 0]); + await sleep(300); - track.setTarget([widths[0] + widths[1] + 10, 0]); - await sleep(track.transitionTime + 100); - track.setTarget(undefined); - await sleep(track.transitionTime + 100); + // target should be set by snap + expect(track.target).toBeDefined(); + expect(track.position[0]).toBeCloseTo(track.target?.[0], -2); + }); - expect(Math.floor(track.currentPosition)).toBeGreaterThanOrEqual(widths[0] + widths[1]); + test(label("drag vertical with snap"), async () => { + const track = await trackWithChildren(10, { snap: true, current: 3, vertical: true }); + logRun(track); - expect(track.currentIndex).toBeGreaterThanOrEqual(2); -}); + await drag(track, [0, 100]); + await sleep(200); -// TODO: Test actual mouse movement with events + // target should be set by snap + expect(track.target).toBeDefined(); + expect(track.position[0]).toBeCloseTo(track.target?.[0], -2); + }); -// TODO: snap with inertia to the correct position -// -// TODO: loop + test(label("stop when grabbing"), async () => { + const track = await trackWithChildren(10, { snap: true }); + logRun(track); -async function sleep(ms = 0) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} + track.transitionTime = 1000; + track.moveTo(8, "ease"); + await sleep(track.transitionTime / 2); + + // grab it bevore transition ends + track.dispatchEvent(new FakePointerEvent("pointerdown", 0, 0)); + console.info("Grabbed track"); + + await sleep(); + const pos = track.position[0]; -async function fixElementSizes(ele: Element, width: number, height: number) { - Object.defineProperty(ele, "offsetWidth", { - writable: true, + // wait + await sleep(200); + // pos should not have changed + expect(track.position[0]).toBe(pos); }); - Object.defineProperty(ele, "offsetHeight", { - writable: true, + + test(label("click without move should not result in a cancled click"), async () => { + const track = await trackWithChildren(10, { snap: true, align: "center" }); + + track.dispatchEvent(new FakePointerEvent("pointerdown", 100, 100)); + console.info("down"); + + await sleep(); + + const ev = new FakePointerEvent("pointerup", 100, 100); + track.dispatchEvent(ev); + console.info("up"); + + expect(ev.defaultPrevented).toBe(false); + + track.dispatchEvent(new FakePointerEvent("pointerdown", 100, 100)); + console.info("down"); + + await sleep(100); + window.dispatchEvent(new FakePointerEvent("pointermove", 150, 110)); + await sleep(100); + + const ev2 = new FakePointerEvent("pointerup", 100, 100); + track.dispatchEvent(ev2); + console.info("up"); + + expect(ev2.defaultPrevented).toBe(true); }); - // @ts-ignore - ele.offsetWidth = width; - // @ts-ignore - ele.offsetHeight = height; -} + test(label("wheel event works"), async () => { + const track = await trackWithChildren(10, {}); + track.moveTo(8, "none"); + await sleep(200); -async function trackWithChildren( - itemCount = 10, - attributes: Record<string, string | boolean | number> = {}, -) { - await import("@sv/elements/track"); - - const widths = new Array<number>(itemCount) - .fill(0) - .map(() => Math.floor(random() * 500 + 150)); - - console.info(widths); - - const div = document.createElement("div"); - const markup = ` - <a-track ${Object.entries(attributes) - .map(([key, value]) => `${key}="${value}"`) - .join(" ")}> - ${widths.map((w) => `<canvas width="${w}" height="800"></canvas>`).join("")} - </a-track> - `; - div.innerHTML = markup; - - const track = div.children[0] as TrackElement; - fixElementSizes(track, 800, 800); - - // increase animation speed for testing - track.transitionTime = 150; - - for (let i = 0; i < itemCount; i++) { - const child = track.children[i] as HTMLCanvasElement; - fixElementSizes( - child, - Number.parseInt(child.getAttribute("width") || "0"), - Number.parseInt(child.getAttribute("height") || "0"), - ); - } + const start = [...track.position]; - document.body.append(div); + const ev = new WheelEvent("wheel", { + deltaX: -200, + deltaY: 0, + }); + track.dispatchEvent(ev); + console.info("fired"); - // @ts-ignore - track.format(); + expect(ev.defaultPrevented).toBe(true); - return track; -} + await sleep(100); -function press(ele: Element, key: string) { - ele.dispatchEvent( - new KeyboardEvent("keydown", { - key: key, - }), - ); -} + expect(track.position[0]).not.toBe(start[0]); + }); + + // TODO: loop +});