From dc8675d2764146984437278552ee5f974ede9f57 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 18 Feb 2026 12:48:36 +0100 Subject: [PATCH 001/123] release: cut the v21.2.0-rc.0 release --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de9cd80be407..85591a312959 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +# 21.2.0-rc.0 "chlorine-canine" (2026-02-18) + + + # 21.2.0-next.5 "chlorine-cat" (2026-02-18) ### aria diff --git a/package.json b/package.json index a52fa52e189f..fd839d00968f 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "ci-docs-monitor-test": "node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only scripts/docs-deploy/monitoring/ci-test.mts", "prepare": "husky" }, - "version": "21.2.0-next.5", + "version": "21.2.0-rc.0", "dependencies": { "@angular-devkit/core": "catalog:", "@angular-devkit/schematics": "catalog:", From f69bb6457d1a747a098be0e3f6a554f408f9d85a Mon Sep 17 00:00:00 2001 From: Angular Robot Date: Thu, 19 Feb 2026 06:09:45 -0700 Subject: [PATCH 002/123] build: update cross-repo angular dependencies (#32795) See associated pull request for more information. --- .../assistant-to-the-branch-manager.yml | 2 +- .github/workflows/ci.material-aio.yml | 18 +- .github/workflows/ci.yml | 50 +- .../workflows/deploy-dev-app-main-push.yml | 6 +- .github/workflows/dev-infra.yml | 4 +- .github/workflows/docs-preview-build.yml | 8 +- .github/workflows/docs-preview-deploy.yml | 2 +- .github/workflows/google-internal-tests.yml | 2 +- .github/workflows/pr.material-aio.yml | 18 +- .github/workflows/pr.yml | 46 +- .github/workflows/preview-build-dev-app.yml | 8 +- .github/workflows/preview-deploy-dev-app.yml | 2 +- .github/workflows/scheduled-ci.yml | 14 +- MODULE.bazel | 2 +- package.json | 2 +- pnpm-lock.yaml | 1242 ++++++----------- pnpm-workspace.yaml | 34 +- 17 files changed, 564 insertions(+), 896 deletions(-) diff --git a/.github/workflows/assistant-to-the-branch-manager.yml b/.github/workflows/assistant-to-the-branch-manager.yml index abc91842d69f..9ec5c522a33f 100644 --- a/.github/workflows/assistant-to-the-branch-manager.yml +++ b/.github/workflows/assistant-to-the-branch-manager.yml @@ -16,6 +16,6 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: angular/dev-infra/github-actions/branch-manager@0edcf22f9ce677699274f2d399325f99d3d56e81 + - uses: angular/dev-infra/github-actions/branch-manager@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/ci.material-aio.yml b/.github/workflows/ci.material-aio.yml index 18bbbe24dcbe..a1cfa026b71d 100644 --- a/.github/workflows/ci.material-aio.yml +++ b/.github/workflows/ci.material-aio.yml @@ -21,11 +21,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Build @@ -35,11 +35,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Tests @@ -56,11 +56,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Lighthouse Audit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94df3bf263b4..2a836a82dc59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile # TODO: Remove --ignore_all_rc_files flag once a repository can be loaded in bazelrc during info @@ -49,11 +49,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -65,11 +65,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -81,11 +81,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -98,11 +98,11 @@ jobs: runs-on: ubuntu-latest-16core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -114,11 +114,11 @@ jobs: runs-on: ubuntu-latest-16core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -130,11 +130,11 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Build Snapshots @@ -154,15 +154,15 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc # See: https://github.com/puppeteer/puppeteer/pull/13196 and # https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md. - name: Disable AppArmor run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Build and Verify Release Output @@ -185,12 +185,12 @@ jobs: CI_RUNNER_NUMBER: ${{ github.run_id }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Browserstack Variables - uses: angular/dev-infra/github-actions/browserstack@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/browserstack@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Run tests on Browserstack run: ./scripts/circleci/run-browserstack-tests.sh diff --git a/.github/workflows/deploy-dev-app-main-push.yml b/.github/workflows/deploy-dev-app-main-push.yml index 8ed0a487511c..e431d51f42c4 100644 --- a/.github/workflows/deploy-dev-app-main-push.yml +++ b/.github/workflows/deploy-dev-app-main-push.yml @@ -17,11 +17,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile diff --git a/.github/workflows/dev-infra.yml b/.github/workflows/dev-infra.yml index 453a0139f3ff..a1db4b822270 100644 --- a/.github/workflows/dev-infra.yml +++ b/.github/workflows/dev-infra.yml @@ -12,13 +12,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: angular/dev-infra/github-actions/pull-request-labeling@0edcf22f9ce677699274f2d399325f99d3d56e81 + - uses: angular/dev-infra/github-actions/pull-request-labeling@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} post_approval_changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: angular/dev-infra/github-actions/pull-request-labeling@0edcf22f9ce677699274f2d399325f99d3d56e81 + - uses: angular/dev-infra/github-actions/pull-request-labeling@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/docs-preview-build.yml b/.github/workflows/docs-preview-build.yml index 4cb414295b27..37cad3457437 100644 --- a/.github/workflows/docs-preview-build.yml +++ b/.github/workflows/docs-preview-build.yml @@ -21,16 +21,16 @@ jobs: (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'docs: preview')) steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Build docs site run: pnpm bazel build //docs:build.production - - uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@0edcf22f9ce677699274f2d399325f99d3d56e81 + - uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: workflow-artifact-name: 'docs-preview' pull-number: '${{github.event.pull_request.number}}' diff --git a/.github/workflows/docs-preview-deploy.yml b/.github/workflows/docs-preview-deploy.yml index 8d94f40d47cf..c171cd91a8c1 100644 --- a/.github/workflows/docs-preview-deploy.yml +++ b/.github/workflows/docs-preview-deploy.yml @@ -40,7 +40,7 @@ jobs: npx -y firebase-tools@latest target:clear --config docs/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting mat-aio npx -y firebase-tools@latest target:apply --config docs/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting mat-aio ${{env.PREVIEW_SITE}} - - uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@0edcf22f9ce677699274f2d399325f99d3d56e81 + - uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: github-token: '${{secrets.GITHUB_TOKEN}}' workflow-artifact-name: 'docs-preview' diff --git a/.github/workflows/google-internal-tests.yml b/.github/workflows/google-internal-tests.yml index 8a8bf4e484be..8d35f0e00700 100644 --- a/.github/workflows/google-internal-tests.yml +++ b/.github/workflows/google-internal-tests.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: angular/dev-infra/github-actions/google-internal-tests@0edcf22f9ce677699274f2d399325f99d3d56e81 + - uses: angular/dev-infra/github-actions/google-internal-tests@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: run-tests-guide-url: http://go/angular-material-presubmit github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr.material-aio.yml b/.github/workflows/pr.material-aio.yml index 7a9cf45a9deb..fece1e72e6dc 100644 --- a/.github/workflows/pr.material-aio.yml +++ b/.github/workflows/pr.material-aio.yml @@ -19,11 +19,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Build @@ -33,11 +33,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Tests @@ -54,11 +54,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Lighthouse Audit diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index bdf5b820097d..7a9eb57bdac6 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile # TODO: Remove --ignore_all_rc_files flag once a repository can be loaded in bazelrc during info @@ -45,7 +45,7 @@ jobs: - name: Check code format run: pnpm ng-dev format changed --check ${{ github.event.pull_request.base.sha }} - name: Check Package Licenses - uses: angular/dev-infra/github-actions/linting/licenses@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/linting/licenses@7c08ac2a4f396bad752829fba09dbaefbcded9fc # Commit message check is last intentionally, because the caretaker can fix it # during merge, while other lint failures have to be resolved by the PR author. - name: Check commit message @@ -55,11 +55,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Check API Goldens @@ -69,11 +69,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Run e2e tests @@ -83,11 +83,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Run integration tests @@ -97,11 +97,11 @@ jobs: runs-on: ubuntu-latest-16core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Run tests @@ -111,11 +111,11 @@ jobs: runs-on: ubuntu-latest-16core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Run tests @@ -125,11 +125,11 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Install node modules run: pnpm install --frozen-lockfile - name: Build and Verify Release Output @@ -152,15 +152,15 @@ jobs: CI_RUNNER_NUMBER: ${{ github.run_id }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: # Checking out the pull request commit is intended here as we need to run the changed code tests. ref: ${{ github.event.pull_request.head.sha }} - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Browserstack Variables - uses: angular/dev-infra/github-actions/browserstack@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/browserstack@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Run tests on Browserstack run: ./scripts/circleci/run-browserstack-tests.sh diff --git a/.github/workflows/preview-build-dev-app.yml b/.github/workflows/preview-build-dev-app.yml index d1a0a3cd6480..51dfbc53bc5b 100644 --- a/.github/workflows/preview-build-dev-app.yml +++ b/.github/workflows/preview-build-dev-app.yml @@ -23,16 +23,16 @@ jobs: (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'dev-app preview')) steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc # Build the web package - run: bazel build //src/dev-app:web_package --symlink_prefix=dist/ - - uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@0edcf22f9ce677699274f2d399325f99d3d56e81 + - uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: workflow-artifact-name: 'dev-app' pull-number: '${{github.event.pull_request.number}}' diff --git a/.github/workflows/preview-deploy-dev-app.yml b/.github/workflows/preview-deploy-dev-app.yml index b28a7f6b113f..f8c782b9667f 100644 --- a/.github/workflows/preview-deploy-dev-app.yml +++ b/.github/workflows/preview-deploy-dev-app.yml @@ -33,7 +33,7 @@ jobs: npx -y firebase-tools@latest target:clear --project ${{env.PREVIEW_PROJECT}} hosting dev-app npx -y firebase-tools@latest target:apply --project ${{env.PREVIEW_PROJECT}} hosting dev-app ${{env.PREVIEW_SITE}} - - uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@0edcf22f9ce677699274f2d399325f99d3d56e81 + - uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: github-token: '${{secrets.GITHUB_TOKEN}}' workflow-artifact-name: 'dev-app' diff --git a/.github/workflows/scheduled-ci.yml b/.github/workflows/scheduled-ci.yml index a37155ba9e02..b532f67b0122 100644 --- a/.github/workflows/scheduled-ci.yml +++ b/.github/workflows/scheduled-ci.yml @@ -19,11 +19,11 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Setting up Angular snapshot builds @@ -39,11 +39,11 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Setting up Angular snapshot builds @@ -61,7 +61,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@0edcf22f9ce677699274f2d399325f99d3d56e81 + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc # See: https://github.com/puppeteer/puppeteer/pull/13196 and # https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md. - name: Disable AppArmor diff --git a/MODULE.bazel b/MODULE.bazel index a9e3fa086352..2d16fdbb9d14 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -39,7 +39,7 @@ git_override( bazel_dep(name = "devinfra") git_override( module_name = "devinfra", - commit = "0edcf22f9ce677699274f2d399325f99d3d56e81", + commit = "7c08ac2a4f396bad752829fba09dbaefbcded9fc", remote = "https://github.com/angular/dev-infra.git", ) diff --git a/package.json b/package.json index fd839d00968f..a0c14a71c3b4 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "devDependencies": { "@angular/compiler-cli": "catalog:", "@angular/localize": "catalog:", - "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#869bfda5998a1298e4eb55dbc97edc059625af5a", + "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#0125e8e025e98825616c46350f58502dbeddb038", "@angular/platform-server": "catalog:", "@angular/router": "catalog:", "@babel/core": "^7.16.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d62f6e9e591d..3df3f27f4693 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,53 +7,53 @@ settings: catalogs: default: '@angular-devkit/build-angular': - specifier: 21.2.0-next.2 - version: 21.2.0-next.2 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular-devkit/core': - specifier: 21.2.0-next.2 - version: 21.2.0-next.2 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular-devkit/schematics': - specifier: 21.2.0-next.2 - version: 21.2.0-next.2 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/cli': - specifier: 21.2.0-next.2 - version: 21.2.0-next.2 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/common': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/compiler': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/compiler-cli': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/core': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/forms': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/localize': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/platform-browser': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/platform-browser-dynamic': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/platform-server': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/router': - specifier: 21.2.0-next.3 - version: 21.2.0-next.3 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@angular/ssr': - specifier: 21.2.0-next.2 - version: 21.2.0-next.2 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 '@schematics/angular': - specifier: 21.2.0-next.2 - version: 21.2.0-next.2 + specifier: 21.2.0-rc.0 + version: 21.2.0-rc.0 rxjs: specifier: ^6.6.7 version: 6.6.7 @@ -69,25 +69,25 @@ importers: dependencies: '@angular-devkit/core': specifier: 'catalog:' - version: 21.2.0-next.2(chokidar@5.0.0) + version: 21.2.0-rc.0(chokidar@5.0.0) '@angular-devkit/schematics': specifier: 'catalog:' - version: 21.2.0-next.2(chokidar@5.0.0) + version: 21.2.0-rc.0(chokidar@5.0.0) '@angular/common': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) '@angular/compiler': specifier: 'catalog:' - version: 21.2.0-next.3 + version: 21.2.0-rc.0 '@angular/core': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) + version: 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) '@angular/forms': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) '@angular/platform-browser': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) '@types/google.maps': specifier: ^3.54.10 version: 3.58.1 @@ -121,19 +121,19 @@ importers: devDependencies: '@angular/compiler-cli': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2) + version: 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) '@angular/localize': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3) + version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0) '@angular/ng-dev': - specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#869bfda5998a1298e4eb55dbc97edc059625af5a - version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/869bfda5998a1298e4eb55dbc97edc059625af5a(@modelcontextprotocol/sdk@1.26.0) + specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#0125e8e025e98825616c46350f58502dbeddb038 + version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/0125e8e025e98825616c46350f58502dbeddb038(@modelcontextprotocol/sdk@1.26.0) '@angular/platform-server': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3)(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) '@angular/router': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) '@babel/core': specifier: ^7.16.12 version: 7.29.0 @@ -166,7 +166,7 @@ importers: version: 16.0.3(rollup@4.57.1) '@schematics/angular': specifier: 'catalog:' - version: 21.2.0-next.2(chokidar@5.0.0) + version: 21.2.0-rc.0(chokidar@5.0.0) '@types/babel__core': specifier: ^7.1.18 version: 7.20.5 @@ -361,25 +361,25 @@ importers: version: link:../src/cdk-experimental '@angular/common': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) '@angular/compiler': specifier: 'catalog:' - version: 21.2.0-next.3 + version: 21.2.0-rc.0 '@angular/components-examples': specifier: workspace:* version: link:../src/components-examples '@angular/core': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) + version: 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) '@angular/forms': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) '@angular/google-maps': specifier: workspace:* version: link:../src/google-maps '@angular/localize': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3) + version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0) '@angular/material': specifier: workspace:* version: link:../src/material @@ -391,16 +391,16 @@ importers: version: link:../src/material-luxon-adapter '@angular/platform-browser': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) '@angular/platform-browser-dynamic': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler@21.2.0-next.3)(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))) '@angular/router': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) '@angular/ssr': specifier: 'catalog:' - version: 21.2.0-next.2(732a4b7fff947bcf4560cdcda99ad9b0) + version: 21.2.0-rc.0(0cbd0fdcfddd4e429cff3ac260204f3f) '@angular/youtube-player': specifier: workspace:* version: link:../src/youtube-player @@ -425,13 +425,13 @@ importers: devDependencies: '@angular-devkit/build-angular': specifier: 'catalog:' - version: 21.2.0-next.2(27ef118a8e7055bf6f347df217a8d356) + version: 21.2.0-rc.0(85e9118f1bcacefdee125f6ee0de5595) '@angular/cli': specifier: 'catalog:' - version: 21.2.0-next.2(@types/node@22.19.11)(chokidar@5.0.0)(hono@4.11.9) + version: 21.2.0-rc.0(@types/node@22.19.11)(chokidar@5.0.0) '@angular/compiler-cli': specifier: 'catalog:' - version: 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2) + version: 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) '@bazel/bazelisk': specifier: ^1.12.1 version: 1.26.0 @@ -734,73 +734,73 @@ packages: '@actions/io@3.0.2': resolution: {integrity: sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==} - '@algolia/abtesting@1.13.0': - resolution: {integrity: sha512-Zrqam12iorp3FjiKMXSTpedGYznZ3hTEOAr2oCxI8tbF8bS1kQHClyDYNq/eV0ewMNLyFkgZVWjaS+8spsOYiQ==} + '@algolia/abtesting@1.14.1': + resolution: {integrity: sha512-Dkj0BgPiLAaim9sbQ97UKDFHJE/880wgStAM18U++NaJ/2Cws34J5731ovJifr6E3Pv4T2CqvMXf8qLCC417Ew==} engines: {node: '>= 14.0.0'} - '@algolia/client-abtesting@5.47.0': - resolution: {integrity: sha512-aOpsdlgS9xTEvz47+nXmw8m0NtUiQbvGWNuSEb7fA46iPL5FxOmOUZkh8PREBJpZ0/H8fclSc7BMJCVr+Dn72w==} + '@algolia/client-abtesting@5.48.1': + resolution: {integrity: sha512-LV5qCJdj+/m9I+Aj91o+glYszrzd7CX6NgKaYdTOj4+tUYfbS62pwYgUfZprYNayhkQpVFcrW8x8ZlIHpS23Vw==} engines: {node: '>= 14.0.0'} - '@algolia/client-analytics@5.47.0': - resolution: {integrity: sha512-EcF4w7IvIk1sowrO7Pdy4Ako7x/S8+nuCgdk6En+u5jsaNQM4rTT09zjBPA+WQphXkA2mLrsMwge96rf6i7Mow==} + '@algolia/client-analytics@5.48.1': + resolution: {integrity: sha512-/AVoMqHhPm14CcHq7mwB+bUJbfCv+jrxlNvRjXAuO+TQa+V37N8k1b0ijaRBPdmSjULMd8KtJbQyUyabXOu6Kg==} engines: {node: '>= 14.0.0'} - '@algolia/client-common@5.47.0': - resolution: {integrity: sha512-Wzg5Me2FqgRDj0lFuPWFK05UOWccSMsIBL2YqmTmaOzxVlLZ+oUqvKbsUSOE5ud8Fo1JU7JyiLmEXBtgDKzTwg==} + '@algolia/client-common@5.48.1': + resolution: {integrity: sha512-VXO+qu2Ep6ota28ktvBm3sG53wUHS2n7bgLWmce5jTskdlCD0/JrV4tnBm1l7qpla1CeoQb8D7ShFhad+UoSOw==} engines: {node: '>= 14.0.0'} - '@algolia/client-insights@5.47.0': - resolution: {integrity: sha512-Ci+cn/FDIsDxSKMRBEiyKrqybblbk8xugo6ujDN1GSTv9RIZxwxqZYuHfdLnLEwLlX7GB8pqVyqrUSlRnR+sJA==} + '@algolia/client-insights@5.48.1': + resolution: {integrity: sha512-zl+Qyb0nLg+Y5YvKp1Ij+u9OaPaKg2/EPzTwKNiVyOHnQJlFxmXyUZL1EInczAZsEY8hVpPCLtNfhMhfxluXKQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-personalization@5.47.0': - resolution: {integrity: sha512-gsLnHPZmWcX0T3IigkDL2imCNtsQ7dR5xfnwiFsb+uTHCuYQt+IwSNjsd8tok6HLGLzZrliSaXtB5mfGBtYZvQ==} + '@algolia/client-personalization@5.48.1': + resolution: {integrity: sha512-r89Qf9Oo9mKWQXumRu/1LtvVJAmEDpn8mHZMc485pRfQUMAwSSrsnaw1tQ3sszqzEgAr1c7rw6fjBI+zrAXTOw==} engines: {node: '>= 14.0.0'} - '@algolia/client-query-suggestions@5.47.0': - resolution: {integrity: sha512-PDOw0s8WSlR2fWFjPQldEpmm/gAoUgLigvC3k/jCSi/DzigdGX6RdC0Gh1RR1P8Cbk5KOWYDuL3TNzdYwkfDyA==} + '@algolia/client-query-suggestions@5.48.1': + resolution: {integrity: sha512-TPKNPKfghKG/bMSc7mQYD9HxHRUkBZA4q1PEmHgICaSeHQscGqL4wBrKkhfPlDV1uYBKW02pbFMUhsOt7p4ZpA==} engines: {node: '>= 14.0.0'} - '@algolia/client-search@5.47.0': - resolution: {integrity: sha512-b5hlU69CuhnS2Rqgsz7uSW0t4VqrLMLTPbUpEl0QVz56rsSwr1Sugyogrjb493sWDA+XU1FU5m9eB8uH7MoI0g==} + '@algolia/client-search@5.48.1': + resolution: {integrity: sha512-4Fu7dnzQyQmMFknYwTiN/HxPbH4DyxvQ1m+IxpPp5oslOgz8m6PG5qhiGbqJzH4HiT1I58ecDiCAC716UyVA8Q==} engines: {node: '>= 14.0.0'} - '@algolia/ingestion@1.47.0': - resolution: {integrity: sha512-WvwwXp5+LqIGISK3zHRApLT1xkuEk320/EGeD7uYy+K8WwDd5OjXnhjuXRhYr1685KnkvWkq1rQ/ihCJjOfHpQ==} + '@algolia/ingestion@1.48.1': + resolution: {integrity: sha512-/RFq3TqtXDUUawwic/A9xylA2P3LDMO8dNhphHAUOU51b1ZLHrmZ6YYJm3df1APz7xLY1aht6okCQf+/vmrV9w==} engines: {node: '>= 14.0.0'} - '@algolia/monitoring@1.47.0': - resolution: {integrity: sha512-j2EUFKAlzM0TE4GRfkDE3IDfkVeJdcbBANWzK16Tb3RHz87WuDfQ9oeEW6XiRE1/bEkq2xf4MvZesvSeQrZRDA==} + '@algolia/monitoring@1.48.1': + resolution: {integrity: sha512-Of0jTeAZRyRhC7XzDSjJef0aBkgRcvRAaw0ooYRlOw57APii7lZdq+layuNdeL72BRq1snaJhoMMwkmLIpJScw==} engines: {node: '>= 14.0.0'} - '@algolia/recommend@5.47.0': - resolution: {integrity: sha512-+kTSE4aQ1ARj2feXyN+DMq0CIDHJwZw1kpxIunedkmpWUg8k3TzFwWsMCzJVkF2nu1UcFbl7xsIURz3Q3XwOXA==} + '@algolia/recommend@5.48.1': + resolution: {integrity: sha512-bE7JcpFXzxF5zHwj/vkl2eiCBvyR1zQ7aoUdO+GDXxGp0DGw7nI0p8Xj6u8VmRQ+RDuPcICFQcCwRIJT5tDJFw==} engines: {node: '>= 14.0.0'} - '@algolia/requester-browser-xhr@5.47.0': - resolution: {integrity: sha512-Ja+zPoeSA2SDowPwCNRbm5Q2mzDvVV8oqxCQ4m6SNmbKmPlCfe30zPfrt9ho3kBHnsg37pGucwOedRIOIklCHw==} + '@algolia/requester-browser-xhr@5.48.1': + resolution: {integrity: sha512-MK3wZ2koLDnvH/AmqIF1EKbJlhRS5j74OZGkLpxI4rYvNi9Jn/C7vb5DytBnQ4KUWts7QsmbdwHkxY5txQHXVw==} engines: {node: '>= 14.0.0'} - '@algolia/requester-fetch@5.47.0': - resolution: {integrity: sha512-N6nOvLbaR4Ge+oVm7T4W/ea1PqcSbsHR4O58FJ31XtZjFPtOyxmnhgCmGCzP9hsJI6+x0yxJjkW5BMK/XI8OvA==} + '@algolia/requester-fetch@5.48.1': + resolution: {integrity: sha512-2oDT43Y5HWRSIQMPQI4tA/W+TN/N2tjggZCUsqQV440kxzzoPGsvv9QP1GhQ4CoDa+yn6ygUsGp6Dr+a9sPPSg==} engines: {node: '>= 14.0.0'} - '@algolia/requester-node-http@5.47.0': - resolution: {integrity: sha512-z1oyLq5/UVkohVXNDEY70mJbT/sv/t6HYtCvCwNrOri6pxBJDomP9R83KOlwcat+xqBQEdJHjbrPh36f1avmZA==} + '@algolia/requester-node-http@5.48.1': + resolution: {integrity: sha512-xcaCqbhupVWhuBP1nwbk1XNvwrGljozutEiLx06mvqDf3o8cHyEgQSHS4fKJM+UAggaWVnnFW+Nne5aQ8SUJXg==} engines: {node: '>= 14.0.0'} '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@angular-devkit/architect@0.2102.0-next.2': - resolution: {integrity: sha512-NyTKJlLThhV/+t5japC3B9aB3+0039edqe9i1M76mPit7R2TRl2N4ChVUfvrsnkWMZPcuYuo51Fiqn4mfZDbuQ==} + '@angular-devkit/architect@0.2102.0-rc.0': + resolution: {integrity: sha512-WutplD9wHcm6B1IraZULr5BU4jcLXDu17GzAU3oWnX4FkVly7jUcsfovHWNpndw0JDb1hK7wW74Xp7wP8PRJtw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular-devkit/build-angular@21.2.0-next.2': - resolution: {integrity: sha512-NEn3C5eRBSva8ELLtge8eYnT8KLWGLqxtFMwTpXmJctapOOmti6dLJNNZTwb+EgwWLHnJtToKy6PfzDhB/lO9w==} + '@angular-devkit/build-angular@21.2.0-rc.0': + resolution: {integrity: sha512-DSUj0Ch3/bSY+cOLrljYXsux7ZCogVZgMN0XFRgvcQo4mqBzpHutljtE6tkqBwiFF0inHkM5XBaXbGDSkX/JKg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: '@angular/compiler-cli': ^21.0.0 || ^21.2.0-next.0 @@ -809,7 +809,7 @@ packages: '@angular/platform-browser': ^21.0.0 || ^21.2.0-next.0 '@angular/platform-server': ^21.0.0 || ^21.2.0-next.0 '@angular/service-worker': ^21.0.0 || ^21.2.0-next.0 - '@angular/ssr': ^21.2.0-next.2 + '@angular/ssr': ^21.2.0-rc.0 '@web/test-runner': ^0.20.0 browser-sync: ^3.0.2 jest: ^30.2.0 @@ -849,15 +849,15 @@ packages: tailwindcss: optional: true - '@angular-devkit/build-webpack@0.2102.0-next.2': - resolution: {integrity: sha512-wefj1JSICwhv7bT5OB+16EAWtE8IyfjZ2rue1AO70c+f4k10nkZuP5dOurQcMJOjCjPlju9HjxC+PqzPje9ttA==} + '@angular-devkit/build-webpack@0.2102.0-rc.0': + resolution: {integrity: sha512-fRRyAOZwyMdWPwvZyLMUt4F+lbMMSS5JufAOAn2ylKm48emjSzZu6dl+E7uDFpQupKB5iIriLcycIjwkRGOtcA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: webpack: ^5.30.0 webpack-dev-server: ^5.0.2 - '@angular-devkit/core@21.2.0-next.2': - resolution: {integrity: sha512-PSwga7qIg6OISYIH01GcYY1CxXgbqqRbw8b8XMM/b4DFWpYmfmxQPN6Gp5qu1qo9xRCdsnI1abS1t2gADIhYQw==} + '@angular-devkit/core@21.2.0-rc.0': + resolution: {integrity: sha512-HnSUf2pkjSDdJMdkcb/eMgwI9TQG/TqZlqtTGjreraD0tr5WI2FWsdOQu2JGys8VgJK1Y+XYpvfL7EF1eSHeWw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: chokidar: ^5.0.0 @@ -865,12 +865,12 @@ packages: chokidar: optional: true - '@angular-devkit/schematics@21.2.0-next.2': - resolution: {integrity: sha512-yhrquiW2Q5WKKEYQwk7dj7XWWLc4Q/lQKsycdtSd5bhoNxWKeairlKKt3kxDFjUMjhxRE8kwUBg4N95FTWB8kA==} + '@angular-devkit/schematics@21.2.0-rc.0': + resolution: {integrity: sha512-G8idL0k1thHcy6cHnSLbBNKG1MSsTpqoEe4aaQIOtoAe8KEhIZ3jQfeFYWCHPFOPhnrExZc0l32UeDdEzQ4akw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - '@angular/build@21.2.0-next.2': - resolution: {integrity: sha512-NGbgWsX5fp4uBm85bDi20tvT8NteP/WB1WX3d0uthP25wdcXvIdxOIMQrJhLEwXsWlyAvDFI3vp6M/5EgzPiYw==} + '@angular/build@21.2.0-rc.0': + resolution: {integrity: sha512-8EORjR9+2KtU9Jc0PFjK8J5hrK1QJdkI9aTZZI7bTZ9Fie2Ymll5p3bEGL5mO5DZaDxGY+iA9vyfl10SsLKBpA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: '@angular/compiler': ^21.0.0 || ^21.2.0-next.0 @@ -880,7 +880,7 @@ packages: '@angular/platform-browser': ^21.0.0 || ^21.2.0-next.0 '@angular/platform-server': ^21.0.0 || ^21.2.0-next.0 '@angular/service-worker': ^21.0.0 || ^21.2.0-next.0 - '@angular/ssr': ^21.2.0-next.2 + '@angular/ssr': ^21.2.0-rc.0 karma: ^6.4.0 less: ^4.2.0 ng-packagr: ^21.0.0 || ^21.2.0-next.0 @@ -915,38 +915,38 @@ packages: vitest: optional: true - '@angular/cli@21.2.0-next.2': - resolution: {integrity: sha512-UI9a2aYBCmHORS4Rc4xXcD4djjcsS1mwVtfrJtROPfZVXVgTF57t+4jOmWv8i9JmcPCb4yR7BYy6AL5+lDEFkA==} + '@angular/cli@21.2.0-rc.0': + resolution: {integrity: sha512-Manaq4uJ+NBAfvtnsHPED88MiUYeD4a8Uy2aBREqypDU2iZOBzi3MdYtVso4TQkA68JtEb5WyazfB4tVZwl/Yw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular/common@21.2.0-next.3': - resolution: {integrity: sha512-7Mfsk/ahcKqvPFW1e9IMnfyvsyGKARIORdVxI8r/05N+Bt1aeW6iZbteEqM2cCEFZ4UqWjkaqdlBZndevqfqsA==} + '@angular/common@21.2.0-rc.0': + resolution: {integrity: sha512-2O3cbBIM8ls97XwkYVdgJwEg3UOy/bVZ0uBoY14cLskhETj6wbrFENiy8KpikZ+xsTxE9gWohairxCRiEoFuKg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/core': 21.2.0-next.3 + '@angular/core': 21.2.0-rc.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/compiler-cli@21.2.0-next.3': - resolution: {integrity: sha512-q3OUWuK/mspdxRfPQq2RPnGosq7yYzWzK+FikEYHv9I2pPTqt1cXWArWzknLouxs2zVaRhpaqXreCGtBeicYwg==} + '@angular/compiler-cli@21.2.0-rc.0': + resolution: {integrity: sha512-lHPA5BzQq9ttHXCAnAC/zW5vW0lFiawBIvRpNRbsI8Vw1noMs614OqZ2R6UBReVPE4kpyGwh7HCQIZyX5Cth6g==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} hasBin: true peerDependencies: - '@angular/compiler': 21.2.0-next.3 + '@angular/compiler': 21.2.0-rc.0 typescript: 5.9.2 peerDependenciesMeta: typescript: optional: true - '@angular/compiler@21.2.0-next.3': - resolution: {integrity: sha512-vMNEt+qFt4+k7lGoalHqmxgB6XiEWUTG7UaT9BkcU5Ezs64RLfkLVSGd0MNAuE2RL1gOa0/wvIl11yv0pD2T7g==} + '@angular/compiler@21.2.0-rc.0': + resolution: {integrity: sha512-gl2dQgMFKkH/iM/YxqWO0oIbYRpBZpOZuxj9W5TjG50EpMDioD1CNu2DfXpODVo3/rOfZJvOa+Jw0Cxpj5ClMQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@angular/core@21.2.0-next.3': - resolution: {integrity: sha512-9cieyRQ3DIWANEQ1DfjOuZS8EdzcPzaikO1Vi81hNmsr7an8yok0oRXfonkkudFUtAE0Xl6B1wYyD4FZ3ig47g==} + '@angular/core@21.2.0-rc.0': + resolution: {integrity: sha512-Txdi6ocSNC8GbCYMGh2AUm1lx+J11LNRjNrfGcgxQhQAiEPVO8jGojfObM+rdjv1h8t0pCms5vzEmFiJ9z06hg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/compiler': 21.2.0-next.3 + '@angular/compiler': 21.2.0-rc.0 rxjs: ^6.5.3 || ^7.4.0 zone.js: ~0.15.0 || ~0.16.0 peerDependenciesMeta: @@ -955,69 +955,69 @@ packages: zone.js: optional: true - '@angular/forms@21.2.0-next.3': - resolution: {integrity: sha512-YHrLsKO1fozXw0jptI3kwCc5w13DRQzf/Q8ajmtu+o2oy1NjYuoPlRyTBuIufThYKgBqC2ZfWOCWkOa8gyyKQA==} + '@angular/forms@21.2.0-rc.0': + resolution: {integrity: sha512-GsX4c+GYUxcKla8yO/hpEzpliCsMslP+yIIk9l6831PkSf3uCyKHUHriJtOEca4uN5fNo23ix5NXo5VPkmldLQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.2.0-next.3 - '@angular/core': 21.2.0-next.3 - '@angular/platform-browser': 21.2.0-next.3 + '@angular/common': 21.2.0-rc.0 + '@angular/core': 21.2.0-rc.0 + '@angular/platform-browser': 21.2.0-rc.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/localize@21.2.0-next.3': - resolution: {integrity: sha512-348iYNZ5PrnjxiSVuPE9XomIWrZNYOPPDq/3VVVTl/f9G+iwmHGfCJ1GsGxwg31DRu3X6ZFKw4IBqUyfLJaJiQ==} + '@angular/localize@21.2.0-rc.0': + resolution: {integrity: sha512-5OfXbWU0L9Py1mBIflZsdz9i39HF7wL38UxXzGe/y3my9I1Jk5fKD3J514htfgVXgdUqWogY6f2fpcxm2EP0Ug==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} hasBin: true peerDependencies: - '@angular/compiler': 21.2.0-next.3 - '@angular/compiler-cli': 21.2.0-next.3 + '@angular/compiler': 21.2.0-rc.0 + '@angular/compiler-cli': 21.2.0-rc.0 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/869bfda5998a1298e4eb55dbc97edc059625af5a': - resolution: {tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/869bfda5998a1298e4eb55dbc97edc059625af5a} - version: 0.0.0-0edcf22f9ce677699274f2d399325f99d3d56e81 + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/0125e8e025e98825616c46350f58502dbeddb038': + resolution: {tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/0125e8e025e98825616c46350f58502dbeddb038} + version: 0.0.0-7c08ac2a4f396bad752829fba09dbaefbcded9fc hasBin: true - '@angular/platform-browser-dynamic@21.2.0-next.3': - resolution: {integrity: sha512-ZuBl1S+sn8Fm8nvEK/ahXi+teT/taWCh4UNa6NrQImUt6BJcsK+2S/6wlYkntLndNHbTQAyVVVBcpmKWuUtOtA==} + '@angular/platform-browser-dynamic@21.2.0-rc.0': + resolution: {integrity: sha512-HicF0UfkwEiWViMngJsu8wQ82S9BhKLeDV8yUCQn4ojihquBTb46Wv2lyPPZNDMNA8RtXkAIIysvvAwPG/26YA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.2.0-next.3 - '@angular/compiler': 21.2.0-next.3 - '@angular/core': 21.2.0-next.3 - '@angular/platform-browser': 21.2.0-next.3 + '@angular/common': 21.2.0-rc.0 + '@angular/compiler': 21.2.0-rc.0 + '@angular/core': 21.2.0-rc.0 + '@angular/platform-browser': 21.2.0-rc.0 - '@angular/platform-browser@21.2.0-next.3': - resolution: {integrity: sha512-YsKkQaZ4jPs/xicQ9baJ0hlSLfKfsBsXrwNBw7XjvnyinU8tlB707KZ0eThyx9FSoLeBO2FgrWM75NTiEd2Rvg==} + '@angular/platform-browser@21.2.0-rc.0': + resolution: {integrity: sha512-FCNRhzkf35l6B18gzaT6GDdTJ3v4AiLOSXc5RdiQ2PMn2dLOkm70SH0caXQGzvtXAzHrHlR+Evj/ZqaFYvjcYg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/animations': 21.2.0-next.3 - '@angular/common': 21.2.0-next.3 - '@angular/core': 21.2.0-next.3 + '@angular/animations': 21.2.0-rc.0 + '@angular/common': 21.2.0-rc.0 + '@angular/core': 21.2.0-rc.0 peerDependenciesMeta: '@angular/animations': optional: true - '@angular/platform-server@21.2.0-next.3': - resolution: {integrity: sha512-ETjC41XcL0m19hONZebrGNKqOTFqtuz2qP6I5g4JKS6jDJ5aLx9ERtcq+ALnuEmPICcR7rbGzMigM2WTDTdZ0A==} + '@angular/platform-server@21.2.0-rc.0': + resolution: {integrity: sha512-Sx4PQVgIooDK8644MMtbN6YPjOb35bfXUImNK9m3saMoADqa8kZxPlM1Vg9ZKLoz4p75FJyPXxlh9sh6WNNTXw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.2.0-next.3 - '@angular/compiler': 21.2.0-next.3 - '@angular/core': 21.2.0-next.3 - '@angular/platform-browser': 21.2.0-next.3 + '@angular/common': 21.2.0-rc.0 + '@angular/compiler': 21.2.0-rc.0 + '@angular/core': 21.2.0-rc.0 + '@angular/platform-browser': 21.2.0-rc.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/router@21.2.0-next.3': - resolution: {integrity: sha512-NHokfVBqk8Elei9AtWreWdrm6oThwCbJZEbi3MqKJBEKCo33BEtZuv3QrwrbpNb+Pnm5RJVYMK4Z0sXvt/qohg==} + '@angular/router@21.2.0-rc.0': + resolution: {integrity: sha512-KZmZCdm4H+w3UC1vorQ/Nj4FEHY4sgRkwp+zf4E4WFV+sflyFzqFxzVIKGJ1xTzjaDebCRmipJnc3DZ09fv1fg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.2.0-next.3 - '@angular/core': 21.2.0-next.3 - '@angular/platform-browser': 21.2.0-next.3 + '@angular/common': 21.2.0-rc.0 + '@angular/core': 21.2.0-rc.0 + '@angular/platform-browser': 21.2.0-rc.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/ssr@21.2.0-next.2': - resolution: {integrity: sha512-KffNLgdclSqpzfY1Lqym25KwpJKBtlJW1GRuisq2OoHCJJq8CBfMFms+NzRmq7nuhMkWPzBtx+6TlMmyqCM3Jg==} + '@angular/ssr@21.2.0-rc.0': + resolution: {integrity: sha512-t2Y+xzXnZwKyT3aC6nhoTNY+gfGlbL9ROdkcsaMcZWGxqW/2qcF5pBj0Wk84Yb1kict+pwPxI1CtugvCgx1YfQ==} peerDependencies: '@angular/common': ^21.0.0 || ^21.2.0-next.0 '@angular/core': ^21.0.0 || ^21.2.0-next.0 @@ -1056,10 +1056,6 @@ packages: resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.0': - resolution: {integrity: sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==} - engines: {node: '>=6.9.0'} - '@babel/generator@7.29.1': resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} engines: {node: '>=6.9.0'} @@ -1625,312 +1621,156 @@ packages: '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} - '@esbuild/aix-ppc64@0.27.2': - resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - '@esbuild/aix-ppc64@0.27.3': resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.27.2': - resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.27.3': resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.27.2': - resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.27.3': resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.27.2': - resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.27.3': resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.27.2': - resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.27.3': resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.27.2': - resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.27.3': resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.27.2': - resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.27.3': resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.2': - resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.27.3': resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.27.2': - resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.27.3': resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.27.2': - resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.27.3': resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.27.2': - resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.27.3': resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.27.2': - resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.27.3': resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.27.2': - resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.27.3': resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.27.2': - resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.27.3': resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.27.2': - resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.27.3': resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.27.2': - resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.27.3': resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.27.2': - resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.27.3': resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.27.2': - resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-arm64@0.27.3': resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.2': - resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.27.3': resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.27.2': - resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.27.3': resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.2': - resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.27.3': resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.27.2': - resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - '@esbuild/openharmony-arm64@0.27.3': resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.27.2': - resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.27.3': resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.27.2': - resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.27.3': resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.27.2': - resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.27.3': resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.27.2': - resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.27.3': resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} engines: {node: '>=18'} @@ -2733,15 +2573,6 @@ packages: '@material/material-color-utilities@0.3.0': resolution: {integrity: sha512-ztmtTd6xwnuh2/xu+Vb01btgV8SQWYCaK56CkRK8gEkWe5TuDyBcYJ0wgkMRn+2VcE9KUmhvkz+N9GHrqw/C0g==} - '@modelcontextprotocol/sdk@1.25.3': - resolution: {integrity: sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==} - engines: {node: '>=18'} - peerDependencies: - '@cfworker/json-schema': ^4.1.1 - peerDependenciesMeta: - '@cfworker/json-schema': - optional: true - '@modelcontextprotocol/sdk@1.26.0': resolution: {integrity: sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==} engines: {node: '>=18'} @@ -2906,8 +2737,8 @@ packages: peerDependencies: '@angular/compiler-cli': '*' - '@ngtools/webpack@21.2.0-next.2': - resolution: {integrity: sha512-Sv1O31v5JDgYGGQFc1R4+R/McMF84CzZXd/wplGkoYnWjnmYY9/1ZrEGvl/QJ6vLaGZq5WRPuQzuZmH4Suq/2A==} + '@ngtools/webpack@21.2.0-rc.0': + resolution: {integrity: sha512-TsZvVcvRZl5xPtRyDpfKfGDyQ0SY5GT8BnJ9xffSV2moJhXTZujSkYHpq8dZTX2tyl9LymsDFrYncQ0f5ViHfQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: '@angular/compiler-cli': ^21.0.0 || ^21.2.0-next.0 @@ -3263,8 +3094,8 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 - '@oxc-project/types@0.112.0': - resolution: {integrity: sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ==} + '@oxc-project/types@0.113.0': + resolution: {integrity: sha512-Tp3XmgxwNQ9pEN9vxgJBAqdRamHibi76iowQ38O2I4PMpcvNRQNVsU2n1x1nv9yh0XoTrGFzf7cZSGxmixxrhA==} '@parcel/watcher-android-arm64@2.5.6': resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} @@ -3472,89 +3303,89 @@ packages: engines: {node: '>=18'} hasBin: true - '@rolldown/binding-android-arm64@1.0.0-rc.3': - resolution: {integrity: sha512-0T1k9FinuBZ/t7rZ8jN6OpUKPnUjNdYHoj/cESWrQ3ZraAJ4OMm6z7QjSfCxqj8mOp9kTKc1zHK3kGz5vMu+nQ==} + '@rolldown/binding-android-arm64@1.0.0-rc.4': + resolution: {integrity: sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-rc.3': - resolution: {integrity: sha512-JWWLzvcmc/3pe7qdJqPpuPk91SoE/N+f3PcWx/6ZwuyDVyungAEJPvKm/eEldiDdwTmaEzWfIR+HORxYWrCi1A==} + '@rolldown/binding-darwin-arm64@1.0.0-rc.4': + resolution: {integrity: sha512-kFgEvkWLqt3YCgKB5re9RlIrx9bRsvyVUnaTakEpOPuLGzLpLapYxE9BufJNvPg8GjT6mB1alN4yN1NjzoeM8Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.3': - resolution: {integrity: sha512-MTakBxfx3tde5WSmbHxuqlDsIW0EzQym+PJYGF4P6lG2NmKzi128OGynoFUqoD5ryCySEY85dug4v+LWGBElIw==} + '@rolldown/binding-darwin-x64@1.0.0-rc.4': + resolution: {integrity: sha512-JXmaOJGsL/+rsmMfutcDjxWM2fTaVgCHGoXS7nE8Z3c9NAYjGqHvXrAhMUZvMpHS/k7Mg+X7n/MVKb7NYWKKww==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-rc.3': - resolution: {integrity: sha512-jje3oopyOLs7IwfvXoS6Lxnmie5JJO7vW29fdGFu5YGY1EDbVDhD+P9vDihqS5X6fFiqL3ZQZCMBg6jyHkSVww==} + '@rolldown/binding-freebsd-x64@1.0.0-rc.4': + resolution: {integrity: sha512-ep3Catd6sPnHTM0P4hNEvIv5arnDvk01PfyJIJ+J3wVCG1eEaPo09tvFqdtcaTrkwQy0VWR24uz+cb4IsK53Qw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3': - resolution: {integrity: sha512-A0n8P3hdLAaqzSFrQoA42p23ZKBYQOw+8EH5r15Sa9X1kD9/JXe0YT2gph2QTWvdr0CVK2BOXiK6ENfy6DXOag==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.4': + resolution: {integrity: sha512-LwA5ayKIpnsgXJEwWc3h8wPiS33NMIHd9BhsV92T8VetVAbGe2qXlJwNVDGHN5cOQ22R9uYvbrQir2AB+ntT2w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3': - resolution: {integrity: sha512-kWXkoxxarYISBJ4bLNf5vFkEbb4JvccOwxWDxuK9yee8lg5XA7OpvlTptfRuwEvYcOZf+7VS69Uenpmpyo5Bjw==} + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.4': + resolution: {integrity: sha512-AC1WsGdlV1MtGay/OQ4J9T7GRadVnpYRzTcygV1hKnypbYN20Yh4t6O1Sa2qRBMqv1etulUknqXjc3CTIsBu6A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.3': - resolution: {integrity: sha512-Z03/wrqau9Bicfgb3Dbs6SYTHliELk2PM2LpG2nFd+cGupTMF5kanLEcj2vuuJLLhptNyS61rtk7SOZ+lPsTUA==} + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.4': + resolution: {integrity: sha512-lU+6rgXXViO61B4EudxtVMXSOfiZONR29Sys5VGSetUY7X8mg9FCKIIjcPPj8xNDeYzKl+H8F/qSKOBVFJChCQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.3': - resolution: {integrity: sha512-iSXXZsQp08CSilff/DCTFZHSVEpEwdicV3W8idHyrByrcsRDVh9sGC3sev6d8BygSGj3vt8GvUKBPCoyMA4tgQ==} + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.4': + resolution: {integrity: sha512-DZaN1f0PGp/bSvKhtw50pPsnln4T13ycDq1FrDWRiHmWt1JeW+UtYg9touPFf8yt993p8tS2QjybpzKNTxYEwg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.3': - resolution: {integrity: sha512-qaj+MFudtdCv9xZo9znFvkgoajLdc+vwf0Kz5N44g+LU5XMe+IsACgn3UG7uTRlCCvhMAGXm1XlpEA5bZBrOcw==} + '@rolldown/binding-linux-x64-musl@1.0.0-rc.4': + resolution: {integrity: sha512-RnGxwZLN7fhMMAItnD6dZ7lvy+TI7ba+2V54UF4dhaWa/p8I/ys1E73KO6HmPmgz92ZkfD8TXS1IMV8+uhbR9g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.3': - resolution: {integrity: sha512-U662UnMETyjT65gFmG9ma+XziENrs7BBnENi/27swZPYagubfHRirXHG2oMl+pEax2WvO7Kb9gHZmMakpYqBHQ==} + '@rolldown/binding-openharmony-arm64@1.0.0-rc.4': + resolution: {integrity: sha512-6lcI79+X8klGiGd8yHuTgQRjuuJYNggmEml+RsyN596P23l/zf9FVmJ7K0KVKkFAeYEdg0iMUKyIxiV5vebDNQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.3': - resolution: {integrity: sha512-gekrQ3Q2HiC1T5njGyuUJoGpK/l6B/TNXKed3fZXNf9YRTJn3L5MOZsFBn4bN2+UX+8+7hgdlTcEsexX988G4g==} + '@rolldown/binding-wasm32-wasi@1.0.0-rc.4': + resolution: {integrity: sha512-wz7ohsKCAIWy91blZ/1FlpPdqrsm1xpcEOQVveWoL6+aSPKL4VUcoYmmzuLTssyZxRpEwzuIxL/GDsvpjaBtOw==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3': - resolution: {integrity: sha512-85y5JifyMgs8m5K2XzR/VDsapKbiFiohl7s5lEj7nmNGO0pkTXE7q6TQScei96BNAsoK7JC3pA7ukA8WRHVJpg==} + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.4': + resolution: {integrity: sha512-cfiMrfuWCIgsFmcVG0IPuO6qTRHvF7NuG3wngX1RZzc6dU8FuBFb+J3MIR5WrdTNozlumfgL4cvz+R4ozBCvsQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.3': - resolution: {integrity: sha512-a4VUQZH7LxGbUJ3qJ/TzQG8HxdHvf+jOnqf7B7oFx1TEBm+j2KNL2zr5SQ7wHkNAcaPevF6gf9tQnVBnC4mD+A==} + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.4': + resolution: {integrity: sha512-p6UeR9y7ht82AH57qwGuFYn69S6CZ7LLKdCKy/8T3zS9VTrJei2/CGsTUV45Da4Z9Rbhc7G4gyWQ/Ioamqn09g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-rc.3': - resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} + '@rolldown/pluginutils@1.0.0-rc.4': + resolution: {integrity: sha512-1BrrmTu0TWfOP1riA8uakjFc9bpIUGzVKETsOtzY39pPga8zELGDl8eu1Dx7/gjM5CAz14UknsUMpBO8L+YntQ==} '@rollup/plugin-commonjs@29.0.0': resolution: {integrity: sha512-U2YHaxR2cU/yAiwKJtJRhnyLk7cifnQw0zUpISsocBDoHDJn+HTV74ABqnwr5bEgWUwFZC9oFL6wLe21lHu5eQ==} @@ -3730,8 +3561,8 @@ packages: cpu: [x64] os: [win32] - '@schematics/angular@21.2.0-next.2': - resolution: {integrity: sha512-INkmbKiw+IWbg049CYyA4V9FEDH2jRC6FhPDOGIP5bRPssJrffmFSCpm+8p0XuKiIPyDCYeRCsbFA2y0rfnNzw==} + '@schematics/angular@21.2.0-rc.0': + resolution: {integrity: sha512-IcQJVAkaEbFe1n7Ar/ktJRzpaxvJVo7pyjq00CK2QWdfwWzPm4KbLh6Dr6JhKomXSE6+OEKEcMmHE0ffr7ZQ1Q==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} '@sentry/core@9.47.1': @@ -4191,14 +4022,11 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} - algoliasearch@5.47.0: - resolution: {integrity: sha512-AGtz2U7zOV4DlsuYV84tLp2tBbA7RPtLA44jbVH4TTpDcc1dIWmULjHSsunlhscbzDydnjuFlNhflR3nV4VJaQ==} + algoliasearch@5.48.1: + resolution: {integrity: sha512-Rf7xmeuIo7nb6S4mp4abW2faW8DauZyE2faBIKFaUfP3wnpOvNSbiI5AwVhqBNj0jPgBWEvhyCu0sLjN2q77Rg==} engines: {node: '>= 14.0.0'} amdefine@1.0.1: @@ -5470,13 +5298,8 @@ packages: es6-promisify@5.0.0: resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} - esbuild-wasm@0.27.2: - resolution: {integrity: sha512-eUTnl8eh+v8UZIZh4MrMOKDAc8Lm7+NqP3pyuTORGFY1s/o9WoiJgKnwXy+te2J3hX7iRbFSHEyig7GsPeeJyw==} - engines: {node: '>=18'} - hasBin: true - - esbuild@0.27.2: - resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + esbuild-wasm@0.27.3: + resolution: {integrity: sha512-AUXuOxZ145/5Az+lIqk6TdJbxKTyDGkXMJpTExmBdbnHR6n6qAFx+F4oG9ORpVYJ9dQYeQAqzv51TO4DFKsbXw==} engines: {node: '>=18'} hasBin: true @@ -5620,12 +5443,6 @@ packages: exponential-backoff@3.1.3: resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} - express-rate-limit@7.5.1: - resolution: {integrity: sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==} - engines: {node: '>= 16'} - peerDependencies: - express: '>= 4.11' - express-rate-limit@8.2.1: resolution: {integrity: sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==} engines: {node: '>= 16'} @@ -6999,11 +6816,11 @@ packages: legacy-javascript@0.0.1: resolution: {integrity: sha512-lPyntS4/aS7jpuvOlitZDFifBCb4W8L/3QU0PLbUTUj+zYah8rfVjYic88yG7ZKTxhS5h9iz7duT8oUXKszLhg==} - less-loader@12.3.0: - resolution: {integrity: sha512-0M6+uYulvYIWs52y0LqN4+QM9TqWAohYSNTo4htE8Z7Cn3G/qQMEmktfHmyJT23k+20kU9zHH2wrfFXkxNLtVw==} + less-loader@12.3.1: + resolution: {integrity: sha512-JZZmG7gMzoDP3VGeEG8Sh6FW5wygB5jYL7Wp29FFihuRTsIBacqO3LbRPr2yStYD11riVf13selLm/CPFRDBRQ==} engines: {node: '>= 18.12.0'} peerDependencies: - '@rspack/core': 0.x || 1.x + '@rspack/core': 0.x || ^1.0.0 || ^2.0.0-0 less: ^3.5.0 || ^4.0.0 webpack: ^5.0.0 peerDependenciesMeta: @@ -7764,8 +7581,8 @@ packages: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} - ora@9.2.0: - resolution: {integrity: sha512-4sGT6oNDbqIuciDfD2aCkoPgHLmOe+g+xpFK2WDO0aQuD/bNHNwfdFosWP+DXmcxRyXeF8vnki6kXnOOHTuRSA==} + ora@9.3.0: + resolution: {integrity: sha512-lBX72MWFduWEf7v7uWf5DHp9Jn5BI8bNPGuFgtXMmr2uDz2Gz2749y3am3agSDdkhHPHYmmxEGSKH85ZLGzgXw==} engines: {node: '>=20'} ordered-binary@1.6.1: @@ -7841,8 +7658,8 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - pacote@21.1.0: - resolution: {integrity: sha512-WF/PwrImIIVaLmtuCeO5L7n6DA0ZGCqmDPO/XbNjZgNUX+2O5z4f4Wdmu6erBWNICkl3ftKJvit2eIVcpegRRw==} + pacote@21.3.1: + resolution: {integrity: sha512-O0EDXi85LF4AzdjG74GUwEArhdvawi/YOHcsW6IijKNj7wm8IvEWNF5GnfuxNpQ/ZpO3L37+v8hqdVh8GgWYhg==} engines: {node: ^20.17.0 || >=22.9.0} hasBin: true @@ -8528,8 +8345,8 @@ packages: resolution: {integrity: sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==} engines: {node: '>=10.0.0'} - rolldown@1.0.0-rc.3: - resolution: {integrity: sha512-Po/YZECDOqVXjIXrtC5h++a5NLvKAQNrd9ggrIG3sbDfGO5BqTUsrI6l8zdniKRp3r5Tp/2JTrXqx4GIguFCMw==} + rolldown@1.0.0-rc.4: + resolution: {integrity: sha512-V2tPDUrY3WSevrvU2E41ijZlpF+5PbZu4giH+VpNraaadsJGHa4fR6IFwsocVwEXDoAdIv5qgPPxgrvKAOIPtA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -8611,11 +8428,11 @@ packages: safevalues@1.2.0: resolution: {integrity: sha512-zIsuhjYvJCjfsfjoim2ab6gLKFYAnTiDSJGh0cC3T44L/4kNLL90hBG2BzrXPrHA3f8Ms8FSJ1mljKH5dVR1cw==} - sass-loader@16.0.6: - resolution: {integrity: sha512-sglGzId5gmlfxNs4gK2U3h7HlVRfx278YK6Ono5lwzuvi1jxig80YiuHkaDBVsYIKFhx8wN7XSCI0M2IDS/3qA==} + sass-loader@16.0.7: + resolution: {integrity: sha512-w6q+fRHourZ+e+xA1kcsF27iGM6jdB8teexYCfdUw0sYgcDNeZESnDNT9sUmmPm3ooziwUJXGwZJSTF3kOdBfA==} engines: {node: '>= 18.12.0'} peerDependencies: - '@rspack/core': 0.x || 1.x + '@rspack/core': 0.x || ^1.0.0 || ^2.0.0-0 node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 sass: ^1.3.0 sass-embedded: '*' @@ -9462,8 +9279,8 @@ packages: resolution: {integrity: sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==} engines: {node: '>=18.17'} - undici@7.20.0: - resolution: {integrity: sha512-MJZrkjyd7DeC+uPZh+5/YaMDxFiiEEaDgbUSVMXayofAkDWF1088CDo+2RPg7B1BuS1qf1vgNE7xqwPxE0DuSQ==} + undici@7.22.0: + resolution: {integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==} engines: {node: '>=20.18.1'} unicode-canonical-property-names-ecmascript@2.0.1: @@ -9752,8 +9569,8 @@ packages: html-webpack-plugin: optional: true - webpack@5.105.0: - resolution: {integrity: sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==} + webpack@5.105.2: + resolution: {integrity: sha512-dRXm0a2qcHPUBEzVk8uph0xWSjV/xZxenQQbLwnwP7caQCYpqG1qddwlyEkIDkYn0K8tvmcrZ+bOrzoQ3HxCDw==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -10063,112 +9880,112 @@ snapshots: '@actions/io@3.0.2': {} - '@algolia/abtesting@1.13.0': + '@algolia/abtesting@1.14.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/client-abtesting@5.47.0': + '@algolia/client-abtesting@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/client-analytics@5.47.0': + '@algolia/client-analytics@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/client-common@5.47.0': {} + '@algolia/client-common@5.48.1': {} - '@algolia/client-insights@5.47.0': + '@algolia/client-insights@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/client-personalization@5.47.0': + '@algolia/client-personalization@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/client-query-suggestions@5.47.0': + '@algolia/client-query-suggestions@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/client-search@5.47.0': + '@algolia/client-search@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/ingestion@1.47.0': + '@algolia/ingestion@1.48.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/monitoring@1.47.0': + '@algolia/monitoring@1.48.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/recommend@5.47.0': + '@algolia/recommend@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + '@algolia/client-common': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 - '@algolia/requester-browser-xhr@5.47.0': + '@algolia/requester-browser-xhr@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 + '@algolia/client-common': 5.48.1 - '@algolia/requester-fetch@5.47.0': + '@algolia/requester-fetch@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 + '@algolia/client-common': 5.48.1 - '@algolia/requester-node-http@5.47.0': + '@algolia/requester-node-http@5.48.1': dependencies: - '@algolia/client-common': 5.47.0 + '@algolia/client-common': 5.48.1 '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 - '@angular-devkit/architect@0.2102.0-next.2(chokidar@5.0.0)': + '@angular-devkit/architect@0.2102.0-rc.0(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.0-next.2(chokidar@5.0.0) + '@angular-devkit/core': 21.2.0-rc.0(chokidar@5.0.0) rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@angular-devkit/build-angular@21.2.0-next.2(27ef118a8e7055bf6f347df217a8d356)': + '@angular-devkit/build-angular@21.2.0-rc.0(85e9118f1bcacefdee125f6ee0de5595)': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.2102.0-next.2(chokidar@5.0.0) - '@angular-devkit/build-webpack': 0.2102.0-next.2(chokidar@5.0.0)(webpack-dev-server@5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.27.2)))(webpack@5.105.0(esbuild@0.27.2)) - '@angular-devkit/core': 21.2.0-next.2(chokidar@5.0.0) - '@angular/build': 21.2.0-next.2(8b7b30166d44cf176f98acb445f20626) - '@angular/compiler-cli': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2) + '@angular-devkit/architect': 0.2102.0-rc.0(chokidar@5.0.0) + '@angular-devkit/build-webpack': 0.2102.0-rc.0(chokidar@5.0.0)(webpack-dev-server@5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.2(esbuild@0.27.3)))(webpack@5.105.2(esbuild@0.27.3)) + '@angular-devkit/core': 21.2.0-rc.0(chokidar@5.0.0) + '@angular/build': 21.2.0-rc.0(6764fc96610980e51d4a5fd693e116ee) + '@angular/compiler-cli': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) '@babel/core': 7.29.0 - '@babel/generator': 7.29.0 + '@babel/generator': 7.29.1 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-split-export-declaration': 7.24.7 '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) @@ -10177,53 +9994,53 @@ snapshots: '@babel/preset-env': 7.29.0(@babel/core@7.29.0) '@babel/runtime': 7.28.6 '@discoveryjs/json-ext': 0.6.3 - '@ngtools/webpack': 21.2.0-next.2(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(typescript@5.9.2)(webpack@5.105.0(esbuild@0.27.2)) + '@ngtools/webpack': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(typescript@5.9.2)(webpack@5.105.2(esbuild@0.27.3)) ansi-colors: 4.1.3 autoprefixer: 10.4.24(postcss@8.5.6) - babel-loader: 10.0.0(@babel/core@7.29.0)(webpack@5.105.0(esbuild@0.27.2)) + babel-loader: 10.0.0(@babel/core@7.29.0)(webpack@5.105.2(esbuild@0.27.3)) browserslist: 4.28.1 - copy-webpack-plugin: 13.0.1(webpack@5.105.0(esbuild@0.27.2)) - css-loader: 7.1.3(webpack@5.105.0(esbuild@0.27.2)) - esbuild-wasm: 0.27.2 + copy-webpack-plugin: 13.0.1(webpack@5.105.2(esbuild@0.27.3)) + css-loader: 7.1.3(webpack@5.105.2(esbuild@0.27.3)) + esbuild-wasm: 0.27.3 http-proxy-middleware: 3.0.5 istanbul-lib-instrument: 6.0.3 jsonc-parser: 3.3.1 karma-source-map-support: 1.4.0 less: 4.4.2 - less-loader: 12.3.0(less@4.4.2)(webpack@5.105.0(esbuild@0.27.2)) - license-webpack-plugin: 4.0.2(webpack@5.105.0(esbuild@0.27.2)) + less-loader: 12.3.1(less@4.4.2)(webpack@5.105.2(esbuild@0.27.3)) + license-webpack-plugin: 4.0.2(webpack@5.105.2(esbuild@0.27.3)) loader-utils: 3.3.1 - mini-css-extract-plugin: 2.10.0(webpack@5.105.0(esbuild@0.27.2)) + mini-css-extract-plugin: 2.10.0(webpack@5.105.2(esbuild@0.27.3)) open: 11.0.0 - ora: 9.2.0 + ora: 9.3.0 picomatch: 4.0.3 piscina: 5.1.4 postcss: 8.5.6 - postcss-loader: 8.2.0(postcss@8.5.6)(typescript@5.9.2)(webpack@5.105.0(esbuild@0.27.2)) + postcss-loader: 8.2.0(postcss@8.5.6)(typescript@5.9.2)(webpack@5.105.2(esbuild@0.27.3)) resolve-url-loader: 5.0.0 rxjs: 7.8.2 sass: 1.97.3 - sass-loader: 16.0.6(sass@1.97.3)(webpack@5.105.0(esbuild@0.27.2)) - semver: 7.7.3 - source-map-loader: 5.0.0(webpack@5.105.0(esbuild@0.27.2)) + sass-loader: 16.0.7(sass@1.97.3)(webpack@5.105.2(esbuild@0.27.3)) + semver: 7.7.4 + source-map-loader: 5.0.0(webpack@5.105.2(esbuild@0.27.3)) source-map-support: 0.5.21 terser: 5.46.0 tinyglobby: 0.2.15 tree-kill: 1.2.2 tslib: 2.8.1 typescript: 5.9.2 - webpack: 5.105.0(esbuild@0.27.2) - webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.105.0(esbuild@0.27.2)) - webpack-dev-server: 5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.27.2)) + webpack: 5.105.2(esbuild@0.27.3) + webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.105.2(esbuild@0.27.3)) + webpack-dev-server: 5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.2(esbuild@0.27.3)) webpack-merge: 6.0.1 - webpack-subresource-integrity: 5.1.0(webpack@5.105.0(esbuild@0.27.2)) + webpack-subresource-integrity: 5.1.0(webpack@5.105.2(esbuild@0.27.3)) optionalDependencies: - '@angular/core': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/localize': 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3) - '@angular/platform-browser': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)) - '@angular/platform-server': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3)(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) - '@angular/ssr': 21.2.0-next.2(732a4b7fff947bcf4560cdcda99ad9b0) - esbuild: 0.27.2 + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/localize': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + '@angular/platform-server': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + '@angular/ssr': 21.2.0-rc.0(0cbd0fdcfddd4e429cff3ac260204f3f) + esbuild: 0.27.3 karma: 6.4.4(bufferutil@4.1.0) protractor: 7.0.0 transitivePeerDependencies: @@ -10249,18 +10066,18 @@ snapshots: - webpack-cli - yaml - '@angular-devkit/build-webpack@0.2102.0-next.2(chokidar@5.0.0)(webpack-dev-server@5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.27.2)))(webpack@5.105.0(esbuild@0.27.2))': + '@angular-devkit/build-webpack@0.2102.0-rc.0(chokidar@5.0.0)(webpack-dev-server@5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.2(esbuild@0.27.3)))(webpack@5.105.2(esbuild@0.27.3))': dependencies: - '@angular-devkit/architect': 0.2102.0-next.2(chokidar@5.0.0) + '@angular-devkit/architect': 0.2102.0-rc.0(chokidar@5.0.0) rxjs: 7.8.2 - webpack: 5.105.0(esbuild@0.27.2) - webpack-dev-server: 5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.27.2)) + webpack: 5.105.2(esbuild@0.27.3) + webpack-dev-server: 5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.2(esbuild@0.27.3)) transitivePeerDependencies: - chokidar - '@angular-devkit/core@21.2.0-next.2(chokidar@5.0.0)': + '@angular-devkit/core@21.2.0-rc.0(chokidar@5.0.0)': dependencies: - ajv: 8.17.1 + ajv: 8.18.0 ajv-formats: 3.0.1 jsonc-parser: 3.3.1 picomatch: 4.0.3 @@ -10269,22 +10086,22 @@ snapshots: optionalDependencies: chokidar: 5.0.0 - '@angular-devkit/schematics@21.2.0-next.2(chokidar@5.0.0)': + '@angular-devkit/schematics@21.2.0-rc.0(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.0-next.2(chokidar@5.0.0) + '@angular-devkit/core': 21.2.0-rc.0(chokidar@5.0.0) jsonc-parser: 3.3.1 magic-string: 0.30.21 - ora: 9.2.0 + ora: 9.3.0 rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@angular/build@21.2.0-next.2(8b7b30166d44cf176f98acb445f20626)': + '@angular/build@21.2.0-rc.0(6764fc96610980e51d4a5fd693e116ee)': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.2102.0-next.2(chokidar@5.0.0) - '@angular/compiler': 21.2.0-next.3 - '@angular/compiler-cli': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2) + '@angular-devkit/architect': 0.2102.0-rc.0(chokidar@5.0.0) + '@angular/compiler': 21.2.0-rc.0 + '@angular/compiler-cli': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-split-export-declaration': 7.24.7 @@ -10292,7 +10109,7 @@ snapshots: '@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.1(@types/node@22.19.11)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) beasties: 0.4.1 browserslist: 4.28.1 - esbuild: 0.27.2 + esbuild: 0.27.3 https-proxy-agent: 7.0.6(supports-color@10.2.2) istanbul-lib-instrument: 6.0.3 jsonc-parser: 3.3.1 @@ -10302,22 +10119,22 @@ snapshots: parse5-html-rewriting-stream: 8.0.0 picomatch: 4.0.3 piscina: 5.1.4 - rolldown: 1.0.0-rc.3 + rolldown: 1.0.0-rc.4 sass: 1.97.3 - semver: 7.7.3 + semver: 7.7.4 source-map-support: 0.5.21 tinyglobby: 0.2.15 tslib: 2.8.1 typescript: 5.9.2 - undici: 7.20.0 + undici: 7.22.0 vite: 7.3.1(@types/node@22.19.11)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) watchpack: 2.5.1 optionalDependencies: - '@angular/core': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/localize': 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3) - '@angular/platform-browser': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)) - '@angular/platform-server': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3)(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) - '@angular/ssr': 21.2.0-next.2(732a4b7fff947bcf4560cdcda99ad9b0) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/localize': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + '@angular/platform-server': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + '@angular/ssr': 21.2.0-rc.0(0cbd0fdcfddd4e429cff3ac260204f3f) karma: 6.4.4(bufferutil@4.1.0) less: 4.4.2 lmdb: 3.5.1 @@ -10335,46 +10152,45 @@ snapshots: - tsx - yaml - '@angular/cli@21.2.0-next.2(@types/node@22.19.11)(chokidar@5.0.0)(hono@4.11.9)': + '@angular/cli@21.2.0-rc.0(@types/node@22.19.11)(chokidar@5.0.0)': dependencies: - '@angular-devkit/architect': 0.2102.0-next.2(chokidar@5.0.0) - '@angular-devkit/core': 21.2.0-next.2(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.0-next.2(chokidar@5.0.0) + '@angular-devkit/architect': 0.2102.0-rc.0(chokidar@5.0.0) + '@angular-devkit/core': 21.2.0-rc.0(chokidar@5.0.0) + '@angular-devkit/schematics': 21.2.0-rc.0(chokidar@5.0.0) '@inquirer/prompts': 7.10.1(@types/node@22.19.11) '@listr2/prompt-adapter-inquirer': 3.0.5(@inquirer/prompts@7.10.1(@types/node@22.19.11))(@types/node@22.19.11)(listr2@9.0.5) - '@modelcontextprotocol/sdk': 1.25.3(hono@4.11.9) - '@schematics/angular': 21.2.0-next.2(chokidar@5.0.0) + '@modelcontextprotocol/sdk': 1.26.0 + '@schematics/angular': 21.2.0-rc.0(chokidar@5.0.0) '@yarnpkg/lockfile': 1.1.0 - algoliasearch: 5.47.0 + algoliasearch: 5.48.1 ini: 6.0.0 jsonc-parser: 3.3.1 listr2: 9.0.5 npm-package-arg: 13.0.2 - pacote: 21.1.0 + pacote: 21.3.1 parse5-html-rewriting-stream: 8.0.0 - semver: 7.7.3 + semver: 7.7.4 yargs: 18.0.0 zod: 4.3.6 transitivePeerDependencies: - '@cfworker/json-schema' - '@types/node' - chokidar - - hono - supports-color - '@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7)': + '@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7)': dependencies: - '@angular/core': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) - '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2)) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) rxjs: 6.6.7 tslib: 2.8.1 transitivePeerDependencies: - '@angular/compiler-cli' - supports-color - '@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2)': + '@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)': dependencies: - '@angular/compiler': 21.2.0-next.3 + '@angular/compiler': 21.2.0-rc.0 '@babel/core': 7.29.0 '@jridgewell/sourcemap-codec': 1.5.5 chokidar: 5.0.0 @@ -10388,24 +10204,24 @@ snapshots: transitivePeerDependencies: - supports-color - '@angular/compiler@21.2.0-next.3': + '@angular/compiler@21.2.0-rc.0': dependencies: tslib: 2.8.1 - '@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)': + '@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)': dependencies: rxjs: 6.6.7 tslib: 2.8.1 optionalDependencies: - '@angular/compiler': 21.2.0-next.3 + '@angular/compiler': 21.2.0-rc.0 zone.js: 0.16.0 - '@angular/forms@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7)': + '@angular/forms@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7)': dependencies: - '@angular/common': 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/core': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/platform-browser': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)) - '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2)) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) '@standard-schema/spec': 1.1.0 rxjs: 6.6.7 tslib: 2.8.1 @@ -10413,19 +10229,19 @@ snapshots: - '@angular/compiler-cli' - supports-color - '@angular/localize@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3)': + '@angular/localize@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)': dependencies: - '@angular/compiler': 21.2.0-next.3 - '@angular/compiler-cli': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2) + '@angular/compiler': 21.2.0-rc.0 + '@angular/compiler-cli': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) '@babel/core': 7.29.0 - '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2)) + '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) '@types/babel__core': 7.20.5 tinyglobby: 0.2.15 yargs: 18.0.0 transitivePeerDependencies: - supports-color - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/869bfda5998a1298e4eb55dbc97edc059625af5a(@modelcontextprotocol/sdk@1.26.0)': + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/0125e8e025e98825616c46350f58502dbeddb038(@modelcontextprotocol/sdk@1.26.0)': dependencies: '@actions/core': 3.0.0 '@google-cloud/spanner': 8.0.0(supports-color@10.2.2) @@ -10486,31 +10302,31 @@ snapshots: - '@modelcontextprotocol/sdk' - '@react-native-async-storage/async-storage' - '@angular/platform-browser-dynamic@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler@21.2.0-next.3)(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))': + '@angular/platform-browser-dynamic@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))': dependencies: - '@angular/common': 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/compiler': 21.2.0-next.3 - '@angular/core': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/platform-browser': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + '@angular/compiler': 21.2.0-rc.0 + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) tslib: 2.8.1 - '@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))': + '@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))': dependencies: - '@angular/common': 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/core': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) - '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2)) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) tslib: 2.8.1 transitivePeerDependencies: - '@angular/compiler-cli' - supports-color - '@angular/platform-server@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3)(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7)': + '@angular/platform-server@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7)': dependencies: - '@angular/common': 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/compiler': 21.2.0-next.3 - '@angular/core': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/platform-browser': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)) - '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2)) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + '@angular/compiler': 21.2.0-rc.0 + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) rxjs: 6.6.7 tslib: 2.8.1 xhr2: 0.2.1 @@ -10518,26 +10334,26 @@ snapshots: - '@angular/compiler-cli' - supports-color - '@angular/router@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7)': + '@angular/router@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7)': dependencies: - '@angular/common': 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/core': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/platform-browser': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)) - '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2)) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) rxjs: 6.6.7 tslib: 2.8.1 transitivePeerDependencies: - '@angular/compiler-cli' - supports-color - '@angular/ssr@21.2.0-next.2(732a4b7fff947bcf4560cdcda99ad9b0)': + '@angular/ssr@21.2.0-rc.0(0cbd0fdcfddd4e429cff3ac260204f3f)': dependencies: - '@angular/common': 21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/core': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/router': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/router': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) tslib: 2.8.1 optionalDependencies: - '@angular/platform-server': 21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/compiler@21.2.0-next.3)(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-next.3(@angular/common@21.2.0-next.3(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(@angular/core@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + '@angular/platform-server': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) '@apidevtools/json-schema-ref-parser@9.1.2': dependencies: @@ -10612,14 +10428,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.0': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - '@babel/generator@7.29.1': dependencies: '@babel/parser': 7.29.0 @@ -11331,159 +11139,81 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.27.2': - optional: true - '@esbuild/aix-ppc64@0.27.3': optional: true - '@esbuild/android-arm64@0.27.2': - optional: true - '@esbuild/android-arm64@0.27.3': optional: true - '@esbuild/android-arm@0.27.2': - optional: true - '@esbuild/android-arm@0.27.3': optional: true - '@esbuild/android-x64@0.27.2': - optional: true - '@esbuild/android-x64@0.27.3': optional: true - '@esbuild/darwin-arm64@0.27.2': - optional: true - '@esbuild/darwin-arm64@0.27.3': optional: true - '@esbuild/darwin-x64@0.27.2': - optional: true - '@esbuild/darwin-x64@0.27.3': optional: true - '@esbuild/freebsd-arm64@0.27.2': - optional: true - '@esbuild/freebsd-arm64@0.27.3': optional: true - '@esbuild/freebsd-x64@0.27.2': - optional: true - '@esbuild/freebsd-x64@0.27.3': optional: true - '@esbuild/linux-arm64@0.27.2': - optional: true - '@esbuild/linux-arm64@0.27.3': optional: true - '@esbuild/linux-arm@0.27.2': - optional: true - '@esbuild/linux-arm@0.27.3': optional: true - '@esbuild/linux-ia32@0.27.2': - optional: true - '@esbuild/linux-ia32@0.27.3': optional: true - '@esbuild/linux-loong64@0.27.2': - optional: true - '@esbuild/linux-loong64@0.27.3': optional: true - '@esbuild/linux-mips64el@0.27.2': - optional: true - '@esbuild/linux-mips64el@0.27.3': optional: true - '@esbuild/linux-ppc64@0.27.2': - optional: true - '@esbuild/linux-ppc64@0.27.3': optional: true - '@esbuild/linux-riscv64@0.27.2': - optional: true - '@esbuild/linux-riscv64@0.27.3': optional: true - '@esbuild/linux-s390x@0.27.2': - optional: true - '@esbuild/linux-s390x@0.27.3': optional: true - '@esbuild/linux-x64@0.27.2': - optional: true - '@esbuild/linux-x64@0.27.3': optional: true - '@esbuild/netbsd-arm64@0.27.2': - optional: true - '@esbuild/netbsd-arm64@0.27.3': optional: true - '@esbuild/netbsd-x64@0.27.2': - optional: true - '@esbuild/netbsd-x64@0.27.3': optional: true - '@esbuild/openbsd-arm64@0.27.2': - optional: true - '@esbuild/openbsd-arm64@0.27.3': optional: true - '@esbuild/openbsd-x64@0.27.2': - optional: true - '@esbuild/openbsd-x64@0.27.3': optional: true - '@esbuild/openharmony-arm64@0.27.2': - optional: true - '@esbuild/openharmony-arm64@0.27.3': optional: true - '@esbuild/sunos-x64@0.27.2': - optional: true - '@esbuild/sunos-x64@0.27.3': optional: true - '@esbuild/win32-arm64@0.27.2': - optional: true - '@esbuild/win32-arm64@0.27.3': optional: true - '@esbuild/win32-ia32@0.27.2': - optional: true - '@esbuild/win32-ia32@0.27.3': optional: true - '@esbuild/win32-x64@0.27.2': - optional: true - '@esbuild/win32-x64@0.27.3': optional: true @@ -12434,28 +12164,6 @@ snapshots: '@material/material-color-utilities@0.3.0': {} - '@modelcontextprotocol/sdk@1.25.3(hono@4.11.9)': - dependencies: - '@hono/node-server': 1.19.9(hono@4.11.9) - ajv: 8.18.0 - ajv-formats: 3.0.1 - content-type: 1.0.5 - cors: 2.8.6 - cross-spawn: 7.0.6 - eventsource: 3.0.7 - eventsource-parser: 3.0.6 - express: 5.2.1 - express-rate-limit: 7.5.1(express@5.2.1) - jose: 6.1.3 - json-schema-typed: 8.0.2 - pkce-challenge: 5.0.1 - raw-body: 3.0.2 - zod: 4.3.6 - zod-to-json-schema: 3.25.1(zod@4.3.6) - transitivePeerDependencies: - - hono - - supports-color - '@modelcontextprotocol/sdk@1.26.0': dependencies: '@hono/node-server': 1.19.9(hono@4.11.9) @@ -12584,9 +12292,9 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@nginfra/angular-linking@1.0.9(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))': + '@nginfra/angular-linking@1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))': dependencies: - '@angular/compiler-cli': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2) + '@angular/compiler-cli': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) '@babel/core': 7.26.10 '@types/babel__core': 7.20.5 '@types/node': 22.19.11 @@ -12595,11 +12303,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@ngtools/webpack@21.2.0-next.2(@angular/compiler-cli@21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2))(typescript@5.9.2)(webpack@5.105.0(esbuild@0.27.2))': + '@ngtools/webpack@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(typescript@5.9.2)(webpack@5.105.2(esbuild@0.27.3))': dependencies: - '@angular/compiler-cli': 21.2.0-next.3(@angular/compiler@21.2.0-next.3)(typescript@5.9.2) + '@angular/compiler-cli': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) typescript: 5.9.2 - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) '@noble/hashes@1.4.0': {} @@ -13050,7 +12758,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@oxc-project/types@0.112.0': {} + '@oxc-project/types@0.113.0': {} '@parcel/watcher-android-arm64@2.5.6': optional: true @@ -13293,48 +13001,48 @@ snapshots: - react-native-b4a - supports-color - '@rolldown/binding-android-arm64@1.0.0-rc.3': + '@rolldown/binding-android-arm64@1.0.0-rc.4': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.3': + '@rolldown/binding-darwin-arm64@1.0.0-rc.4': optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.3': + '@rolldown/binding-darwin-x64@1.0.0-rc.4': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.3': + '@rolldown/binding-freebsd-x64@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3': + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.3': + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.3': + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.4': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.3': + '@rolldown/binding-linux-x64-musl@1.0.0-rc.4': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.3': + '@rolldown/binding-openharmony-arm64@1.0.0-rc.4': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.3': + '@rolldown/binding-wasm32-wasi@1.0.0-rc.4': dependencies: '@napi-rs/wasm-runtime': 1.1.1 optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3': + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.4': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.3': + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.4': optional: true - '@rolldown/pluginutils@1.0.0-rc.3': {} + '@rolldown/pluginutils@1.0.0-rc.4': {} '@rollup/plugin-commonjs@29.0.0(rollup@4.57.1)': dependencies: @@ -13449,10 +13157,10 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.57.1': optional: true - '@schematics/angular@21.2.0-next.2(chokidar@5.0.0)': + '@schematics/angular@21.2.0-rc.0(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.0-next.2(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.0-next.2(chokidar@5.0.0) + '@angular-devkit/core': 21.2.0-rc.0(chokidar@5.0.0) + '@angular-devkit/schematics': 21.2.0-rc.0(chokidar@5.0.0) jsonc-parser: 3.3.1 transitivePeerDependencies: - chokidar @@ -13991,13 +13699,6 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 @@ -14005,22 +13706,22 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - algoliasearch@5.47.0: - dependencies: - '@algolia/abtesting': 1.13.0 - '@algolia/client-abtesting': 5.47.0 - '@algolia/client-analytics': 5.47.0 - '@algolia/client-common': 5.47.0 - '@algolia/client-insights': 5.47.0 - '@algolia/client-personalization': 5.47.0 - '@algolia/client-query-suggestions': 5.47.0 - '@algolia/client-search': 5.47.0 - '@algolia/ingestion': 1.47.0 - '@algolia/monitoring': 1.47.0 - '@algolia/recommend': 5.47.0 - '@algolia/requester-browser-xhr': 5.47.0 - '@algolia/requester-fetch': 5.47.0 - '@algolia/requester-node-http': 5.47.0 + algoliasearch@5.48.1: + dependencies: + '@algolia/abtesting': 1.14.1 + '@algolia/client-abtesting': 5.48.1 + '@algolia/client-analytics': 5.48.1 + '@algolia/client-common': 5.48.1 + '@algolia/client-insights': 5.48.1 + '@algolia/client-personalization': 5.48.1 + '@algolia/client-query-suggestions': 5.48.1 + '@algolia/client-search': 5.48.1 + '@algolia/ingestion': 1.48.1 + '@algolia/monitoring': 1.48.1 + '@algolia/recommend': 5.48.1 + '@algolia/requester-browser-xhr': 5.48.1 + '@algolia/requester-fetch': 5.48.1 + '@algolia/requester-node-http': 5.48.1 amdefine@1.0.1: optional: true @@ -14188,11 +13889,11 @@ snapshots: b4a@1.7.4: {} - babel-loader@10.0.0(@babel/core@7.29.0)(webpack@5.105.0(esbuild@0.27.2)): + babel-loader@10.0.0(@babel/core@7.29.0)(webpack@5.105.2(esbuild@0.27.3)): dependencies: '@babel/core': 7.29.0 find-up: 5.0.0 - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.29.0): dependencies: @@ -14860,14 +14561,14 @@ snapshots: dependencies: is-what: 3.14.1 - copy-webpack-plugin@13.0.1(webpack@5.105.0(esbuild@0.27.2)): + copy-webpack-plugin@13.0.1(webpack@5.105.2(esbuild@0.27.3)): dependencies: glob-parent: 6.0.2 normalize-path: 3.0.0 schema-utils: 4.3.3 serialize-javascript: 6.0.2 tinyglobby: 0.2.15 - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) core-js-compat@3.48.0: dependencies: @@ -14932,7 +14633,7 @@ snapshots: css-functions-list@3.3.3: {} - css-loader@7.1.3(webpack@5.105.0(esbuild@0.27.2)): + css-loader@7.1.3(webpack@5.105.2(esbuild@0.27.3)): dependencies: icss-utils: 5.1.0(postcss@8.5.6) postcss: 8.5.6 @@ -14943,7 +14644,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.7.4 optionalDependencies: - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) css-select@6.0.0: dependencies: @@ -15420,36 +15121,7 @@ snapshots: dependencies: es6-promise: 4.2.8 - esbuild-wasm@0.27.2: {} - - esbuild@0.27.2: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.2 - '@esbuild/android-arm': 0.27.2 - '@esbuild/android-arm64': 0.27.2 - '@esbuild/android-x64': 0.27.2 - '@esbuild/darwin-arm64': 0.27.2 - '@esbuild/darwin-x64': 0.27.2 - '@esbuild/freebsd-arm64': 0.27.2 - '@esbuild/freebsd-x64': 0.27.2 - '@esbuild/linux-arm': 0.27.2 - '@esbuild/linux-arm64': 0.27.2 - '@esbuild/linux-ia32': 0.27.2 - '@esbuild/linux-loong64': 0.27.2 - '@esbuild/linux-mips64el': 0.27.2 - '@esbuild/linux-ppc64': 0.27.2 - '@esbuild/linux-riscv64': 0.27.2 - '@esbuild/linux-s390x': 0.27.2 - '@esbuild/linux-x64': 0.27.2 - '@esbuild/netbsd-arm64': 0.27.2 - '@esbuild/netbsd-x64': 0.27.2 - '@esbuild/openbsd-arm64': 0.27.2 - '@esbuild/openbsd-x64': 0.27.2 - '@esbuild/openharmony-arm64': 0.27.2 - '@esbuild/sunos-x64': 0.27.2 - '@esbuild/win32-arm64': 0.27.2 - '@esbuild/win32-ia32': 0.27.2 - '@esbuild/win32-x64': 0.27.2 + esbuild-wasm@0.27.3: {} esbuild@0.27.3: optionalDependencies: @@ -15621,10 +15293,6 @@ snapshots: exponential-backoff@3.1.3: {} - express-rate-limit@7.5.1(express@5.2.1): - dependencies: - express: 5.2.1 - express-rate-limit@8.2.1(express@5.2.1): dependencies: express: 5.2.1 @@ -17315,11 +16983,11 @@ snapshots: legacy-javascript@0.0.1: {} - less-loader@12.3.0(less@4.4.2)(webpack@5.105.0(esbuild@0.27.2)): + less-loader@12.3.1(less@4.4.2)(webpack@5.105.2(esbuild@0.27.3)): dependencies: less: 4.4.2 optionalDependencies: - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) less@4.4.2: dependencies: @@ -17348,11 +17016,11 @@ snapshots: libsodium@0.7.16: {} - license-webpack-plugin@4.0.2(webpack@5.105.0(esbuild@0.27.2)): + license-webpack-plugin@4.0.2(webpack@5.105.2(esbuild@0.27.3)): dependencies: webpack-sources: 3.3.4 optionalDependencies: - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) lie@3.3.0: dependencies: @@ -17735,11 +17403,11 @@ snapshots: min-indent@1.0.1: {} - mini-css-extract-plugin@2.10.0(webpack@5.105.0(esbuild@0.27.2)): + mini-css-extract-plugin@2.10.0(webpack@5.105.2(esbuild@0.27.3)): dependencies: schema-utils: 4.3.3 tapable: 2.3.0 - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) minimalistic-assert@1.0.1: {} @@ -18192,7 +17860,7 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 - ora@9.2.0: + ora@9.3.0: dependencies: chalk: 5.6.2 cli-cursor: 5.0.0 @@ -18277,7 +17945,7 @@ snapshots: package-json-from-dist@1.0.1: {} - pacote@21.1.0: + pacote@21.3.1: dependencies: '@npmcli/git': 7.0.1 '@npmcli/installed-package-contents': 4.0.0 @@ -18484,14 +18152,14 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-loader@8.2.0(postcss@8.5.6)(typescript@5.9.2)(webpack@5.105.0(esbuild@0.27.2)): + postcss-loader@8.2.0(postcss@8.5.6)(typescript@5.9.2)(webpack@5.105.2(esbuild@0.27.3)): dependencies: cosmiconfig: 9.0.0(typescript@5.9.2) jiti: 2.6.1 postcss: 8.5.6 semver: 7.7.4 optionalDependencies: - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) transitivePeerDependencies: - typescript @@ -19027,24 +18695,24 @@ snapshots: robots-parser@3.0.1: {} - rolldown@1.0.0-rc.3: + rolldown@1.0.0-rc.4: dependencies: - '@oxc-project/types': 0.112.0 - '@rolldown/pluginutils': 1.0.0-rc.3 + '@oxc-project/types': 0.113.0 + '@rolldown/pluginutils': 1.0.0-rc.4 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.3 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.3 - '@rolldown/binding-darwin-x64': 1.0.0-rc.3 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.3 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.3 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.3 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.3 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.3 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.3 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.3 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.3 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.3 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.3 + '@rolldown/binding-android-arm64': 1.0.0-rc.4 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.4 + '@rolldown/binding-darwin-x64': 1.0.0-rc.4 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.4 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.4 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.4 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.4 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.4 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.4 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.4 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.4 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.4 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.4 rollup-plugin-dts@6.3.0(rollup@4.57.1)(typescript@5.9.2): dependencies: @@ -19172,12 +18840,12 @@ snapshots: safevalues@1.2.0: {} - sass-loader@16.0.6(sass@1.97.3)(webpack@5.105.0(esbuild@0.27.2)): + sass-loader@16.0.7(sass@1.97.3)(webpack@5.105.2(esbuild@0.27.3)): dependencies: neo-async: 2.6.2 optionalDependencies: sass: 1.97.3 - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) sass@1.97.2: dependencies: @@ -19514,11 +19182,11 @@ snapshots: source-map-js@1.2.1: {} - source-map-loader@5.0.0(webpack@5.105.0(esbuild@0.27.2)): + source-map-loader@5.0.0(webpack@5.105.2(esbuild@0.27.3)): dependencies: iconv-lite: 0.6.3 source-map-js: 1.2.1 - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) source-map-support@0.4.18: dependencies: @@ -19942,16 +19610,16 @@ snapshots: transitivePeerDependencies: - supports-color - terser-webpack-plugin@5.3.16(esbuild@0.27.2)(webpack@5.105.0(esbuild@0.27.2)): + terser-webpack-plugin@5.3.16(esbuild@0.27.3)(webpack@5.105.2(esbuild@0.27.3)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.46.0 - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) optionalDependencies: - esbuild: 0.27.2 + esbuild: 0.27.3 terser@5.46.0: dependencies: @@ -20242,7 +19910,7 @@ snapshots: undici@6.23.0: {} - undici@7.20.0: {} + undici@7.22.0: {} unicode-canonical-property-names-ecmascript@2.0.1: {} @@ -20475,7 +20143,7 @@ snapshots: webidl-conversions@3.0.1: {} - webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.105.0(esbuild@0.27.2)): + webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.105.2(esbuild@0.27.3)): dependencies: colorette: 2.0.20 memfs: 4.56.10(tslib@2.8.1) @@ -20484,11 +20152,11 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.3.3 optionalDependencies: - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) transitivePeerDependencies: - tslib - webpack-dev-server@5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.0(esbuild@0.27.2)): + webpack-dev-server@5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.2(esbuild@0.27.3)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -20516,10 +20184,10 @@ snapshots: serve-index: 1.9.2 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.105.0(esbuild@0.27.2)) + webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.105.2(esbuild@0.27.3)) ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) transitivePeerDependencies: - bufferutil - debug @@ -20535,12 +20203,12 @@ snapshots: webpack-sources@3.3.4: {} - webpack-subresource-integrity@5.1.0(webpack@5.105.0(esbuild@0.27.2)): + webpack-subresource-integrity@5.1.0(webpack@5.105.2(esbuild@0.27.3)): dependencies: typed-assert: 1.0.9 - webpack: 5.105.0(esbuild@0.27.2) + webpack: 5.105.2(esbuild@0.27.3) - webpack@5.105.0(esbuild@0.27.2): + webpack@5.105.2(esbuild@0.27.3): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -20564,7 +20232,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(esbuild@0.27.2)(webpack@5.105.0(esbuild@0.27.2)) + terser-webpack-plugin: 5.3.16(esbuild@0.27.3)(webpack@5.105.2(esbuild@0.27.3)) watchpack: 2.5.1 webpack-sources: 3.3.4 transitivePeerDependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 896ab3c1d241..cf72b4700980 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -18,23 +18,23 @@ packages: - src/youtube-player catalog: - '@angular-devkit/build-angular': 21.2.0-next.2 - '@angular-devkit/core': 21.2.0-next.2 - '@angular-devkit/schematics': 21.2.0-next.2 - '@angular/build': 21.2.0-next.2 - '@angular/cli': 21.2.0-next.2 - '@angular/common': 21.2.0-next.3 - '@angular/compiler-cli': 21.2.0-next.3 - '@angular/compiler': 21.2.0-next.3 - '@angular/core': 21.2.0-next.3 - '@angular/ssr': 21.2.0-next.2 - '@angular/forms': 21.2.0-next.3 - '@angular/localize': 21.2.0-next.3 - '@angular/platform-browser': 21.2.0-next.3 - '@angular/platform-browser-dynamic': 21.2.0-next.3 - '@angular/platform-server': 21.2.0-next.3 - '@angular/router': 21.2.0-next.3 - '@schematics/angular': 21.2.0-next.2 + '@angular-devkit/build-angular': 21.2.0-rc.0 + '@angular-devkit/core': 21.2.0-rc.0 + '@angular-devkit/schematics': 21.2.0-rc.0 + '@angular/build': 21.2.0-rc.0 + '@angular/cli': 21.2.0-rc.0 + '@angular/common': 21.2.0-rc.0 + '@angular/compiler-cli': 21.2.0-rc.0 + '@angular/compiler': 21.2.0-rc.0 + '@angular/core': 21.2.0-rc.0 + '@angular/ssr': 21.2.0-rc.0 + '@angular/forms': 21.2.0-rc.0 + '@angular/localize': 21.2.0-rc.0 + '@angular/platform-browser': 21.2.0-rc.0 + '@angular/platform-browser-dynamic': 21.2.0-rc.0 + '@angular/platform-server': 21.2.0-rc.0 + '@angular/router': 21.2.0-rc.0 + '@schematics/angular': 21.2.0-rc.0 'rxjs': ^6.6.7 # The minimum age of a release to be considered for dependency installation. From 1c14bfbc30383293ca0735245c8b7d628678f69f Mon Sep 17 00:00:00 2001 From: Andrey Dolgachev Date: Thu, 19 Feb 2026 08:41:07 -0800 Subject: [PATCH 003/123] fix(aria/combobox): Adjust AutoComplete examples to properly announce no results text (#32786) (cherry picked from commit fcdfed8d2eabdd6f6b4e16454092fd80c53a48c7) --- .../autocomplete-auto-select-example.html | 4 ++-- .../autocomplete-auto-select-example.ts | 2 -- .../autocomplete-highlight-example.html | 4 ++++ .../autocomplete-manual/autocomplete-manual-example.html | 4 ++++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components-examples/aria/autocomplete/autocomplete-auto-select/autocomplete-auto-select-example.html b/src/components-examples/aria/autocomplete/autocomplete-auto-select/autocomplete-auto-select-example.html index 0f936ab4c3e6..b7ec4065b427 100644 --- a/src/components-examples/aria/autocomplete/autocomplete-auto-select/autocomplete-auto-select-example.html +++ b/src/components-examples/aria/autocomplete/autocomplete-auto-select/autocomplete-auto-select-example.html @@ -16,8 +16,8 @@ -
- {{countries().length === 0 ? 'No results found' : ''}} +
+ {{countries().length === 0 ? 'No results found for ' + query() : ''}}
diff --git a/src/components-examples/aria/autocomplete/autocomplete-auto-select/autocomplete-auto-select-example.ts b/src/components-examples/aria/autocomplete/autocomplete-auto-select/autocomplete-auto-select-example.ts index 85954d71424c..1171dacdc2c7 100644 --- a/src/components-examples/aria/autocomplete/autocomplete-auto-select/autocomplete-auto-select-example.ts +++ b/src/components-examples/aria/autocomplete/autocomplete-auto-select/autocomplete-auto-select-example.ts @@ -22,7 +22,6 @@ import { viewChildren, } from '@angular/core'; import {COUNTRIES} from '../countries'; -import {CdkAriaLive} from '@angular/cdk/a11y'; import {OverlayModule} from '@angular/cdk/overlay'; import {FormsModule} from '@angular/forms'; @@ -32,7 +31,6 @@ import {FormsModule} from '@angular/forms'; templateUrl: 'autocomplete-auto-select-example.html', styleUrl: '../autocomplete.css', imports: [ - CdkAriaLive, Combobox, ComboboxInput, ComboboxPopup, diff --git a/src/components-examples/aria/autocomplete/autocomplete-highlight/autocomplete-highlight-example.html b/src/components-examples/aria/autocomplete/autocomplete-highlight/autocomplete-highlight-example.html index 50b08c79bcd2..cdb91f4ec1d6 100644 --- a/src/components-examples/aria/autocomplete/autocomplete-highlight/autocomplete-highlight-example.html +++ b/src/components-examples/aria/autocomplete/autocomplete-highlight/autocomplete-highlight-example.html @@ -16,6 +16,10 @@
+
+ {{countries().length === 0 ? 'No results found for ' + query() : ''}} +
+ +
+ {{countries().length === 0 ? 'No results found for ' + query() : ''}} +
+ Date: Fri, 20 Feb 2026 06:52:12 -0700 Subject: [PATCH 004/123] build: update pnpm to v10.30.0 (#32804) See associated pull request for more information. --- MODULE.bazel | 4 ++-- MODULE.bazel.lock | 8 ++++---- package.json | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 2d16fdbb9d14..b361250c6048 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -73,8 +73,8 @@ use_repo(node, "nodejs_toolchains") pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm") pnpm.pnpm( name = "pnpm", - pnpm_version = "10.29.3", - pnpm_version_integrity = "sha512-SY4ftMylqgbB3PJhHm+vxQly/+cYmZjECekN50VmREKY/+Q+bNKs3Hdboap8xeCSqLcFTIEbqMV3D4RpPTPS3A==", + pnpm_version = "10.30.0", + pnpm_version_integrity = "sha512-K1dT3gFdSA7riPW1th4AUfBbQwGAioLsi4QMnSrfd0jrNSyD9cFZPKcD/xAXKVvD/dMRmruWhu/Ja5/LGCAJNw==", ) use_repo(pnpm, "pnpm") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index bd0c8bfc396a..1675b4b4c42c 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -414,7 +414,7 @@ "@@aspect_rules_js+//npm:extensions.bzl%pnpm": { "general": { "bzlTransitiveDigest": "HC+l+mTivq1p/KbcVQ+iV5QwYR+oKESJh827FY68SH8=", - "usagesDigest": "CKLxpc3lNVLihz4+HVhcvPgL41EqRS5CZTzZG42uXl0=", + "usagesDigest": "8VTfxO3bSvcmHK5E3+3Jz/XMUvLTTgMLH1VyY8r1LDM=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -423,11 +423,11 @@ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_rule", "attributes": { "package": "pnpm", - "version": "10.29.3", + "version": "10.30.0", "root_package": "", "link_workspace": "", "link_packages": {}, - "integrity": "sha512-SY4ftMylqgbB3PJhHm+vxQly/+cYmZjECekN50VmREKY/+Q+bNKs3Hdboap8xeCSqLcFTIEbqMV3D4RpPTPS3A==", + "integrity": "sha512-K1dT3gFdSA7riPW1th4AUfBbQwGAioLsi4QMnSrfd0jrNSyD9cFZPKcD/xAXKVvD/dMRmruWhu/Ja5/LGCAJNw==", "url": "", "commit": "", "patch_args": [ @@ -450,7 +450,7 @@ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_links", "attributes": { "package": "pnpm", - "version": "10.29.3", + "version": "10.30.0", "dev": false, "root_package": "", "link_packages": {}, diff --git a/package.json b/package.json index a0c14a71c3b4..db21dccd9e73 100644 --- a/package.json +++ b/package.json @@ -8,11 +8,11 @@ "url": "https://github.com/angular/components.git" }, "license": "MIT", - "packageManager": "pnpm@10.29.3", + "packageManager": "pnpm@10.30.0", "engines": { "npm": "Please use pnpm instead of NPM to install dependencies", "yarn": "Please use pnpm instead of Yarn to install dependencies", - "pnpm": "10.29.3" + "pnpm": "10.30.0" }, "scripts": { "ng-dev": "node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only node_modules/@angular/ng-dev/bundles/cli.mjs", From f9e7149dbc42f2dc23f99bed11722645807dfe70 Mon Sep 17 00:00:00 2001 From: Angular Robot Date: Fri, 20 Feb 2026 06:52:58 -0700 Subject: [PATCH 005/123] build: update cross-repo angular dependencies (#32802) See associated pull request for more information. --- .../assistant-to-the-branch-manager.yml | 2 +- .github/workflows/ci.material-aio.yml | 18 +++---- .github/workflows/ci.yml | 50 +++++++++---------- .../workflows/deploy-dev-app-main-push.yml | 6 +-- .github/workflows/dev-infra.yml | 4 +- .github/workflows/docs-preview-build.yml | 8 +-- .github/workflows/docs-preview-deploy.yml | 2 +- .github/workflows/google-internal-tests.yml | 2 +- .github/workflows/pr.material-aio.yml | 18 +++---- .github/workflows/pr.yml | 46 ++++++++--------- .github/workflows/preview-build-dev-app.yml | 8 +-- .github/workflows/preview-deploy-dev-app.yml | 2 +- .github/workflows/scheduled-ci.yml | 14 +++--- MODULE.bazel | 2 +- package.json | 2 +- pnpm-lock.yaml | 12 ++--- 16 files changed, 98 insertions(+), 98 deletions(-) diff --git a/.github/workflows/assistant-to-the-branch-manager.yml b/.github/workflows/assistant-to-the-branch-manager.yml index 9ec5c522a33f..ffcf56aeb2b2 100644 --- a/.github/workflows/assistant-to-the-branch-manager.yml +++ b/.github/workflows/assistant-to-the-branch-manager.yml @@ -16,6 +16,6 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: angular/dev-infra/github-actions/branch-manager@7c08ac2a4f396bad752829fba09dbaefbcded9fc + - uses: angular/dev-infra/github-actions/branch-manager@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/ci.material-aio.yml b/.github/workflows/ci.material-aio.yml index a1cfa026b71d..b76959d833c4 100644 --- a/.github/workflows/ci.material-aio.yml +++ b/.github/workflows/ci.material-aio.yml @@ -21,11 +21,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Build @@ -35,11 +35,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Tests @@ -56,11 +56,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Lighthouse Audit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a836a82dc59..3c4630dd1d27 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile # TODO: Remove --ignore_all_rc_files flag once a repository can be loaded in bazelrc during info @@ -49,11 +49,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -65,11 +65,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -81,11 +81,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -98,11 +98,11 @@ jobs: runs-on: ubuntu-latest-16core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -114,11 +114,11 @@ jobs: runs-on: ubuntu-latest-16core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Install node modules @@ -130,11 +130,11 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Build Snapshots @@ -154,15 +154,15 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 # See: https://github.com/puppeteer/puppeteer/pull/13196 and # https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md. - name: Disable AppArmor run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Build and Verify Release Output @@ -185,12 +185,12 @@ jobs: CI_RUNNER_NUMBER: ${{ github.run_id }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Browserstack Variables - uses: angular/dev-infra/github-actions/browserstack@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/browserstack@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Run tests on Browserstack run: ./scripts/circleci/run-browserstack-tests.sh diff --git a/.github/workflows/deploy-dev-app-main-push.yml b/.github/workflows/deploy-dev-app-main-push.yml index e431d51f42c4..c0ab8a8b6595 100644 --- a/.github/workflows/deploy-dev-app-main-push.yml +++ b/.github/workflows/deploy-dev-app-main-push.yml @@ -17,11 +17,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile diff --git a/.github/workflows/dev-infra.yml b/.github/workflows/dev-infra.yml index a1db4b822270..3fedefd8be35 100644 --- a/.github/workflows/dev-infra.yml +++ b/.github/workflows/dev-infra.yml @@ -12,13 +12,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: angular/dev-infra/github-actions/pull-request-labeling@7c08ac2a4f396bad752829fba09dbaefbcded9fc + - uses: angular/dev-infra/github-actions/pull-request-labeling@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} post_approval_changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: angular/dev-infra/github-actions/pull-request-labeling@7c08ac2a4f396bad752829fba09dbaefbcded9fc + - uses: angular/dev-infra/github-actions/pull-request-labeling@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} diff --git a/.github/workflows/docs-preview-build.yml b/.github/workflows/docs-preview-build.yml index 37cad3457437..5d1804523c98 100644 --- a/.github/workflows/docs-preview-build.yml +++ b/.github/workflows/docs-preview-build.yml @@ -21,16 +21,16 @@ jobs: (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'docs: preview')) steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Build docs site run: pnpm bazel build //docs:build.production - - uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@7c08ac2a4f396bad752829fba09dbaefbcded9fc + - uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: workflow-artifact-name: 'docs-preview' pull-number: '${{github.event.pull_request.number}}' diff --git a/.github/workflows/docs-preview-deploy.yml b/.github/workflows/docs-preview-deploy.yml index c171cd91a8c1..c871dd3b22bc 100644 --- a/.github/workflows/docs-preview-deploy.yml +++ b/.github/workflows/docs-preview-deploy.yml @@ -40,7 +40,7 @@ jobs: npx -y firebase-tools@latest target:clear --config docs/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting mat-aio npx -y firebase-tools@latest target:apply --config docs/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting mat-aio ${{env.PREVIEW_SITE}} - - uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@7c08ac2a4f396bad752829fba09dbaefbcded9fc + - uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: github-token: '${{secrets.GITHUB_TOKEN}}' workflow-artifact-name: 'docs-preview' diff --git a/.github/workflows/google-internal-tests.yml b/.github/workflows/google-internal-tests.yml index 8d35f0e00700..e637819af05e 100644 --- a/.github/workflows/google-internal-tests.yml +++ b/.github/workflows/google-internal-tests.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: angular/dev-infra/github-actions/google-internal-tests@7c08ac2a4f396bad752829fba09dbaefbcded9fc + - uses: angular/dev-infra/github-actions/google-internal-tests@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: run-tests-guide-url: http://go/angular-material-presubmit github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr.material-aio.yml b/.github/workflows/pr.material-aio.yml index fece1e72e6dc..2a5caba26b64 100644 --- a/.github/workflows/pr.material-aio.yml +++ b/.github/workflows/pr.material-aio.yml @@ -19,11 +19,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Build @@ -33,11 +33,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Tests @@ -54,11 +54,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Execute Lighthouse Audit diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7a9eb57bdac6..125e2dbdd31a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile # TODO: Remove --ignore_all_rc_files flag once a repository can be loaded in bazelrc during info @@ -45,7 +45,7 @@ jobs: - name: Check code format run: pnpm ng-dev format changed --check ${{ github.event.pull_request.base.sha }} - name: Check Package Licenses - uses: angular/dev-infra/github-actions/linting/licenses@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/linting/licenses@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 # Commit message check is last intentionally, because the caretaker can fix it # during merge, while other lint failures have to be resolved by the PR author. - name: Check commit message @@ -55,11 +55,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Check API Goldens @@ -69,11 +69,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Run e2e tests @@ -83,11 +83,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Run integration tests @@ -97,11 +97,11 @@ jobs: runs-on: ubuntu-latest-16core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Run tests @@ -111,11 +111,11 @@ jobs: runs-on: ubuntu-latest-16core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Run tests @@ -125,11 +125,11 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Install node modules run: pnpm install --frozen-lockfile - name: Build and Verify Release Output @@ -152,15 +152,15 @@ jobs: CI_RUNNER_NUMBER: ${{ github.run_id }} steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: # Checking out the pull request commit is intended here as we need to run the changed code tests. ref: ${{ github.event.pull_request.head.sha }} - name: Install node modules run: pnpm install --frozen-lockfile - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Browserstack Variables - uses: angular/dev-infra/github-actions/browserstack@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/browserstack@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Run tests on Browserstack run: ./scripts/circleci/run-browserstack-tests.sh diff --git a/.github/workflows/preview-build-dev-app.yml b/.github/workflows/preview-build-dev-app.yml index 51dfbc53bc5b..43c94489b9d2 100644 --- a/.github/workflows/preview-build-dev-app.yml +++ b/.github/workflows/preview-build-dev-app.yml @@ -23,16 +23,16 @@ jobs: (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'dev-app preview')) steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 # Build the web package - run: bazel build //src/dev-app:web_package --symlink_prefix=dist/ - - uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@7c08ac2a4f396bad752829fba09dbaefbcded9fc + - uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: workflow-artifact-name: 'dev-app' pull-number: '${{github.event.pull_request.number}}' diff --git a/.github/workflows/preview-deploy-dev-app.yml b/.github/workflows/preview-deploy-dev-app.yml index f8c782b9667f..6890a1fc4874 100644 --- a/.github/workflows/preview-deploy-dev-app.yml +++ b/.github/workflows/preview-deploy-dev-app.yml @@ -33,7 +33,7 @@ jobs: npx -y firebase-tools@latest target:clear --project ${{env.PREVIEW_PROJECT}} hosting dev-app npx -y firebase-tools@latest target:apply --project ${{env.PREVIEW_PROJECT}} hosting dev-app ${{env.PREVIEW_SITE}} - - uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@7c08ac2a4f396bad752829fba09dbaefbcded9fc + - uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: github-token: '${{secrets.GITHUB_TOKEN}}' workflow-artifact-name: 'dev-app' diff --git a/.github/workflows/scheduled-ci.yml b/.github/workflows/scheduled-ci.yml index b532f67b0122..78403b9a415a 100644 --- a/.github/workflows/scheduled-ci.yml +++ b/.github/workflows/scheduled-ci.yml @@ -19,11 +19,11 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Setting up Angular snapshot builds @@ -39,11 +39,11 @@ jobs: runs-on: ubuntu-latest-4core steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel - uses: angular/dev-infra/github-actions/bazel/setup@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/setup@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 - name: Setup Bazel RBE - uses: angular/dev-infra/github-actions/bazel/configure-remote@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/bazel/configure-remote@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 with: google_credential: ${{ secrets.RBE_TRUSTED_BUILDS_USER }} - name: Setting up Angular snapshot builds @@ -61,7 +61,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Initialize environment - uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7c08ac2a4f396bad752829fba09dbaefbcded9fc + uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 # See: https://github.com/puppeteer/puppeteer/pull/13196 and # https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md. - name: Disable AppArmor diff --git a/MODULE.bazel b/MODULE.bazel index b361250c6048..cd7d1ae2a832 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -39,7 +39,7 @@ git_override( bazel_dep(name = "devinfra") git_override( module_name = "devinfra", - commit = "7c08ac2a4f396bad752829fba09dbaefbcded9fc", + commit = "e006a332028a4c3cb24e9d92437fac7ae99e2ed5", remote = "https://github.com/angular/dev-infra.git", ) diff --git a/package.json b/package.json index db21dccd9e73..8ec7e46d0c9c 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "devDependencies": { "@angular/compiler-cli": "catalog:", "@angular/localize": "catalog:", - "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#0125e8e025e98825616c46350f58502dbeddb038", + "@angular/ng-dev": "https://github.com/angular/dev-infra-private-ng-dev-builds.git#b0ab31189ecbeaaafce2bd9259385879b9beabcc", "@angular/platform-server": "catalog:", "@angular/router": "catalog:", "@babel/core": "^7.16.12", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3df3f27f4693..2698aa45fff3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -126,8 +126,8 @@ importers: specifier: 'catalog:' version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0) '@angular/ng-dev': - specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#0125e8e025e98825616c46350f58502dbeddb038 - version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/0125e8e025e98825616c46350f58502dbeddb038(@modelcontextprotocol/sdk@1.26.0) + specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#b0ab31189ecbeaaafce2bd9259385879b9beabcc + version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b0ab31189ecbeaaafce2bd9259385879b9beabcc(@modelcontextprotocol/sdk@1.26.0) '@angular/platform-server': specifier: 'catalog:' version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) @@ -972,9 +972,9 @@ packages: '@angular/compiler': 21.2.0-rc.0 '@angular/compiler-cli': 21.2.0-rc.0 - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/0125e8e025e98825616c46350f58502dbeddb038': - resolution: {tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/0125e8e025e98825616c46350f58502dbeddb038} - version: 0.0.0-7c08ac2a4f396bad752829fba09dbaefbcded9fc + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b0ab31189ecbeaaafce2bd9259385879b9beabcc': + resolution: {tarball: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b0ab31189ecbeaaafce2bd9259385879b9beabcc} + version: 0.0.0-e006a332028a4c3cb24e9d92437fac7ae99e2ed5 hasBin: true '@angular/platform-browser-dynamic@21.2.0-rc.0': @@ -10241,7 +10241,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/0125e8e025e98825616c46350f58502dbeddb038(@modelcontextprotocol/sdk@1.26.0)': + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b0ab31189ecbeaaafce2bd9259385879b9beabcc(@modelcontextprotocol/sdk@1.26.0)': dependencies: '@actions/core': 3.0.0 '@google-cloud/spanner': 8.0.0(supports-color@10.2.2) From ddd5114e779bb6686f0450caf350218ab3fb1543 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sun, 22 Feb 2026 08:34:30 +0100 Subject: [PATCH 006/123] build: update dependencies and resolve breaking change (#32799) Takes over the dependency bump from #32690 and resolves a breaking change. (cherry picked from commit 3521e20c27b0669962d303d55cd3ba3e3bbe337a) --- docs/package.json | 4 +- package.json | 6 +-- pnpm-lock.yaml | 44 +++++++++++-------- .../ng-generate/theme-color/index.ts | 5 ++- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/docs/package.json b/docs/package.json index 7ced509a11af..bbfe57987b09 100644 --- a/docs/package.json +++ b/docs/package.json @@ -61,7 +61,7 @@ "@types/jasmine": "^6.0.0", "@types/node": "^22.14.1", "@types/shelljs": "0.10.0", - "firebase-tools": "15.2.1", + "firebase-tools": "15.6.0", "jasmine-core": "^6.0.0", "jasmine-spec-reporter": "7.0.0", "karma": "~6.4.4", @@ -75,7 +75,7 @@ "npm-run-all": "^4.1.5", "protractor": "^7.0.0", "puppeteer-core": "^24.6.1", - "sass": "1.97.2", + "sass": "1.97.3", "shelljs": "^0.10.0", "ts-node": "10.9.2", "typescript": "~5.9.2" diff --git a/package.json b/package.json index 8ec7e46d0c9c..720f9b23251a 100644 --- a/package.json +++ b/package.json @@ -80,12 +80,12 @@ "@angular/platform-server": "catalog:", "@angular/router": "catalog:", "@babel/core": "^7.16.12", - "@bazel/bazelisk": "1.26.0", + "@bazel/bazelisk": "1.28.1", "@bazel/buildifier": "8.2.1", "@bazel/ibazel": "^0.28.0", "@bazel/runfiles": "6.5.0", "@firebase/app-types": "^0.9.0", - "@material/material-color-utilities": "^0.3.0", + "@material/material-color-utilities": "^0.4.0", "@octokit/rest": "22.0.1", "@rollup/plugin-commonjs": "^29.0.0", "@rollup/plugin-node-resolve": "^16.0.0", @@ -105,7 +105,7 @@ "dgeni": "^0.4.14", "dgeni-packages": "^0.30.0", "esbuild": "^0.27.0", - "firebase-tools": "15.2.1", + "firebase-tools": "15.6.0", "fs-extra": "^11.0.0", "glob": "^13.0.0", "highlight.js": "^11.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2698aa45fff3..9f46ebbf3044 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -138,8 +138,8 @@ importers: specifier: ^7.16.12 version: 7.29.0 '@bazel/bazelisk': - specifier: 1.26.0 - version: 1.26.0 + specifier: 1.28.1 + version: 1.28.1 '@bazel/buildifier': specifier: 8.2.1 version: 8.2.1 @@ -153,8 +153,8 @@ importers: specifier: ^0.9.0 version: 0.9.3 '@material/material-color-utilities': - specifier: ^0.3.0 - version: 0.3.0 + specifier: ^0.4.0 + version: 0.4.0 '@octokit/rest': specifier: 22.0.1 version: 22.0.1 @@ -213,8 +213,8 @@ importers: specifier: ^0.27.0 version: 0.27.3 firebase-tools: - specifier: 15.2.1 - version: 15.2.1(@types/node@22.19.11)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2) + specifier: 15.6.0 + version: 15.6.0(@types/node@22.19.11)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2) fs-extra: specifier: ^11.0.0 version: 11.3.3 @@ -322,7 +322,7 @@ importers: version: 10.9.2(@types/node@22.19.11)(typescript@5.9.2) tsec: specifier: 0.2.9 - version: 0.2.9(@bazel/bazelisk@1.26.0)(typescript@5.9.2) + version: 0.2.9(@bazel/bazelisk@1.28.1)(typescript@5.9.2) tsickle: specifier: 0.46.3 version: 0.46.3(typescript@5.9.2) @@ -445,8 +445,8 @@ importers: specifier: 0.10.0 version: 0.10.0 firebase-tools: - specifier: 15.2.1 - version: 15.2.1(@types/node@22.19.11)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2) + specifier: 15.6.0 + version: 15.6.0(@types/node@22.19.11)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2) jasmine-core: specifier: ^6.0.0 version: 6.0.1 @@ -487,8 +487,8 @@ importers: specifier: ^24.6.1 version: 24.37.3(bufferutil@4.1.0) sass: - specifier: 1.97.2 - version: 1.97.2 + specifier: 1.97.3 + version: 1.97.3 shelljs: specifier: ^0.10.0 version: 0.10.0 @@ -1553,6 +1553,10 @@ packages: resolution: {integrity: sha512-bTNcHdGyEQ9r7SczEYUa0gkEQhJo1ld2BjXI8fWBvsUeoHi03QpUs2HZgDbjjrpQFQqG2ZbO7ihZvH8MjhUTHw==} hasBin: true + '@bazel/bazelisk@1.28.1': + resolution: {integrity: sha512-K21x83NXOtd0yb2qzjMES3UV4xEWZ1q1vnXFhADA1u7IoiMVQkJAVQRK3oZ5txpnrGafY15HS+YYr2nmsEP4Tg==} + hasBin: true + '@bazel/buildifier@8.2.1': resolution: {integrity: sha512-eZ/Aq+2r4PcJa6LbPCT6ffgIJfTU/gYilqIzoX2OLM4nNkbQC6tTMPZNn7aHHjhGPxbNLv41zm4Xqt1olCLgXw==} hasBin: true @@ -2570,8 +2574,8 @@ packages: cpu: [x64] os: [win32] - '@material/material-color-utilities@0.3.0': - resolution: {integrity: sha512-ztmtTd6xwnuh2/xu+Vb01btgV8SQWYCaK56CkRK8gEkWe5TuDyBcYJ0wgkMRn+2VcE9KUmhvkz+N9GHrqw/C0g==} + '@material/material-color-utilities@0.4.0': + resolution: {integrity: sha512-dlq6VExJReb8dhjj3a/yTigr3ncNwoFmL5Iy2ENtbDX03EmNeOEdZ+vsaGrj7RTuO+mB7L58II4LCsl4NpM8uw==} '@modelcontextprotocol/sdk@1.26.0': resolution: {integrity: sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==} @@ -5569,8 +5573,8 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - firebase-tools@15.2.1: - resolution: {integrity: sha512-S75K4L/CsYSpyoOZAWHeTrx5TrpNCdUeSutr9oto+yBgg5qfbtnrGUxP+iPiBK6g4pdQFzf4p6rN1c7RoGE09A==} + firebase-tools@15.6.0: + resolution: {integrity: sha512-AE9VtePOMbufjs4NlsRX3z4LNvP5yQXvWbohDmuygUAE1RVs498IXrNNliwhwnc6yguV+ZolawBGcGF4izy2gw==} engines: {node: '>=20.0.0 || >=22.0.0 || >=24.0.0'} hasBin: true @@ -11081,6 +11085,8 @@ snapshots: '@bazel/bazelisk@1.26.0': {} + '@bazel/bazelisk@1.28.1': {} + '@bazel/buildifier@8.2.1': {} '@bazel/ibazel@0.28.0': {} @@ -12162,7 +12168,7 @@ snapshots: '@lmdb/lmdb-win32-x64@3.5.1': optional: true - '@material/material-color-utilities@0.3.0': {} + '@material/material-color-utilities@0.4.0': {} '@modelcontextprotocol/sdk@1.26.0': dependencies: @@ -15497,7 +15503,7 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - firebase-tools@15.2.1(@types/node@22.19.11)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2): + firebase-tools@15.6.0(@types/node@22.19.11)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2): dependencies: '@apphosting/build': 0.1.7(@types/node@22.19.11)(typescript@5.9.2) '@apphosting/common': 0.0.8 @@ -19741,9 +19747,9 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - tsec@0.2.9(@bazel/bazelisk@1.26.0)(typescript@5.9.2): + tsec@0.2.9(@bazel/bazelisk@1.28.1)(typescript@5.9.2): dependencies: - '@bazel/bazelisk': 1.26.0 + '@bazel/bazelisk': 1.28.1 glob: 11.1.0 minimatch: 10.2.0 typescript: 5.9.2 diff --git a/src/material/schematics/ng-generate/theme-color/index.ts b/src/material/schematics/ng-generate/theme-color/index.ts index c299b42c2e02..d17310676052 100644 --- a/src/material/schematics/ng-generate/theme-color/index.ts +++ b/src/material/schematics/ng-generate/theme-color/index.ts @@ -16,6 +16,7 @@ import { DynamicScheme, DislikeAnalyzer, TemperatureCache, + Variant, } from '@material/material-color-utilities'; // For each color tonal palettes are created using the following hue tones. The @@ -90,8 +91,8 @@ export function getMaterialDynamicScheme( contrastLevel: number, ): DynamicScheme { return new DynamicScheme({ - sourceColorArgb: primaryPalette.keyColor.toInt(), - variant: 6, // Variant.FIDELITY, used number representation since enum is not accessible outside of @material/material-color-utilities + sourceColorHct: primaryPalette.keyColor, + variant: Variant.FIDELITY, contrastLevel: contrastLevel, isDark: isDark, primaryPalette: primaryPalette, From 8c4526935ef7e960ed4245a4621d41065ba34e3b Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sun, 22 Feb 2026 08:35:52 +0100 Subject: [PATCH 007/123] fix(material/core): expose strong focus indicator structural styles (#32808) Exposes the structural styles for strong focus indicators so users can use them in their own components. Fixes #32773. (cherry picked from commit 2aff3c8ca42a9fb01a248f28960a58b28f4e7679) --- src/material/_index.scss | 2 +- src/material/core/focus-indicators/_private.scss | 2 +- src/material/core/focus-indicators/structural-styles.scss | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/material/_index.scss b/src/material/_index.scss index 851e39654078..31089de57f34 100644 --- a/src/material/_index.scss +++ b/src/material/_index.scss @@ -37,7 +37,7 @@ @forward './core/core' show core, app-background, elevation-classes; @forward './core/ripple/ripple' show ripple; @forward './core/focus-indicators/private' show strong-focus-indicators, - strong-focus-indicators-color, strong-focus-indicators-theme; + strong-focus-indicators-color, strong-focus-indicators-theme, strong-focus-indicators-structure; @forward './core/style/elevation' show elevation, overridable-elevation, elevation-transition; // Theme bundles diff --git a/src/material/core/focus-indicators/_private.scss b/src/material/core/focus-indicators/_private.scss index 1d2127e032bb..c71b3131efcf 100644 --- a/src/material/core/focus-indicators/_private.scss +++ b/src/material/core/focus-indicators/_private.scss @@ -11,7 +11,7 @@ $default-border-color: transparent; $default-border-radius: 4px; // Mixin that renders the focus indicator structural styles. -@mixin structural-styling() { +@mixin strong-focus-indicators-structure() { .mat-focus-indicator { position: relative; diff --git a/src/material/core/focus-indicators/structural-styles.scss b/src/material/core/focus-indicators/structural-styles.scss index 4764f56397df..9087e727cb98 100644 --- a/src/material/core/focus-indicators/structural-styles.scss +++ b/src/material/core/focus-indicators/structural-styles.scss @@ -1,3 +1,3 @@ @use './private'; -@include private.structural-styling(); +@include private.strong-focus-indicators-structure(); From ef2f1cb303a04e1d127fbc15819fff843ccd4749 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sun, 22 Feb 2026 08:36:17 +0100 Subject: [PATCH 008/123] build: set up schematics for v22 (#32806) One of the pre-requisites to release the next version of v22 is to have schematics set up. These changes add them ahead of time so we don't run into any issues when we go to release. (cherry picked from commit dce147f6cac375983f1379a366dc40c46e8163e6) --- src/cdk/schematics/migration.json | 5 +++++ src/cdk/schematics/ng-update/index.ts | 12 +++++++++++- src/cdk/schematics/update-tool/target-version.ts | 1 + src/google-maps/schematics/migration.json | 5 +++++ src/google-maps/schematics/ng-update/index.ts | 7 ++++++- src/material/schematics/migration.json | 5 +++++ src/material/schematics/ng-update/index.ts | 7 +++++++ 7 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/cdk/schematics/migration.json b/src/cdk/schematics/migration.json index 7d641b126f1a..eb51147ed44a 100644 --- a/src/cdk/schematics/migration.json +++ b/src/cdk/schematics/migration.json @@ -6,6 +6,11 @@ "description": "Updates the Angular CDK to v21", "factory": "./ng-update/index#updateToV21" }, + "migration-v22": { + "version": "22.0.0-0", + "description": "Updates the Angular CDK to v22", + "factory": "./ng-update/index#updateToV22" + }, "ng-post-update": { "description": "Prints out results after ng-update.", "factory": "./ng-update/index#postUpdate", diff --git a/src/cdk/schematics/ng-update/index.ts b/src/cdk/schematics/ng-update/index.ts index 68f963d2c521..34d2f720d010 100644 --- a/src/cdk/schematics/ng-update/index.ts +++ b/src/cdk/schematics/ng-update/index.ts @@ -13,7 +13,7 @@ import {createMigrationSchematicRule, NullableDevkitMigration} from './devkit-mi const cdkMigrations: NullableDevkitMigration[] = []; -/** Entry point for the migration schematics with target of Angular CDK 20.0.0 */ +/** Entry point for the migration schematics with target of Angular CDK 21.0.0 */ export function updateToV21(): Rule { return createMigrationSchematicRule( TargetVersion.V21, @@ -23,6 +23,16 @@ export function updateToV21(): Rule { ); } +/** Entry point for the migration schematics with target of Angular CDK 22.0.0 */ +export function updateToV22(): Rule { + return createMigrationSchematicRule( + TargetVersion.V22, + cdkMigrations, + cdkUpgradeData, + onMigrationComplete, + ); +} + /** Function that will be called when the migration completed. */ function onMigrationComplete( context: SchematicContext, diff --git a/src/cdk/schematics/update-tool/target-version.ts b/src/cdk/schematics/update-tool/target-version.ts index ba2646bb0a62..eb25c0c0bfda 100644 --- a/src/cdk/schematics/update-tool/target-version.ts +++ b/src/cdk/schematics/update-tool/target-version.ts @@ -11,6 +11,7 @@ // tslint:disable-next-line:prefer-const-enum export enum TargetVersion { V21 = 'version 21', + V22 = 'version 22', } /** diff --git a/src/google-maps/schematics/migration.json b/src/google-maps/schematics/migration.json index 8cf681dd7570..321f4eea071d 100644 --- a/src/google-maps/schematics/migration.json +++ b/src/google-maps/schematics/migration.json @@ -4,6 +4,11 @@ "version": "21.0.0-0", "description": "Updates the Angular Google Maps package to v21", "factory": "./ng-update/index#updateToV21" + }, + "migration-v22": { + "version": "22.0.0-0", + "description": "Updates the Angular Google Maps package to v22", + "factory": "./ng-update/index#updateToV22" } } } diff --git a/src/google-maps/schematics/ng-update/index.ts b/src/google-maps/schematics/ng-update/index.ts index 3bca7b6e169f..a6eece0c7c02 100644 --- a/src/google-maps/schematics/ng-update/index.ts +++ b/src/google-maps/schematics/ng-update/index.ts @@ -8,7 +8,12 @@ import {Rule} from '@angular-devkit/schematics'; -/** Entry point for the migration schematics with target of Angular Material v21 */ +/** Entry point for the migration schematics with target of Google Maps v21 */ export function updateToV21(): Rule { return () => {}; } + +/** Entry point for the migration schematics with target of Google Maps v22 */ +export function updateToV22(): Rule { + return () => {}; +} diff --git a/src/material/schematics/migration.json b/src/material/schematics/migration.json index 76b3c2e3713d..c353c5313bd2 100644 --- a/src/material/schematics/migration.json +++ b/src/material/schematics/migration.json @@ -5,6 +5,11 @@ "version": "21.0.0-0", "description": "Updates Angular Material to v21", "factory": "./ng-update/index_bundled#updateToV21" + }, + "migration-v22": { + "version": "22.0.0-0", + "description": "Updates Angular Material to v22", + "factory": "./ng-update/index_bundled#updateToV22" } } } diff --git a/src/material/schematics/ng-update/index.ts b/src/material/schematics/ng-update/index.ts index 3ce5dd9c6ce4..1539a6098768 100644 --- a/src/material/schematics/ng-update/index.ts +++ b/src/material/schematics/ng-update/index.ts @@ -23,3 +23,10 @@ export function updateToV21(): Rule { createMigrationSchematicRule(TargetVersion.V21, materialMigrations, materialUpgradeData), ]); } + +/** Entry point for the migration schematics with target of Angular Material v22 */ +export function updateToV22(): Rule { + return chain([ + createMigrationSchematicRule(TargetVersion.V22, materialMigrations, materialUpgradeData), + ]); +} From 7fe308114829c4ce454cc247e59e59387ee7fd17 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 23 Feb 2026 18:24:44 +0100 Subject: [PATCH 009/123] fix(material/datepicker): drop dependency on NgClass (#32810) Drops the dependency on `NgClass` from the datepicker in favor of a direct `class` binding. (cherry picked from commit 0d36e863ba6752596b6cee5810b5d953d536a9a9) --- goldens/material/datepicker/index.api.md | 6 ++---- src/material/datepicker/calendar-body.html | 2 +- src/material/datepicker/calendar-body.ts | 11 ++++++----- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/goldens/material/datepicker/index.api.md b/goldens/material/datepicker/index.api.md index f7d1db2fb8ff..ee5b9cab654c 100644 --- a/goldens/material/datepicker/index.api.md +++ b/goldens/material/datepicker/index.api.md @@ -229,7 +229,7 @@ export class MatCalendarCell { // (undocumented) compareValue: number; // (undocumented) - cssClasses: MatCalendarCellCssClasses; + readonly cssClasses: string | string[] | Record | undefined; // (undocumented) displayValue: string; // (undocumented) @@ -246,9 +246,7 @@ export class MatCalendarCell { export type MatCalendarCellClassFunction = (date: D, view: 'month' | 'year' | 'multi-year') => MatCalendarCellCssClasses; // @public -export type MatCalendarCellCssClasses = string | string[] | Set | { - [key: string]: any; -}; +export type MatCalendarCellCssClasses = string | string[] | Set | Record; // @public export class MatCalendarHeader { diff --git a/src/material/datepicker/calendar-body.html b/src/material/datepicker/calendar-body.html index 4bd24d90fa83..1b6c113fe87e 100644 --- a/src/material/datepicker/calendar-body.html +++ b/src/material/datepicker/calendar-body.html @@ -49,7 +49,7 @@ -
+
Apple
Banana
@@ -1007,7 +1018,9 @@ class StandaloneMenuExample { `, imports: [Menu, MenuItem, MenuTrigger, MenuContent], }) -class MenuTriggerExample {} +class MenuTriggerExample { + itemSelected(value: string) {} +} @Component({ template: ` diff --git a/src/aria/private/menu/menu.ts b/src/aria/private/menu/menu.ts index 6ad86e70ae2a..04f3449d7025 100644 --- a/src/aria/private/menu/menu.ts +++ b/src/aria/private/menu/menu.ts @@ -357,26 +357,21 @@ export class MenuPattern { /** Submits the menu. */ submit(item = this.inputs.activeItem()) { - const root = this.root(); - - if (item && !item.disabled()) { - const isMenu = root instanceof MenuPattern; - const isMenuBar = root instanceof MenuBarPattern; - const isMenuTrigger = root instanceof MenuTriggerPattern; - - if (!item.submenu() && isMenuTrigger) { - root.close({refocus: true}); - } + if (!item || item.disabled() || item.submenu()) { + return; + } - if (!item.submenu() && isMenuBar) { - root.close(); - root?.inputs.itemSelected?.(item.value()); - } + const root = this.root(); - if (!item.submenu() && isMenu) { - root.inputs.activeItem()?.close({refocus: true}); - root?.inputs.itemSelected?.(item.value()); - } + if (root instanceof MenuTriggerPattern) { + root.close({refocus: true}); + root?.inputs.menu()?.inputs.itemSelected?.(item.value()); + } else if (root instanceof MenuBarPattern) { + root.close(); + root?.inputs.itemSelected?.(item.value()); + } else if (root instanceof MenuPattern) { + root.inputs.activeItem()?.close({refocus: true}); + root?.inputs.itemSelected?.(item.value()); } } From 2929803fee58984f8983e972b078610b9b585f39 Mon Sep 17 00:00:00 2001 From: Angular Robot Date: Wed, 4 Mar 2026 17:14:09 -0700 Subject: [PATCH 019/123] build: update pnpm to v10.30.3 (#32813) See associated pull request for more information. --- MODULE.bazel | 4 ++-- MODULE.bazel.lock | 8 ++++---- package.json | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index cd7d1ae2a832..c3e285a19db4 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -73,8 +73,8 @@ use_repo(node, "nodejs_toolchains") pnpm = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm") pnpm.pnpm( name = "pnpm", - pnpm_version = "10.30.0", - pnpm_version_integrity = "sha512-K1dT3gFdSA7riPW1th4AUfBbQwGAioLsi4QMnSrfd0jrNSyD9cFZPKcD/xAXKVvD/dMRmruWhu/Ja5/LGCAJNw==", + pnpm_version = "10.30.3", + pnpm_version_integrity = "sha512-yWHR4KLY41TsqlFmuCJRZmi39Ey1vZUSLVkN2Bki9gb1RzttI+xKW+Bef80Y6EiNR9l4u+mBhy8RRdBumnQAFw==", ) use_repo(pnpm, "pnpm") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 1675b4b4c42c..c585e47edc8f 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -414,7 +414,7 @@ "@@aspect_rules_js+//npm:extensions.bzl%pnpm": { "general": { "bzlTransitiveDigest": "HC+l+mTivq1p/KbcVQ+iV5QwYR+oKESJh827FY68SH8=", - "usagesDigest": "8VTfxO3bSvcmHK5E3+3Jz/XMUvLTTgMLH1VyY8r1LDM=", + "usagesDigest": "1DL4k1YLMRyc3/R106AHSyj/qZzIf09zOU4IPkPoNnk=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -423,11 +423,11 @@ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_rule", "attributes": { "package": "pnpm", - "version": "10.30.0", + "version": "10.30.3", "root_package": "", "link_workspace": "", "link_packages": {}, - "integrity": "sha512-K1dT3gFdSA7riPW1th4AUfBbQwGAioLsi4QMnSrfd0jrNSyD9cFZPKcD/xAXKVvD/dMRmruWhu/Ja5/LGCAJNw==", + "integrity": "sha512-yWHR4KLY41TsqlFmuCJRZmi39Ey1vZUSLVkN2Bki9gb1RzttI+xKW+Bef80Y6EiNR9l4u+mBhy8RRdBumnQAFw==", "url": "", "commit": "", "patch_args": [ @@ -450,7 +450,7 @@ "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_links", "attributes": { "package": "pnpm", - "version": "10.30.0", + "version": "10.30.3", "dev": false, "root_package": "", "link_packages": {}, diff --git a/package.json b/package.json index e2355b13821b..159c9e44cbc6 100644 --- a/package.json +++ b/package.json @@ -8,11 +8,11 @@ "url": "https://github.com/angular/components.git" }, "license": "MIT", - "packageManager": "pnpm@10.30.0", + "packageManager": "pnpm@10.30.3", "engines": { "npm": "Please use pnpm instead of NPM to install dependencies", "yarn": "Please use pnpm instead of Yarn to install dependencies", - "pnpm": "10.30.0" + "pnpm": "10.30.3" }, "scripts": { "ng-dev": "node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only node_modules/@angular/ng-dev/bundles/cli.mjs", From 5fc772df544c5b1a4b91dd32b030cb8002b3ba72 Mon Sep 17 00:00:00 2001 From: Angular Robot Date: Wed, 4 Mar 2026 17:18:49 -0700 Subject: [PATCH 020/123] build: update github/codeql-action action to v4.32.5 (#32863) See associated pull request for more information. --- .github/workflows/scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index e00f8790ea99..840ff2c0d16d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -47,6 +47,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: sarif_file: results.sarif From f35bfe5b3a46cea136b5b0eedd78a89a581825a6 Mon Sep 17 00:00:00 2001 From: Angular Robot Date: Wed, 4 Mar 2026 17:19:28 -0700 Subject: [PATCH 021/123] build: update bazel dependencies (#32862) See associated pull request for more information. --- MODULE.bazel | 10 +++++----- MODULE.bazel.lock | 28 +++++++++++++++++----------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index c3e285a19db4..49553f337938 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -4,21 +4,21 @@ module( name = "components", ) -bazel_dep(name = "yq.bzl", version = "0.3.4") +bazel_dep(name = "yq.bzl", version = "0.3.5") bazel_dep(name = "rules_nodejs", version = "6.7.3") bazel_dep(name = "aspect_rules_js", version = "2.9.2") bazel_dep(name = "rules_pkg", version = "1.2.0") -bazel_dep(name = "tar.bzl", version = "0.8.1") +bazel_dep(name = "tar.bzl", version = "0.9.0") bazel_dep(name = "aspect_bazel_lib", version = "2.22.5") bazel_dep(name = "aspect_rules_esbuild", version = "0.25.0") -bazel_dep(name = "aspect_rules_jasmine", version = "2.0.2") +bazel_dep(name = "aspect_rules_jasmine", version = "2.0.4") bazel_dep(name = "platforms", version = "1.0.0") -bazel_dep(name = "aspect_rules_ts", version = "3.8.4") +bazel_dep(name = "aspect_rules_ts", version = "3.8.5") bazel_dep(name = "bazel_skylib", version = "1.9.0") bazel_dep(name = "rules_browsers") git_override( module_name = "rules_browsers", - commit = "ceb52751831f3e6249aba83f688a612e57a8d14a", + commit = "8231142fc5516323b040883bf774ba8362645387", remote = "https://github.com/devversion/rules_browsers.git", ) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index c585e47edc8f..a36f0117c155 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -22,7 +22,8 @@ "https://bcr.bazel.build/modules/aspect_rules_esbuild/0.25.0/MODULE.bazel": "5fef5ec709c837312823f9bcf0f276661e2cb48ad52f17c4e01176bbf1e9bf58", "https://bcr.bazel.build/modules/aspect_rules_esbuild/0.25.0/source.json": "5e42968c6d23ab8bd95c02634b16864d866334347827cb6a8425b86c11cc4363", "https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.2/MODULE.bazel": "45f054400ff242c4433f6d7f20f6123a9a72739cb7a1f44247d738db1644f46c", - "https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.2/source.json": "3ed399a5654259a822448f9cdbf21f6c738f16ccd7f89249c7507e374cbdd1e3", + "https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.4/MODULE.bazel": "fbb819eb8b7e5d7f67fdd38f7cecb413e287594cd666ce192c72c8828527775a", + "https://bcr.bazel.build/modules/aspect_rules_jasmine/2.0.4/source.json": "81ffb708333cd98ec3c0b4cc004f4d5cf92a16914b5196a2892c45141bba7cff", "https://bcr.bazel.build/modules/aspect_rules_js/2.0.0/MODULE.bazel": "b45b507574aa60a92796e3e13c195cd5744b3b8aff516a9c0cb5ae6a048161c5", "https://bcr.bazel.build/modules/aspect_rules_js/2.4.2/MODULE.bazel": "0d01db38b96d25df7ed952a5e96eac4b3802723d146961974bf020f6dd07591d", "https://bcr.bazel.build/modules/aspect_rules_js/2.6.2/MODULE.bazel": "ed2a871f4ab8fbde0cab67c425745069d84ea64b64313fa1a2954017326511f5", @@ -31,7 +32,8 @@ "https://bcr.bazel.build/modules/aspect_rules_ts/3.6.3/MODULE.bazel": "d09db394970f076176ce7bab5b5fa7f0d560fd4f30b8432ea5e2c2570505b130", "https://bcr.bazel.build/modules/aspect_rules_ts/3.7.0/MODULE.bazel": "5aace216caf88638950ef061245d23c36f57c8359e56e97f02a36f70bb09c50f", "https://bcr.bazel.build/modules/aspect_rules_ts/3.8.4/MODULE.bazel": "a50254ac3add6232d0f9f93103836f9afaf614315589a13abf74183982c4101d", - "https://bcr.bazel.build/modules/aspect_rules_ts/3.8.4/source.json": "f786e0763f3ea5de7ea6d4c4e38fccb48bf4d9c5eafaf95091c0e1590502510e", + "https://bcr.bazel.build/modules/aspect_rules_ts/3.8.5/MODULE.bazel": "bcf8f0b6b9375f0f74451e2f70671efae9bb366acef8fdc04675305eaf137f06", + "https://bcr.bazel.build/modules/aspect_rules_ts/3.8.5/source.json": "fa35e43f6359f654e4b70ce55efdf280d0b06c0b3ef9fc0b06ba52327a0e6311", "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.2.3/MODULE.bazel": "20f53b145f40957a51077ae90b37b7ce83582a1daf9350349f0f86179e19dd0d", "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.2.6/MODULE.bazel": "cafb8781ad591bc57cc765dca5fefab08cf9f65af363d162b79d49205c7f8af7", "https://bcr.bazel.build/modules/aspect_tools_telemetry/0.2.8/MODULE.bazel": "aa975a83e72bcaac62ee61ab12b788ea324a1d05c4aab28aadb202f647881679", @@ -74,7 +76,8 @@ "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", "https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/MODULE.bazel": "cdf8cbe5ee750db04b78878c9633cc76e80dcf4416cbe982ac3a9222f80713c8", - "https://bcr.bazel.build/modules/gawk/5.3.2.bcr.1/source.json": "fa7b512dfcb5eafd90ce3959cf42a2a6fe96144ebbb4b3b3928054895f2afac2", + "https://bcr.bazel.build/modules/gawk/5.3.2.bcr.3/MODULE.bazel": "f1b7bb2dd53e8f2ef984b39485ec8a44e9076dda5c4b8efd2fb4c6a6e856a31d", + "https://bcr.bazel.build/modules/gawk/5.3.2.bcr.3/source.json": "ebe931bfe362e4b41e59ee00a528db6074157ff2ced92eb9e970acab2e1089c9", "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", @@ -123,6 +126,7 @@ "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", "https://bcr.bazel.build/modules/rules_cc/0.2.16/MODULE.bazel": "9242fa89f950c6ef7702801ab53922e99c69b02310c39fb6e62b2bd30df2a1d4", "https://bcr.bazel.build/modules/rules_cc/0.2.16/source.json": "d03d5cde49376d87e14ec14b666c56075e5e3926930327fd5d0484a1ff2ac1cc", + "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", @@ -196,13 +200,15 @@ "https://bcr.bazel.build/modules/tar.bzl/0.2.1/MODULE.bazel": "52d1c00a80a8cc67acbd01649e83d8dd6a9dc426a6c0b754a04fe8c219c76468", "https://bcr.bazel.build/modules/tar.bzl/0.5.1/MODULE.bazel": "7c2eb3dcfc53b0f3d6f9acdfd911ca803eaf92aadf54f8ca6e4c1f3aee288351", "https://bcr.bazel.build/modules/tar.bzl/0.8.1/MODULE.bazel": "6ffe8907ed4c555bc94bd35a5a01411cc4470c6dace84f9cf487815409e077d1", - "https://bcr.bazel.build/modules/tar.bzl/0.8.1/source.json": "835f83b482facf6205ad8708cf2b2f6524d1d7b1075a90fe9bb540da761d6d2e", + "https://bcr.bazel.build/modules/tar.bzl/0.9.0/MODULE.bazel": "452a22d7f02b1c9d7a22ab25edf20f46f3e1101f0f67dc4bfbf9a474ddf02445", + "https://bcr.bazel.build/modules/tar.bzl/0.9.0/source.json": "c732760a374831a2cf5b08839e4be75017196b4d796a5aa55235272ee17cd839", "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", "https://bcr.bazel.build/modules/yq.bzl/0.1.1/MODULE.bazel": "9039681f9bcb8958ee2c87ffc74bdafba9f4369096a2b5634b88abc0eaefa072", "https://bcr.bazel.build/modules/yq.bzl/0.2.0/MODULE.bazel": "6f3a675677db8885be4d607fde14cc51829715e3a879fb016eb9bf336786ce6d", "https://bcr.bazel.build/modules/yq.bzl/0.3.2/MODULE.bazel": "0384efa70e8033d842ea73aa4b7199fa099709e236a7264345c03937166670b6", "https://bcr.bazel.build/modules/yq.bzl/0.3.4/MODULE.bazel": "d3a270662f5d766cd7229732d65a5a5bc485240c3007343dd279edfb60c9ae27", - "https://bcr.bazel.build/modules/yq.bzl/0.3.4/source.json": "786dafdc2843722da3416e4343ee1a05237227f068590779a6e8496a2064c0f9", + "https://bcr.bazel.build/modules/yq.bzl/0.3.5/MODULE.bazel": "130c603e54be717bdf84100210f06598a0d2b4b4e01888fb01b70f50f41767ec", + "https://bcr.bazel.build/modules/yq.bzl/0.3.5/source.json": "1ae7bdc03cb26aaa8bd2bceadf65e90d90f0b2d03008ba9a0564da2e21396c39", "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", @@ -567,7 +573,7 @@ }, "@@aspect_rules_ts+//ts:extensions.bzl%ext": { "general": { - "bzlTransitiveDigest": "QDTi1Wl/eEY4IgbXjRhegUQfHj+bB8ZEVyiSGLZc6qo=", + "bzlTransitiveDigest": "jrh/WHprsSSVvWjNLpDRdUl48LnV4xm2+ZssEvasHxQ=", "usagesDigest": "81NsRsd41daCKu8Q5ap/9nRQmXxXRmDwzKd17wtFeok=", "recordedFileInputs": { "@@rules_browsers+//package.json": "772d873d450a539e2133635aeb5e63744cf1cec86e6b37aeecd9267a147fb0d7" @@ -634,7 +640,7 @@ "@@aspect_tools_telemetry+//:extension.bzl%telemetry": { "general": { "bzlTransitiveDigest": "cl5A2O84vDL6Tt+Qga8FCj1DUDGqn+e7ly5rZ+4xvcc=", - "usagesDigest": "vdKKVXjay7FaDAQ2dFXDiqaEZRBFoxDm7X0xW0sNT5o=", + "usagesDigest": "t+N/B+tCaenTdxqjGDF2Y47ccxdueSBZEFb+zpMxd1I=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -645,8 +651,8 @@ "deps": { "aspect_rules_js": "2.9.2", "aspect_rules_esbuild": "0.25.0", - "aspect_rules_jasmine": "2.0.2", - "aspect_rules_ts": "3.8.4", + "aspect_rules_jasmine": "2.0.4", + "aspect_rules_ts": "3.8.5", "aspect_tools_telemetry": "0.3.3" } } @@ -4310,8 +4316,8 @@ }, "@@yq.bzl+//yq:extensions.bzl%yq": { "general": { - "bzlTransitiveDigest": "tDqk+ntWTdxNAWPDjRY1uITgHbti2jcXR5ZdinltBs0=", - "usagesDigest": "jINqtIprI8xAo9NmAr+0vIXtkTtn9IasKnGcw8TX32U=", + "bzlTransitiveDigest": "UfFMy8CWK4/dVo/tfaSAIYUiDGNAPes5eRllx9O9Q9Q=", + "usagesDigest": "hiHV/I61eANWBbRh50H3odPLRnOEZ7VsjgV8OyI9mrc=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, From 6a8da0890d7cf4495902c767e34fe3e1f2e55a33 Mon Sep 17 00:00:00 2001 From: Angular Robot Date: Wed, 4 Mar 2026 17:28:07 -0700 Subject: [PATCH 022/123] build: lock file maintenance (#32844) See associated pull request for more information. --- pnpm-lock.yaml | 1772 ++++++++++++++++++++++++------------------------ 1 file changed, 895 insertions(+), 877 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9f46ebbf3044..f62a0cdac36d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -75,19 +75,19 @@ importers: version: 21.2.0-rc.0(chokidar@5.0.0) '@angular/common': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7) '@angular/compiler': specifier: 'catalog:' version: 21.2.0-rc.0 '@angular/core': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + version: 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) '@angular/forms': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7) '@angular/platform-browser': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)) '@types/google.maps': specifier: ^3.54.10 version: 3.58.1 @@ -117,7 +117,7 @@ importers: version: 2.8.1 zone.js: specifier: ~0.16.0 - version: 0.16.0 + version: 0.16.1 devDependencies: '@angular/compiler-cli': specifier: 'catalog:' @@ -127,13 +127,13 @@ importers: version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0) '@angular/ng-dev': specifier: https://github.com/angular/dev-infra-private-ng-dev-builds.git#b0ab31189ecbeaaafce2bd9259385879b9beabcc - version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b0ab31189ecbeaaafce2bd9259385879b9beabcc(@modelcontextprotocol/sdk@1.26.0) + version: https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b0ab31189ecbeaaafce2bd9259385879b9beabcc(@modelcontextprotocol/sdk@1.27.1) '@angular/platform-server': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7) '@angular/router': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7) '@babel/core': specifier: ^7.16.12 version: 7.29.0 @@ -160,10 +160,10 @@ importers: version: 22.0.1 '@rollup/plugin-commonjs': specifier: ^29.0.0 - version: 29.0.0(rollup@4.57.1) + version: 29.0.0(rollup@4.59.0) '@rollup/plugin-node-resolve': specifier: ^16.0.0 - version: 16.0.3(rollup@4.57.1) + version: 16.0.3(rollup@4.59.0) '@schematics/angular': specifier: 'catalog:' version: 21.2.0-rc.0(chokidar@5.0.0) @@ -181,7 +181,7 @@ importers: version: 3.7.1 '@types/node': specifier: ^22.14.1 - version: 22.19.11 + version: 22.19.13 '@types/selenium-webdriver': specifier: ^3.0.17 version: 3.0.26 @@ -196,7 +196,7 @@ importers: version: 17.0.35 autoprefixer: specifier: ^10.4.2 - version: 10.4.24(postcss@8.5.6) + version: 10.4.27(postcss@8.5.8) axe-core: specifier: ^4.10.3 version: 4.11.1 @@ -214,13 +214,13 @@ importers: version: 0.27.3 firebase-tools: specifier: 15.6.0 - version: 15.6.0(@types/node@22.19.11)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2) + version: 15.6.0(@types/node@22.19.13)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2) fs-extra: specifier: ^11.0.0 version: 11.3.3 glob: specifier: ^13.0.0 - version: 13.0.3 + version: 13.0.6 highlight.js: specifier: ^11.0.0 version: 11.11.1 @@ -229,10 +229,10 @@ importers: version: 9.1.7 jasmine: specifier: ^6.0.0 - version: 6.0.0 + version: 6.1.0 jasmine-core: specifier: ^6.0.0 - version: 6.0.1 + version: 6.1.0 jasmine-reporters: specifier: ^2.5.2 version: 2.5.2 @@ -262,19 +262,19 @@ importers: version: 0.30.21 marked: specifier: ^17.0.0 - version: 17.0.2 + version: 17.0.3 minimatch: specifier: ^10.0.3 - version: 10.2.0 + version: 10.2.4 parse5: specifier: ^8.0.0 version: 8.0.0 postcss: specifier: ^8.4.17 - version: 8.5.6 + version: 8.5.8 postcss-scss: specifier: ^4.0.4 - version: 4.0.9(postcss@8.5.6) + version: 4.0.9(postcss@8.5.8) prettier: specifier: ^3.5.3 version: 3.8.1 @@ -286,16 +286,16 @@ importers: version: 2.3.8 rollup: specifier: ^4.52.3 - version: 4.57.1 + version: 4.59.0 rollup-plugin-dts: specifier: 6.3.0 - version: 6.3.0(rollup@4.57.1)(typescript@5.9.2) + version: 6.3.0(rollup@4.59.0)(typescript@5.9.2) rollup-plugin-sourcemaps2: specifier: 0.5.4 - version: 0.5.4(@types/node@22.19.11)(rollup@4.57.1) + version: 0.5.4(@types/node@22.19.13)(rollup@4.59.0) sass: specifier: ^1.97.2 - version: 1.97.2 + version: 1.97.3 selenium-webdriver: specifier: ^3.6.0 version: 3.6.0 @@ -319,7 +319,7 @@ importers: version: 5.46.0 ts-node: specifier: ^10.9.1 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.2) + version: 10.9.2(@types/node@22.19.13)(typescript@5.9.2) tsec: specifier: 0.2.9 version: 0.2.9(@bazel/bazelisk@1.28.1)(typescript@5.9.2) @@ -361,7 +361,7 @@ importers: version: link:../src/cdk-experimental '@angular/common': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7) '@angular/compiler': specifier: 'catalog:' version: 21.2.0-rc.0 @@ -370,10 +370,10 @@ importers: version: link:../src/components-examples '@angular/core': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + version: 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) '@angular/forms': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7) '@angular/google-maps': specifier: workspace:* version: link:../src/google-maps @@ -391,16 +391,16 @@ importers: version: link:../src/material-luxon-adapter '@angular/platform-browser': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)) '@angular/platform-browser-dynamic': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))) '@angular/router': specifier: 'catalog:' - version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + version: 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7) '@angular/ssr': specifier: 'catalog:' - version: 21.2.0-rc.0(0cbd0fdcfddd4e429cff3ac260204f3f) + version: 21.2.0-rc.0(4f6c63f876d0dabb1b5ac88e842da9cd) '@angular/youtube-player': specifier: workspace:* version: link:../src/youtube-player @@ -421,35 +421,35 @@ importers: version: 2.8.1 zone.js: specifier: ~0.16.0 - version: 0.16.0 + version: 0.16.1 devDependencies: '@angular-devkit/build-angular': specifier: 'catalog:' - version: 21.2.0-rc.0(85e9118f1bcacefdee125f6ee0de5595) + version: 21.2.0-rc.0(ac7d81f2a93fedccccd94ec8e5875310) '@angular/cli': specifier: 'catalog:' - version: 21.2.0-rc.0(@types/node@22.19.11)(chokidar@5.0.0) + version: 21.2.0-rc.0(@types/node@22.19.13)(chokidar@5.0.0) '@angular/compiler-cli': specifier: 'catalog:' version: 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) '@bazel/bazelisk': specifier: ^1.12.1 - version: 1.26.0 + version: 1.28.1 '@types/jasmine': specifier: ^6.0.0 version: 6.0.0 '@types/node': specifier: ^22.14.1 - version: 22.19.11 + version: 22.19.13 '@types/shelljs': specifier: 0.10.0 version: 0.10.0 firebase-tools: specifier: 15.6.0 - version: 15.6.0(@types/node@22.19.11)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2) + version: 15.6.0(@types/node@22.19.13)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2) jasmine-core: specifier: ^6.0.0 - version: 6.0.1 + version: 6.1.0 jasmine-spec-reporter: specifier: 7.0.0 version: 7.0.0 @@ -485,7 +485,7 @@ importers: version: 7.0.0 puppeteer-core: specifier: ^24.6.1 - version: 24.37.3(bufferutil@4.1.0) + version: 24.37.5(bufferutil@4.1.0) sass: specifier: 1.97.3 version: 1.97.3 @@ -494,7 +494,7 @@ importers: version: 0.10.0 ts-node: specifier: 10.9.2 - version: 10.9.2(@types/node@22.19.11)(typescript@5.9.2) + version: 10.9.2(@types/node@22.19.13)(typescript@5.9.2) typescript: specifier: 5.9.2 version: 5.9.2 @@ -1549,10 +1549,6 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@bazel/bazelisk@1.26.0': - resolution: {integrity: sha512-bTNcHdGyEQ9r7SczEYUa0gkEQhJo1ld2BjXI8fWBvsUeoHi03QpUs2HZgDbjjrpQFQqG2ZbO7ihZvH8MjhUTHw==} - hasBin: true - '@bazel/bazelisk@1.28.1': resolution: {integrity: sha512-K21x83NXOtd0yb2qzjMES3UV4xEWZ1q1vnXFhADA1u7IoiMVQkJAVQRK3oZ5txpnrGafY15HS+YYr2nmsEP4Tg==} hasBin: true @@ -2006,8 +2002,12 @@ packages: '@formatjs/intl-localematcher@0.6.2': resolution: {integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==} - '@google-cloud/cloud-sql-connector@1.9.0': - resolution: {integrity: sha512-kCsWuWBCHBdRSyrNHoJ4lIsd6P3JeXQk3OopsS/TCfJzTs2dfEzQvwl5G7Gn7u/rX60m+X7wv4wHDMP2sG5AFA==} + '@gar/promise-retry@1.0.2': + resolution: {integrity: sha512-Lm/ZLhDZcBECta3TmCQSngiQykFdfw+QtI1/GYMsZd4l3nG+P8WLB16XuS7WaBGLQ+9E+cOcWQsth9cayuGt8g==} + engines: {node: ^20.17.0 || >=22.9.0} + + '@google-cloud/cloud-sql-connector@1.9.1': + resolution: {integrity: sha512-K7pkjQCq3u6r6KTeAbEdSDCXKmL5Ve8TNPAoek6ndkFmt44kvAZh0sTwRBipkGM0B5UmWljFROqCWGP4IHXBpg==} engines: {node: '>=18'} '@google-cloud/common@6.0.0': @@ -2038,8 +2038,8 @@ packages: resolution: {integrity: sha512-N8qS6dlORGHwk7WjGXKOSsLjIjNINCPicsOX6gyyLiYk7mq3MtII96NZ9N2ahwA2vnkLmZODOIH9rlNniYWvCQ==} engines: {node: '>=18'} - '@google-cloud/pubsub@5.2.3': - resolution: {integrity: sha512-YKsFl4Qs+nhy20CPNVeafxAt5erQ8LoJuz/gpPAP0WHGQFXnV3KcSZ5HvzgEiUNYsQs/AjjOUdqwnZ4XKaBY/Q==} + '@google-cloud/pubsub@5.3.0': + resolution: {integrity: sha512-hyUoE85Rj3rRUVk3VU+Selp4MorBwEzsQEqAj6+SE+WabR9LIFitYS6A4R+PyiwVaRk/tggGD8p7bNiIY5sk4w==} engines: {node: '>=18'} '@google-cloud/spanner@8.0.0': @@ -2103,8 +2103,8 @@ packages: '@types/node': optional: true - '@inquirer/checkbox@5.0.6': - resolution: {integrity: sha512-qLZ1gOpsqsieB5k98GQ9bWYggvMsCXTc7HUwhEQpTsxFQYGthqR9UysCwqB7L9h47THYdXhJegnYb1IqURMjng==} + '@inquirer/checkbox@5.1.0': + resolution: {integrity: sha512-/HjF1LN0a1h4/OFsbGKHNDtWICFU/dqXCdym719HFTyJo9IG7Otr+ziGWc9S0iQuohRZllh+WprSgd5UW5Fw0g==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2121,8 +2121,8 @@ packages: '@types/node': optional: true - '@inquirer/confirm@6.0.6': - resolution: {integrity: sha512-9ZkrGYiWnOKQPc3xfLIORE3lZW1qvtgRoJcoqopr5zssBn7yk4yONmzGynEOjc16FnUXzkAejj/I29BbfcoUfQ==} + '@inquirer/confirm@6.0.8': + resolution: {integrity: sha512-Di6dgmiZ9xCSUxWUReWTqDtbhXCuG2MQm2xmgSAIruzQzBqNf49b8E07/vbCYY506kDe8BiwJbegXweG8M1klw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2139,8 +2139,8 @@ packages: '@types/node': optional: true - '@inquirer/core@11.1.3': - resolution: {integrity: sha512-TBAGPDGvpwFSQ4nkawQzq5/X7DhElANjvKeUtcjpVnBIfuH/OEu4M+79R3+bGPtwxST4DOIGRtF933mUH2bRVw==} + '@inquirer/core@11.1.5': + resolution: {integrity: sha512-QQPAX+lka8GyLcZ7u7Nb1h6q72iZ/oy0blilC3IB2nSt1Qqxp7akt94Jqhi/DzARuN3Eo9QwJRvtl4tmVe4T5A==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2157,8 +2157,8 @@ packages: '@types/node': optional: true - '@inquirer/editor@5.0.6': - resolution: {integrity: sha512-dxTi/TB29NaW18u0pQl3B140695izGUMzr340a4Yhxll3oa0/iwxl6C88sX9LDUPFaaM4FDASEMnLm8XVk2VVg==} + '@inquirer/editor@5.0.8': + resolution: {integrity: sha512-sLcpbb9B3XqUEGrj1N66KwhDhEckzZ4nI/W6SvLXyBX8Wic3LDLENlWRvkOGpCPoserabe+MxQkpiMoI8irvyA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2175,8 +2175,8 @@ packages: '@types/node': optional: true - '@inquirer/expand@5.0.6': - resolution: {integrity: sha512-HmgMzFdMk/gmPXfuFy4xgWkyIVbdH81otQkrFbhklFZcGauwDFD1EbgmZdgmYCN5pWhSEnYIadg1kysLgPIYag==} + '@inquirer/expand@5.0.8': + resolution: {integrity: sha512-QieW3F1prNw3j+hxO7/NKkG1pk3oz7pOB6+5Upwu3OIwADfPX0oZVppsqlL+Vl/uBHHDSOBY0BirLctLnXwGGg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2219,8 +2219,8 @@ packages: '@types/node': optional: true - '@inquirer/input@5.0.6': - resolution: {integrity: sha512-RZsJcjMJA3QNI9q9OiAi1fAom+Pb8on6alJB1Teh5jjKaiG5C79P69cG955ZRfgPdxTmI4uyhf33+94Xj7xWig==} + '@inquirer/input@5.0.8': + resolution: {integrity: sha512-p0IJslw0AmedLEkOU+yrEX3Aj2RTpQq7ZOf8nc1DIhjzaxRWrrgeuE5Kyh39fVRgtcACaMXx/9WNo8+GjgBOfw==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2237,8 +2237,8 @@ packages: '@types/node': optional: true - '@inquirer/number@4.0.6': - resolution: {integrity: sha512-owMkAY+gR0BggomDTL+Z22x/yfE4ocFrmNyJacOiaDVA/d+iL4IWyk7Ds7JEuDMxuhHFB46Dubdxg1uiD7GlCA==} + '@inquirer/number@4.0.8': + resolution: {integrity: sha512-uGLiQah9A0F9UIvJBX52m0CnqtLaym0WpT9V4YZrjZ+YRDKZdwwoEPz06N6w8ChE2lrnsdyhY9sL+Y690Kh9gQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2255,8 +2255,8 @@ packages: '@types/node': optional: true - '@inquirer/password@5.0.6': - resolution: {integrity: sha512-c4BT4SB79iYwPhtGVBSvrlTnn4oFSYnwocafmktpay8RK75T2c2+fLlR0i1Cxw0QOhdy/YULdmpHoy1sOrPzvA==} + '@inquirer/password@5.0.8': + resolution: {integrity: sha512-zt1sF4lYLdvPqvmvHdmjOzuUUjuCQ897pdUCO8RbXMUDKXJTTyOQgtn23le+jwcb+MpHl3VAFvzIdxRAf6aPlA==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2291,8 +2291,8 @@ packages: '@types/node': optional: true - '@inquirer/rawlist@5.2.2': - resolution: {integrity: sha512-ld2EhLlf3fsBv7QfxR31NdBecGdS6eeFFZ+Nx88ApjtifeCEc9TNrw8x5tGe+gd6HG1ERczOb4B/bMojiGIp1g==} + '@inquirer/rawlist@5.2.4': + resolution: {integrity: sha512-fTuJ5Cq9W286isLxwj6GGyfTjx1Zdk4qppVEPexFuA6yioCCXS4V1zfKroQqw7QdbDPN73xs2DiIAlo55+kBqg==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2309,8 +2309,8 @@ packages: '@types/node': optional: true - '@inquirer/search@4.1.2': - resolution: {integrity: sha512-kdGbbbWYKldWxpxodKYPmFl/ctBi3DjWlA4LX48jXtqJ7NEeoEKlyFTbE4xNEFcGDi15tvaxRLzCV4A53zqYIw==} + '@inquirer/search@4.1.4': + resolution: {integrity: sha512-9yPTxq7LPmYjrGn3DRuaPuPbmC6u3fiWcsE9ggfLcdgO/ICHYgxq7mEy1yJ39brVvgXhtOtvDVjDh9slJxE4LQ==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2327,8 +2327,8 @@ packages: '@types/node': optional: true - '@inquirer/select@5.0.6': - resolution: {integrity: sha512-9DyVbNCo4q0C3CkGd6zW0SW3NQuuk4Hy0NSbP6zErz2YNWF4EHHJCRzcV34/CDQLraeAQXbHYlMofuUrs6BBZQ==} + '@inquirer/select@5.1.0': + resolution: {integrity: sha512-OyYbKnchS1u+zRe14LpYrN8S0wH1vD0p2yKISvSsJdH2TpI87fh4eZdWnpdbrGauCRWDph3NwxRmM4Pcm/hx1Q==} engines: {node: '>=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0'} peerDependencies: '@types/node': '>=18' @@ -2586,6 +2586,15 @@ packages: '@cfworker/json-schema': optional: true + '@modelcontextprotocol/sdk@1.27.1': + resolution: {integrity: sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} cpu: [arm64] @@ -2773,8 +2782,8 @@ packages: resolution: {integrity: sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==} engines: {node: ^20.17.0 || >=22.9.0} - '@npmcli/git@7.0.1': - resolution: {integrity: sha512-+XTFxK2jJF/EJJ5SoAzXk3qwIDfvFc5/g+bD274LZ7uY7LE8sTfG6Z8rOanPl2ZEvZWqNvmEdtXC25cE54VcoA==} + '@npmcli/git@7.0.2': + resolution: {integrity: sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==} engines: {node: ^20.17.0 || >=22.9.0} '@npmcli/installed-package-contents@4.0.0': @@ -2786,8 +2795,8 @@ packages: resolution: {integrity: sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==} engines: {node: ^20.17.0 || >=22.9.0} - '@npmcli/package-json@7.0.4': - resolution: {integrity: sha512-0wInJG3j/K40OJt/33ax47WfWMzZTm6OQxB9cDhTt5huCP2a9g2GnlsxmfN+PulItNPIpPrZ+kfwwUil7eHcZQ==} + '@npmcli/package-json@7.0.5': + resolution: {integrity: sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ==} engines: {node: ^20.17.0 || >=22.9.0} '@npmcli/promise-spawn@3.0.0': @@ -2802,8 +2811,8 @@ packages: resolution: {integrity: sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==} engines: {node: ^20.17.0 || >=22.9.0} - '@npmcli/run-script@10.0.3': - resolution: {integrity: sha512-ER2N6itRkzWbbtVmZ9WKaWxVlKlOeBFF1/7xx+KA5J1xKa4JjUwBdb6tDpk0v1qA+d+VDwHI9qmLcXSWcmi+Rw==} + '@npmcli/run-script@10.0.4': + resolution: {integrity: sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==} engines: {node: ^20.17.0 || >=22.9.0} '@octokit/auth-app@8.1.2': @@ -2830,8 +2839,8 @@ packages: resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==} engines: {node: '>= 20'} - '@octokit/endpoint@11.0.2': - resolution: {integrity: sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==} + '@octokit/endpoint@11.0.3': + resolution: {integrity: sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==} engines: {node: '>= 20'} '@octokit/graphql-schema@15.26.1': @@ -2874,8 +2883,8 @@ packages: resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} engines: {node: '>= 20'} - '@octokit/request@10.0.7': - resolution: {integrity: sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==} + '@octokit/request@10.0.8': + resolution: {integrity: sha512-SJZNwY9pur9Agf7l87ywFi14W+Hd9Jg6Ifivsd33+/bGUQIjNujdFiXII2/qSlN2ybqUHfp5xpekMEjIBTjlSw==} engines: {node: '>= 20'} '@octokit/rest@22.0.1': @@ -3084,14 +3093,14 @@ packages: resolution: {integrity: sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==} engines: {node: '>=14'} - '@opentelemetry/semantic-conventions@1.34.0': - resolution: {integrity: sha512-aKcOkyrorBGlajjRdVoJWHTxfxO1vCNHLJVlSDaRHDIdjU+pX8IYQPvPDkYiujKLbRnWU+1TBwEt0QRgSm4SGA==} - engines: {node: '>=14'} - '@opentelemetry/semantic-conventions@1.39.0': resolution: {integrity: sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==} engines: {node: '>=14'} + '@opentelemetry/semantic-conventions@1.40.0': + resolution: {integrity: sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==} + engines: {node: '>=14'} + '@opentelemetry/sql-common@0.40.1': resolution: {integrity: sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==} engines: {node: '>=14'} @@ -3302,8 +3311,8 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@puppeteer/browsers@2.12.1': - resolution: {integrity: sha512-fXa6uXLxfslBlus3MEpW8S6S9fe5RwmAE5Gd8u3krqOwnkZJV3/lQJiY3LaFdTctLLqJtyMgEUGkbDnRNf6vbQ==} + '@puppeteer/browsers@2.13.0': + resolution: {integrity: sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA==} engines: {node: '>=18'} hasBin: true @@ -3427,141 +3436,141 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.57.1': - resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} + '@rollup/rollup-android-arm-eabi@4.59.0': + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.57.1': - resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==} + '@rollup/rollup-android-arm64@4.59.0': + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.57.1': - resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==} + '@rollup/rollup-darwin-arm64@4.59.0': + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.57.1': - resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==} + '@rollup/rollup-darwin-x64@4.59.0': + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.57.1': - resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==} + '@rollup/rollup-freebsd-arm64@4.59.0': + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.57.1': - resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==} + '@rollup/rollup-freebsd-x64@4.59.0': + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': - resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.57.1': - resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.57.1': - resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} + '@rollup/rollup-linux-arm64-gnu@4.59.0': + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.57.1': - resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} + '@rollup/rollup-linux-arm64-musl@4.59.0': + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.57.1': - resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} + '@rollup/rollup-linux-loong64-gnu@4.59.0': + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-loong64-musl@4.57.1': - resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} + '@rollup/rollup-linux-loong64-musl@4.59.0': + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] libc: [musl] - '@rollup/rollup-linux-ppc64-gnu@4.57.1': - resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.57.1': - resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} + '@rollup/rollup-linux-ppc64-musl@4.59.0': + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.57.1': - resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.57.1': - resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} + '@rollup/rollup-linux-riscv64-musl@4.59.0': + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.57.1': - resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} + '@rollup/rollup-linux-s390x-gnu@4.59.0': + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.57.1': - resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} + '@rollup/rollup-linux-x64-gnu@4.59.0': + resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.57.1': - resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} + '@rollup/rollup-linux-x64-musl@4.59.0': + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.57.1': - resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} + '@rollup/rollup-openbsd-x64@4.59.0': + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.57.1': - resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==} + '@rollup/rollup-openharmony-arm64@4.59.0': + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.57.1': - resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==} + '@rollup/rollup-win32-arm64-msvc@4.59.0': + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.57.1': - resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==} + '@rollup/rollup-win32-ia32-msvc@4.59.0': + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.57.1': - resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==} + '@rollup/rollup-win32-x64-gnu@4.59.0': + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.57.1': - resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==} + '@rollup/rollup-win32-x64-msvc@4.59.0': + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} cpu: [x64] os: [win32] @@ -3765,8 +3774,8 @@ packages: '@types/mysql@2.15.26': resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==} - '@types/node@22.19.11': - resolution: {integrity: sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==} + '@types/node@22.19.13': + resolution: {integrity: sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==} '@types/node@24.10.9': resolution: {integrity: sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==} @@ -3973,8 +3982,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} engines: {node: '>=0.4.0'} acorn@7.4.1: @@ -3982,8 +3991,8 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} hasBin: true @@ -4023,8 +4032,8 @@ packages: peerDependencies: ajv: ^8.8.2 - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.14.0: + resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} @@ -4198,6 +4207,13 @@ packages: peerDependencies: postcss: ^8.1.0 + autoprefixer@10.4.27: + resolution: {integrity: sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -4212,8 +4228,8 @@ packages: resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==} engines: {node: '>=4'} - b4a@1.7.4: - resolution: {integrity: sha512-u20zJLDaSWpxaZ+zaAkEIB2dZZ1o+DF4T/MRbmsvGp9nletHOyiai19OzX1fF8xUBYsO1bPXxODvcd0978pnug==} + b4a@1.8.0: + resolution: {integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==} peerDependencies: react-native-b4a: '*' peerDependenciesMeta: @@ -4256,9 +4272,9 @@ packages: balanced-match@2.0.0: resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} - balanced-match@4.0.2: - resolution: {integrity: sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==} - engines: {node: 20 || >=22} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} bare-events@2.8.2: resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} @@ -4268,8 +4284,8 @@ packages: bare-abort-controller: optional: true - bare-fs@4.5.4: - resolution: {integrity: sha512-POK4oplfA7P7gqvetNmCs4CNtm9fNsx+IAh7jH7GgU0OJdge2rso0R20TNWVq6VoWcCvsTdlNDaleLHGaKx8CA==} + bare-fs@4.5.5: + resolution: {integrity: sha512-XvwYM6VZqKoqDll8BmSww5luA5eflDzY0uEFfBJtFKe4PAAtxBjU3YIxzIBzhyaEQBy1VXEQBto4cpN5RZJw+w==} engines: {bare: '>=1.16.0'} peerDependencies: bare-buffer: '*' @@ -4277,15 +4293,15 @@ packages: bare-buffer: optional: true - bare-os@3.6.2: - resolution: {integrity: sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==} + bare-os@3.7.0: + resolution: {integrity: sha512-64Rcwj8qlnTZU8Ps6JJEdSmxBEUGgI7g8l+lMtsJLl4IsfTcHMTfJ188u2iGV6P6YPRZrtv72B2kjn+hp+Yv3g==} engines: {bare: '>=1.14.0'} bare-path@3.0.0: resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} - bare-stream@2.7.0: - resolution: {integrity: sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==} + bare-stream@2.8.0: + resolution: {integrity: sha512-reUN0M2sHRqCdG4lUK3Fw8w98eeUIZHL5c3H7Mbhk2yVBL+oofgaIp0ieLfD5QXwPCypBpmEEKU2WZKzbAk8GA==} peerDependencies: bare-buffer: '*' bare-events: '*' @@ -4305,8 +4321,9 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - baseline-browser-mapping@2.9.19: - resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} + baseline-browser-mapping@2.10.0: + resolution: {integrity: sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==} + engines: {node: '>=6.0.0'} hasBin: true basic-auth-connect@1.1.0: @@ -4316,8 +4333,8 @@ packages: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} - basic-ftp@5.1.0: - resolution: {integrity: sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==} + basic-ftp@5.2.0: + resolution: {integrity: sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==} engines: {node: '>=10.0.0'} batch@0.6.1: @@ -4381,9 +4398,9 @@ packages: brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - brace-expansion@5.0.2: - resolution: {integrity: sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==} - engines: {node: 20 || >=22} + brace-expansion@5.0.4: + resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + engines: {node: 18 || 20 || >=22} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -4394,8 +4411,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true - browserstack-local@1.5.10: - resolution: {integrity: sha512-b9VCPzbcZ9heJIlMsexE/zj3D5Y0l0v2lSalKDmjCvdX//KsUBA+g1evWx6yjkMX1DLdfuEBe8fMn4iK7S1vUA==} + browserstack-local@1.5.11: + resolution: {integrity: sha512-RNq0yrezPq7BXXxl/cvsbORfswUQi744po6ECkTEC2RkqNbdPyzewdy4VR9k4QHSzPHTkZx8PeH08veRtfFI8A==} browserstack@1.5.3: resolution: {integrity: sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==} @@ -4483,8 +4500,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001770: - resolution: {integrity: sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==} + caniuse-lite@1.0.30001776: + resolution: {integrity: sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==} canonical-path@0.0.2: resolution: {integrity: sha512-y8EIEvL+IW81S4hRQWCRFtly+g1cc1G+wxHpjhYR9jI2+JJjWiaKnkH8mmvNHOMOAd9fzgARDO3AEzjuR51qaA==} @@ -4610,8 +4627,8 @@ packages: resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} engines: {node: 10.* || >= 12.*} - cli-truncate@5.1.1: - resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==} + cli-truncate@5.2.0: + resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} engines: {node: '>=20'} cli-width@4.1.0: @@ -4824,8 +4841,8 @@ packages: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} - cosmiconfig@9.0.0: - resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} engines: {node: '>=14'} peerDependencies: typescript: 5.9.2 @@ -4992,8 +5009,8 @@ packages: decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - deep-equal-in-any-order@2.1.0: - resolution: {integrity: sha512-9FklcFjcehm1yBWiOYtmazJOiMbT+v81Kq6nThIuXbWLWIZMX3ZI+QoLf7wCi0T8XzTAXf6XqEdEyVrjZkhbGA==} + deep-equal-in-any-order@2.2.0: + resolution: {integrity: sha512-lUYf3Oz/HrPcNmKe+S+QSdY5/hzKleftcFBWLwbHNZ5007RUKgN0asWlAHuQGvT9djYd9PYQFiu0TyNS+h3j/g==} deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} @@ -5151,9 +5168,6 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - duplexer@0.1.2: - resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - duplexify@3.7.1: resolution: {integrity: sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==} @@ -5177,8 +5191,8 @@ packages: engines: {node: '>=0.12.18'} hasBin: true - electron-to-chromium@1.5.286: - resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==} + electron-to-chromium@1.5.302: + resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==} emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -5221,8 +5235,8 @@ packages: resolution: {integrity: sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==} engines: {node: '>=10.2.0'} - enhanced-resolve@5.19.0: - resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} + enhanced-resolve@5.20.0: + resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} engines: {node: '>=10.13.0'} enquirer@2.4.1: @@ -5394,9 +5408,6 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} - event-stream@3.3.4: - resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} - event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -5542,8 +5553,8 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} - filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + filelist@1.0.6: + resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} filesize@6.4.0: resolution: {integrity: sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ==} @@ -5589,8 +5600,8 @@ packages: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + flatted@3.3.4: + resolution: {integrity: sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==} fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} @@ -5650,9 +5661,6 @@ packages: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} - from@0.1.7: - resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -5699,6 +5707,10 @@ packages: resolution: {integrity: sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==} engines: {node: '>=18'} + gaxios@7.1.4: + resolution: {integrity: sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==} + engines: {node: '>=18'} + gaze@1.1.3: resolution: {integrity: sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==} engines: {node: '>= 4.0.0'} @@ -5723,8 +5735,8 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.4.0: - resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} engines: {node: '>=18'} get-intrinsic@1.3.0: @@ -5760,6 +5772,7 @@ packages: git-raw-commits@5.0.0: resolution: {integrity: sha512-I2ZXrXeOc0KrCvC7swqtIFXFN+rbjnC7b2T943tvemIOVNl+XP8YnA9UVwqFhzzLClnSA60KR/qEjLpXzs73Qg==} engines: {node: '>=18'} + deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead. hasBin: true glob-parent@5.1.2: @@ -5796,9 +5809,9 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true - glob@13.0.3: - resolution: {integrity: sha512-/g3B0mC+4x724v1TgtBlBtt2hPi/EWptsIAmXUx9Z2rvBYleQcsrmaOzd5LyL50jf/Soi83ZDJmw2+XqvH/EeA==} - engines: {node: 20 || >=22} + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} glob@5.0.15: resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} @@ -5843,8 +5856,8 @@ packages: resolution: {integrity: sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==} engines: {node: '>= 0.10'} - google-auth-library@10.5.0: - resolution: {integrity: sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==} + google-auth-library@10.6.1: + resolution: {integrity: sha512-5awwuLrzNol+pFDmKJd0dKtZ0fPLAtoA5p7YO4ODsDu6ONJUVqbYwvv8y2ZBO5MBNp9TJXigB19710kYpBPdtA==} engines: {node: '>=18'} google-auth-library@9.15.1: @@ -5883,8 +5896,8 @@ packages: peerDependencies: graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - graphql@16.12.0: - resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==} + graphql@16.13.0: + resolution: {integrity: sha512-uSisMYERbaB9bkA9M4/4dnqyktaEkf1kMHNKq/7DHyxVeWqHQ2mBmVqm5u6/FVHwF3iCNalKcg82Zfl+tffWoA==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} grpc-gcp@1.0.1: @@ -5895,10 +5908,6 @@ packages: resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} engines: {node: '>=14.0.0'} - gtoken@8.0.0: - resolution: {integrity: sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==} - engines: {node: '>=18'} - handle-thing@2.0.1: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} @@ -5995,8 +6004,8 @@ packages: resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} engines: {node: '>=12.0.0'} - hono@4.11.9: - resolution: {integrity: sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ==} + hono@4.12.3: + resolution: {integrity: sha512-SFsVSjp8sj5UumXOOFlkZOG6XS9SJDKw0TbwFeV+AJ8xlST8kxK5Z/5EYa111UY8732lK2S/xB653ceuaoGwpg==} engines: {node: '>=16.9.0'} hosted-git-info@2.8.9: @@ -6370,8 +6379,8 @@ packages: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} - is-network-error@1.3.0: - resolution: {integrity: sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==} + is-network-error@1.3.1: + resolution: {integrity: sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==} engines: {node: '>=16'} is-node-process@1.2.0: @@ -6611,8 +6620,8 @@ packages: jasmine-core@6.0.0: resolution: {integrity: sha512-fmBb8aruz2mEIDBUGWOGNmxhXwFJs44SSzwbMcBDqQnNChavPTq3Ra9A6WAn6WdxvxWEdakKTcEb3NzeR3yD1A==} - jasmine-core@6.0.1: - resolution: {integrity: sha512-gUtzV5ASR0MLBwDNqri4kBsgKNCcRQd9qOlNw/w/deavD0cl3JmWXXfH8JhKM4LTg6LPTt2IOQ4px3YYfgh2Xg==} + jasmine-core@6.1.0: + resolution: {integrity: sha512-p/tjBw58O6vxKIWMlrU+yys8lqR3+l3UrqwNTT7wpj+dQ7N4etQekFM8joI+cWzPDYqZf54kN+hLC1+s5TvZvg==} jasmine-reporters@2.5.2: resolution: {integrity: sha512-qdewRUuFOSiWhiyWZX8Yx3YNQ9JG51ntBEO4ekLQRpktxFTwUHy24a86zD/Oi2BRTKksEdfWQZcQFqzjqIkPig==} @@ -6628,6 +6637,10 @@ packages: resolution: {integrity: sha512-eSPL6LPWT39WwvHSEEbRXuSvioXMTheNhIPaeUT1OPmSprDZwj4S29884DkTx6/tyiOWTWB1N+LdW2ZSg74aEA==} hasBin: true + jasmine@6.1.0: + resolution: {integrity: sha512-WPphPqEMY0uBRMjuhRHoVoxQNvJuxIMqz0yIcJ3k3oYxBedeGoH60/NXNgasxnx2FvfXrq5/r+2wssJ7WE8ABw==} + hasBin: true + jasminewd2@2.2.0: resolution: {integrity: sha512-Rn0nZe4rfDhzA63Al3ZGh0E+JTmM6ESZYXJGKuqKGZObsAB9fwXPD03GjtIEvJBDOhN94T5MzbwZSqzFHSQPzg==} engines: {node: '>= 6.9.x'} @@ -6713,6 +6726,9 @@ packages: json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + json-with-bigint@3.5.7: + resolution: {integrity: sha512-7ei3MdAI5+fJPVnKlW77TKNKwQ5ppSzWvhPuSuINT/GYW9ZOC1eRKOuhV9yHG5aEsUPj9BBx5JIekkmoLHxZOw==} + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -6810,8 +6826,8 @@ packages: kuler@2.0.0: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} - launch-editor@2.12.0: - resolution: {integrity: sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==} + launch-editor@2.13.1: + resolution: {integrity: sha512-lPSddlAAluRKJ7/cjRFoXUFzaX7q/YKI7yPHuEvSJVqoXvFnJov1/Ud87Aa4zULIbA9Nja4mSPK8l0z/7eV2wA==} lazystream@1.0.1: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} @@ -6952,9 +6968,6 @@ packages: lodash.isstring@4.0.1: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} - lodash.mapvalues@4.6.0: - resolution: {integrity: sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==} - lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} @@ -7049,8 +7062,8 @@ packages: make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - make-fetch-happen@15.0.3: - resolution: {integrity: sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==} + make-fetch-happen@15.0.4: + resolution: {integrity: sha512-vM2sG+wbVeVGYcCm16mM3d5fuem9oC28n436HjsGO3LcxoTI8LNVa4rwZDn3f76+cWyT4GGJDxjTYU1I2nr6zw==} engines: {node: ^20.17.0 || >=22.9.0} map-obj@1.0.1: @@ -7061,9 +7074,6 @@ packages: resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} engines: {node: '>=8'} - map-stream@0.1.0: - resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} - marked-terminal@7.3.0: resolution: {integrity: sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==} engines: {node: '>=16.0.0'} @@ -7080,8 +7090,8 @@ packages: engines: {node: '>= 18'} hasBin: true - marked@17.0.2: - resolution: {integrity: sha512-s5HZGFQea7Huv5zZcAGhJLT3qLpAfnY7v7GWkICUr0+Wd5TFEtdlRR2XUL5Gg+RH7u2Df595ifrxR03mBaw7gA==} + marked@17.0.3: + resolution: {integrity: sha512-jt1v2ObpyOKR8p4XaUJVk3YWRJ5n+i4+rjQopxvV32rSndTJXvIzuUdWWIy/1pFQMkQmvTXawzDNqOH/CUmx6A==} engines: {node: '>= 20'} hasBin: true @@ -7193,30 +7203,30 @@ packages: resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} engines: {node: 20 || >=22} - minimatch@10.2.0: - resolution: {integrity: sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==} - engines: {node: 20 || >=22} + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} minimatch@3.0.8: resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} engines: {node: '>=10'} - minimatch@6.2.0: - resolution: {integrity: sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==} + minimatch@6.2.3: + resolution: {integrity: sha512-5rvZbDy5y2k40rre/0OBbYnl03en25XPU3gOVO7532beGMjAipq88VdS9OeLOZNrD+Tb0lDhBJHZ7Gcd8qKlPg==} engines: {node: '>=10'} minimatch@7.4.6: resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} engines: {node: '>=10'} - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} minimist-options@4.1.0: @@ -7230,8 +7240,8 @@ packages: resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} engines: {node: '>=16 || 14 >=14.17'} - minipass-fetch@5.0.1: - resolution: {integrity: sha512-yHK8pb0iCGat0lDrs/D6RZmCdaBT64tULXjdxjSMAqoDi18Q3qKEUTHypHQZQd9+FYpIS+lkvpq6C/R6SbUeRw==} + minipass-fetch@5.0.2: + resolution: {integrity: sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==} engines: {node: ^20.17.0 || >=22.9.0} minipass-flush@1.0.5: @@ -7250,8 +7260,8 @@ packages: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} minizlib@3.1.0: @@ -7276,8 +7286,8 @@ packages: moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} - moo@0.5.2: - resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} + moo@0.5.3: + resolution: {integrity: sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==} morgan@1.10.1: resolution: {integrity: sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==} @@ -7460,8 +7470,8 @@ packages: resolution: {integrity: sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==} engines: {node: ^20.17.0 || >=22.9.0} - npm-packlist@10.0.3: - resolution: {integrity: sha512-zPukTwJMOu5X5uvm0fztwS5Zxyvmk38H/LfidkOMt3gbZVCyro2cD/ETzwzVPcWZA3JOyPznfUN/nkyFiyUbxg==} + npm-packlist@10.0.4: + resolution: {integrity: sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==} engines: {node: ^20.17.0 || >=22.9.0} npm-pick-manifest@11.0.3: @@ -7747,9 +7757,9 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} - path-scurry@2.0.1: - resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} - engines: {node: 20 || >=22} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} path-to-regexp@0.1.12: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} @@ -7768,9 +7778,6 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - pause-stream@0.0.11: - resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} - pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -7790,20 +7797,20 @@ packages: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} engines: {node: '>=4.0.0'} - pg-pool@3.11.0: - resolution: {integrity: sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==} + pg-pool@3.12.0: + resolution: {integrity: sha512-eIJ0DES8BLaziFHW7VgJEBPi5hg3Nyng5iKpYtj3wbcAUV9A1wLgWiY7ajf/f/oO1wfxt83phXPY8Emztg7ITg==} peerDependencies: pg: '>=8.0' - pg-protocol@1.11.0: - resolution: {integrity: sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==} + pg-protocol@1.12.0: + resolution: {integrity: sha512-uOANXNRACNdElMXJ0tPz6RBM0XQ61nONGAwlt8da5zs/iUOOCLBQOHSXnrC6fMsvtjxbOJrZZl5IScGv+7mpbg==} pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} - pg@8.18.0: - resolution: {integrity: sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ==} + pg@8.19.0: + resolution: {integrity: sha512-QIcLGi508BAHkQ3pJNptsFz5WQMlpGbuBGBaIaXsWK8mel2kQ/rThYI+DbgjUvZrIr7MiuEuc9LcChJoEZK1xQ==} engines: {node: '>= 16.0.0'} peerDependencies: pg-native: '>=3.0.1' @@ -7946,6 +7953,10 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.8: + resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + engines: {node: ^10 || ^12 || >=14} + postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} @@ -8047,19 +8058,14 @@ packages: prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} - ps-tree@1.2.0: - resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} - engines: {node: '>= 0.10'} - hasBin: true - psl@1.15.0: resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} pump@2.0.1: resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} - pump@3.0.3: - resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} pumpify@1.5.1: resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==} @@ -8075,8 +8081,8 @@ packages: resolution: {integrity: sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==} engines: {node: '>=8'} - puppeteer-core@24.37.3: - resolution: {integrity: sha512-fokQ8gv+hNgsRWqVuP5rUjGp+wzV5aMTP3fcm8ekNabmLGlJdFHas1OdMscAH9Gzq4Qcf7cfI/Pe6wEcAqQhqg==} + puppeteer-core@24.37.5: + resolution: {integrity: sha512-ybL7iE78YPN4T6J+sPLO7r0lSByp/0NN6PvfBEql219cOnttoTFzCWKiBOjstXSqi/OKpwae623DWAsL7cn2MQ==} engines: {node: '>=18'} pvtsutils@1.3.6: @@ -8371,8 +8377,8 @@ packages: '@types/node': optional: true - rollup@4.57.1: - resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==} + rollup@4.59.0: + resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -8453,11 +8459,6 @@ packages: webpack: optional: true - sass@1.97.2: - resolution: {integrity: sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==} - engines: {node: '>=14.0.0'} - hasBin: true - sass@1.97.3: resolution: {integrity: sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==} engines: {node: '>=14.0.0'} @@ -8466,8 +8467,8 @@ packages: saucelabs@1.5.0: resolution: {integrity: sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==} - sax@1.4.4: - resolution: {integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==} + sax@1.5.0: + resolution: {integrity: sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==} engines: {node: '>=11.0.0'} schema-utils@4.3.3: @@ -8639,6 +8640,10 @@ packages: resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} engines: {node: '>=18'} + slice-ansi@8.0.0: + resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} + engines: {node: '>=20'} + slugify@1.6.6: resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==} engines: {node: '>=8.0.0'} @@ -8672,8 +8677,9 @@ packages: resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - sort-any@2.0.0: - resolution: {integrity: sha512-T9JoiDewQEmWcnmPn/s9h/PH9t3d/LSWi0RgVmXSuDYeZXTZOZ1/wrK2PHaptuR1VXe3clLLt0pD6sgVOwjNEA==} + sort-any@4.0.7: + resolution: {integrity: sha512-UuZVEXClHW+bVa6ZBQ4biTWmLXMP7y6/jv5arfA0rKk7ZExy+5Zm19uekIqqDx6ZuvUMu7z5Ba9FfBi6FlGXPQ==} + engines: {node: '>=12'} source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} @@ -8719,8 +8725,11 @@ packages: spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.22: - resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + spdx-expression-parse@4.0.0: + resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} + + spdx-license-ids@3.0.23: + resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} spdx-license-list@2.1.0: resolution: {integrity: sha512-5PXVk9n4XDEzXOOxggv0SK6HmIaoGG28InH2qfFpURP/hUf/iwLXUxJMBg0flQLNlnHsgH6H1GPwNH55KOkqzA==} @@ -8747,14 +8756,11 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - split@0.3.3: - resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} - sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - sql-formatter@15.7.1: - resolution: {integrity: sha512-O8h51MnuQAnsInO7is6VoBGeB9wFvXhiTi4AqY5yGWUdF7fNcEDA6F67AAD4OvV4Seb95bPXaAPmnSii/mModg==} + sql-formatter@15.7.2: + resolution: {integrity: sha512-b0BGoM81KFRVSpZFwPpIPU5gng4YD8DI/taLD96NXCFRf5af3FzSE4aSwjKmxcyTmf/MfPu91j75883nRrWDBw==} hasBin: true sshpk@1.18.0: @@ -8796,9 +8802,6 @@ packages: stream-chain@2.2.5: resolution: {integrity: sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==} - stream-combiner@0.0.4: - resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} - stream-events@1.0.5: resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==} @@ -8830,8 +8833,8 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string-width@8.1.1: - resolution: {integrity: sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==} + string-width@8.2.0: + resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} engines: {node: '>=20'} string.prototype.padend@3.1.6: @@ -8867,8 +8870,8 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} strip-bom@3.0.0: @@ -8966,8 +8969,8 @@ packages: tar-fs@3.1.1: resolution: {integrity: sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==} - tar-stream@3.1.7: - resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} + tar-stream@3.1.8: + resolution: {integrity: sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ==} tar@7.5.9: resolution: {integrity: sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==} @@ -8980,6 +8983,9 @@ packages: resolution: {integrity: sha512-3ZnLvgWF29jikg1sAQ1g0o+lr5JX6sVgYvfUJazn7ZjJroDBUTWp44/+cFVX0bULjv4vci+rBD+oGVAkWqhUbw==} engines: {node: '>=18'} + teex@1.0.1: + resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} + terser-webpack-plugin@5.3.16: resolution: {integrity: sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==} engines: {node: '>= 10.13.0'} @@ -9032,9 +9038,6 @@ packages: through2@4.0.2: resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} @@ -9049,11 +9052,11 @@ packages: title-case@2.1.1: resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} - tldts-core@7.0.23: - resolution: {integrity: sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==} + tldts-core@7.0.24: + resolution: {integrity: sha512-pj7yygNMoMRqG7ML2SDQ0xNIOfN3IBDUcPVM2Sg6hP96oFNN2nqnzHreT3z9xLq85IWJyNTvD38O002DdOrPMw==} - tldts-icann@7.0.23: - resolution: {integrity: sha512-LMc6V1KOHFjKDU8wyDsIEJdV8o2bpc2OaYw2NxncJB2oZxJMPpiNVAbiu1HnqsUy81fkK1QWwFztVqY81hUFEg==} + tldts-icann@7.0.24: + resolution: {integrity: sha512-WgCMgvvJEUBU0ZByo0dz8mdLDJE0XoVdu6egZDPJYX2aaxHGX8dJEbF4Il5+M6qix8Br9O5OOeLfyyESU0MoEQ==} tmp@0.0.30: resolution: {integrity: sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==} @@ -9246,8 +9249,8 @@ packages: typed-graphqlify@3.1.6: resolution: {integrity: sha512-Snlg1ZrokbkQuemOb4xjWWCJrNcOMeb2Ii0/BwMfwLCcJVNjygyqhrFkrYNvi4gDrwWFrGE0TvxxM+Slym2JMg==} - typed-query-selector@2.12.0: - resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} + typed-query-selector@2.12.1: + resolution: {integrity: sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA==} typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} @@ -9858,8 +9861,8 @@ packages: zod@4.3.6: resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} - zone.js@0.16.0: - resolution: {integrity: sha512-LqLPpIQANebrlxY6jKcYKdgN5DTXyyHAKnnWWjE5pPfEQ4n7j5zn7mOEEpwNZVKGqx3kKKmvplEmoBrvpgROTA==} + zone.js@0.16.1: + resolution: {integrity: sha512-dpvY17vxYIW3+bNrP0ClUlaiY0CiIRK3tnoLaGoQsQcY9/I/NpzIWQ7tQNhbV7LacQMpCII6wVzuL3tuWOyfuA==} zx@8.8.5: resolution: {integrity: sha512-SNgDF5L0gfN7FwVOdEFguY3orU5AkfFZm9B5YSHog/UDHv+lvmd82ZAsOenOkQixigwH2+yyH198AwNdKhj+RA==} @@ -9980,13 +9983,13 @@ snapshots: transitivePeerDependencies: - chokidar - '@angular-devkit/build-angular@21.2.0-rc.0(85e9118f1bcacefdee125f6ee0de5595)': + '@angular-devkit/build-angular@21.2.0-rc.0(ac7d81f2a93fedccccd94ec8e5875310)': dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.2102.0-rc.0(chokidar@5.0.0) '@angular-devkit/build-webpack': 0.2102.0-rc.0(chokidar@5.0.0)(webpack-dev-server@5.2.3(bufferutil@4.1.0)(tslib@2.8.1)(webpack@5.105.2(esbuild@0.27.3)))(webpack@5.105.2(esbuild@0.27.3)) '@angular-devkit/core': 21.2.0-rc.0(chokidar@5.0.0) - '@angular/build': 21.2.0-rc.0(6764fc96610980e51d4a5fd693e116ee) + '@angular/build': 21.2.0-rc.0(8a80140bb057e2e24c1ae90a75117a65) '@angular/compiler-cli': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) '@babel/core': 7.29.0 '@babel/generator': 7.29.1 @@ -10039,11 +10042,11 @@ snapshots: webpack-merge: 6.0.1 webpack-subresource-integrity: 5.1.0(webpack@5.105.2(esbuild@0.27.3)) optionalDependencies: - '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) '@angular/localize': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0) - '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) - '@angular/platform-server': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) - '@angular/ssr': 21.2.0-rc.0(0cbd0fdcfddd4e429cff3ac260204f3f) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)) + '@angular/platform-server': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7) + '@angular/ssr': 21.2.0-rc.0(4f6c63f876d0dabb1b5ac88e842da9cd) esbuild: 0.27.3 karma: 6.4.4(bufferutil@4.1.0) protractor: 7.0.0 @@ -10100,7 +10103,7 @@ snapshots: transitivePeerDependencies: - chokidar - '@angular/build@21.2.0-rc.0(6764fc96610980e51d4a5fd693e116ee)': + '@angular/build@21.2.0-rc.0(8a80140bb057e2e24c1ae90a75117a65)': dependencies: '@ampproject/remapping': 2.3.0 '@angular-devkit/architect': 0.2102.0-rc.0(chokidar@5.0.0) @@ -10109,8 +10112,8 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-split-export-declaration': 7.24.7 - '@inquirer/confirm': 5.1.21(@types/node@22.19.11) - '@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.1(@types/node@22.19.11)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + '@inquirer/confirm': 5.1.21(@types/node@22.19.13) + '@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.1(@types/node@22.19.13)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) beasties: 0.4.1 browserslist: 4.28.1 esbuild: 0.27.3 @@ -10131,14 +10134,14 @@ snapshots: tslib: 2.8.1 typescript: 5.9.2 undici: 7.22.0 - vite: 7.3.1(@types/node@22.19.11)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@22.19.13)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) watchpack: 2.5.1 optionalDependencies: - '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) '@angular/localize': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0) - '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) - '@angular/platform-server': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) - '@angular/ssr': 21.2.0-rc.0(0cbd0fdcfddd4e429cff3ac260204f3f) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)) + '@angular/platform-server': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7) + '@angular/ssr': 21.2.0-rc.0(4f6c63f876d0dabb1b5ac88e842da9cd) karma: 6.4.4(bufferutil@4.1.0) less: 4.4.2 lmdb: 3.5.1 @@ -10156,13 +10159,13 @@ snapshots: - tsx - yaml - '@angular/cli@21.2.0-rc.0(@types/node@22.19.11)(chokidar@5.0.0)': + '@angular/cli@21.2.0-rc.0(@types/node@22.19.13)(chokidar@5.0.0)': dependencies: '@angular-devkit/architect': 0.2102.0-rc.0(chokidar@5.0.0) '@angular-devkit/core': 21.2.0-rc.0(chokidar@5.0.0) '@angular-devkit/schematics': 21.2.0-rc.0(chokidar@5.0.0) - '@inquirer/prompts': 7.10.1(@types/node@22.19.11) - '@listr2/prompt-adapter-inquirer': 3.0.5(@inquirer/prompts@7.10.1(@types/node@22.19.11))(@types/node@22.19.11)(listr2@9.0.5) + '@inquirer/prompts': 7.10.1(@types/node@22.19.13) + '@listr2/prompt-adapter-inquirer': 3.0.5(@inquirer/prompts@7.10.1(@types/node@22.19.13))(@types/node@22.19.13)(listr2@9.0.5) '@modelcontextprotocol/sdk': 1.26.0 '@schematics/angular': 21.2.0-rc.0(chokidar@5.0.0) '@yarnpkg/lockfile': 1.1.0 @@ -10182,9 +10185,9 @@ snapshots: - chokidar - supports-color - '@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7)': + '@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7)': dependencies: - '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) rxjs: 6.6.7 tslib: 2.8.1 @@ -10212,19 +10215,19 @@ snapshots: dependencies: tslib: 2.8.1 - '@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)': + '@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)': dependencies: rxjs: 6.6.7 tslib: 2.8.1 optionalDependencies: '@angular/compiler': 21.2.0-rc.0 - zone.js: 0.16.0 + zone.js: 0.16.1 - '@angular/forms@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7)': + '@angular/forms@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7)': dependencies: - '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)) '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) '@standard-schema/spec': 1.1.0 rxjs: 6.6.7 @@ -10245,11 +10248,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b0ab31189ecbeaaafce2bd9259385879b9beabcc(@modelcontextprotocol/sdk@1.26.0)': + '@angular/ng-dev@https://codeload.github.com/angular/dev-infra-private-ng-dev-builds/tar.gz/b0ab31189ecbeaaafce2bd9259385879b9beabcc(@modelcontextprotocol/sdk@1.27.1)': dependencies: '@actions/core': 3.0.0 '@google-cloud/spanner': 8.0.0(supports-color@10.2.2) - '@google/genai': 1.38.0(@modelcontextprotocol/sdk@1.26.0)(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) + '@google/genai': 1.38.0(@modelcontextprotocol/sdk@1.27.1)(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6) '@inquirer/prompts': 8.2.0(@types/node@24.10.9) '@inquirer/type': 4.0.3(@types/node@24.10.9) '@octokit/auth-app': 8.1.2 @@ -10306,30 +10309,30 @@ snapshots: - '@modelcontextprotocol/sdk' - '@react-native-async-storage/async-storage' - '@angular/platform-browser-dynamic@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))': + '@angular/platform-browser-dynamic@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))': dependencies: - '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7) '@angular/compiler': 21.2.0-rc.0 - '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)) tslib: 2.8.1 - '@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))': + '@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))': dependencies: - '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) tslib: 2.8.1 transitivePeerDependencies: - '@angular/compiler-cli' - supports-color - '@angular/platform-server@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7)': + '@angular/platform-server@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7)': dependencies: - '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7) '@angular/compiler': 21.2.0-rc.0 - '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)) '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) rxjs: 6.6.7 tslib: 2.8.1 @@ -10338,11 +10341,11 @@ snapshots: - '@angular/compiler-cli' - supports-color - '@angular/router@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7)': + '@angular/router@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7)': dependencies: - '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) + '@angular/platform-browser': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)) '@nginfra/angular-linking': 1.0.9(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2)) rxjs: 6.6.7 tslib: 2.8.1 @@ -10350,14 +10353,14 @@ snapshots: - '@angular/compiler-cli' - supports-color - '@angular/ssr@21.2.0-rc.0(0cbd0fdcfddd4e429cff3ac260204f3f)': + '@angular/ssr@21.2.0-rc.0(4f6c63f876d0dabb1b5ac88e842da9cd)': dependencies: - '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7) - '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0) - '@angular/router': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + '@angular/common': 21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7) + '@angular/core': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1) + '@angular/router': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7) tslib: 2.8.1 optionalDependencies: - '@angular/platform-server': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.0)))(rxjs@6.6.7) + '@angular/platform-server': 21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/compiler@21.2.0-rc.0)(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(@angular/platform-browser@21.2.0-rc.0(@angular/common@21.2.0-rc.0(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1))(rxjs@6.6.7))(@angular/compiler-cli@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2))(@angular/core@21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(rxjs@6.6.7)(zone.js@0.16.1)))(rxjs@6.6.7) '@apidevtools/json-schema-ref-parser@9.1.2': dependencies: @@ -10366,14 +10369,14 @@ snapshots: call-me-maybe: 1.0.2 js-yaml: 4.1.1 - '@apphosting/build@0.1.7(@types/node@22.19.11)(typescript@5.9.2)': + '@apphosting/build@0.1.7(@types/node@22.19.13)(typescript@5.9.2)': dependencies: '@apphosting/common': 0.0.9 '@npmcli/promise-spawn': 3.0.0 colorette: 2.0.20 commander: 11.1.0 npm-pick-manifest: 9.1.0 - ts-node: 10.9.2(@types/node@22.19.11)(typescript@5.9.2) + ts-node: 10.9.2(@types/node@22.19.13)(typescript@5.9.2) transitivePeerDependencies: - '@swc/core' - '@swc/wasm' @@ -11083,8 +11086,6 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@bazel/bazelisk@1.26.0': {} - '@bazel/bazelisk@1.28.1': {} '@bazel/buildifier@8.2.1': {} @@ -11567,11 +11568,15 @@ snapshots: dependencies: tslib: 2.8.1 - '@google-cloud/cloud-sql-connector@1.9.0': + '@gar/promise-retry@1.0.2': + dependencies: + retry: 0.13.1 + + '@google-cloud/cloud-sql-connector@1.9.1': dependencies: '@googleapis/sqladmin': 35.2.0 - gaxios: 7.1.3(supports-color@10.2.2) - google-auth-library: 10.5.0(supports-color@10.2.2) + gaxios: 7.1.4 + google-auth-library: 10.6.1(supports-color@10.2.2) p-throttle: 7.0.0 transitivePeerDependencies: - supports-color @@ -11583,7 +11588,7 @@ snapshots: arrify: 2.0.1 duplexify: 4.1.3 extend: 3.0.2 - google-auth-library: 10.5.0(supports-color@10.2.2) + google-auth-library: 10.6.1(supports-color@10.2.2) html-entities: 2.6.0 retry-request: 8.0.2(supports-color@10.2.2) teeny-request: 10.1.0(supports-color@10.2.2) @@ -11604,7 +11609,7 @@ snapshots: '@google-cloud/promisify@5.0.0': {} - '@google-cloud/pubsub@5.2.3': + '@google-cloud/pubsub@5.3.0': dependencies: '@google-cloud/paginator': 6.0.0 '@google-cloud/precise-date': 5.0.0 @@ -11612,10 +11617,10 @@ snapshots: '@google-cloud/promisify': 5.0.0 '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.34.0 + '@opentelemetry/semantic-conventions': 1.39.0 arrify: 2.0.1 extend: 3.0.2 - google-auth-library: 10.5.0(supports-color@10.2.2) + google-auth-library: 10.6.1(supports-color@10.2.2) google-gax: 5.0.6(supports-color@10.2.2) heap-js: 2.7.1 is-stream-ended: 0.1.4 @@ -11634,7 +11639,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 2.5.1(@opentelemetry/api@1.9.0) '@opentelemetry/core': 2.5.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/big.js': 6.2.2 '@types/stack-trace': 0.0.33 big.js: 7.0.1 @@ -11642,7 +11647,7 @@ snapshots: duplexify: 4.1.3 events-intercept: 2.0.0 extend: 3.0.2 - google-auth-library: 10.5.0(supports-color@10.2.2) + google-auth-library: 10.6.1(supports-color@10.2.2) google-gax: 5.0.6(supports-color@10.2.2) grpc-gcp: 1.0.1 is: 3.3.2 @@ -11659,13 +11664,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@google/genai@1.38.0(@modelcontextprotocol/sdk@1.26.0)(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)': + '@google/genai@1.38.0(@modelcontextprotocol/sdk@1.27.1)(bufferutil@4.1.0)(supports-color@10.2.2)(utf-8-validate@6.0.6)': dependencies: - google-auth-library: 10.5.0(supports-color@10.2.2) + google-auth-library: 10.6.1(supports-color@10.2.2) protobufjs: 7.5.4 ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) optionalDependencies: - '@modelcontextprotocol/sdk': 1.26.0 + '@modelcontextprotocol/sdk': 1.27.1 transitivePeerDependencies: - bufferutil - supports-color @@ -11685,7 +11690,7 @@ snapshots: '@grpc/grpc-js@1.9.15': dependencies: '@grpc/proto-loader': 0.7.15 - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@grpc/proto-loader@0.7.15': dependencies: @@ -11704,61 +11709,61 @@ snapshots: '@harperfast/extended-iterable@1.0.3': optional: true - '@hono/node-server@1.19.9(hono@4.11.9)': + '@hono/node-server@1.19.9(hono@4.12.3)': dependencies: - hono: 4.11.9 + hono: 4.12.3 '@inquirer/ansi@1.0.2': {} '@inquirer/ansi@2.0.3': {} - '@inquirer/checkbox@4.3.2(@types/node@22.19.11)': + '@inquirer/checkbox@4.3.2(@types/node@22.19.13)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/type': 3.0.10(@types/node@22.19.13) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/checkbox@5.0.6(@types/node@24.10.9)': + '@inquirer/checkbox@5.1.0(@types/node@24.10.9)': dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/figures': 2.0.3 '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/confirm@5.1.21(@types/node@22.19.11)': + '@inquirer/confirm@5.1.21(@types/node@22.19.13)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.11) - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) + '@inquirer/type': 3.0.10(@types/node@22.19.13) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/confirm@6.0.6(@types/node@24.10.9)': + '@inquirer/confirm@6.0.8(@types/node@24.10.9)': dependencies: - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/core@10.3.2(@types/node@22.19.11)': + '@inquirer/core@10.3.2(@types/node@22.19.13)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/type': 3.0.10(@types/node@22.19.13) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/core@11.1.3(@types/node@24.10.9)': + '@inquirer/core@11.1.5(@types/node@24.10.9)': dependencies: '@inquirer/ansi': 2.0.3 '@inquirer/figures': 2.0.3 @@ -11770,43 +11775,43 @@ snapshots: optionalDependencies: '@types/node': 24.10.9 - '@inquirer/editor@4.2.23(@types/node@22.19.11)': + '@inquirer/editor@4.2.23(@types/node@22.19.13)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.11) - '@inquirer/external-editor': 1.0.3(@types/node@22.19.11) - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) + '@inquirer/external-editor': 1.0.3(@types/node@22.19.13) + '@inquirer/type': 3.0.10(@types/node@22.19.13) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/editor@5.0.6(@types/node@24.10.9)': + '@inquirer/editor@5.0.8(@types/node@24.10.9)': dependencies: - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/external-editor': 2.0.3(@types/node@24.10.9) '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/expand@4.0.23(@types/node@22.19.11)': + '@inquirer/expand@4.0.23(@types/node@22.19.13)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.11) - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) + '@inquirer/type': 3.0.10(@types/node@22.19.13) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/expand@5.0.6(@types/node@24.10.9)': + '@inquirer/expand@5.0.8(@types/node@24.10.9)': dependencies: - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/external-editor@1.0.3(@types/node@22.19.11)': + '@inquirer/external-editor@1.0.3(@types/node@22.19.13)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@inquirer/external-editor@2.0.3(@types/node@24.10.9)': dependencies: @@ -11819,134 +11824,134 @@ snapshots: '@inquirer/figures@2.0.3': {} - '@inquirer/input@4.3.1(@types/node@22.19.11)': + '@inquirer/input@4.3.1(@types/node@22.19.13)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.11) - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) + '@inquirer/type': 3.0.10(@types/node@22.19.13) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/input@5.0.6(@types/node@24.10.9)': + '@inquirer/input@5.0.8(@types/node@24.10.9)': dependencies: - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/number@3.0.23(@types/node@22.19.11)': + '@inquirer/number@3.0.23(@types/node@22.19.13)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.11) - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) + '@inquirer/type': 3.0.10(@types/node@22.19.13) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/number@4.0.6(@types/node@24.10.9)': + '@inquirer/number@4.0.8(@types/node@24.10.9)': dependencies: - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/password@4.0.23(@types/node@22.19.11)': + '@inquirer/password@4.0.23(@types/node@22.19.13)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.11) - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) + '@inquirer/type': 3.0.10(@types/node@22.19.13) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/password@5.0.6(@types/node@24.10.9)': + '@inquirer/password@5.0.8(@types/node@24.10.9)': dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/prompts@7.10.1(@types/node@22.19.11)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@22.19.11) - '@inquirer/confirm': 5.1.21(@types/node@22.19.11) - '@inquirer/editor': 4.2.23(@types/node@22.19.11) - '@inquirer/expand': 4.0.23(@types/node@22.19.11) - '@inquirer/input': 4.3.1(@types/node@22.19.11) - '@inquirer/number': 3.0.23(@types/node@22.19.11) - '@inquirer/password': 4.0.23(@types/node@22.19.11) - '@inquirer/rawlist': 4.1.11(@types/node@22.19.11) - '@inquirer/search': 3.2.2(@types/node@22.19.11) - '@inquirer/select': 4.4.2(@types/node@22.19.11) + '@inquirer/prompts@7.10.1(@types/node@22.19.13)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@22.19.13) + '@inquirer/confirm': 5.1.21(@types/node@22.19.13) + '@inquirer/editor': 4.2.23(@types/node@22.19.13) + '@inquirer/expand': 4.0.23(@types/node@22.19.13) + '@inquirer/input': 4.3.1(@types/node@22.19.13) + '@inquirer/number': 3.0.23(@types/node@22.19.13) + '@inquirer/password': 4.0.23(@types/node@22.19.13) + '@inquirer/rawlist': 4.1.11(@types/node@22.19.13) + '@inquirer/search': 3.2.2(@types/node@22.19.13) + '@inquirer/select': 4.4.2(@types/node@22.19.13) optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@inquirer/prompts@8.2.0(@types/node@24.10.9)': dependencies: - '@inquirer/checkbox': 5.0.6(@types/node@24.10.9) - '@inquirer/confirm': 6.0.6(@types/node@24.10.9) - '@inquirer/editor': 5.0.6(@types/node@24.10.9) - '@inquirer/expand': 5.0.6(@types/node@24.10.9) - '@inquirer/input': 5.0.6(@types/node@24.10.9) - '@inquirer/number': 4.0.6(@types/node@24.10.9) - '@inquirer/password': 5.0.6(@types/node@24.10.9) - '@inquirer/rawlist': 5.2.2(@types/node@24.10.9) - '@inquirer/search': 4.1.2(@types/node@24.10.9) - '@inquirer/select': 5.0.6(@types/node@24.10.9) + '@inquirer/checkbox': 5.1.0(@types/node@24.10.9) + '@inquirer/confirm': 6.0.8(@types/node@24.10.9) + '@inquirer/editor': 5.0.8(@types/node@24.10.9) + '@inquirer/expand': 5.0.8(@types/node@24.10.9) + '@inquirer/input': 5.0.8(@types/node@24.10.9) + '@inquirer/number': 4.0.8(@types/node@24.10.9) + '@inquirer/password': 5.0.8(@types/node@24.10.9) + '@inquirer/rawlist': 5.2.4(@types/node@24.10.9) + '@inquirer/search': 4.1.4(@types/node@24.10.9) + '@inquirer/select': 5.1.0(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/rawlist@4.1.11(@types/node@22.19.11)': + '@inquirer/rawlist@4.1.11(@types/node@22.19.13)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.11) - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) + '@inquirer/type': 3.0.10(@types/node@22.19.13) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/rawlist@5.2.2(@types/node@24.10.9)': + '@inquirer/rawlist@5.2.4(@types/node@24.10.9)': dependencies: - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/search@3.2.2(@types/node@22.19.11)': + '@inquirer/search@3.2.2(@types/node@22.19.13)': dependencies: - '@inquirer/core': 10.3.2(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/type': 3.0.10(@types/node@22.19.13) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/search@4.1.2(@types/node@24.10.9)': + '@inquirer/search@4.1.4(@types/node@24.10.9)': dependencies: - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/figures': 2.0.3 '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/select@4.4.2(@types/node@22.19.11)': + '@inquirer/select@4.4.2(@types/node@22.19.13)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@22.19.11) + '@inquirer/core': 10.3.2(@types/node@22.19.13) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/type': 3.0.10(@types/node@22.19.13) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@inquirer/select@5.0.6(@types/node@24.10.9)': + '@inquirer/select@5.1.0(@types/node@24.10.9)': dependencies: '@inquirer/ansi': 2.0.3 - '@inquirer/core': 11.1.3(@types/node@24.10.9) + '@inquirer/core': 11.1.5(@types/node@24.10.9) '@inquirer/figures': 2.0.3 '@inquirer/type': 4.0.3(@types/node@24.10.9) optionalDependencies: '@types/node': 24.10.9 - '@inquirer/type@3.0.10(@types/node@22.19.11)': + '@inquirer/type@3.0.10(@types/node@22.19.13)': optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@inquirer/type@4.0.3(@types/node@24.10.9)': optionalDependencies: @@ -11962,7 +11967,7 @@ snapshots: dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 @@ -11971,7 +11976,7 @@ snapshots: '@isaacs/fs-minipass@4.0.1': dependencies: - minipass: 7.1.2 + minipass: 7.1.3 '@istanbuljs/schema@0.1.3': {} @@ -12139,10 +12144,10 @@ snapshots: '@leichtgewicht/ip-codec@2.0.5': {} - '@listr2/prompt-adapter-inquirer@3.0.5(@inquirer/prompts@7.10.1(@types/node@22.19.11))(@types/node@22.19.11)(listr2@9.0.5)': + '@listr2/prompt-adapter-inquirer@3.0.5(@inquirer/prompts@7.10.1(@types/node@22.19.13))(@types/node@22.19.13)(listr2@9.0.5)': dependencies: - '@inquirer/prompts': 7.10.1(@types/node@22.19.11) - '@inquirer/type': 3.0.10(@types/node@22.19.11) + '@inquirer/prompts': 7.10.1(@types/node@22.19.13) + '@inquirer/type': 3.0.10(@types/node@22.19.13) listr2: 9.0.5 transitivePeerDependencies: - '@types/node' @@ -12172,7 +12177,7 @@ snapshots: '@modelcontextprotocol/sdk@1.26.0': dependencies: - '@hono/node-server': 1.19.9(hono@4.11.9) + '@hono/node-server': 1.19.9(hono@4.12.3) ajv: 8.18.0 ajv-formats: 3.0.1 content-type: 1.0.5 @@ -12182,7 +12187,7 @@ snapshots: eventsource-parser: 3.0.6 express: 5.2.1 express-rate-limit: 8.2.1(express@5.2.1) - hono: 4.11.9 + hono: 4.12.3 jose: 6.1.3 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 @@ -12192,6 +12197,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@modelcontextprotocol/sdk@1.27.1': + dependencies: + '@hono/node-server': 1.19.9(hono@4.12.3) + ajv: 8.18.0 + ajv-formats: 3.0.1 + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.0.6 + express: 5.2.1 + express-rate-limit: 8.2.1(express@5.2.1) + hono: 4.12.3 + jose: 6.1.3 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + transitivePeerDependencies: + - supports-color + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': optional: true @@ -12303,7 +12330,7 @@ snapshots: '@angular/compiler-cli': 21.2.0-rc.0(@angular/compiler@21.2.0-rc.0)(typescript@5.9.2) '@babel/core': 7.26.10 '@types/babel__core': 7.20.5 - '@types/node': 22.19.11 + '@types/node': 22.19.13 tinyglobby: 0.2.12 typescript: 5.9.2 transitivePeerDependencies: @@ -12343,14 +12370,14 @@ snapshots: dependencies: semver: 7.7.4 - '@npmcli/git@7.0.1': + '@npmcli/git@7.0.2': dependencies: + '@gar/promise-retry': 1.0.2 '@npmcli/promise-spawn': 9.0.1 ini: 6.0.0 lru-cache: 11.2.6 npm-pick-manifest: 11.0.3 proc-log: 6.1.0 - promise-retry: 2.0.1 semver: 7.7.4 which: 6.0.1 @@ -12361,15 +12388,15 @@ snapshots: '@npmcli/node-gyp@5.0.0': {} - '@npmcli/package-json@7.0.4': + '@npmcli/package-json@7.0.5': dependencies: - '@npmcli/git': 7.0.1 - glob: 13.0.3 + '@npmcli/git': 7.0.2 + glob: 13.0.6 hosted-git-info: 9.0.2 json-parse-even-better-errors: 5.0.0 proc-log: 6.1.0 semver: 7.7.4 - validate-npm-package-license: 3.0.4 + spdx-expression-parse: 4.0.0 '@npmcli/promise-spawn@3.0.0': dependencies: @@ -12381,14 +12408,13 @@ snapshots: '@npmcli/redact@4.0.0': {} - '@npmcli/run-script@10.0.3': + '@npmcli/run-script@10.0.4': dependencies: '@npmcli/node-gyp': 5.0.0 - '@npmcli/package-json': 7.0.4 + '@npmcli/package-json': 7.0.5 '@npmcli/promise-spawn': 9.0.1 node-gyp: 12.2.0 proc-log: 6.1.0 - which: 6.0.1 transitivePeerDependencies: - supports-color @@ -12396,7 +12422,7 @@ snapshots: dependencies: '@octokit/auth-oauth-app': 9.0.3 '@octokit/auth-oauth-user': 6.0.2 - '@octokit/request': 10.0.7 + '@octokit/request': 10.0.8 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 toad-cache: 3.7.0 @@ -12407,14 +12433,14 @@ snapshots: dependencies: '@octokit/auth-oauth-device': 8.0.3 '@octokit/auth-oauth-user': 6.0.2 - '@octokit/request': 10.0.7 + '@octokit/request': 10.0.8 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 '@octokit/auth-oauth-device@8.0.3': dependencies: '@octokit/oauth-methods': 6.0.2 - '@octokit/request': 10.0.7 + '@octokit/request': 10.0.8 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 @@ -12422,7 +12448,7 @@ snapshots: dependencies: '@octokit/auth-oauth-device': 8.0.3 '@octokit/oauth-methods': 6.0.2 - '@octokit/request': 10.0.7 + '@octokit/request': 10.0.8 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 @@ -12432,25 +12458,25 @@ snapshots: dependencies: '@octokit/auth-token': 6.0.0 '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.7 + '@octokit/request': 10.0.8 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 before-after-hook: 4.0.0 universal-user-agent: 7.0.3 - '@octokit/endpoint@11.0.2': + '@octokit/endpoint@11.0.3': dependencies: '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 '@octokit/graphql-schema@15.26.1': dependencies: - graphql: 16.12.0 - graphql-tag: 2.12.6(graphql@16.12.0) + graphql: 16.13.0 + graphql-tag: 2.12.6(graphql@16.13.0) '@octokit/graphql@9.0.3': dependencies: - '@octokit/request': 10.0.7 + '@octokit/request': 10.0.8 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 @@ -12459,7 +12485,7 @@ snapshots: '@octokit/oauth-methods@6.0.2': dependencies: '@octokit/oauth-authorization-url': 8.0.0 - '@octokit/request': 10.0.7 + '@octokit/request': 10.0.8 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 @@ -12483,12 +12509,13 @@ snapshots: dependencies: '@octokit/types': 16.0.0 - '@octokit/request@10.0.7': + '@octokit/request@10.0.8': dependencies: - '@octokit/endpoint': 11.0.2 + '@octokit/endpoint': 11.0.3 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 fast-content-type-parse: 3.0.0 + json-with-bigint: 3.5.7 universal-user-agent: 7.0.3 '@octokit/rest@22.0.1': @@ -12533,14 +12560,14 @@ snapshots: '@opentelemetry/core@2.5.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/instrumentation-amqplib@0.46.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12549,7 +12576,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/connect': 3.4.38 transitivePeerDependencies: - supports-color @@ -12566,7 +12593,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12597,7 +12624,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12617,7 +12644,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/redis-common': 0.36.2 - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12625,7 +12652,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12633,7 +12660,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12642,7 +12669,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12657,7 +12684,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12666,7 +12693,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12674,7 +12701,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color @@ -12683,7 +12710,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/mysql': 2.15.26 transitivePeerDependencies: - supports-color @@ -12693,7 +12720,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0) '@types/pg': 8.6.1 '@types/pg-pool': 2.0.6 @@ -12705,7 +12732,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/redis-common': 0.36.2 - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -12713,7 +12740,7 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@types/tedious': 4.0.14 transitivePeerDependencies: - supports-color @@ -12755,10 +12782,10 @@ snapshots: '@opentelemetry/semantic-conventions@1.28.0': {} - '@opentelemetry/semantic-conventions@1.34.0': {} - '@opentelemetry/semantic-conventions@1.39.0': {} + '@opentelemetry/semantic-conventions@1.40.0': {} + '@opentelemetry/sql-common@0.40.1(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -12992,7 +13019,7 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@puppeteer/browsers@2.12.1': + '@puppeteer/browsers@2.13.0': dependencies: debug: 4.4.3(supports-color@10.2.2) extract-zip: 2.0.1 @@ -13050,9 +13077,9 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.4': {} - '@rollup/plugin-commonjs@29.0.0(rollup@4.57.1)': + '@rollup/plugin-commonjs@29.0.0(rollup@4.59.0)': dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + '@rollup/pluginutils': 5.3.0(rollup@4.59.0) commondir: 1.0.1 estree-walker: 2.0.2 fdir: 6.5.0(picomatch@4.0.3) @@ -13060,107 +13087,107 @@ snapshots: magic-string: 0.30.21 picomatch: 4.0.3 optionalDependencies: - rollup: 4.57.1 + rollup: 4.59.0 - '@rollup/plugin-node-resolve@16.0.3(rollup@4.57.1)': + '@rollup/plugin-node-resolve@16.0.3(rollup@4.59.0)': dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + '@rollup/pluginutils': 5.3.0(rollup@4.59.0) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 resolve: 1.22.11 optionalDependencies: - rollup: 4.57.1 + rollup: 4.59.0 - '@rollup/pluginutils@5.2.0(rollup@4.57.1)': + '@rollup/pluginutils@5.2.0(rollup@4.59.0)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.57.1 + rollup: 4.59.0 - '@rollup/pluginutils@5.3.0(rollup@4.57.1)': + '@rollup/pluginutils@5.3.0(rollup@4.59.0)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.57.1 + rollup: 4.59.0 - '@rollup/rollup-android-arm-eabi@4.57.1': + '@rollup/rollup-android-arm-eabi@4.59.0': optional: true - '@rollup/rollup-android-arm64@4.57.1': + '@rollup/rollup-android-arm64@4.59.0': optional: true - '@rollup/rollup-darwin-arm64@4.57.1': + '@rollup/rollup-darwin-arm64@4.59.0': optional: true - '@rollup/rollup-darwin-x64@4.57.1': + '@rollup/rollup-darwin-x64@4.59.0': optional: true - '@rollup/rollup-freebsd-arm64@4.57.1': + '@rollup/rollup-freebsd-arm64@4.59.0': optional: true - '@rollup/rollup-freebsd-x64@4.57.1': + '@rollup/rollup-freebsd-x64@4.59.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.57.1': + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.57.1': + '@rollup/rollup-linux-arm-musleabihf@4.59.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.57.1': + '@rollup/rollup-linux-arm64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.57.1': + '@rollup/rollup-linux-arm64-musl@4.59.0': optional: true - '@rollup/rollup-linux-loong64-gnu@4.57.1': + '@rollup/rollup-linux-loong64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-loong64-musl@4.57.1': + '@rollup/rollup-linux-loong64-musl@4.59.0': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.57.1': + '@rollup/rollup-linux-ppc64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-ppc64-musl@4.57.1': + '@rollup/rollup-linux-ppc64-musl@4.59.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.57.1': + '@rollup/rollup-linux-riscv64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.57.1': + '@rollup/rollup-linux-riscv64-musl@4.59.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.57.1': + '@rollup/rollup-linux-s390x-gnu@4.59.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.57.1': + '@rollup/rollup-linux-x64-gnu@4.59.0': optional: true - '@rollup/rollup-linux-x64-musl@4.57.1': + '@rollup/rollup-linux-x64-musl@4.59.0': optional: true - '@rollup/rollup-openbsd-x64@4.57.1': + '@rollup/rollup-openbsd-x64@4.59.0': optional: true - '@rollup/rollup-openharmony-arm64@4.57.1': + '@rollup/rollup-openharmony-arm64@4.59.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.57.1': + '@rollup/rollup-win32-arm64-msvc@4.59.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.57.1': + '@rollup/rollup-win32-ia32-msvc@4.59.0': optional: true - '@rollup/rollup-win32-x64-gnu@4.57.1': + '@rollup/rollup-win32-x64-gnu@4.59.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.57.1': + '@rollup/rollup-win32-x64-msvc@4.59.0': optional: true '@schematics/angular@21.2.0-rc.0(chokidar@5.0.0)': @@ -13173,7 +13200,7 @@ snapshots: '@sentry/core@9.47.1': {} - '@sentry/node-core@9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.39.0)': + '@sentry/node-core@9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 1.30.1(@opentelemetry/api@1.9.0) @@ -13181,9 +13208,9 @@ snapshots: '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@sentry/core': 9.47.1 - '@sentry/opentelemetry': 9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.39.0) + '@sentry/opentelemetry': 9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) import-in-the-middle: 1.15.0 '@sentry/node@9.47.1': @@ -13216,23 +13243,23 @@ snapshots: '@opentelemetry/instrumentation-undici': 0.10.1(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@prisma/instrumentation': 6.11.1(@opentelemetry/api@1.9.0) '@sentry/core': 9.47.1 - '@sentry/node-core': 9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.39.0) - '@sentry/opentelemetry': 9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.39.0) + '@sentry/node-core': 9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/opentelemetry': 9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0) import-in-the-middle: 1.15.0 - minimatch: 9.0.5 + minimatch: 9.0.9 transitivePeerDependencies: - supports-color - '@sentry/opentelemetry@9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.39.0)': + '@sentry/opentelemetry@9.47.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) - '@opentelemetry/semantic-conventions': 1.39.0 + '@opentelemetry/semantic-conventions': 1.40.0 '@sentry/core': 9.47.1 '@sigstore/bundle@4.0.0': @@ -13248,7 +13275,7 @@ snapshots: '@sigstore/bundle': 4.0.0 '@sigstore/core': 3.1.0 '@sigstore/protobuf-specs': 0.5.0 - make-fetch-happen: 15.0.3 + make-fetch-happen: 15.0.4 proc-log: 6.1.0 promise-retry: 2.0.1 transitivePeerDependencies: @@ -13297,7 +13324,7 @@ snapshots: '@tufjs/models@4.1.0': dependencies: '@tufjs/canonical-json': 2.0.0 - minimatch: 10.2.0 + minimatch: 10.2.4 '@tybys/wasm-util@0.10.1': dependencies: @@ -13330,32 +13357,32 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/bonjour@3.5.13': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/cli-progress@3.11.6': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.19.8 - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/connect@3.4.38': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/cors@2.8.19': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/duplexify@3.6.5': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/ejs@3.1.5': {} @@ -13375,7 +13402,7 @@ snapshots: '@types/express-serve-static-core@4.19.8': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -13392,11 +13419,11 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/git-raw-commits@5.0.1': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/google.maps@3.58.1': {} @@ -13404,7 +13431,7 @@ snapshots: '@types/http-proxy@1.17.17': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/jasmine@6.0.0': {} @@ -13412,7 +13439,7 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/luxon@3.7.1': {} @@ -13422,9 +13449,9 @@ snapshots: '@types/mysql@2.15.26': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - '@types/node@22.19.11': + '@types/node@22.19.13': dependencies: undici-types: 6.21.0 @@ -13442,14 +13469,14 @@ snapshots: '@types/pg@8.6.1': dependencies: - '@types/node': 22.19.11 - pg-protocol: 1.11.0 + '@types/node': 22.19.13 + pg-protocol: 1.12.0 pg-types: 2.2.0 '@types/pumpify@1.4.5': dependencies: '@types/duplexify': 3.6.5 - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/q@0.0.32': {} @@ -13468,11 +13495,11 @@ snapshots: '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/send@1.2.1': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/serve-index@1.9.4': dependencies: @@ -13481,25 +13508,25 @@ snapshots: '@types/serve-static@1.15.10': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/send': 0.17.6 '@types/shelljs@0.10.0': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 fast-glob: 3.3.3 '@types/shimmer@1.2.0': {} '@types/sockjs@0.3.36': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/stack-trace@0.0.33': {} '@types/tedious@4.0.14': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/triple-beam@1.3.5': {} @@ -13513,7 +13540,7 @@ snapshots: '@types/vfile@3.0.2': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/unist': 2.0.11 '@types/vfile-message': 2.0.0 @@ -13521,7 +13548,7 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 '@types/yargs-parser@21.0.3': {} @@ -13533,14 +13560,14 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 optional: true '@types/youtube@0.1.2': {} - '@vitejs/plugin-basic-ssl@2.1.4(vite@7.3.1(@types/node@22.19.11)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': + '@vitejs/plugin-basic-ssl@2.1.4(vite@7.3.1(@types/node@22.19.13)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - vite: 7.3.1(@types/node@22.19.11)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@22.19.13)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) '@webassemblyjs/ast@1.14.1': dependencies: @@ -13646,25 +13673,25 @@ snapshots: mime-types: 3.0.2 negotiator: 1.0.0 - acorn-import-attributes@1.9.5(acorn@8.15.0): + acorn-import-attributes@1.9.5(acorn@8.16.0): dependencies: - acorn: 8.15.0 + acorn: 8.16.0 - acorn-import-phases@1.0.4(acorn@8.15.0): + acorn-import-phases@1.0.4(acorn@8.16.0): dependencies: - acorn: 8.15.0 + acorn: 8.16.0 acorn-jsx@5.3.2(acorn@7.4.1): dependencies: acorn: 7.4.1 - acorn-walk@8.3.4: + acorn-walk@8.3.5: dependencies: - acorn: 8.15.0 + acorn: 8.16.0 acorn@7.4.1: {} - acorn@8.15.0: {} + acorn@8.16.0: {} adjust-sourcemap-loader@4.0.0: dependencies: @@ -13698,7 +13725,7 @@ snapshots: ajv: 8.18.0 fast-deep-equal: 3.1.3 - ajv@6.12.6: + ajv@6.14.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 @@ -13786,10 +13813,11 @@ snapshots: buffer-crc32: 1.0.0 readable-stream: 4.7.0 readdir-glob: 1.1.3 - tar-stream: 3.1.7 + tar-stream: 3.1.8 zip-stream: 6.0.1 transitivePeerDependencies: - bare-abort-controller + - bare-buffer - react-native-b4a arg@4.1.3: {} @@ -13877,12 +13905,21 @@ snapshots: autoprefixer@10.4.24(postcss@8.5.6): dependencies: browserslist: 4.28.1 - caniuse-lite: 1.0.30001770 + caniuse-lite: 1.0.30001776 fraction.js: 5.3.4 picocolors: 1.1.1 postcss: 8.5.6 postcss-value-parser: 4.2.0 + autoprefixer@10.4.27(postcss@8.5.8): + dependencies: + browserslist: 4.28.1 + caniuse-lite: 1.0.30001776 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.8 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -13893,7 +13930,7 @@ snapshots: axe-core@4.11.1: {} - b4a@1.7.4: {} + b4a@1.8.0: {} babel-loader@10.0.0(@babel/core@7.29.0)(webpack@5.105.2(esbuild@0.27.3)): dependencies: @@ -13939,52 +13976,46 @@ snapshots: balanced-match@2.0.0: {} - balanced-match@4.0.2: - dependencies: - jackspeak: 4.2.3 + balanced-match@4.0.4: {} bare-events@2.8.2: {} - bare-fs@4.5.4: + bare-fs@4.5.5: dependencies: bare-events: 2.8.2 bare-path: 3.0.0 - bare-stream: 2.7.0(bare-events@2.8.2) + bare-stream: 2.8.0(bare-events@2.8.2) bare-url: 2.3.2 fast-fifo: 1.3.2 transitivePeerDependencies: - bare-abort-controller - react-native-b4a - optional: true - bare-os@3.6.2: - optional: true + bare-os@3.7.0: {} bare-path@3.0.0: dependencies: - bare-os: 3.6.2 - optional: true + bare-os: 3.7.0 - bare-stream@2.7.0(bare-events@2.8.2): + bare-stream@2.8.0(bare-events@2.8.2): dependencies: streamx: 2.23.0 + teex: 1.0.1 optionalDependencies: bare-events: 2.8.2 transitivePeerDependencies: - bare-abort-controller - react-native-b4a - optional: true bare-url@2.3.2: dependencies: bare-path: 3.0.0 - optional: true base64-js@1.5.1: {} base64id@2.0.0: {} - baseline-browser-mapping@2.9.19: {} + baseline-browser-mapping@2.10.0: {} basic-auth-connect@1.1.0: dependencies: @@ -13994,7 +14025,7 @@ snapshots: dependencies: safe-buffer: 5.1.2 - basic-ftp@5.1.0: {} + basic-ftp@5.2.0: {} batch@0.6.1: {} @@ -14098,9 +14129,9 @@ snapshots: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.2: + brace-expansion@5.0.4: dependencies: - balanced-match: 4.0.2 + balanced-match: 4.0.4 braces@3.0.3: dependencies: @@ -14108,18 +14139,18 @@ snapshots: browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.9.19 - caniuse-lite: 1.0.30001770 - electron-to-chromium: 1.5.286 + baseline-browser-mapping: 2.10.0 + caniuse-lite: 1.0.30001776 + electron-to-chromium: 1.5.302 node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) - browserstack-local@1.5.10: + browserstack-local@1.5.11: dependencies: agent-base: 6.0.2(supports-color@10.2.2) https-proxy-agent: 5.0.1(supports-color@10.2.2) is-running: 2.1.0 - ps-tree: 1.2.0 + tree-kill: 1.2.2 transitivePeerDependencies: - supports-color @@ -14173,9 +14204,9 @@ snapshots: dependencies: '@npmcli/fs': 5.0.0 fs-minipass: 3.0.3 - glob: 13.0.3 + glob: 13.0.6 lru-cache: 11.2.6 - minipass: 7.1.2 + minipass: 7.1.3 minipass-collect: 2.0.1 minipass-flush: 1.0.5 minipass-pipeline: 1.2.4 @@ -14219,7 +14250,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001770: {} + caniuse-lite@1.0.30001776: {} canonical-path@0.0.2: {} @@ -14315,7 +14346,7 @@ snapshots: chrome-launcher@1.2.1: dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.2 @@ -14371,10 +14402,10 @@ snapshots: optionalDependencies: '@colors/colors': 1.5.0 - cli-truncate@5.1.1: + cli-truncate@5.2.0: dependencies: - slice-ansi: 7.1.2 - string-width: 8.1.1 + slice-ansi: 8.0.0 + string-width: 8.2.0 cli-width@4.1.0: {} @@ -14399,7 +14430,7 @@ snapshots: cliui@9.0.1: dependencies: string-width: 7.2.0 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrap-ansi: 9.0.2 clone-deep@4.0.1: @@ -14597,7 +14628,7 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 - cosmiconfig@9.0.0(typescript@5.9.2): + cosmiconfig@9.0.1(typescript@5.9.2): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 @@ -14735,10 +14766,9 @@ snapshots: decimal.js@10.6.0: {} - deep-equal-in-any-order@2.1.0: + deep-equal-in-any-order@2.2.0: dependencies: - lodash.mapvalues: 4.6.0 - sort-any: 2.0.0 + sort-any: 4.0.7 deep-extend@0.6.0: {} @@ -14827,7 +14857,7 @@ snapshots: lodash.difference: 4.5.0 lodash.template: 4.5.0 marked: 0.7.0 - minimatch: 3.1.2 + minimatch: 3.1.5 nunjucks: 3.2.4 rehype: 8.0.0 semver: 5.7.2 @@ -14922,8 +14952,6 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - duplexer@0.1.2: {} - duplexify@3.7.1: dependencies: end-of-stream: 1.4.5 @@ -14955,7 +14983,7 @@ snapshots: dependencies: jake: 10.9.4 - electron-to-chromium@1.5.286: {} + electron-to-chromium@1.5.302: {} emoji-regex@10.6.0: {} @@ -14986,7 +15014,7 @@ snapshots: engine.io@6.6.5(bufferutil@4.1.0): dependencies: '@types/cors': 2.8.19 - '@types/node': 22.19.11 + '@types/node': 22.19.13 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -14999,7 +15027,7 @@ snapshots: - supports-color - utf-8-validate - enhanced-resolve@5.19.0: + enhanced-resolve@5.20.0: dependencies: graceful-fs: 4.2.11 tapable: 2.3.0 @@ -15222,16 +15250,6 @@ snapshots: etag@1.8.1: {} - event-stream@3.3.4: - dependencies: - duplexer: 0.1.2 - from: 0.1.7 - map-stream: 0.1.0 - pause-stream: 0.0.11 - split: 0.3.3 - stream-combiner: 0.0.4 - through: 2.3.8 - event-target-shim@5.0.1: {} eventemitter3@4.0.7: {} @@ -15448,9 +15466,9 @@ snapshots: dependencies: flat-cache: 3.2.0 - filelist@1.0.4: + filelist@1.0.6: dependencies: - minimatch: 5.1.6 + minimatch: 5.1.9 filesize@6.4.0: {} @@ -15503,16 +15521,16 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - firebase-tools@15.6.0(@types/node@22.19.11)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2): + firebase-tools@15.6.0(@types/node@22.19.13)(bufferutil@4.1.0)(encoding@0.1.13)(typescript@5.9.2): dependencies: - '@apphosting/build': 0.1.7(@types/node@22.19.11)(typescript@5.9.2) + '@apphosting/build': 0.1.7(@types/node@22.19.13)(typescript@5.9.2) '@apphosting/common': 0.0.8 '@electric-sql/pglite': 0.3.15 '@electric-sql/pglite-tools': 0.2.20(@electric-sql/pglite@0.3.15) - '@google-cloud/cloud-sql-connector': 1.9.0 - '@google-cloud/pubsub': 5.2.3 - '@inquirer/prompts': 7.10.1(@types/node@22.19.11) - '@modelcontextprotocol/sdk': 1.26.0 + '@google-cloud/cloud-sql-connector': 1.9.1 + '@google-cloud/pubsub': 5.3.0 + '@inquirer/prompts': 7.10.1(@types/node@22.19.13) + '@modelcontextprotocol/sdk': 1.27.1 abort-controller: 3.0.0 ajv: 8.18.0 ajv-formats: 3.0.1 @@ -15529,7 +15547,7 @@ snapshots: cross-env: 7.0.3 cross-spawn: 7.0.6 csv-parse: 5.6.0 - deep-equal-in-any-order: 2.1.0 + deep-equal-in-any-order: 2.2.0 exegesis: 4.3.0 exegesis-express: 4.0.0 express: 4.22.1 @@ -15550,13 +15568,13 @@ snapshots: marked: 13.0.3 marked-terminal: 7.3.0(marked@13.0.3) mime: 2.6.0 - minimatch: 3.1.2 + minimatch: 3.1.5 morgan: 1.10.1 node-fetch: 2.7.0(encoding@0.1.13) open: 6.4.0 ora: 5.4.1 p-limit: 3.1.0 - pg: 8.18.0 + pg: 8.19.0 pg-gateway: 0.3.0-beta.4 pglite-2: '@electric-sql/pglite@0.2.17' portfinder: 1.0.38 @@ -15564,7 +15582,7 @@ snapshots: proxy-agent: 6.5.0 retry: 0.13.1 semver: 7.7.4 - sql-formatter: 15.7.1 + sql-formatter: 15.7.2 stream-chain: 2.2.5 stream-json: 1.9.1 superstatic: 10.0.0(encoding@0.1.13) @@ -15586,6 +15604,7 @@ snapshots: - '@swc/wasm' - '@types/node' - bare-abort-controller + - bare-buffer - bufferutil - encoding - pg-native @@ -15629,13 +15648,13 @@ snapshots: flat-cache@3.2.0: dependencies: - flatted: 3.3.3 + flatted: 3.3.4 keyv: 4.5.4 rimraf: 3.0.2 flat@5.0.2: {} - flatted@3.3.3: {} + flatted@3.3.4: {} fn.name@1.1.0: {} @@ -15689,8 +15708,6 @@ snapshots: fresh@2.0.0: {} - from@0.1.7: {} - fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -15711,7 +15728,7 @@ snapshots: fs-minipass@3.0.3: dependencies: - minipass: 7.1.2 + minipass: 7.1.3 fs.realpath@1.0.0: {} @@ -15753,6 +15770,14 @@ snapshots: transitivePeerDependencies: - supports-color + gaxios@7.1.4: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6(supports-color@10.2.2) + node-fetch: 3.3.2 + transitivePeerDependencies: + - supports-color + gaze@1.1.3: dependencies: globule: 1.3.4 @@ -15780,7 +15805,7 @@ snapshots: get-caller-file@2.0.5: {} - get-east-asian-width@1.4.0: {} + get-east-asian-width@1.5.0: {} get-intrinsic@1.3.0: dependencies: @@ -15802,7 +15827,7 @@ snapshots: get-stream@5.2.0: dependencies: - pump: 3.0.3 + pump: 3.0.4 get-stream@6.0.1: {} @@ -15818,7 +15843,7 @@ snapshots: get-uri@6.0.5: dependencies: - basic-ftp: 5.1.0 + basic-ftp: 5.2.0 data-uri-to-buffer: 6.0.2 debug: 4.4.3(supports-color@10.2.2) transitivePeerDependencies: @@ -15862,8 +15887,8 @@ snapshots: dependencies: foreground-child: 3.3.1 jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 + minimatch: 9.0.9 + minipass: 7.1.3 package-json-from-dist: 1.0.1 path-scurry: 1.11.1 @@ -15871,22 +15896,22 @@ snapshots: dependencies: foreground-child: 3.3.1 jackspeak: 4.2.3 - minimatch: 10.2.0 - minipass: 7.1.2 + minimatch: 10.2.4 + minipass: 7.1.3 package-json-from-dist: 1.0.1 - path-scurry: 2.0.1 + path-scurry: 2.0.2 - glob@13.0.3: + glob@13.0.6: dependencies: - minimatch: 10.2.0 - minipass: 7.1.2 - path-scurry: 2.0.1 + minimatch: 10.2.4 + minipass: 7.1.3 + path-scurry: 2.0.2 glob@5.0.15: dependencies: inflight: 1.0.6 inherits: 2.0.4 - minimatch: 3.1.2 + minimatch: 3.1.5 once: 1.4.0 path-is-absolute: 1.0.1 @@ -15895,7 +15920,7 @@ snapshots: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 3.1.2 + minimatch: 3.0.8 once: 1.4.0 path-is-absolute: 1.0.1 @@ -15904,7 +15929,7 @@ snapshots: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 3.1.2 + minimatch: 3.1.5 once: 1.4.0 path-is-absolute: 1.0.1 @@ -15953,14 +15978,13 @@ snapshots: lodash: 4.17.23 minimatch: 3.0.8 - google-auth-library@10.5.0(supports-color@10.2.2): + google-auth-library@10.6.1(supports-color@10.2.2): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 gaxios: 7.1.3(supports-color@10.2.2) gcp-metadata: 8.1.2(supports-color@10.2.2) google-logging-utils: 1.1.3 - gtoken: 8.0.0(supports-color@10.2.2) jws: 4.0.1 transitivePeerDependencies: - supports-color @@ -15982,7 +16006,7 @@ snapshots: '@grpc/grpc-js': 1.14.3 '@grpc/proto-loader': 0.8.0 duplexify: 4.1.3 - google-auth-library: 10.5.0(supports-color@10.2.2) + google-auth-library: 10.6.1(supports-color@10.2.2) google-logging-utils: 1.1.3 node-fetch: 3.3.2 object-hash: 3.0.0 @@ -16000,8 +16024,8 @@ snapshots: googleapis-common@8.0.1: dependencies: extend: 3.0.2 - gaxios: 7.1.3(supports-color@10.2.2) - google-auth-library: 10.5.0(supports-color@10.2.2) + gaxios: 7.1.4 + google-auth-library: 10.6.1(supports-color@10.2.2) qs: 6.15.0 url-template: 2.0.8 transitivePeerDependencies: @@ -16013,12 +16037,12 @@ snapshots: graceful-fs@4.2.11: {} - graphql-tag@2.12.6(graphql@16.12.0): + graphql-tag@2.12.6(graphql@16.13.0): dependencies: - graphql: 16.12.0 + graphql: 16.13.0 tslib: 2.8.1 - graphql@16.12.0: {} + graphql@16.13.0: {} grpc-gcp@1.0.1: dependencies: @@ -16033,13 +16057,6 @@ snapshots: - encoding - supports-color - gtoken@8.0.0(supports-color@10.2.2): - dependencies: - gaxios: 7.1.3(supports-color@10.2.2) - jws: 4.0.1 - transitivePeerDependencies: - - supports-color - handle-thing@2.0.1: {} handlebars@4.7.8: @@ -16055,7 +16072,7 @@ snapshots: har-validator@5.1.5: dependencies: - ajv: 6.12.6 + ajv: 6.14.0 har-schema: 2.0.0 hard-rejection@2.1.0: {} @@ -16137,7 +16154,7 @@ snapshots: highlight.js@11.11.1: {} - hono@4.11.9: {} + hono@4.12.3: {} hosted-git-info@2.8.9: {} @@ -16311,7 +16328,7 @@ snapshots: ignore-walk@8.0.0: dependencies: - minimatch: 10.2.0 + minimatch: 10.2.4 ignore@5.3.2: {} @@ -16333,8 +16350,8 @@ snapshots: import-in-the-middle@1.15.0: dependencies: - acorn: 8.15.0 - acorn-import-attributes: 1.9.5(acorn@8.15.0) + acorn: 8.16.0 + acorn-import-attributes: 1.9.5(acorn@8.16.0) cjs-module-lexer: 1.4.3 module-details-from-path: 1.0.4 @@ -16464,7 +16481,7 @@ snapshots: is-fullwidth-code-point@5.1.0: dependencies: - get-east-asian-width: 1.4.0 + get-east-asian-width: 1.5.0 is-generator-function@1.1.2: dependencies: @@ -16505,7 +16522,7 @@ snapshots: is-negative-zero@2.0.3: {} - is-network-error@1.3.0: {} + is-network-error@1.3.1: {} is-node-process@1.2.0: {} @@ -16727,7 +16744,7 @@ snapshots: jake@10.9.4: dependencies: async: 3.2.6 - filelist: 1.0.4 + filelist: 1.0.6 picocolors: 1.1.1 jasmine-core@2.8.0: {} @@ -16736,7 +16753,7 @@ snapshots: jasmine-core@6.0.0: {} - jasmine-core@6.0.1: {} + jasmine-core@6.1.0: {} jasmine-reporters@2.5.2: dependencies: @@ -16756,14 +16773,20 @@ snapshots: jasmine@6.0.0: dependencies: '@jasminejs/reporters': 1.0.0 - glob: 13.0.3 - jasmine-core: 6.0.1 + glob: 13.0.6 + jasmine-core: 6.0.0 + + jasmine@6.1.0: + dependencies: + '@jasminejs/reporters': 1.0.0 + glob: 13.0.6 + jasmine-core: 6.1.0 jasminewd2@2.2.0: {} jest-worker@27.5.1: dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -16826,6 +16849,8 @@ snapshots: json-stringify-safe@5.0.1: {} + json-with-bigint@3.5.7: {} + json5@2.2.3: {} jsonc-parser@3.3.1: {} @@ -16885,7 +16910,7 @@ snapshots: karma-browserstack-launcher@1.6.0(karma@6.4.4(bufferutil@4.1.0)): dependencies: browserstack: 1.5.3 - browserstack-local: 1.5.10 + browserstack-local: 1.5.11 karma: 6.4.4(bufferutil@4.1.0) q: 1.5.1 transitivePeerDependencies: @@ -16902,7 +16927,7 @@ snapshots: istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 4.0.1 istanbul-reports: 3.2.0 - minimatch: 3.1.2 + minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -16946,7 +16971,7 @@ snapshots: lodash: 4.17.23 log4js: 6.9.1 mime: 2.6.0 - minimatch: 3.1.2 + minimatch: 3.1.5 mkdirp: 0.5.6 qjobs: 1.2.0 range-parser: 1.2.1 @@ -16978,7 +17003,7 @@ snapshots: kuler@2.0.0: {} - launch-editor@2.12.0: + launch-editor@2.13.1: dependencies: picocolors: 1.1.1 shell-quote: 1.8.3 @@ -17082,11 +17107,11 @@ snapshots: lodash-es: 4.17.23 lookup-closest-locale: 6.2.0 open: 8.4.2 - puppeteer-core: 24.37.3(bufferutil@4.1.0) + puppeteer-core: 24.37.5(bufferutil@4.1.0) robots-parser: 3.0.1 speedline-core: 1.4.3 third-party-web: 0.27.0 - tldts-icann: 7.0.23 + tldts-icann: 7.0.24 ws: 7.5.10(bufferutil@4.1.0) yargs: 17.7.2 yargs-parser: 21.1.1 @@ -17102,7 +17127,7 @@ snapshots: listr2@9.0.5: dependencies: - cli-truncate: 5.1.1 + cli-truncate: 5.2.0 colorette: 2.0.20 eventemitter3: 5.0.4 log-update: 6.1.0 @@ -17180,8 +17205,6 @@ snapshots: lodash.isstring@4.0.1: {} - lodash.mapvalues@4.6.0: {} - lodash.once@4.1.1: {} lodash.snakecase@4.1.1: {} @@ -17214,14 +17237,14 @@ snapshots: ansi-escapes: 7.3.0 cli-cursor: 5.0.0 slice-ansi: 7.1.2 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrap-ansi: 9.0.2 log4js@6.9.1: dependencies: date-format: 4.0.14 debug: 4.4.3(supports-color@10.2.2) - flatted: 3.3.3 + flatted: 3.3.4 rfdc: 1.4.1 streamroller: 3.1.5 transitivePeerDependencies: @@ -17287,18 +17310,18 @@ snapshots: make-error@1.3.6: {} - make-fetch-happen@15.0.3: + make-fetch-happen@15.0.4: dependencies: + '@gar/promise-retry': 1.0.2 '@npmcli/agent': 4.0.0 cacache: 20.0.3 http-cache-semantics: 4.2.0 - minipass: 7.1.2 - minipass-fetch: 5.0.1 + minipass: 7.1.3 + minipass-fetch: 5.0.2 minipass-flush: 1.0.5 minipass-pipeline: 1.2.4 negotiator: 1.0.0 proc-log: 6.1.0 - promise-retry: 2.0.1 ssri: 13.0.1 transitivePeerDependencies: - supports-color @@ -17307,8 +17330,6 @@ snapshots: map-obj@4.3.0: {} - map-stream@0.1.0: {} - marked-terminal@7.3.0(marked@13.0.3): dependencies: ansi-escapes: 7.3.0 @@ -17324,7 +17345,7 @@ snapshots: marked@13.0.3: {} - marked@17.0.2: {} + marked@17.0.3: {} marky@1.3.0: {} @@ -17421,23 +17442,23 @@ snapshots: dependencies: '@isaacs/brace-expansion': 5.0.1 - minimatch@10.2.0: + minimatch@10.2.4: dependencies: - brace-expansion: 5.0.2 + brace-expansion: 5.0.4 minimatch@3.0.8: dependencies: brace-expansion: 1.1.12 - minimatch@3.1.2: + minimatch@3.1.5: dependencies: brace-expansion: 1.1.12 - minimatch@5.1.6: + minimatch@5.1.9: dependencies: brace-expansion: 2.0.2 - minimatch@6.2.0: + minimatch@6.2.3: dependencies: brace-expansion: 2.0.2 @@ -17445,7 +17466,7 @@ snapshots: dependencies: brace-expansion: 2.0.2 - minimatch@9.0.5: + minimatch@9.0.9: dependencies: brace-expansion: 2.0.2 @@ -17459,15 +17480,15 @@ snapshots: minipass-collect@2.0.1: dependencies: - minipass: 7.1.2 + minipass: 7.1.3 - minipass-fetch@5.0.1: + minipass-fetch@5.0.2: dependencies: - minipass: 7.1.2 + minipass: 7.1.3 minipass-sized: 2.0.0 minizlib: 3.1.0 optionalDependencies: - encoding: 0.1.13 + iconv-lite: 0.7.2 minipass-flush@1.0.5: dependencies: @@ -17479,17 +17500,17 @@ snapshots: minipass-sized@2.0.0: dependencies: - minipass: 7.1.2 + minipass: 7.1.3 minipass@3.3.6: dependencies: yallist: 4.0.0 - minipass@7.1.2: {} + minipass@7.1.3: {} minizlib@3.1.0: dependencies: - minipass: 7.1.2 + minipass: 7.1.3 mitt@3.0.1: {} @@ -17503,7 +17524,7 @@ snapshots: moment@2.30.1: {} - moo@0.5.2: {} + moo@0.5.3: {} morgan@1.10.1: dependencies: @@ -17549,7 +17570,7 @@ snapshots: dependencies: array-differ: 4.0.0 array-union: 3.0.1 - minimatch: 9.0.5 + minimatch: 9.0.9 mute-stream@2.0.0: {} @@ -17569,14 +17590,14 @@ snapshots: nearley@2.20.1: dependencies: commander: 2.20.3 - moo: 0.5.2 + moo: 0.5.3 railroad-diagrams: 1.0.0 randexp: 0.4.6 needle@3.3.1: dependencies: iconv-lite: 0.6.3 - sax: 1.4.4 + sax: 1.5.0 optional: true negotiator@0.6.3: {} @@ -17640,7 +17661,7 @@ snapshots: env-paths: 2.2.1 exponential-backoff: 3.1.3 graceful-fs: 4.2.11 - make-fetch-happen: 15.0.3 + make-fetch-happen: 15.0.4 nopt: 9.0.0 proc-log: 6.1.0 semver: 7.7.4 @@ -17706,7 +17727,7 @@ snapshots: semver: 7.7.4 validate-npm-package-name: 7.0.2 - npm-packlist@10.0.3: + npm-packlist@10.0.4: dependencies: ignore-walk: 8.0.0 proc-log: 6.1.0 @@ -17729,9 +17750,9 @@ snapshots: dependencies: '@npmcli/redact': 4.0.0 jsonparse: 1.3.1 - make-fetch-happen: 15.0.3 - minipass: 7.1.2 - minipass-fetch: 5.0.1 + make-fetch-happen: 15.0.4 + minipass: 7.1.3 + minipass-fetch: 5.0.2 minizlib: 3.1.0 npm-package-arg: 13.0.2 proc-log: 6.1.0 @@ -17744,7 +17765,7 @@ snapshots: chalk: 2.4.2 cross-spawn: 6.0.6 memorystream: 0.3.1 - minimatch: 3.1.2 + minimatch: 3.1.5 pidtree: 0.3.1 read-pkg: 3.0.0 shell-quote: 1.8.3 @@ -17875,7 +17896,7 @@ snapshots: is-unicode-supported: 2.1.0 log-symbols: 7.0.1 stdin-discarder: 0.3.1 - string-width: 8.1.1 + string-width: 8.2.0 ordered-binary@1.6.1: optional: true @@ -17920,7 +17941,7 @@ snapshots: p-retry@6.2.1: dependencies: '@types/retry': 0.12.2 - is-network-error: 1.3.0 + is-network-error: 1.3.1 retry: 0.13.1 p-throttle@7.0.0: {} @@ -17953,16 +17974,16 @@ snapshots: pacote@21.3.1: dependencies: - '@npmcli/git': 7.0.1 + '@npmcli/git': 7.0.2 '@npmcli/installed-package-contents': 4.0.0 - '@npmcli/package-json': 7.0.4 + '@npmcli/package-json': 7.0.5 '@npmcli/promise-spawn': 9.0.1 - '@npmcli/run-script': 10.0.3 + '@npmcli/run-script': 10.0.4 cacache: 20.0.3 fs-minipass: 3.0.3 - minipass: 7.1.2 + minipass: 7.1.3 npm-package-arg: 13.0.2 - npm-packlist: 10.0.3 + npm-packlist: 10.0.4 npm-pick-manifest: 11.0.3 npm-registry-fetch: 19.1.1 proc-log: 6.1.0 @@ -18047,12 +18068,12 @@ snapshots: path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 - minipass: 7.1.2 + minipass: 7.1.3 - path-scurry@2.0.1: + path-scurry@2.0.2: dependencies: lru-cache: 11.2.6 - minipass: 7.1.2 + minipass: 7.1.3 path-to-regexp@0.1.12: {} @@ -18068,10 +18089,6 @@ snapshots: path-type@4.0.0: {} - pause-stream@0.0.11: - dependencies: - through: 2.3.8 - pend@1.2.0: {} performance-now@2.1.0: {} @@ -18085,11 +18102,11 @@ snapshots: pg-int8@1.0.1: {} - pg-pool@3.11.0(pg@8.18.0): + pg-pool@3.12.0(pg@8.19.0): dependencies: - pg: 8.18.0 + pg: 8.19.0 - pg-protocol@1.11.0: {} + pg-protocol@1.12.0: {} pg-types@2.2.0: dependencies: @@ -18099,11 +18116,11 @@ snapshots: postgres-date: 1.0.7 postgres-interval: 1.2.0 - pg@8.18.0: + pg@8.19.0: dependencies: pg-connection-string: 2.11.0 - pg-pool: 3.11.0(pg@8.18.0) - pg-protocol: 1.11.0 + pg-pool: 3.12.0(pg@8.19.0) + pg-protocol: 1.12.0 pg-types: 2.2.0 pgpass: 1.0.5 optionalDependencies: @@ -18160,7 +18177,7 @@ snapshots: postcss-loader@8.2.0(postcss@8.5.6)(typescript@5.9.2)(webpack@5.105.2(esbuild@0.27.3)): dependencies: - cosmiconfig: 9.0.0(typescript@5.9.2) + cosmiconfig: 9.0.1(typescript@5.9.2) jiti: 2.6.1 postcss: 8.5.6 semver: 7.7.4 @@ -18194,17 +18211,17 @@ snapshots: postcss-resolve-nested-selector@0.1.6: {} - postcss-safe-parser@6.0.0(postcss@8.5.6): + postcss-safe-parser@6.0.0(postcss@8.5.8): dependencies: - postcss: 8.5.6 + postcss: 8.5.8 postcss-safe-parser@7.0.1(postcss@8.5.6): dependencies: postcss: 8.5.6 - postcss-scss@4.0.9(postcss@8.5.6): + postcss-scss@4.0.9(postcss@8.5.8): dependencies: - postcss: 8.5.6 + postcss: 8.5.8 postcss-selector-parser@6.1.2: dependencies: @@ -18224,6 +18241,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.8: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postgres-array@2.0.0: {} postgres-bytea@1.0.1: {} @@ -18286,7 +18309,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.19.11 + '@types/node': 22.19.13 long: 5.3.2 protobufjs@7.5.4: @@ -18301,7 +18324,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.19.11 + '@types/node': 22.19.13 long: 5.3.2 protractor@7.0.0: @@ -18347,10 +18370,6 @@ snapshots: prr@1.0.1: optional: true - ps-tree@1.2.0: - dependencies: - event-stream: 3.3.4 - psl@1.15.0: dependencies: punycode: 2.3.1 @@ -18360,7 +18379,7 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 - pump@3.0.3: + pump@3.0.4: dependencies: end-of-stream: 1.4.5 once: 1.4.0 @@ -18379,13 +18398,13 @@ snapshots: dependencies: escape-goat: 2.1.1 - puppeteer-core@24.37.3(bufferutil@4.1.0): + puppeteer-core@24.37.5(bufferutil@4.1.0): dependencies: - '@puppeteer/browsers': 2.12.1 + '@puppeteer/browsers': 2.13.0 chromium-bidi: 14.0.0(devtools-protocol@0.0.1566079) debug: 4.4.3(supports-color@10.2.2) devtools-protocol: 0.0.1566079 - typed-query-selector: 2.12.0 + typed-query-selector: 2.12.1 webdriver-bidi-protocol: 0.4.1 ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) transitivePeerDependencies: @@ -18510,7 +18529,7 @@ snapshots: readdir-glob@1.1.3: dependencies: - minimatch: 5.1.6 + minimatch: 5.1.9 readdirp@3.6.0: dependencies: @@ -18720,50 +18739,50 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.4 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.4 - rollup-plugin-dts@6.3.0(rollup@4.57.1)(typescript@5.9.2): + rollup-plugin-dts@6.3.0(rollup@4.59.0)(typescript@5.9.2): dependencies: magic-string: 0.30.21 - rollup: 4.57.1 + rollup: 4.59.0 typescript: 5.9.2 optionalDependencies: '@babel/code-frame': 7.29.0 - rollup-plugin-sourcemaps2@0.5.4(@types/node@22.19.11)(rollup@4.57.1): + rollup-plugin-sourcemaps2@0.5.4(@types/node@22.19.13)(rollup@4.59.0): dependencies: - '@rollup/pluginutils': 5.2.0(rollup@4.57.1) - rollup: 4.57.1 + '@rollup/pluginutils': 5.2.0(rollup@4.59.0) + rollup: 4.59.0 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 - rollup@4.57.1: + rollup@4.59.0: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.57.1 - '@rollup/rollup-android-arm64': 4.57.1 - '@rollup/rollup-darwin-arm64': 4.57.1 - '@rollup/rollup-darwin-x64': 4.57.1 - '@rollup/rollup-freebsd-arm64': 4.57.1 - '@rollup/rollup-freebsd-x64': 4.57.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.57.1 - '@rollup/rollup-linux-arm-musleabihf': 4.57.1 - '@rollup/rollup-linux-arm64-gnu': 4.57.1 - '@rollup/rollup-linux-arm64-musl': 4.57.1 - '@rollup/rollup-linux-loong64-gnu': 4.57.1 - '@rollup/rollup-linux-loong64-musl': 4.57.1 - '@rollup/rollup-linux-ppc64-gnu': 4.57.1 - '@rollup/rollup-linux-ppc64-musl': 4.57.1 - '@rollup/rollup-linux-riscv64-gnu': 4.57.1 - '@rollup/rollup-linux-riscv64-musl': 4.57.1 - '@rollup/rollup-linux-s390x-gnu': 4.57.1 - '@rollup/rollup-linux-x64-gnu': 4.57.1 - '@rollup/rollup-linux-x64-musl': 4.57.1 - '@rollup/rollup-openbsd-x64': 4.57.1 - '@rollup/rollup-openharmony-arm64': 4.57.1 - '@rollup/rollup-win32-arm64-msvc': 4.57.1 - '@rollup/rollup-win32-ia32-msvc': 4.57.1 - '@rollup/rollup-win32-x64-gnu': 4.57.1 - '@rollup/rollup-win32-x64-msvc': 4.57.1 + '@rollup/rollup-android-arm-eabi': 4.59.0 + '@rollup/rollup-android-arm64': 4.59.0 + '@rollup/rollup-darwin-arm64': 4.59.0 + '@rollup/rollup-darwin-x64': 4.59.0 + '@rollup/rollup-freebsd-arm64': 4.59.0 + '@rollup/rollup-freebsd-x64': 4.59.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 + '@rollup/rollup-linux-arm-musleabihf': 4.59.0 + '@rollup/rollup-linux-arm64-gnu': 4.59.0 + '@rollup/rollup-linux-arm64-musl': 4.59.0 + '@rollup/rollup-linux-loong64-gnu': 4.59.0 + '@rollup/rollup-linux-loong64-musl': 4.59.0 + '@rollup/rollup-linux-ppc64-gnu': 4.59.0 + '@rollup/rollup-linux-ppc64-musl': 4.59.0 + '@rollup/rollup-linux-riscv64-gnu': 4.59.0 + '@rollup/rollup-linux-riscv64-musl': 4.59.0 + '@rollup/rollup-linux-s390x-gnu': 4.59.0 + '@rollup/rollup-linux-x64-gnu': 4.59.0 + '@rollup/rollup-linux-x64-musl': 4.59.0 + '@rollup/rollup-openbsd-x64': 4.59.0 + '@rollup/rollup-openharmony-arm64': 4.59.0 + '@rollup/rollup-win32-arm64-msvc': 4.59.0 + '@rollup/rollup-win32-ia32-msvc': 4.59.0 + '@rollup/rollup-win32-x64-gnu': 4.59.0 + '@rollup/rollup-win32-x64-msvc': 4.59.0 fsevents: 2.3.3 router@2.2.0: @@ -18853,14 +18872,6 @@ snapshots: sass: 1.97.3 webpack: 5.105.2(esbuild@0.27.3) - sass@1.97.2: - dependencies: - chokidar: 4.0.3 - immutable: 5.1.4 - source-map-js: 1.2.1 - optionalDependencies: - '@parcel/watcher': 2.5.6 - sass@1.97.3: dependencies: chokidar: 4.0.3 @@ -18875,7 +18886,7 @@ snapshots: transitivePeerDependencies: - supports-color - sax@1.4.4: {} + sax@1.5.0: {} schema-utils@4.3.3: dependencies: @@ -19125,6 +19136,11 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 + slice-ansi@8.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + slugify@1.6.6: {} smart-buffer@4.2.0: {} @@ -19182,9 +19198,7 @@ snapshots: ip-address: 10.1.0 smart-buffer: 4.2.0 - sort-any@2.0.0: - dependencies: - lodash: 4.17.23 + sort-any@4.0.7: {} source-map-js@1.2.1: {} @@ -19219,16 +19233,21 @@ snapshots: spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.23 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.23 + + spdx-expression-parse@4.0.0: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.23 - spdx-license-ids@3.0.22: {} + spdx-license-ids@3.0.23: {} spdx-license-list@2.1.0: {} @@ -19255,7 +19274,7 @@ snapshots: speedline-core@1.4.3: dependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 image-ssim: 0.2.0 jpeg-js: 0.4.4 @@ -19270,13 +19289,9 @@ snapshots: split2@4.2.0: {} - split@0.3.3: - dependencies: - through: 2.3.8 - sprintf-js@1.0.3: {} - sql-formatter@15.7.1: + sql-formatter@15.7.2: dependencies: argparse: 2.0.1 nearley: 2.20.1 @@ -19295,11 +19310,11 @@ snapshots: ssri@10.0.5: dependencies: - minipass: 7.1.2 + minipass: 7.1.3 ssri@13.0.1: dependencies: - minipass: 7.1.2 + minipass: 7.1.3 stack-trace@0.0.10: {} @@ -19318,10 +19333,6 @@ snapshots: stream-chain@2.2.5: {} - stream-combiner@0.0.4: - dependencies: - duplexer: 0.1.2 - stream-events@1.0.5: dependencies: stubs: 3.0.0 @@ -19361,18 +19372,18 @@ snapshots: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 string-width@7.2.0: dependencies: emoji-regex: 10.6.0 - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 - string-width@8.1.1: + string-width@8.2.0: dependencies: - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 string.prototype.padend@3.1.6: dependencies: @@ -19428,7 +19439,7 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.2: + strip-ansi@7.2.0: dependencies: ansi-regex: 6.2.2 @@ -19479,10 +19490,10 @@ snapshots: micromatch: 4.0.8 normalize-path: 3.0.0 picocolors: 1.1.1 - postcss: 8.5.6 + postcss: 8.5.8 postcss-media-query-parser: 0.2.3 postcss-resolve-nested-selector: 0.1.6 - postcss-safe-parser: 6.0.0(postcss@8.5.6) + postcss-safe-parser: 6.0.0(postcss@8.5.8) postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 resolve-from: 5.0.0 @@ -19509,7 +19520,7 @@ snapshots: join-path: 1.1.1 lodash: 4.17.23 mime-types: 2.1.35 - minimatch: 6.2.0 + minimatch: 6.2.3 morgan: 1.10.1 on-finished: 2.4.1 on-headers: 1.1.0 @@ -19573,30 +19584,32 @@ snapshots: tar-fs@3.1.1: dependencies: - pump: 3.0.3 - tar-stream: 3.1.7 + pump: 3.0.4 + tar-stream: 3.1.8 optionalDependencies: - bare-fs: 4.5.4 + bare-fs: 4.5.5 bare-path: 3.0.0 transitivePeerDependencies: - bare-abort-controller - bare-buffer - react-native-b4a - tar-stream@3.1.7: + tar-stream@3.1.8: dependencies: - b4a: 1.7.4 + b4a: 1.8.0 + bare-fs: 4.5.5 fast-fifo: 1.3.2 streamx: 2.23.0 transitivePeerDependencies: - bare-abort-controller + - bare-buffer - react-native-b4a tar@7.5.9: dependencies: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 - minipass: 7.1.2 + minipass: 7.1.3 minizlib: 3.1.0 yallist: 5.0.0 @@ -19616,6 +19629,13 @@ snapshots: transitivePeerDependencies: - supports-color + teex@1.0.1: + dependencies: + streamx: 2.23.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + terser-webpack-plugin@5.3.16(esbuild@0.27.3)(webpack@5.105.2(esbuild@0.27.3)): dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -19630,13 +19650,13 @@ snapshots: terser@5.46.0: dependencies: '@jridgewell/source-map': 0.3.11 - acorn: 8.15.0 + acorn: 8.16.0 commander: 2.20.3 source-map-support: 0.5.21 text-decoder@1.2.7: dependencies: - b4a: 1.7.4 + b4a: 1.8.0 transitivePeerDependencies: - react-native-b4a @@ -19667,8 +19687,6 @@ snapshots: dependencies: readable-stream: 3.6.2 - through@2.3.8: {} - thunky@1.1.0: {} tinyglobby@0.2.12: @@ -19686,11 +19704,11 @@ snapshots: no-case: 2.3.2 upper-case: 1.1.3 - tldts-core@7.0.23: {} + tldts-core@7.0.24: {} - tldts-icann@7.0.23: + tldts-icann@7.0.24: dependencies: - tldts-core: 7.0.23 + tldts-core: 7.0.24 tmp@0.0.30: dependencies: @@ -19729,16 +19747,16 @@ snapshots: trough@1.0.5: {} - ts-node@10.9.2(@types/node@22.19.11)(typescript@5.9.2): + ts-node@10.9.2(@types/node@22.19.13)(typescript@5.9.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.12 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.19.11 - acorn: 8.15.0 - acorn-walk: 8.3.4 + '@types/node': 22.19.13 + acorn: 8.16.0 + acorn-walk: 8.3.5 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.4 @@ -19751,7 +19769,7 @@ snapshots: dependencies: '@bazel/bazelisk': 1.28.1 glob: 11.1.0 - minimatch: 10.2.0 + minimatch: 10.2.4 typescript: 5.9.2 tsickle@0.46.3(typescript@5.9.2): @@ -19772,7 +19790,7 @@ snapshots: diff: 4.0.4 glob: 7.2.3 js-yaml: 3.14.2 - minimatch: 3.1.2 + minimatch: 3.1.5 mkdirp: 0.5.6 resolve: 1.22.11 semver: 5.7.2 @@ -19814,7 +19832,7 @@ snapshots: dependencies: '@tufjs/models': 4.1.0 debug: 4.4.3(supports-color@10.2.2) - make-fetch-happen: 15.0.3 + make-fetch-happen: 15.0.4 transitivePeerDependencies: - supports-color @@ -19888,7 +19906,7 @@ snapshots: typed-graphqlify@3.1.6: {} - typed-query-selector@2.12.0: {} + typed-query-selector@2.12.1: {} typedarray-to-buffer@3.1.5: dependencies: @@ -20079,16 +20097,16 @@ snapshots: unist-util-stringify-position: 1.1.2 vfile-message: 1.1.1 - vite@7.3.1(@types/node@22.19.11)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2): + vite@7.3.1(@types/node@22.19.13)(jiti@2.6.1)(less@4.4.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.57.1 + rollup: 4.59.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 22.19.11 + '@types/node': 22.19.13 fsevents: 2.3.3 jiti: 2.6.1 less: 4.4.2 @@ -20182,7 +20200,7 @@ snapshots: graceful-fs: 4.2.11 http-proxy-middleware: 2.0.9(@types/express@4.17.25) ipaddr.js: 2.3.0 - launch-editor: 2.12.0 + launch-editor: 2.13.1 open: 10.2.0 p-retry: 6.2.1 schema-utils: 4.3.3 @@ -20222,11 +20240,11 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.15.0 - acorn-import-phases: 1.0.4(acorn@8.15.0) + acorn: 8.16.0 + acorn-import-phases: 1.0.4(acorn@8.16.0) browserslist: 4.28.1 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.19.0 + enhanced-resolve: 5.20.0 es-module-lexer: 2.0.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -20381,13 +20399,13 @@ snapshots: dependencies: ansi-styles: 6.2.3 string-width: 5.1.2 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 string-width: 7.2.0 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrappy@1.0.2: {} @@ -20435,7 +20453,7 @@ snapshots: xml2js@0.4.23: dependencies: - sax: 1.4.4 + sax: 1.5.0 xmlbuilder: 11.0.1 xmlbuilder@11.0.1: {} @@ -20541,6 +20559,6 @@ snapshots: zod@4.3.6: {} - zone.js@0.16.0: {} + zone.js@0.16.1: {} zx@8.8.5: {} From 902a1f6c562149fcd52c6f5a76dc5ef4047395f8 Mon Sep 17 00:00:00 2001 From: tjshiu <35056071+tjshiu@users.noreply.github.com> Date: Wed, 4 Mar 2026 17:22:56 -0800 Subject: [PATCH 023/123] release: cut the v21.2.1 release --- CHANGELOG.md | 19 +++++++++++++++++++ package.json | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15036c69c970..cb7cbb26e601 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ + +# 21.2.1 "leather heels" (2026-03-04) +### aria +| Commit | Type | Description | +| -- | -- | -- | +| [c1295c5818](https://github.com/angular/components/commit/c1295c5818c820ab182727b4f85e5f55a05f6385) | fix | **menu:** itemSelected not emitted when menu is attached to a trigger ([#32880](https://github.com/angular/components/pull/32880)) | +### material +| Commit | Type | Description | +| -- | -- | -- | +| [cebf303417](https://github.com/angular/components/commit/cebf303417678ea4f48e32f17e55d6649da04a27) | fix | **checkbox:** hide decorative elements from assistive technology | +| [2abe8e6b73](https://github.com/angular/components/commit/2abe8e6b7330f5281b560b202ab70bdf593782cc) | fix | **menu:** render backdrop for context menu if explicitly opted in ([#32845](https://github.com/angular/components/pull/32845)) | +| [e2f7308dc4](https://github.com/angular/components/commit/e2f7308dc4b5e539c2ccacf138a7997f9f5fdf03) | fix | **radio:** hide decorative elements from assistive technology | +### multiple +| Commit | Type | Description | +| -- | -- | -- | +| [17c19cc73b](https://github.com/angular/components/commit/17c19cc73b4e7e24ae5579c32ae5a784d92c2a12) | fix | expand type for restoreFocus ([#32877](https://github.com/angular/components/pull/32877)) | + + + # 21.2.0 "plastic-lion" (2026-02-25) ### aria diff --git a/package.json b/package.json index 159c9e44cbc6..4e8613940e5e 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "ci-docs-monitor-test": "node --no-warnings=ExperimentalWarning --loader ts-node/esm/transpile-only scripts/docs-deploy/monitoring/ci-test.mts", "prepare": "husky" }, - "version": "21.2.0", + "version": "21.2.1", "dependencies": { "@angular-devkit/core": "catalog:", "@angular-devkit/schematics": "catalog:", From 93315d5fce1eb76540995ae091e95dc7e3184978 Mon Sep 17 00:00:00 2001 From: Cheng-Hsuan Tsai Date: Thu, 5 Mar 2026 10:41:47 -0800 Subject: [PATCH 024/123] refactor(aria/grid): code clean up (#32842) focus and navigation behaviors have integrated into grid behavior (cherry picked from commit 65db13a620b98a6a36917a88bde32cab2029490e) --- .../private/behaviors/grid-focus/BUILD.bazel | 28 - .../behaviors/grid-focus/grid-focus.spec.ts | 443 ------ .../behaviors/grid-focus/grid-focus.ts | 223 --- .../behaviors/grid-navigation/BUILD.bazel | 30 - .../grid-navigation/grid-navigation.spec.ts | 1253 ----------------- .../grid-navigation/grid-navigation.ts | 158 --- 6 files changed, 2135 deletions(-) delete mode 100644 src/aria/private/behaviors/grid-focus/BUILD.bazel delete mode 100644 src/aria/private/behaviors/grid-focus/grid-focus.spec.ts delete mode 100644 src/aria/private/behaviors/grid-focus/grid-focus.ts delete mode 100644 src/aria/private/behaviors/grid-navigation/BUILD.bazel delete mode 100644 src/aria/private/behaviors/grid-navigation/grid-navigation.spec.ts delete mode 100644 src/aria/private/behaviors/grid-navigation/grid-navigation.ts diff --git a/src/aria/private/behaviors/grid-focus/BUILD.bazel b/src/aria/private/behaviors/grid-focus/BUILD.bazel deleted file mode 100644 index eb4f60a59a92..000000000000 --- a/src/aria/private/behaviors/grid-focus/BUILD.bazel +++ /dev/null @@ -1,28 +0,0 @@ -load("//tools:defaults.bzl", "ng_project", "ng_web_test_suite", "ts_project") - -package(default_visibility = ["//visibility:public"]) - -ts_project( - name = "grid-focus", - srcs = ["grid-focus.ts"], - deps = [ - "//:node_modules/@angular/core", - "//src/aria/private/behaviors/signal-like", - ], -) - -ng_project( - name = "unit_test_sources", - testonly = True, - srcs = ["grid-focus.spec.ts"], - deps = [ - ":grid-focus", - "//:node_modules/@angular/core", - "//src/aria/private/behaviors/signal-like", - ], -) - -ng_web_test_suite( - name = "unit_tests", - deps = [":unit_test_sources"], -) diff --git a/src/aria/private/behaviors/grid-focus/grid-focus.spec.ts b/src/aria/private/behaviors/grid-focus/grid-focus.spec.ts deleted file mode 100644 index 3fc7c3141b88..000000000000 --- a/src/aria/private/behaviors/grid-focus/grid-focus.spec.ts +++ /dev/null @@ -1,443 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import {computed, SignalLike, signal, WritableSignalLike} from '../signal-like/signal-like'; -import {GridFocus, GridFocusInputs, GridFocusCell, RowCol} from './grid-focus'; - -// Helper type for test cells, extending GridFocusCell -interface TestGridCell extends GridFocusCell { - id: WritableSignalLike; - element: WritableSignalLike; - disabled: WritableSignalLike; -} - -// Helper type for configuring GridFocus inputs in tests -type TestSetupInputs = Partial> & { - numRows?: number; - numCols?: number; - gridFocus?: WritableSignalLike | undefined>; -}; - -export function createTestCell( - gridFocus: SignalLike | undefined>, - opts: {id: string; rowspan?: number; colspan?: number}, -): TestGridCell { - const el = document.createElement('div'); - spyOn(el, 'focus').and.callThrough(); - let coordinates: SignalLike = signal({row: -1, col: -1}); - const cell: TestGridCell = { - id: signal(opts.id), - element: signal(el as HTMLElement), - disabled: signal(false), - rowspan: signal(opts.rowspan ?? 1), - colspan: signal(opts.rowspan ?? 1), - rowindex: signal(-1), - colindex: signal(-1), - }; - coordinates = computed(() => gridFocus()?.getCoordinates(cell) ?? {row: -1, col: -1}); - cell.rowindex = computed(() => coordinates().row); - cell.colindex = computed(() => coordinates().col); - return cell; -} - -export function createTestCells( - gridFocus: SignalLike | undefined>, - numRows: number, - numCols: number, -): WritableSignalLike { - return signal( - Array.from({length: numRows}).map((_, r) => - Array.from({length: numCols}).map((_, c) => { - return createTestCell(gridFocus, {id: `cell-${r}-${c}`}); - }), - ), - ); -} - -// Main helper function to instantiate GridFocus and its dependencies for testing -export function setupGridFocus(inputs: TestSetupInputs = {}): { - cells: TestGridCell[][]; - gridFocus: GridFocus; -} { - const numRows = inputs.numRows ?? 3; - const numCols = inputs.numCols ?? 3; - - const gridFocus = inputs.gridFocus ?? signal | undefined>(undefined); - const cells = inputs.cells ?? createTestCells(gridFocus, numRows, numCols); - - const activeCoords = inputs.activeCoords ?? signal({row: 0, col: 0}); - const focusMode = signal<'roving' | 'activedescendant'>( - inputs.focusMode ? inputs.focusMode() : 'roving', - ); - const disabled = signal(inputs.disabled ? inputs.disabled() : false); - const softDisabled = signal(inputs.softDisabled ? inputs.softDisabled() : false); - - gridFocus.set( - new GridFocus({ - cells: cells, - activeCoords: activeCoords, - focusMode: focusMode, - disabled: disabled, - softDisabled: softDisabled, - }), - ); - - return { - cells: cells(), - gridFocus: gridFocus()!, - }; -} - -describe('GridFocus', () => { - describe('Initialization', () => { - it('should initialize with activeCell at {row: 0, col: 0} by default', () => { - const {gridFocus} = setupGridFocus(); - expect(gridFocus.inputs.activeCoords()).toEqual({row: 0, col: 0}); - }); - - it('should compute activeCell based on activeCell', () => { - const {gridFocus, cells} = setupGridFocus({ - activeCoords: signal({row: 1, col: 1}), - }); - expect(gridFocus.activeCell()).toBe(cells[1][1]); - }); - - it('should compute activeCell correctly when rowspan and colspan are set', () => { - const activeCoords = signal({row: 0, col: 0}); - const gridFocusSignal = signal | undefined>(undefined); - - // Visualization of this irregular grid. - // - // +---+---+---+ - // | |0,2| - // + 0,0 +---+ - // | |1,2| - // +---+---+---+ - // - const cell_0_0 = createTestCell(gridFocusSignal, {id: `cell-0-0`, rowspan: 2, colspan: 2}); - const cell_0_2 = createTestCell(gridFocusSignal, {id: `cell-0-2`}); - const cell_1_2 = createTestCell(gridFocusSignal, {id: `cell-1-2`}); - const cells = signal([[cell_0_0, cell_0_2], [cell_1_2]]); - - const {gridFocus} = setupGridFocus({ - cells, - activeCoords, - gridFocus: gridFocusSignal, - }); - - activeCoords.set({row: 0, col: 0}); - expect(gridFocus.activeCell()).toBe(cell_0_0); - activeCoords.set({row: 0, col: 1}); - expect(gridFocus.activeCell()).toBe(cell_0_0); - activeCoords.set({row: 1, col: 0}); - expect(gridFocus.activeCell()).toBe(cell_0_0); - activeCoords.set({row: 1, col: 1}); - expect(gridFocus.activeCell()).toBe(cell_0_0); - - activeCoords.set({row: 0, col: 2}); - expect(gridFocus.activeCell()).toBe(cell_0_2); - - activeCoords.set({row: 1, col: 2}); - expect(gridFocus.activeCell()).toBe(cell_1_2); - }); - - it('should compute rowCount and colCount correctly', () => { - const {gridFocus} = setupGridFocus({ - numRows: 2, - numCols: 3, - }); - expect(gridFocus.rowCount()).toBe(2); - expect(gridFocus.colCount()).toBe(3); - }); - - it('should compute rowCount and colCount correctly when rowspan and colspan are set', () => { - const gridFocusSignal = signal | undefined>(undefined); - - // Visualization of this irregular grid. - // - // +---+---+---+ - // | |0,2| - // + 0,0 +---+ - // | |1,2| - // +---+---+---+ - // - const cell_0_0 = createTestCell(gridFocusSignal, {id: `cell-0-0`, rowspan: 2, colspan: 2}); - const cell_0_2 = createTestCell(gridFocusSignal, {id: `cell-0-2`}); - const cell_1_2 = createTestCell(gridFocusSignal, {id: `cell-1-2`}); - const cells = signal([[cell_0_0, cell_0_2], [cell_1_2]]); - - const {gridFocus} = setupGridFocus({ - cells, - gridFocus: gridFocusSignal, - }); - - expect(gridFocus.rowCount()).toBe(2); - expect(gridFocus.colCount()).toBe(3); - }); - }); - - describe('isGridDisabled', () => { - it('should return true if inputs.disabled is true', () => { - const {gridFocus} = setupGridFocus({disabled: signal(true)}); - expect(gridFocus.isGridDisabled()).toBeTrue(); - }); - - it('should return true if all cells are disabled', () => { - const {gridFocus, cells} = setupGridFocus({numRows: 2, numCols: 1}); - cells.forEach(row => row.forEach(cell => cell.disabled.set(true))); - expect(gridFocus.isGridDisabled()).toBeTrue(); - }); - - it('should return true if inputs.cells is empty', () => { - const {gridFocus} = setupGridFocus({numRows: 0, numCols: 0}); - expect(gridFocus.isGridDisabled()).toBeTrue(); - }); - - it('should return true if the grid contains only empty rows', () => { - const cells = signal([[], []]); - const {gridFocus} = setupGridFocus({cells: cells}); - expect(gridFocus.isGridDisabled()).toBeTrue(); - }); - }); - - describe('getActiveDescendant', () => { - it('should return undefined if focusMode is "roving"', () => { - const {gridFocus} = setupGridFocus({focusMode: signal('roving')}); - expect(gridFocus.getActiveDescendant()).toBeUndefined(); - }); - - it('should return undefined if the grid is disabled', () => { - const {gridFocus} = setupGridFocus({ - disabled: signal(true), - focusMode: signal('activedescendant'), - }); - expect(gridFocus.getActiveDescendant()).toBeUndefined(); - }); - - it('should return the activeCell id if focusMode is "activedescendant"', () => { - const {gridFocus, cells} = setupGridFocus({ - focusMode: signal('activedescendant'), - activeCoords: signal({row: 2, col: 2}), - }); - expect(gridFocus.getActiveDescendant()).toBe(cells[2][2].id()); - }); - }); - - describe('getGridTabindex', () => { - it('should return 0 if grid is disabled', () => { - const {gridFocus} = setupGridFocus({disabled: signal(true)}); - expect(gridFocus.getGridTabIndex()).toBe(0); - }); - - it('should return -1 if focusMode is "roving" and grid is not disabled', () => { - const {gridFocus} = setupGridFocus({focusMode: signal('roving')}); - expect(gridFocus.getGridTabIndex()).toBe(-1); - }); - - it('should return 0 if focusMode is "activedescendant" and grid is not disabled', () => { - const {gridFocus} = setupGridFocus({focusMode: signal('activedescendant')}); - expect(gridFocus.getGridTabIndex()).toBe(0); - }); - }); - - describe('getCellTabindex', () => { - it('should return -1 if grid is disabled', () => { - const {gridFocus, cells} = setupGridFocus({ - numRows: 1, - numCols: 3, - disabled: signal(true), - }); - expect(gridFocus.getCellTabIndex(cells[0][0])).toBe(-1); - expect(gridFocus.getCellTabIndex(cells[0][1])).toBe(-1); - expect(gridFocus.getCellTabIndex(cells[0][2])).toBe(-1); - }); - - it('should return -1 if focusMode is "activedescendant"', () => { - const {gridFocus, cells} = setupGridFocus({ - numRows: 1, - numCols: 3, - focusMode: signal('activedescendant'), - }); - expect(gridFocus.getCellTabIndex(cells[0][0])).toBe(-1); - expect(gridFocus.getCellTabIndex(cells[0][1])).toBe(-1); - expect(gridFocus.getCellTabIndex(cells[0][2])).toBe(-1); - }); - - it('should return 0 if focusMode is "roving" and cell is the activeCell', () => { - const {gridFocus, cells} = setupGridFocus({ - numRows: 1, - numCols: 3, - focusMode: signal('roving'), - }); - - expect(gridFocus.getCellTabIndex(cells[0][0])).toBe(0); - expect(gridFocus.getCellTabIndex(cells[0][1])).toBe(-1); - expect(gridFocus.getCellTabIndex(cells[0][2])).toBe(-1); - }); - }); - - describe('isFocusable', () => { - it('should return true if cell is not disabled', () => { - const {gridFocus, cells} = setupGridFocus({ - numRows: 1, - numCols: 3, - }); - expect(gridFocus.isFocusable(cells[0][0])).toBeTrue(); - expect(gridFocus.isFocusable(cells[0][1])).toBeTrue(); - expect(gridFocus.isFocusable(cells[0][2])).toBeTrue(); - }); - - it('should return false if cell is disabled and softDisabled is false', () => { - const {gridFocus, cells} = setupGridFocus({ - numRows: 1, - numCols: 3, - softDisabled: signal(false), - }); - cells[0][1].disabled.set(true); - expect(gridFocus.isFocusable(cells[0][0])).toBeTrue(); - expect(gridFocus.isFocusable(cells[0][1])).toBeFalse(); - expect(gridFocus.isFocusable(cells[0][2])).toBeTrue(); - }); - - it('should return true if cell is disabled but softDisabled is true', () => { - const {gridFocus, cells} = setupGridFocus({ - numRows: 1, - numCols: 3, - softDisabled: signal(true), - }); - cells[0][1].disabled.set(true); - expect(gridFocus.isFocusable(cells[0][0])).toBeTrue(); - expect(gridFocus.isFocusable(cells[0][1])).toBeTrue(); - expect(gridFocus.isFocusable(cells[0][2])).toBeTrue(); - }); - }); - - describe('focusCoordinates', () => { - it('should return false and not change state if grid is disabled', () => { - const activeCoords = signal({row: 0, col: 0}); - const {gridFocus, cells} = setupGridFocus({ - activeCoords, - disabled: signal(true), - }); - - const success = gridFocus.focusCoordinates({row: 1, col: 0}); - - expect(success).toBeFalse(); - expect(activeCoords()).toEqual({row: 0, col: 0}); - expect(cells[1][0].element().focus).not.toHaveBeenCalled(); - }); - - it('should return false and not change state if cell is not focusable', () => { - const activeCoords = signal({row: 0, col: 0}); - const {gridFocus, cells} = setupGridFocus({activeCoords}); - cells[1][0].disabled.set(true); - - const success = gridFocus.focusCoordinates({row: 1, col: 0}); - - expect(success).toBeFalse(); - expect(activeCoords()).toEqual({row: 0, col: 0}); - expect(cells[1][0].element().focus).not.toHaveBeenCalled(); - }); - - it('should focus cell, update activeCell and prevActiveCell in "roving" mode', () => { - const activeCoords = signal({row: 0, col: 0}); - const {gridFocus, cells} = setupGridFocus({ - activeCoords, - focusMode: signal('roving'), - }); - - const success = gridFocus.focusCoordinates({row: 1, col: 0}); - - expect(success).toBeTrue(); - expect(activeCoords()).toEqual({row: 1, col: 0}); - expect(cells[1][0].element().focus).toHaveBeenCalled(); - - expect(gridFocus.activeCell()).toBe(cells[1][0]); - expect(gridFocus.prevActiveCoords()).toEqual({row: 0, col: 0}); - }); - - it('should update activeCell and prevActiveCell but not call element.focus in "activedescendant" mode', () => { - const activeCoords = signal({row: 0, col: 0}); - const {gridFocus, cells} = setupGridFocus({ - activeCoords, - focusMode: signal('activedescendant'), - }); - - const success = gridFocus.focusCoordinates({row: 1, col: 0}); - - expect(success).toBeTrue(); - expect(activeCoords()).toEqual({row: 1, col: 0}); - expect(cells[1][0].element().focus).not.toHaveBeenCalled(); - - expect(gridFocus.activeCell()).toBe(cells[1][0]); - expect(gridFocus.prevActiveCoords()).toEqual({row: 0, col: 0}); - }); - }); - - describe('focusCell', () => { - it('should return false and not change state if grid is disabled', () => { - const activeCoords = signal({row: 0, col: 0}); - const {gridFocus, cells} = setupGridFocus({ - activeCoords, - disabled: signal(true), - }); - - const success = gridFocus.focusCell(cells[1][0]); - - expect(success).toBeFalse(); - expect(activeCoords()).toEqual({row: 0, col: 0}); - expect(cells[1][0].element().focus).not.toHaveBeenCalled(); - }); - - it('should return false and not change state if cell is not focusable', () => { - const activeCoords = signal({row: 0, col: 0}); - const {gridFocus, cells} = setupGridFocus({activeCoords}); - cells[1][0].disabled.set(true); - - const success = gridFocus.focusCell(cells[1][0]); - - expect(success).toBeFalse(); - expect(activeCoords()).toEqual({row: 0, col: 0}); - expect(cells[1][0].element().focus).not.toHaveBeenCalled(); - }); - - it('should focus cell, update activeCell and prevActiveCell in "roving" mode', () => { - const activeCoords = signal({row: 0, col: 0}); - const {gridFocus, cells} = setupGridFocus({ - activeCoords, - focusMode: signal('roving'), - }); - - const success = gridFocus.focusCell(cells[1][0]); - - expect(success).toBeTrue(); - expect(activeCoords()).toEqual({row: 1, col: 0}); - expect(cells[1][0].element().focus).toHaveBeenCalled(); - - expect(gridFocus.activeCell()).toBe(cells[1][0]); - expect(gridFocus.prevActiveCoords()).toEqual({row: 0, col: 0}); - }); - - it('should update activeCell and prevActiveCell but not call element.focus in "activedescendant" mode', () => { - const activeCoords = signal({row: 0, col: 0}); - const {gridFocus, cells} = setupGridFocus({ - activeCoords, - focusMode: signal('activedescendant'), - }); - - const success = gridFocus.focusCell(cells[1][0]); - - expect(success).toBeTrue(); - expect(activeCoords()).toEqual({row: 1, col: 0}); - expect(cells[1][0].element().focus).not.toHaveBeenCalled(); - - expect(gridFocus.activeCell()).toBe(cells[1][0]); - expect(gridFocus.prevActiveCoords()).toEqual({row: 0, col: 0}); - }); - }); -}); diff --git a/src/aria/private/behaviors/grid-focus/grid-focus.ts b/src/aria/private/behaviors/grid-focus/grid-focus.ts deleted file mode 100644 index 508026eb9726..000000000000 --- a/src/aria/private/behaviors/grid-focus/grid-focus.ts +++ /dev/null @@ -1,223 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import {computed, signal} from '@angular/core'; -import {SignalLike, WritableSignalLike} from '../signal-like/signal-like'; - -/** Represents an cell in a grid, such as a grid cell, that may receive focus. */ -export interface GridFocusCell { - /** A unique identifier for the cell. */ - id: SignalLike; - - /** The html element that should receive focus. */ - element: SignalLike; - - /** Whether an cell is disabled. */ - disabled: SignalLike; - - /** The number of rows the cell should span. Defaults to 1. */ - rowspan: SignalLike; - - /** The number of columns the cell should span. Defaults to 1. */ - colspan: SignalLike; - - /** The row index of the cell within the grid. */ - rowindex: SignalLike; - - /** The column index of the cell within the grid. */ - colindex: SignalLike; -} - -/** Represents the required inputs for a grid that contains focusable cells. */ -export interface GridFocusInputs { - /** The focus strategy used by the grid. */ - focusMode: SignalLike<'roving' | 'activedescendant'>; - - /** Whether the grid is disabled. */ - disabled: SignalLike; - - /** The cells in the grid, represented as a 2D array (rows and columns). */ - cells: SignalLike; - - /** The coordinates (row and column) of the current active cell. */ - activeCoords: WritableSignalLike; - - /** Whether disabled cells in the grid should be focusable. */ - softDisabled: SignalLike; -} - -/** Represents coordinates in a grid. */ -export interface RowCol { - /** The row index. */ - row: number; - - /** The column index. */ - col: number; -} - -/** Controls focus for a 2D grid of cells. */ -export class GridFocus { - /** The last active cell coordinates. */ - prevActiveCoords = signal({row: 0, col: 0}); - - /** The current active cell based on `activeCoords` coordinates. */ - activeCell = computed(() => this.getCell(this.inputs.activeCoords())); - - /** The number of rows in the grid. */ - rowCount = computed(() => this.inputs.cells().length); - - /** The number of columns in the grid. */ - colCount = computed(() => { - return this.inputs.cells()[0].reduce((count, curr) => count + curr.colspan(), 0); - }); - - constructor(readonly inputs: GridFocusInputs) {} - - /** The id of the current active cell, for ARIA activedescendant. */ - getActiveDescendant(): string | undefined { - if (this.isGridDisabled() || this.inputs.focusMode() === 'roving') { - return undefined; - } - const currentActiveCell = this.activeCell(); - return currentActiveCell ? currentActiveCell.id() : undefined; - } - - /** Whether the grid is in a disabled state. */ - isGridDisabled(): boolean { - if (this.inputs.disabled()) { - return true; - } - const gridCells = this.inputs.cells(); - return gridCells.length === 0 || gridCells.every(row => row.every(cell => cell.disabled())); - } - - /** The tab index for the grid container. */ - getGridTabIndex(): -1 | 0 { - if (this.isGridDisabled()) { - return 0; - } - return this.inputs.focusMode() === 'activedescendant' ? 0 : -1; - } - - /** Returns the tab index for the given grid cell cell. */ - getCellTabIndex(cell: T): -1 | 0 { - if (this.isGridDisabled()) { - return -1; - } - if (this.inputs.focusMode() === 'activedescendant') { - return -1; - } - return this.activeCell() === cell ? 0 : -1; - } - - /** Focuses the given cell. */ - focusCell(cell: T): boolean { - if (this.isGridDisabled()) { - return false; - } - - if (!this.isFocusable(cell)) { - return false; - } - - this.prevActiveCoords.set(this.inputs.activeCoords()); - this.inputs.activeCoords.set({row: cell.rowindex(), col: cell.colindex()}); - this._focus(cell); - - return true; - } - - /** Moves focus to the cell at the given coordinates if it's part of a focusable cell. */ - focusCoordinates(coordinates: RowCol): boolean { - if (this.isGridDisabled()) { - return false; - } - - const cell = this.getCell(coordinates); - - if (!cell || !this.isFocusable(cell)) { - return false; - } - - this.prevActiveCoords.set(this.inputs.activeCoords()); - this.inputs.activeCoords.set(coordinates); - this._focus(cell); - - return true; - } - - /** Handles conditionally calling `focus` on the HTML element of the cell. */ - private _focus(cell: T) { - if (this.inputs.focusMode() === 'roving') { - const element = cell.element(); - if (element && typeof element.focus === 'function') { - element.focus(); - } - } - } - - /** Returns true if the given cell can be navigated to. */ - isFocusable(cell: T): boolean { - return !cell.disabled() || this.inputs.softDisabled(); - } - - /** Finds the top-left anchor coordinates of a given cell instance in the grid. */ - getCoordinates(cellToFind: T): RowCol | void { - const grid = this.inputs.cells(); - const occupiedCells = new Set(); - - for (let rowindex = 0; rowindex < grid.length; rowindex++) { - let colindex = 0; - const gridRow = grid[rowindex]; - - for (const gridCell of gridRow) { - // Skip past cells that are already taken. - while (occupiedCells.has(`${rowindex},${colindex}`)) { - colindex++; - } - - // Check if this is the cell we're looking for. - if (gridCell === cellToFind) { - return {row: rowindex, col: colindex}; - } - - const rowspan = gridCell.rowspan(); - const colspan = gridCell.colspan(); - - // If this cell spans multiple rows, mark those cells as occupied. - if (rowspan > 1) { - for (let rOffset = 1; rOffset < rowspan; rOffset++) { - const spannedRow = rowindex + rOffset; - for (let cOffset = 0; cOffset < colspan; cOffset++) { - const spannedCol = colindex + cOffset; - occupiedCells.add(`${spannedRow},${spannedCol}`); - } - } - } - - colindex += colspan; - } - } - } - - /** Gets the cell that covers the given coordinates, considering rowspan and colspan. */ - getCell(coords: RowCol): T | void { - for (const row of this.inputs.cells()) { - for (const cell of row) { - if ( - coords.row >= cell.rowindex() && - coords.row <= cell.rowindex() + cell.rowspan() - 1 && - coords.col >= cell.colindex() && - coords.col <= cell.colindex() + cell.colspan() - 1 - ) { - return cell; - } - } - } - } -} diff --git a/src/aria/private/behaviors/grid-navigation/BUILD.bazel b/src/aria/private/behaviors/grid-navigation/BUILD.bazel deleted file mode 100644 index eb67f76f4e6d..000000000000 --- a/src/aria/private/behaviors/grid-navigation/BUILD.bazel +++ /dev/null @@ -1,30 +0,0 @@ -load("//tools:defaults.bzl", "ng_project", "ng_web_test_suite", "ts_project") - -package(default_visibility = ["//visibility:public"]) - -ts_project( - name = "grid-navigation", - srcs = ["grid-navigation.ts"], - deps = [ - "//:node_modules/@angular/core", - "//src/aria/private/behaviors/grid-focus", - "//src/aria/private/behaviors/signal-like", - ], -) - -ng_project( - name = "unit_test_sources", - testonly = True, - srcs = ["grid-navigation.spec.ts"], - deps = [ - ":grid-navigation", - "//:node_modules/@angular/core", - "//src/aria/private/behaviors/grid-focus", - "//src/aria/private/behaviors/signal-like", - ], -) - -ng_web_test_suite( - name = "unit_tests", - deps = [":unit_test_sources"], -) diff --git a/src/aria/private/behaviors/grid-navigation/grid-navigation.spec.ts b/src/aria/private/behaviors/grid-navigation/grid-navigation.spec.ts deleted file mode 100644 index ddbd297fca6c..000000000000 --- a/src/aria/private/behaviors/grid-navigation/grid-navigation.spec.ts +++ /dev/null @@ -1,1253 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import {computed, signal, WritableSignalLike} from '../../behaviors/signal-like/signal-like'; -import {GridFocus} from '../grid-focus/grid-focus'; -import {GridNavigation, GridNavigationCell, GridNavigationInputs} from './grid-navigation'; - -type TestGridNav = GridNavigation; - -interface TestCell extends GridNavigationCell { - disabled: WritableSignalLike; -} - -interface TestCellInputs { - rowspan?: number; - colspan?: number; -} - -function createCell(config?: TestCellInputs): TestCell { - const element = document.createElement('div'); - spyOn(element, 'focus').and.callThrough(); - - return { - id: signal(''), - element: signal(element), - disabled: signal(false), - rowindex: signal(0), - colindex: signal(0), - rowspan: signal(config?.rowspan ?? 1), - colspan: signal(config?.colspan ?? 1), - }; -} - -type TestGridNavInputs = Partial> & - Pick, 'cells'>; - -function createGridNav(config: TestGridNavInputs): {gridNav: TestGridNav; cells: TestCell[][]} { - const wrap = signal(true); - const disabled = signal(false); - const softDisabled = signal(true); - const focusMode = signal('roving' as const); - const activeCoords = signal({row: 0, col: 0}); - const wrapBehavior = signal('continuous' as const); - - const gridFocus = new GridFocus({ - disabled, - focusMode, - activeCoords, - softDisabled, - ...config, - }); - - const gridNav = new GridNavigation({ - wrap, - disabled, - focusMode, - activeCoords, - softDisabled, - wrapBehavior, - gridFocus, - ...config, - }); - - for (const row of config.cells()) { - for (const cell of row) { - const coordinates = computed(() => gridFocus.getCoordinates(cell) ?? {row: -1, col: -1}); - cell.rowindex = computed(() => coordinates().row); - cell.colindex = computed(() => coordinates().col); - } - } - - return {gridNav, cells: config.cells()}; -} - -describe('GridNavigation', () => { - /** - * GRID A: - * ┌─────┬─────┬─────┐ - * │ 0,0 │ 0,1 │ 0,2 │ - * ├─────┼─────┼─────┤ - * │ 1,0 │ 1,1 │ 1,2 │ - * ├─────┼─────┼─────┤ - * │ 2,0 │ 2,1 │ 2,2 │ - * └─────┴─────┴─────┘ - */ - let gridA = signal([]); - - /** - * GRID B: - * ┌─────┬─────┬─────┐ - * │ 0,0 │ 0,1 │ 0,2 │ - * ├─────┼─────┤ │ - * │ 1,0 │ 1,1 │ │ - * ├─────┤ ├─────┤ - * │ 2,0 │ │ 2,2 │ - * │ ├─────┼─────┤ - * │ │ 3,1 │ 3,2 │ - * └─────┴─────┴─────┘ - */ - let gridB = signal([]); - - /** - * GRID C: - * ┌───────────┬─────┬─────┐ - * │ 0,0 │ 0,2 │ 0,3 │ - * ├─────┬─────┴─────┼─────┤ - * │ 1,0 │ 1,1 │ 1,3 │ - * ├─────┼─────┬─────┴─────┤ - * │ 2,0 │ 2,1 │ 2,2 │ - * └─────┴─────┴───────────┘ - */ - let gridC = signal([]); - - /** - * GRID D: - * ┌─────┬───────────┬─────┐ - * │ 0,0 │ 0,1 │ 0,3 │ - * │ ├───────────┼─────┤ - * │ │ 1,1 │ 1,3 │ - * ├─────┤ │ │ - * │ 2,0 │ │ │ - * ├─────┼─────┬─────┴─────┤ - * │ 3,0 │ 3,1 │ 3,2 │ - * └─────┴─────┴───────────┘ - */ - let gridD = signal([]); - - beforeEach(() => { - gridA.set([ - [createCell(), createCell(), createCell()], - [createCell(), createCell(), createCell()], - [createCell(), createCell(), createCell()], - ]); - - gridB.set([ - [createCell(), createCell(), createCell({rowspan: 2})], - [createCell(), createCell({rowspan: 2})], - [createCell({rowspan: 2}), createCell()], - [createCell(), createCell()], - ]); - - gridC.set([ - [createCell({colspan: 2}), createCell(), createCell()], - [createCell(), createCell({colspan: 2}), createCell()], - [createCell(), createCell(), createCell({colspan: 2})], - ]); - - gridD.set([ - [createCell({rowspan: 2}), createCell({colspan: 2}), createCell()], - [createCell({rowspan: 2, colspan: 2}), createCell({rowspan: 2})], - [createCell()], - [createCell(), createCell(), createCell({colspan: 2})], - ]); - }); - - describe('up()', () => { - it('should navigate up', () => { - const {gridNav} = createGridNav({ - cells: gridA, - activeCoords: signal({row: 1, col: 1}), - }); - const result = gridNav.up(); - expect(result).toBeTrue(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - - it('(wrap: false) should not wrap', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(false), - activeCoords: signal({row: 0, col: 1}), - }); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - - it('(soft disabled: true) should be able to navigate through disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - softDisabled: signal(true), - activeCoords: signal({row: 1, col: 1}), - }); - cells[0][1].disabled.set(true); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - softDisabled: signal(false), - activeCoords: signal({row: 2, col: 1}), - }); - cells[1][1].disabled.set(true); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - - it('(wrap: false) (soft disabled: false) should not navigate through disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(false), - softDisabled: signal(false), - activeCoords: signal({row: 1, col: 1}), - }); - cells[0][1].disabled.set(true); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('(disabled: true) should not navigate', () => { - const {gridNav} = createGridNav({ - cells: gridA, - disabled: signal(true), - activeCoords: signal({row: 1, col: 1}), - }); - const result = gridNav.up(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - describe('(wrap: true)', () => { - describe('(wrap behavior: loop)', () => { - it('should loop to the last cell of the current column', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 0, col: 1}), - }); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 1}); - }); - - it('should wrap until it finds a cell that is focusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 0, col: 1}), - }); - cells[2][1].disabled.set(true); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('should not navigate if all cells that would be navigated to are unfocusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 0, col: 1}), - }); - cells[1][1].disabled.set(true); - cells[2][1].disabled.set(true); - const result = gridNav.up(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - }); - - describe('(wrap behavior: continuous)', () => { - it('should wrap to the last cell of the previous column', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 0, col: 1}), - }); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 0}); - }); - - it('should wrap to the last cell of the last column', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 0, col: 0}), - }); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - }); - - it('should wrap until it finds a cell that is focusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 0, col: 1}), - }); - - cells[0][0].disabled.set(true); - cells[1][0].disabled.set(true); - cells[2][0].disabled.set(true); - - cells[1][1].disabled.set(true); - cells[2][1].disabled.set(true); - - cells[0][2].disabled.set(true); - cells[2][2].disabled.set(true); - - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - }); - - it('should wrap until it finds a cell that is focusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 0, col: 1}), - }); - - cells[0][0].disabled.set(true); - cells[1][0].disabled.set(true); - cells[2][0].disabled.set(true); - - cells[1][1].disabled.set(true); - cells[2][1].disabled.set(true); - - cells[0][2].disabled.set(true); - cells[0][1].disabled.set(true); - cells[2][2].disabled.set(true); - - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - }); - - it('should not navigate if all cells that would be navigated to are unfocusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 1, col: 1}), - }); - cells[0][0].disabled.set(true); - cells[1][0].disabled.set(true); - cells[2][0].disabled.set(true); - cells[0][1].disabled.set(true); - cells[2][1].disabled.set(true); - cells[0][2].disabled.set(true); - cells[1][2].disabled.set(true); - cells[2][2].disabled.set(true); - - const result = gridNav.up(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - }); - }); - - describe('with rowspan set', () => { - it('should navigate correctly', () => { - const {gridNav} = createGridNav({ - cells: gridB, - activeCoords: signal({row: 3, col: 2}), - }); - - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 3, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 3, col: 2}); - }); - - it('should navigate correctly when in a subcoordinate of a cell', () => { - const {gridNav} = createGridNav({ - cells: gridB, - activeCoords: signal({row: 3, col: 0}), - }); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridB, - softDisabled: signal(false), - activeCoords: signal({row: 2, col: 2}), - }); - cells[0][2].disabled.set(true); - cells[2][0].disabled.set(true); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 3, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - - it('(wrap: false) should navigate correctly when in a subcoordinate of a cell', () => { - const {gridNav} = createGridNav({ - cells: gridB, - wrap: signal(false), - activeCoords: signal({row: 1, col: 2}), - }); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - }); - }); - - describe('with colspan set', () => { - it('should navigate correctly', () => { - const {gridNav} = createGridNav({ - cells: gridC, - activeCoords: signal({row: 2, col: 3}), - }); - - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 3}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 3}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 3}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridC, - softDisabled: signal(false), - activeCoords: signal({row: 1, col: 2}), - }); - cells[0][0].disabled.set(true); - cells[0][1].disabled.set(true); - cells[2][1].disabled.set(true); - - const result = gridNav.up(); - expect(result).toBeTrue(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 3}); - }); - }); - - describe('with rowspan and colspan set', () => { - it('should navigate correctly', () => { - const {gridNav} = createGridNav({ - cells: gridD, - activeCoords: signal({row: 3, col: 3}), - }); - - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 3}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 3}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 3, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 3, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 3, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 3, col: 3}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridD, - softDisabled: signal(false), - activeCoords: signal({row: 3, col: 3}), - }); - - cells[1][0].disabled.set(true); - cells[1][1].disabled.set(true); - - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 3}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 3, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 3, col: 1}); - gridNav.up(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - }); - }); - - describe('down()', () => { - it('should navigate down', () => { - const {gridNav} = createGridNav({ - cells: gridA, - activeCoords: signal({row: 1, col: 1}), - }); - const result = gridNav.down(); - expect(result).toBeTrue(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 1}); - }); - - it('(wrap: false) should not wrap', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(false), - activeCoords: signal({row: 2, col: 1}), - }); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 1}); - }); - - it('(soft disabled: true) should be able to navigate through disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - softDisabled: signal(true), - activeCoords: signal({row: 1, col: 1}), - }); - cells[2][1].disabled.set(true); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 1}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - softDisabled: signal(false), - activeCoords: signal({row: 0, col: 1}), - }); - cells[1][1].disabled.set(true); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 1}); - }); - - it('(wrap: false) (soft disabled: false) should not navigate through disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(false), - softDisabled: signal(false), - activeCoords: signal({row: 1, col: 1}), - }); - cells[2][1].disabled.set(true); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('(disabled: true) should not navigate', () => { - const {gridNav} = createGridNav({ - cells: gridA, - disabled: signal(true), - activeCoords: signal({row: 1, col: 1}), - }); - const result = gridNav.down(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - describe('(wrap: true)', () => { - describe('(wrap behavior: loop)', () => { - it('should loop to the first cell of the current column', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 2, col: 1}), - }); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - - it('should wrap until it finds a cell that is focusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 2, col: 1}), - }); - cells[0][1].disabled.set(true); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('should not navigate if all cells that would be navigated to are unfocusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 2, col: 1}), - }); - cells[0][1].disabled.set(true); - cells[1][1].disabled.set(true); - const result = gridNav.down(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 1}); - }); - }); - - describe('(wrap behavior: continuous)', () => { - it('should wrap to the first cell of the next column', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 2, col: 1}), - }); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - }); - - it('should wrap until it finds a cell that is focusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 2, col: 1}), - }); - - cells[0][2].disabled.set(true); - cells[1][2].disabled.set(true); - - gridNav.down(); - // Should land on (2,2) - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - }); - - it('should not navigate if all cells that would be navigated to are unfocusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 1, col: 1}), - }); - cells[0][0].disabled.set(true); - cells[1][0].disabled.set(true); - cells[2][0].disabled.set(true); - cells[0][1].disabled.set(true); - cells[2][1].disabled.set(true); - cells[0][2].disabled.set(true); - cells[1][2].disabled.set(true); - cells[2][2].disabled.set(true); - - const result = gridNav.down(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('should wrap to the first cell of the first column', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 2, col: 2}), - }); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - }); - }); - }); - - describe('with rowspan set', () => { - it('should navigate correctly', () => { - const {gridNav} = createGridNav({ - cells: gridB, - activeCoords: signal({row: 0, col: 0}), - }); - - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 0}); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - - it('should navigate correctly when in a subcoordinate of a cell', () => { - const {gridNav} = createGridNav({ - cells: gridB, - activeCoords: signal({row: 1, col: 2}), - }); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridB, - softDisabled: signal(false), - activeCoords: signal({row: 0, col: 0}), - }); - cells[1][0].disabled.set(true); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 0}); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - - it('(wrap: false) should navigate correctly when in a subcoordinate of a cell', () => { - const {gridNav} = createGridNav({ - cells: gridB, - wrap: signal(false), - activeCoords: signal({row: 0, col: 2}), - }); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - }); - }); - - describe('with colspan set', () => { - // For `down()`, colspan doesn't affect vertical navigation as much as rowspan. - // Basic navigation should still work. - it('should navigate correctly', () => { - const {gridNav} = createGridNav({cells: gridC, activeCoords: signal({row: 0, col: 0})}); - gridNav.down(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - }); - }); - - describe('left()', () => { - it('should navigate left', () => { - const {gridNav} = createGridNav({ - cells: gridA, - activeCoords: signal({row: 1, col: 1}), - }); - const result = gridNav.left(); - expect(result).toBeTrue(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - - it('(wrap: false) should not wrap', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(false), - activeCoords: signal({row: 1, col: 0}), - }); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - - it('(soft disabled: true) should be able to navigate through disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - softDisabled: signal(true), - activeCoords: signal({row: 1, col: 1}), - }); - cells[1][0].disabled.set(true); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - softDisabled: signal(false), - activeCoords: signal({row: 1, col: 2}), - }); - cells[1][1].disabled.set(true); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - - it('(wrap: false) (soft disabled: false) should not navigate through disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(false), - softDisabled: signal(false), - activeCoords: signal({row: 1, col: 1}), - }); - cells[1][0].disabled.set(true); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('(disabled: true) should not navigate', () => { - const {gridNav} = createGridNav({ - cells: gridA, - disabled: signal(true), - activeCoords: signal({row: 1, col: 1}), - }); - const result = gridNav.left(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - describe('(wrap: true)', () => { - describe('(wrap behavior: loop)', () => { - it('should loop to the last cell of the current row', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 1, col: 0}), - }); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - }); - - it('should wrap until it finds a cell that is focusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 1, col: 0}), - }); - cells[1][2].disabled.set(true); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('should not navigate if all cells that would be navigated to are unfocusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 1, col: 0}), - }); - cells[1][2].disabled.set(true); - cells[1][1].disabled.set(true); - const result = gridNav.left(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - }); - - describe('(wrap behavior: continuous)', () => { - it('should wrap to the last cell of the previous row', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 1, col: 0}), - }); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - }); - - it('should wrap until it finds a cell that is focusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 1, col: 0}), - }); - - cells[0][2].disabled.set(true); - cells[0][1].disabled.set(true); - - gridNav.left(); - // Should land on (0,0) - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - }); - - it('should not navigate if all cells that would be navigated to are unfocusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 1, col: 1}), - }); - cells[0][0].disabled.set(true); - cells[1][0].disabled.set(true); - cells[2][0].disabled.set(true); - cells[0][1].disabled.set(true); - cells[2][1].disabled.set(true); - cells[0][2].disabled.set(true); - cells[1][2].disabled.set(true); - cells[2][2].disabled.set(true); - const result = gridNav.left(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('should wrap to the last cell of the last row', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 0, col: 0}), - }); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - }); - }); - }); - - describe('with rowspan set', () => { - // For `left()`, rowspan doesn't affect horizontal navigation as much as colspan. - // Basic navigation should still work. - it('should navigate correctly', () => { - const {gridNav} = createGridNav({cells: gridB, activeCoords: signal({row: 0, col: 1})}); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - }); - }); - - describe('with colspan set', () => { - it('should navigate correctly', () => { - const {gridNav} = createGridNav({ - cells: gridC, - activeCoords: signal({row: 0, col: 3}), - }); - - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - }); - - it('should navigate correctly when in a subcoordinate of a cell', () => { - const {gridNav} = createGridNav({ - cells: gridC, - activeCoords: signal({row: 0, col: 1}), - }); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridC, - softDisabled: signal(false), - activeCoords: signal({row: 0, col: 3}), - }); - - cells[0][1].disabled.set(true); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - }); - - it('(wrap: false) should navigate correctly when in a subcoordinate of a cell', () => { - const {gridNav} = createGridNav({ - cells: gridC, - wrap: signal(false), - activeCoords: signal({row: 0, col: 1}), - }); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - }); - }); - - describe('with rowspan and colspan set', () => { - it('should navigate correctly', () => { - const {gridNav} = createGridNav({ - cells: gridD, - activeCoords: signal({row: 0, col: 3}), - }); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - gridNav.left(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - }); - }); - }); - - describe('right()', () => { - it('should navigate right', () => { - const {gridNav} = createGridNav({ - cells: gridA, - activeCoords: signal({row: 1, col: 1}), - }); - const result = gridNav.right(); - expect(result).toBeTrue(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - }); - - it('(wrap: false) should not wrap', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(false), - activeCoords: signal({row: 1, col: 2}), - }); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - }); - - it('(soft disabled: true) should be able to navigate through disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - softDisabled: signal(true), - activeCoords: signal({row: 1, col: 1}), - }); - cells[1][2].disabled.set(true); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - softDisabled: signal(false), - activeCoords: signal({row: 1, col: 0}), - }); - cells[1][1].disabled.set(true); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - }); - - it('(wrap: false) (soft disabled: false) should not navigate through disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(false), - softDisabled: signal(false), - activeCoords: signal({row: 1, col: 1}), - }); - cells[1][2].disabled.set(true); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('(disabled: true) should not navigate', () => { - const {gridNav} = createGridNav({ - cells: gridA, - disabled: signal(true), - activeCoords: signal({row: 1, col: 1}), - }); - const result = gridNav.right(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - describe('(wrap: true)', () => { - describe('(wrap behavior: loop)', () => { - it('should loop to the first cell of the current row', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 1, col: 2}), - }); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - - it('should wrap until it finds a cell that is focusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 1, col: 2}), - }); - cells[1][0].disabled.set(true); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('should not navigate if all cells that would be navigated to are unfocusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('loop'), - activeCoords: signal({row: 1, col: 2}), - }); - cells[1][0].disabled.set(true); - cells[1][1].disabled.set(true); - const result = gridNav.right(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 2}); - }); - }); - - describe('(wrap behavior: continuous)', () => { - it('should wrap to the first cell of the next row', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 1, col: 2}), - }); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 0}); - }); - - it('should wrap until it finds a cell that is focusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 1, col: 2}), - }); - - cells[2][0].disabled.set(true); - cells[2][1].disabled.set(true); - - gridNav.right(); - // Should land on (2,2) - expect(gridNav.inputs.activeCoords()).toEqual({row: 2, col: 2}); - }); - - it('should not navigate if all cells that would be navigated to are unfocusable', () => { - const {gridNav, cells} = createGridNav({ - cells: gridA, - wrap: signal(true), - softDisabled: signal(false), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 1, col: 1}), - }); - cells[0][0].disabled.set(true); - cells[1][0].disabled.set(true); - cells[2][0].disabled.set(true); - cells[0][1].disabled.set(true); - cells[2][1].disabled.set(true); - cells[0][2].disabled.set(true); - cells[1][2].disabled.set(true); - cells[2][2].disabled.set(true); - const result = gridNav.right(); - expect(result).toBeFalse(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 1}); - }); - - it('should wrap to the first cell of the first row', () => { - const {gridNav} = createGridNav({ - cells: gridA, - wrap: signal(true), - wrapBehavior: signal('continuous'), - activeCoords: signal({row: 2, col: 2}), - }); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 0}); - }); - }); - }); - - describe('with rowspan set', () => { - // For `right()`, rowspan doesn't affect horizontal navigation as much as colspan. - // Basic navigation should still work. - it('should navigate correctly', () => { - const {gridNav} = createGridNav({cells: gridB, activeCoords: signal({row: 0, col: 0})}); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - }); - }); - - describe('with colspan set', () => { - it('should navigate correctly', () => { - const {gridNav} = createGridNav({ - cells: gridC, - activeCoords: signal({row: 0, col: 0}), - }); - - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 3}); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 1, col: 0}); - }); - - it('should navigate correctly when in a subcoordinate of a cell', () => { - const {gridNav} = createGridNav({ - cells: gridC, - activeCoords: signal({row: 0, col: 1}), - }); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - }); - - it('(soft disabled: false) should skip disabled cells', () => { - const {gridNav, cells} = createGridNav({ - cells: gridC, - softDisabled: signal(false), - activeCoords: signal({row: 0, col: 0}), - }); - cells[0][1].disabled.set(true); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 3}); - }); - - it('(wrap: false) should navigate correctly when in a subcoordinate of a cell', () => { - const {gridNav} = createGridNav({ - cells: gridC, - wrap: signal(false), - activeCoords: signal({row: 0, col: 1}), - }); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 2}); - }); - }); - - describe('with rowspan and colspan set', () => { - it('should navigate correctly', () => { - const {gridNav} = createGridNav({ - cells: gridD, - activeCoords: signal({row: 0, col: 0}), - }); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 1}); - gridNav.right(); - expect(gridNav.inputs.activeCoords()).toEqual({row: 0, col: 3}); - }); - }); - }); -}); diff --git a/src/aria/private/behaviors/grid-navigation/grid-navigation.ts b/src/aria/private/behaviors/grid-navigation/grid-navigation.ts deleted file mode 100644 index 62cce7975bcf..000000000000 --- a/src/aria/private/behaviors/grid-navigation/grid-navigation.ts +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import {SignalLike} from '../signal-like/signal-like'; -import {GridFocus, GridFocusCell, GridFocusInputs, RowCol} from '../grid-focus/grid-focus'; -import {computed} from '@angular/core'; - -/** Represents an item in a collection, such as a listbox option, than can be navigated to. */ -export interface GridNavigationCell extends GridFocusCell {} - -/** Represents the required inputs for a collection that has navigable items. */ -export interface GridNavigationInputs extends GridFocusInputs { - gridFocus: GridFocus; - wrap: SignalLike; - wrapBehavior: SignalLike<'continuous' | 'loop'>; -} - -/** Controls navigation for a grid of items. */ -export class GridNavigation { - rowcount = computed(() => this.inputs.gridFocus.rowCount()); - colcount = computed(() => this.inputs.gridFocus.colCount()); - - constructor(readonly inputs: GridNavigationInputs) {} - - /** Navigates to the given item. */ - gotoCell(cell?: T): boolean { - return cell ? this.inputs.gridFocus.focusCell(cell) : false; - } - - /** Navigates to the given coordinates. */ - gotoCoords(coords: RowCol): boolean { - return this.inputs.gridFocus.focusCoordinates(coords); - } - - /** Navigates to the item above the current item. */ - up(): boolean { - return this._advance((cell: T, {col}: RowCol) => { - const rowindex = cell.rowindex(); - const isRowWrapping = this.inputs.wrap() && rowindex - 1 < 0; - const isColumnWrapping = isRowWrapping && this.inputs.wrapBehavior() === 'continuous'; - - const nextCoords = { - row: isRowWrapping - ? (rowindex - 1 + this.rowcount()) % this.rowcount() - : Math.max(rowindex - 1, 0), - col: isColumnWrapping ? (col - 1 + this.colcount()) % this.colcount() : col, - }; - - const nextCell = this.inputs.gridFocus.getCell(nextCoords)!; - - return { - row: nextCell.rowindex(), - col: nextCoords.col, - }; - }); - } - - /** Navigates to the item below the current item. */ - down(): boolean { - return this._advance((cell: T, {col}: RowCol) => { - const rowspan = cell.rowspan(); - const rowindex = cell.rowindex(); - const isRowWrapping = this.inputs.wrap() && rowindex + rowspan >= this.rowcount(); - const isColumnWrapping = isRowWrapping && this.inputs.wrapBehavior() === 'continuous'; - - return { - row: isRowWrapping - ? (rowindex + rowspan) % this.rowcount() - : Math.min(rowindex + rowspan, this.rowcount() - 1), - col: isColumnWrapping ? (col + 1 + this.colcount()) % this.colcount() : col, - }; - }); - } - - /** Navigates to the item to the left of the current item. */ - left(): boolean { - return this._advance((cell: T, {row, col}: RowCol) => { - const colindex = cell.colindex(); - const isColumnWrapping = this.inputs.wrap() && colindex - 1 < 0; - const isRowWrapping = isColumnWrapping && this.inputs.wrapBehavior() === 'continuous'; - - const nextCoords = { - row: isRowWrapping ? (row - 1 + this.rowcount()) % this.rowcount() : row, - col: isColumnWrapping - ? (colindex - 1 + this.colcount()) % this.colcount() - : Math.max(colindex - 1, 0), - }; - - const nextCell = this.inputs.gridFocus.getCell(nextCoords)!; - - return { - row: nextCoords.row, - col: nextCell.colindex(), - }; - }); - } - - /** Navigates to the item to the right of the current item. */ - right(): boolean { - return this._advance((cell: T, {row}: RowCol) => { - const colspan = cell.colspan(); - const colindex = cell.colindex(); - const isColumnWrapping = this.inputs.wrap() && colindex + colspan >= this.colcount(); - const isRowWrapping = isColumnWrapping && this.inputs.wrapBehavior() === 'continuous'; - - return { - row: isRowWrapping ? (row + 1 + this.rowcount()) % this.rowcount() : row, - col: isColumnWrapping - ? (colindex + colspan + this.colcount()) % this.colcount() - : Math.min(colindex + colspan, this.colcount() - 1), - }; - }); - } - - /** - * Continuously calls the given stepFn starting at the given coordinates - * until either a new focusable cell is reached or the grid fully loops. - */ - private _advance(stepFn: (cell: T, coords: RowCol) => RowCol) { - const startCoords = this.inputs.activeCoords(); - let prevCoords = {row: startCoords.row, col: startCoords.col}; - let nextCoords = {row: startCoords.row, col: startCoords.col}; - let nextCell = this.inputs.gridFocus.activeCell()!; - - while (true) { - prevCoords = {row: nextCoords.row, col: nextCoords.col}; - nextCoords = stepFn(nextCell, nextCoords); - - // The step did not result in any change in coordinates. - // - // This will happen if the user is at a boundary (start/end row or col) - // and tries to advance past it while `wrap` is false. - if (nextCoords.row === prevCoords.row && nextCoords.col === prevCoords.col) { - return false; - } - - // The step has resulted in arriving back to the original coordinates. - // - // This will happen if the other cells in the grid are unfocusable and `wrap` - // is true. The `stepFn` will eventually loop all the way back to the original cells. - if (nextCoords.row === startCoords.row && nextCoords.col === startCoords.col) { - return false; - } - - nextCell = this.inputs.gridFocus.getCell(nextCoords)!; - - // The `stepFn` has successfully reached a cell that is focusable. - if (this.inputs.gridFocus.isFocusable(nextCell)) { - return this.gotoCoords(nextCoords); - } - } - } -} From 345c543dcb8cf5869930ffdec37a3101483eddd8 Mon Sep 17 00:00:00 2001 From: Cheng-Hsuan Tsai Date: Thu, 5 Mar 2026 10:45:20 -0800 Subject: [PATCH 025/123] fix(aria/grid): unit tests and small fixes for grid directives (#32841) (cherry picked from commit 72498b49431d7afb67fe78f97ea7adc07191bf63) --- goldens/aria/private/index.api.md | 1 + src/aria/grid/BUILD.bazel | 23 +- src/aria/grid/grid-cell-widget.ts | 1 + src/aria/grid/grid-cell.ts | 2 +- src/aria/grid/grid.spec.ts | 1074 +++++++++++++++++++++++++++++ src/aria/grid/grid.ts | 1 + src/aria/private/grid/grid.ts | 9 +- src/aria/private/grid/widget.ts | 4 +- 8 files changed, 1109 insertions(+), 6 deletions(-) create mode 100644 src/aria/grid/grid.spec.ts diff --git a/goldens/aria/private/index.api.md b/goldens/aria/private/index.api.md index 3635c307d839..1125a5dda649 100644 --- a/goldens/aria/private/index.api.md +++ b/goldens/aria/private/index.api.md @@ -421,6 +421,7 @@ export class GridPattern { readonly inputs: GridInputs; readonly isFocused: WritableSignalLike; readonly keydown: SignalLike>; + readonly multiSelectable: SignalLike; readonly nextColKey: SignalLike<"ArrowRight" | "ArrowLeft">; onFocusIn(event: FocusEvent): void; onFocusOut(event: FocusEvent): void; diff --git a/src/aria/grid/BUILD.bazel b/src/aria/grid/BUILD.bazel index c03e388e1e9e..085b3c9305c6 100644 --- a/src/aria/grid/BUILD.bazel +++ b/src/aria/grid/BUILD.bazel @@ -1,4 +1,4 @@ -load("//tools:defaults.bzl", "extract_api_to_json", "ng_project") +load("//tools:defaults.bzl", "extract_api_to_json", "ng_project", "ng_web_test_suite") package(default_visibility = ["//visibility:public"]) @@ -16,6 +16,27 @@ ng_project( ], ) +ng_project( + name = "unit_test_sources", + testonly = True, + srcs = glob( + ["**/*.spec.ts"], + exclude = ["**/*.e2e.spec.ts"], + ), + deps = [ + ":grid", + "//:node_modules/@angular/core", + "//:node_modules/@angular/platform-browser", + "//:node_modules/axe-core", + "//src/cdk/testing/private", + ], +) + +ng_web_test_suite( + name = "unit_tests", + deps = [":unit_test_sources"], +) + filegroup( name = "source-files", srcs = glob( diff --git a/src/aria/grid/grid-cell-widget.ts b/src/aria/grid/grid-cell-widget.ts index f4402f8fbd50..4cf9312e84eb 100644 --- a/src/aria/grid/grid-cell-widget.ts +++ b/src/aria/grid/grid-cell-widget.ts @@ -46,6 +46,7 @@ import {GRID_CELL} from './grid-tokens'; '[attr.data-active]': 'active()', '[attr.data-active-control]': 'isActivated() ? "widget" : "cell"', '[tabindex]': '_tabIndex()', + '[attr.id]': 'id()', }, }) export class GridCellWidget { diff --git a/src/aria/grid/grid-cell.ts b/src/aria/grid/grid-cell.ts index 16820bd35940..2148a58723dd 100644 --- a/src/aria/grid/grid-cell.ts +++ b/src/aria/grid/grid-cell.ts @@ -135,7 +135,7 @@ export class GridCell { toggle('role', this.role()); toggle('id', pattern.id()); toggle('rowspan', rowSpan); - toggle('colspan', rowSpan); + toggle('colspan', colSpan); toggle('aria-rowspan', rowSpan); toggle('aria-colspan', colSpan); toggle('data-active', this.active()); diff --git a/src/aria/grid/grid.spec.ts b/src/aria/grid/grid.spec.ts new file mode 100644 index 000000000000..62ee745bb921 --- /dev/null +++ b/src/aria/grid/grid.spec.ts @@ -0,0 +1,1074 @@ +import {Component, DebugElement, signal} from '@angular/core'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {By} from '@angular/platform-browser'; +import {Grid} from './grid'; +import {GridRow} from './grid-row'; +import {GridCell} from './grid-cell'; +import {GridCellWidget} from './grid-cell-widget'; + +interface ModifierKeys { + ctrlKey?: boolean; + shiftKey?: boolean; + altKey?: boolean; + metaKey?: boolean; +} + +interface WidgetConfig { + id?: string; + type?: 'simple' | 'complex' | 'editable'; + disabled?: boolean; + tabindex?: number; + hasTarget?: boolean; +} + +interface CellConfig { + id: string; + disabled?: boolean; + role?: 'gridcell' | 'columnheader' | 'rowheader'; + rowIndex?: number; + colIndex?: number; + rowSpan?: number; + colSpan?: number; + selectable?: boolean; + widgets?: WidgetConfig[]; +} + +interface RowConfig { + rowIndex?: number; + cells: CellConfig[]; +} + +function createGridData(): RowConfig[] { + return Array.from({length: 3}, (_, rIndex) => ({ + cells: Array.from({length: 3}, (_, cIndex) => ({ + id: `c${rIndex}-${cIndex}`, + })), + })); +} + +describe('Grid directives', () => { + let fixture: ComponentFixture; + let gridDebugElement: DebugElement; + let gridElement: HTMLElement; + let gridInstance: Grid; + + const keydown = (key: string, modifierKeys: ModifierKeys = {}) => { + const event = new KeyboardEvent('keydown', {key, bubbles: true, ...modifierKeys}); + gridElement.dispatchEvent(event); + fixture.detectChanges(); + }; + + const pointerDown = (target: HTMLElement, eventInit: PointerEventInit = {}) => { + target.dispatchEvent(new PointerEvent('pointerdown', {bubbles: true, ...eventInit})); + fixture.detectChanges(); + }; + + const pointerMove = (target: HTMLElement | Window, eventInit: PointerEventInit = {}) => { + target.dispatchEvent(new PointerEvent('pointermove', {bubbles: true, ...eventInit})); + fixture.detectChanges(); + }; + + const pointerUp = (target: HTMLElement | Window, eventInit: PointerEventInit = {}) => { + target.dispatchEvent(new PointerEvent('pointerup', {bubbles: true, ...eventInit})); + fixture.detectChanges(); + }; + + const up = (modifierKeys?: ModifierKeys) => keydown('ArrowUp', modifierKeys); + const down = (modifierKeys?: ModifierKeys) => keydown('ArrowDown', modifierKeys); + const left = (modifierKeys?: ModifierKeys) => keydown('ArrowLeft', modifierKeys); + const right = (modifierKeys?: ModifierKeys) => keydown('ArrowRight', modifierKeys); + const home = (modifierKeys?: ModifierKeys) => keydown('Home', modifierKeys); + const end = (modifierKeys?: ModifierKeys) => keydown('End', modifierKeys); + const enter = (modifierKeys?: ModifierKeys) => keydown('Enter', modifierKeys); + const space = (modifierKeys?: ModifierKeys) => keydown(' ', modifierKeys); + + const tabIntoGrid = () => { + const focusableElement = gridElement.querySelector('[tabindex="0"]') as HTMLElement; + focusableElement?.focus(); + fixture.detectChanges(); + }; + + function getActiveCellId(): string | null { + if (fixture.componentInstance.focusMode() === 'roving') { + const activeEl = gridElement.querySelector('[tabindex="0"]'); + return activeEl ? activeEl.id : null; + } + return gridElement.getAttribute('aria-activedescendant'); + } + + function setupGrid(opts?: { + disabled?: boolean; + multi?: boolean; + rowWrap?: 'continuous' | 'loop' | 'nowrap'; + colWrap?: 'continuous' | 'loop' | 'nowrap'; + focusMode?: 'roving' | 'activedescendant'; + softDisabled?: boolean; + enableSelection?: boolean; + selectionMode?: 'follow' | 'explicit'; + enableRangeSelection?: boolean; + gridData?: RowConfig[]; + }) { + TestBed.resetTestingModule(); + TestBed.configureTestingModule({}); + fixture = TestBed.createComponent(GridTestComponent); + const testComponent = fixture.componentInstance; + + if (opts?.disabled !== undefined) testComponent.disabled.set(opts.disabled); + if (opts?.multi !== undefined) testComponent.multi.set(opts.multi); + if (opts?.rowWrap !== undefined) testComponent.rowWrap.set(opts.rowWrap); + if (opts?.colWrap !== undefined) testComponent.colWrap.set(opts.colWrap); + if (opts?.focusMode !== undefined) testComponent.focusMode.set(opts.focusMode); + if (opts?.softDisabled !== undefined) testComponent.softDisabled.set(opts.softDisabled); + if (opts?.enableSelection !== undefined) + testComponent.enableSelection.set(opts.enableSelection); + if (opts?.selectionMode !== undefined) testComponent.selectionMode.set(opts.selectionMode); + if (opts?.enableRangeSelection !== undefined) + testComponent.enableRangeSelection.set(opts.enableRangeSelection); + + if (opts?.gridData !== undefined) { + testComponent.gridData.set(opts.gridData); + } else { + testComponent.gridData.set(createGridData()); + } + + fixture.detectChanges(); + gridDebugElement = fixture.debugElement.query(By.directive(Grid)); + gridElement = gridDebugElement.nativeElement; + gridInstance = gridDebugElement.injector.get(Grid); + } + + describe('Grid', () => { + describe('ARIA attributes and roles', () => { + it('should set role="grid" on the host element', () => { + setupGrid(); + expect(gridElement.getAttribute('role')).toBe('grid'); + }); + + it('should set aria-disabled="true" when the disabled input is true', () => { + setupGrid({disabled: true}); + expect(gridElement.getAttribute('aria-disabled')).toBe('true'); + }); + + it('should set aria-disabled="false" when the disabled input is false', () => { + setupGrid({disabled: false}); + expect(gridElement.getAttribute('aria-disabled')).toBe('false'); + }); + + it('should set aria-multiselectable="true" when the multi input is true', () => { + setupGrid({enableSelection: true, multi: true}); + expect(gridElement.getAttribute('aria-multiselectable')).toBe('true'); + }); + + it('should set aria-multiselectable="false" when the multi input is false', () => { + setupGrid({enableSelection: true, multi: false}); + expect(gridElement.getAttribute('aria-multiselectable')).toBe('false'); + }); + + it('should set aria-activedescendant to the active cell id', () => { + setupGrid({focusMode: 'activedescendant'}); + // Simulate gaining focus so active Descendant gets populated + gridElement.dispatchEvent(new Event('focusin')); + fixture.detectChanges(); + expect(gridElement.getAttribute('aria-activedescendant')).toBe('c0-0'); + }); + }); + + describe('focus management', () => { + it('should set tabindex based on the pattern tabIndex', () => { + setupGrid({focusMode: 'roving'}); + expect(gridElement.getAttribute('tabindex')).toBe('-1'); // roving defaults to -1 on host + + setupGrid({focusMode: 'activedescendant'}); + expect(gridElement.getAttribute('tabindex')).toBe('0'); // activedescendant defaults to 0 on host + }); + + it('should activate the cell when the grid receives focusin', () => { + setupGrid(); + + // Let effect run to set default state which sets initial active cell + gridInstance._pattern.setDefaultStateEffect(); + + const cell1 = fixture.debugElement.query(By.directive(GridCell)).nativeElement; + + // Dispatch focusin to the cell + cell1.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + expect(gridInstance._pattern.activeCell()?.element()).toBe(cell1); + expect(gridInstance._pattern.isFocused()).toBeTrue(); + }); + + it('should deactivate the grid when focusout moves outside the grid', () => { + setupGrid(); + const cell1 = fixture.debugElement.query(By.directive(GridCell)).nativeElement; + + // Focus first + + gridInstance._pattern.setDefaultStateEffect(); + cell1.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + expect(gridInstance._pattern.isFocused()).toBeTrue(); + + // Focusout (blur) + // Add relatedTarget so we simulate moving focus out completely, otherwise the target doesn't update correctly + const focusOutEvent = new FocusEvent('focusout', { + bubbles: true, + relatedTarget: document.body, + }); + cell1.dispatchEvent(focusOutEvent); + fixture.detectChanges(); + + expect(gridInstance._pattern.isFocused()).toBeFalse(); + }); + }); + + describe('keyboard interactions', () => { + describe('navigation keys', () => { + beforeEach(() => { + setupGrid(); + // Let effect run to set default state which sets initial active cell + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + // Start interactions from the middle cell (c1-1) + const centerCell = gridElement.querySelector('#c1-1') as HTMLElement; + centerCell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + }); + + it('should move focus up to the previous row on ArrowUp', () => { + up(); + + expect(getActiveCellId()).toBe('c0-1'); + }); + + it('should move focus down to the next row on ArrowDown', () => { + down(); + + expect(getActiveCellId()).toBe('c2-1'); + }); + + it('should move focus left to the previous column on ArrowLeft', () => { + left(); + + expect(getActiveCellId()).toBe('c1-0'); + }); + + it('should move focus right to the next column on ArrowRight', () => { + right(); + + expect(getActiveCellId()).toBe('c1-2'); + }); + + it('should move focus to the first cell in the row on Home', () => { + home(); + + expect(getActiveCellId()).toBe('c1-0'); + }); + + it('should move focus to the last cell in the row on End', () => { + end(); + + expect(getActiveCellId()).toBe('c1-2'); + }); + + describe('colWrap configuration', () => { + it('should wrap to next row when moving right from last column of a row', () => { + setupGrid({colWrap: 'continuous'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-2') as HTMLElement; + cell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + right(); + expect(getActiveCellId()).toBe('c2-0'); + }); + + it('should wrap to previous row when moving left from first column of a row', () => { + setupGrid({colWrap: 'continuous'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-0') as HTMLElement; + cell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + left(); + expect(getActiveCellId()).toBe('c0-2'); + }); + + it('should not wrap to next row when passing row boundaries if colWrap is nowrap', () => { + setupGrid({colWrap: 'nowrap'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-2') as HTMLElement; + cell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + right(); + expect(getActiveCellId()).toBe('c1-2'); + }); + + it('should wrap around the same row when passing row boundaries if colWrap is loop', () => { + setupGrid({colWrap: 'loop'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-2') as HTMLElement; + cell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + right(); + expect(getActiveCellId()).toBe('c1-0'); + }); + }); + + describe('rowWrap configuration', () => { + it('should wrap to next column when moving down from last row of a column', () => { + setupGrid({rowWrap: 'continuous'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c2-1') as HTMLElement; + cell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + down(); + expect(getActiveCellId()).toBe('c0-2'); + }); + + it('should wrap to previous column when moving up from first row of a column', () => { + setupGrid({rowWrap: 'continuous'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c0-1') as HTMLElement; + cell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + up(); + expect(getActiveCellId()).toBe('c2-0'); + }); + + it('should not wrap to next column when passing column boundaries if rowWrap is nowrap', () => { + setupGrid({rowWrap: 'nowrap'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c2-1') as HTMLElement; + cell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + down(); + expect(getActiveCellId()).toBe('c2-1'); + }); + + it('should wrap around the same column when passing column boundaries if rowWrap is loop', () => { + setupGrid({rowWrap: 'loop'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c2-1') as HTMLElement; + cell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + down(); + expect(getActiveCellId()).toBe('c0-1'); + }); + }); + }); + + describe('selection keys', () => { + describe('selectionMode="explicit"', () => { + beforeEach(() => { + setupGrid({ + enableSelection: true, + selectionMode: 'explicit', + multi: true, + enableRangeSelection: true, + }); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + // Start interactions from the middle cell + const centerCell = gridElement.querySelector('#c1-1') as HTMLElement; + centerCell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + }); + + it('should toggle selection of the active cell on Space', () => { + const centerCell = gridElement.querySelector('#c1-1') as HTMLElement; + + expect(centerCell.getAttribute('aria-selected')).toBe('false'); + + space(); + + expect(centerCell.getAttribute('aria-selected')).toBe('true'); + + space(); + + expect(centerCell.getAttribute('aria-selected')).toBe('false'); + }); + + it('should trigger default action of the active cell on Enter', () => { + const centerCell = gridElement.querySelector('#c1-1') as HTMLElement; + + expect(centerCell.getAttribute('aria-selected')).toBe('false'); + + enter(); + + expect(centerCell.getAttribute('aria-selected')).toBe('true'); + + enter(); + + expect(centerCell.getAttribute('aria-selected')).toBe('false'); + }); + + it('should select all selectable cells on Ctrl+A', () => { + keydown('a', {ctrlKey: true}); + + const cells = gridElement.querySelectorAll('[ngGridCell]'); + for (let i = 0; i < cells.length; i++) { + expect(cells[i].getAttribute('aria-selected')).toBe('true'); + } + + keydown('a', {ctrlKey: true}); + + for (let i = 0; i < cells.length; i++) { + expect(cells[i].getAttribute('aria-selected')).toBe('false'); + } + }); + }); + + describe('selectionMode="follow"', () => { + beforeEach(() => { + setupGrid({ + enableSelection: true, + selectionMode: 'follow', + multi: false, + }); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + // Start interactions from the middle cell + const centerCell = gridElement.querySelector('#c1-1') as HTMLElement; + centerCell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + }); + + it('should select an item when navigated to with Arrow keys and deselect others', () => { + const centerCell = gridElement.querySelector('#c1-1') as HTMLElement; + const topCell = gridElement.querySelector('#c0-1') as HTMLElement; + + // Focus does not select by itself + expect(centerCell.getAttribute('aria-selected')).toBe('false'); + expect(topCell.getAttribute('aria-selected')).toBe('false'); + + up(); + + // Arrow keys select the target + expect(centerCell.getAttribute('aria-selected')).toBe('false'); + expect(topCell.getAttribute('aria-selected')).toBe('true'); + + down(); + + expect(topCell.getAttribute('aria-selected')).toBe('false'); + expect(centerCell.getAttribute('aria-selected')).toBe('true'); + }); + }); + }); + }); + + describe('pointer interactions', () => { + beforeEach(() => { + setupGrid({ + enableSelection: true, + selectionMode: 'explicit', + multi: true, + enableRangeSelection: true, + }); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + }); + + it('should focus and select the clicked cell on pointerdown', () => { + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + expect(cell.getAttribute('aria-selected')).toBe('false'); + + pointerDown(cell); + + expect(cell.getAttribute('aria-selected')).toBe('true'); + expect(getActiveCellId()).toBe('c1-1'); + }); + + it('should expand selection on pointermove while dragging without changing active cell', () => { + const startCell = gridElement.querySelector('#c0-0') as HTMLElement; + const dragCell = gridElement.querySelector('#c1-1') as HTMLElement; + + pointerDown(startCell); + pointerMove(dragCell); + + expect(getActiveCellId()).toBe('c0-0'); + // Dragging expands selection + expect(startCell.getAttribute('aria-selected')).toBe('true'); + expect(dragCell.getAttribute('aria-selected')).toBe('true'); + }); + + it('should stop dragging on pointerup', () => { + const startCell = gridElement.querySelector('#c0-0') as HTMLElement; + const endCell = gridElement.querySelector('#c1-1') as HTMLElement; + + pointerDown(startCell); + pointerUp(gridElement); + pointerMove(endCell); + + // Active cell should still be c0-0 because dragging stopped before moving to c1-1 + expect(getActiveCellId()).toBe('c0-0'); + expect(endCell.getAttribute('aria-selected')).toBe('false'); + }); + + it('should not change active cell on pointermove outside of the grid cells', () => { + const startCell = gridElement.querySelector('#c0-0') as HTMLElement; + + pointerDown(startCell); + pointerMove(gridElement); + + expect(getActiveCellId()).toBe('c0-0'); + }); + }); + + describe('configuration', () => { + it('should prevent multiple selections if selectionMode is single (multi false)', () => { + setupGrid({ + enableSelection: true, + selectionMode: 'explicit', + multi: false, + }); + + const cell1 = gridElement.querySelector('#c0-0') as HTMLElement; + const cell2 = gridElement.querySelector('#c1-1') as HTMLElement; + + pointerDown(cell1); + expect(cell1.getAttribute('aria-selected')).toBe('true'); + + pointerDown(cell2); + expect(cell1.getAttribute('aria-selected')).toBe('false'); + expect(cell2.getAttribute('aria-selected')).toBe('true'); + }); + + it('should allow interaction but indicate disabled state if softDisabled is true', () => { + const gridData = createGridData(); + gridData[1].cells[1].disabled = true; + setupGrid({ + enableSelection: true, + selectionMode: 'explicit', + softDisabled: true, + gridData, + }); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const disabledCell = gridElement.querySelector('#c1-1') as HTMLElement; + expect(disabledCell.getAttribute('aria-disabled')).toBe('true'); + + // Can still interact visually, e.g. focus + disabledCell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + expect(getActiveCellId()).toBe('c1-1'); + + // But space should not select it? Wait, interaction is allowed, but actions might be blocked. + space(); + expect(disabledCell.getAttribute('aria-selected')).toBe('false'); + }); + + it('should skip disabled cells if softDisabled is false', () => { + const gridData = createGridData(); + gridData[1].cells[1].disabled = true; + setupGrid({ + softDisabled: false, + gridData, + }); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const startCell = gridElement.querySelector('#c1-0') as HTMLElement; + startCell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + // Navigating right from c1-0 should skip c1-1 and go to c1-2 + right(); + expect(getActiveCellId()).toBe('c1-2'); + }); + }); + }); + + describe('GridRow', () => { + describe('ARIA attributes and roles', () => { + it('should set role="row" on the host element', () => { + setupGrid(); + const row = gridElement.querySelector('tr') as HTMLElement; + expect(row.getAttribute('role')).toBe('row'); + }); + + it('should set aria-rowindex based on the rowIndex input', () => { + const gridData = createGridData(); + gridData[0].rowIndex = 5; + setupGrid({gridData}); + const row = gridElement.querySelector('tr') as HTMLElement; + expect(row.getAttribute('aria-rowindex')).toBe('5'); + }); + }); + }); + + describe('GridCell', () => { + describe('ARIA attributes and roles', () => { + it('should set the role based on the role input', () => { + const gridData = createGridData(); + gridData[1].cells[1].role = 'columnheader'; + setupGrid({gridData}); + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + expect(cell.getAttribute('role')).toBe('columnheader'); + }); + + it('should set aria-rowindex to the provided row index', () => { + const gridData = createGridData(); + gridData[1].cells[1].rowIndex = 4; + setupGrid({gridData}); + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + expect(cell.getAttribute('aria-rowindex')).toBe('4'); + }); + + it('should set aria-colindex to the provided column index', () => { + const gridData = createGridData(); + gridData[1].cells[1].colIndex = 3; + setupGrid({gridData}); + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + expect(cell.getAttribute('aria-colindex')).toBe('3'); + }); + + it('should set aria-selected="true" when the cell is selected', () => { + setupGrid({enableSelection: true, selectionMode: 'explicit'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + expect(cell.getAttribute('aria-selected')).toBe('false'); + + pointerDown(cell); + + expect(cell.getAttribute('aria-selected')).toBe('true'); + }); + + it('should set aria-selected="false" when the cell is unselected', () => { + setupGrid({enableSelection: true, selectionMode: 'explicit'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + pointerDown(cell); + expect(cell.getAttribute('aria-selected')).toBe('true'); + + pointerDown(cell); + expect(cell.getAttribute('aria-selected')).toBe('false'); + }); + + it('should set aria-rowspan to the provided rowspan configuration', () => { + const gridData = createGridData(); + gridData[1].cells[1].rowSpan = 2; + setupGrid({gridData}); + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + expect(cell.getAttribute('rowspan')).toBe('2'); + expect(cell.getAttribute('aria-rowspan')).toBe('2'); + }); + + it('should set aria-colspan to the provided colspan configuration', () => { + const gridData = createGridData(); + gridData[1].cells[1].colSpan = 3; + setupGrid({gridData}); + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + expect(cell.getAttribute('colspan')).toBe('3'); + expect(cell.getAttribute('aria-colspan')).toBe('3'); + }); + + it('should set id from the id input if provided', () => { + const gridData = createGridData(); + gridData[1].cells[1].id = 'custom-id'; + setupGrid({gridData}); + const cell = gridElement.querySelector('#custom-id') as HTMLElement; + expect(cell.getAttribute('id')).toBe('custom-id'); + }); + }); + + describe('focus management', () => { + it('should set tabindex="0" on the active cell', () => { + setupGrid({focusMode: 'roving'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c0-0') as HTMLElement; + expect(cell.getAttribute('tabindex')).toBe('0'); + }); + + it('should set tabindex="-1" on inactive cells', () => { + setupGrid({focusMode: 'roving'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + expect(cell.getAttribute('tabindex')).toBe('-1'); + }); + + it('should set data-active="true" when the cell becomes active', () => { + setupGrid(); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c0-0') as HTMLElement; + expect(cell.getAttribute('data-active')).toBe('true'); + }); + }); + + describe('configuration', () => { + it('should prevent selection when disabled input is true', () => { + const gridData = createGridData(); + gridData[1].cells[1].disabled = true; + setupGrid({enableSelection: true, selectionMode: 'explicit', gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + pointerDown(cell); + + expect(cell.getAttribute('aria-selected')).toBe('false'); + }); + + it('should prevent interaction when disabled input is true', () => { + const gridData = createGridData(); + gridData[1].cells[1].disabled = true; + setupGrid({ + enableSelection: true, + selectionMode: 'explicit', + softDisabled: false, + gridData, + }); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const startCell = gridElement.querySelector('#c1-0') as HTMLElement; + startCell.dispatchEvent(new FocusEvent('focusin', {bubbles: true})); + fixture.detectChanges(); + + // Navigating right from c1-0 should skip c1-1 and go to c1-2 because it's completely disabled + right(); + expect(getActiveCellId()).toBe('c1-2'); + }); + + it('should prevent selection when selectable input is false', () => { + const gridData = createGridData(); + gridData[1].cells[1].selectable = false; + setupGrid({enableSelection: true, selectionMode: 'explicit', gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + pointerDown(cell); + + expect(cell.hasAttribute('aria-selected')).toBeFalse(); + }); + + it('should update the selected property when bound value changes', () => { + // Needs a two-way binding test, but we can just test selection updates since it is model() + setupGrid({enableSelection: true, selectionMode: 'explicit'}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cellDirective = fixture.debugElement.query(By.css('#c1-1')).injector.get(GridCell); + expect(cellDirective.selected()).toBeFalse(); + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + pointerDown(cell); + + expect(cellDirective.selected()).toBeTrue(); + }); + }); + }); + + describe('GridCellWidget', () => { + describe('ARIA and Host attributes', () => { + it('should set data-active="true" when the widget is active', () => { + const gridData = createGridData(); + gridData[1].cells[1].widgets = [{id: 'w1', type: 'simple'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + const widget = gridElement.querySelector('#w1') as HTMLElement; + + expect(widget.getAttribute('data-active')).toBe('false'); + pointerDown(cell); + expect(widget.getAttribute('data-active')).toBe('true'); + }); + + it('should set data-active-control="widget" when the widget is activated', () => { + const gridData = createGridData(); + gridData[1].cells[1].widgets = [{id: 'w1', type: 'editable'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + const widget = gridElement.querySelector('#w1') as HTMLElement; + + pointerDown(cell); + expect(widget.getAttribute('data-active-control')).toBe('cell'); + + keydown('Enter'); + expect(widget.getAttribute('data-active-control')).toBe('widget'); + }); + + it('should set tabindex="0" on the active widget', () => { + const gridData = createGridData(); + gridData[1].cells[1].widgets = [{id: 'w1', type: 'simple'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + const widget = gridElement.querySelector('#w1') as HTMLElement; + + pointerDown(cell); + expect(widget.getAttribute('tabindex')).toBe('0'); + }); + + it('should set tabindex="-1" on inactive widgets', () => { + const gridData = createGridData(); + gridData[1].cells[1].widgets = [{id: 'w1', type: 'simple'}]; + gridData[1].cells[2].widgets = [{id: 'w2', type: 'simple'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const widget1 = gridElement.querySelector('#w1') as HTMLElement; + const widget2 = gridElement.querySelector('#w2') as HTMLElement; + + const cell = gridElement.querySelector('#c1-1') as HTMLElement; + pointerDown(cell); + + expect(widget1.getAttribute('tabindex')).toBe('0'); + expect(widget2.getAttribute('tabindex')).toBe('-1'); + }); + }); + + describe('widget activation', () => { + it('should immediately delegate focus when widgetType is simple', () => { + const gridData = createGridData(); + gridData[0].cells[0].widgets = [{id: 'w1', type: 'simple'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const widget = gridElement.querySelector('#w1') as HTMLElement; + + tabIntoGrid(); + + expect(document.activeElement).toBe(widget); + }); + + it('should wait for enter key to delegate focus when widgetType is complex', () => { + const gridData = createGridData(); + gridData[0].cells[0].widgets = [{id: 'w1', type: 'complex'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const widgetDirective = fixture.debugElement + .query(By.css('#w1')) + .injector.get(GridCellWidget); + + tabIntoGrid(); + + expect(widgetDirective.isActivated()).toBeFalse(); + + keydown('Enter'); + expect(widgetDirective.isActivated()).toBeTrue(); + }); + + it('should enter edit mode when widgetType is editable and enter is pressed', () => { + const gridData = createGridData(); + gridData[0].cells[0].widgets = [{id: 'w1', type: 'editable'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const widgetDirective = fixture.debugElement + .query(By.css('#w1')) + .injector.get(GridCellWidget); + + tabIntoGrid(); + + keydown('Enter'); + expect(widgetDirective.isActivated()).toBeTrue(); + }); + + it('should give widget tabindex -1 when focusTarget is present', () => { + const gridData = createGridData(); + gridData[0].cells[0].widgets = [{id: 'w1', type: 'complex', hasTarget: true}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const widgetElement = gridElement.querySelector('#w1') as HTMLElement; + expect(widgetElement.getAttribute('tabindex')).toBe('-1'); + }); + + it('should emit the activated output when the widget becomes active', () => { + const gridData = createGridData(); + gridData[0].cells[0].widgets = [{id: 'w1', type: 'complex'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + tabIntoGrid(); + + expect(fixture.componentInstance.onActivated).not.toHaveBeenCalled(); + + keydown('Enter'); + expect(fixture.componentInstance.onActivated).toHaveBeenCalled(); + }); + + it('should emit the deactivated output when the widget loses active state', () => { + const gridData = createGridData(); + gridData[0].cells[0].widgets = [{id: 'w1', type: 'complex'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + tabIntoGrid(); + + keydown('Enter'); + expect(fixture.componentInstance.onDeactivated).not.toHaveBeenCalled(); + + keydown('Escape'); + expect(fixture.componentInstance.onDeactivated).toHaveBeenCalled(); + }); + + it('should become active when activate() is called programmatically', () => { + const gridData = createGridData(); + gridData[0].cells[0].widgets = [{id: 'w1', type: 'complex'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const widgetDirective = fixture.debugElement + .query(By.css('#w1')) + .injector.get(GridCellWidget); + + widgetDirective.activate(); + fixture.detectChanges(); + + expect(widgetDirective.isActivated()).toBeTrue(); + }); + + it('should lose active state when deactivate() is called programmatically', () => { + const gridData = createGridData(); + gridData[0].cells[0].widgets = [{id: 'w1', type: 'complex'}]; + setupGrid({gridData}); + gridInstance._pattern.setDefaultStateEffect(); + fixture.detectChanges(); + + const widgetDirective = fixture.debugElement + .query(By.css('#w1')) + .injector.get(GridCellWidget); + + widgetDirective.activate(); + fixture.detectChanges(); + + expect(widgetDirective.isActivated()).toBeTrue(); + + widgetDirective.deactivate(); + fixture.detectChanges(); + + expect(widgetDirective.isActivated()).toBeFalse(); + }); + }); + }); +}); + +@Component({ + template: ` + + @for (row of gridData(); track $index; let rIndex = $index) { + + @for (cell of row.cells; track $index; let cIndex = $index) { + + } + + } +
+ Cell {{rIndex}}-{{cIndex}} + @for (widget of cell.widgets || []; track $index; let wIndex = $index) { + @if (widget.hasTarget) { + + + } @else { + + } + } +
+ `, + imports: [Grid, GridRow, GridCell, GridCellWidget], +}) +class GridTestComponent { + readonly disabled = signal(false); + readonly multi = signal(false); + readonly rowWrap = signal<'continuous' | 'loop' | 'nowrap'>('loop'); + readonly colWrap = signal<'continuous' | 'loop' | 'nowrap'>('loop'); + readonly focusMode = signal<'roving' | 'activedescendant'>('roving'); + readonly softDisabled = signal(true); + readonly enableSelection = signal(false); + readonly selectionMode = signal<'follow' | 'explicit'>('follow'); + readonly enableRangeSelection = signal(false); + readonly gridData = signal(createGridData()); + + onActivated = jasmine.createSpy('activated'); + onDeactivated = jasmine.createSpy('deactivated'); +} diff --git a/src/aria/grid/grid.ts b/src/aria/grid/grid.ts index c54b4d5a95bb..7799f2defb40 100644 --- a/src/aria/grid/grid.ts +++ b/src/aria/grid/grid.ts @@ -52,6 +52,7 @@ import {GRID_ROW} from './grid-tokens'; 'role': 'grid', '[tabindex]': '_pattern.tabIndex()', '[attr.aria-disabled]': '_pattern.disabled()', + '[attr.aria-multiselectable]': '_pattern.multiSelectable()', '[attr.aria-activedescendant]': '_pattern.activeDescendant()', '(keydown)': '_pattern.onKeydown($event)', '(pointerdown)': '_pattern.onPointerdown($event)', diff --git a/src/aria/private/grid/grid.ts b/src/aria/private/grid/grid.ts index 030d2a71c3b7..6f5bcf03dd99 100644 --- a/src/aria/private/grid/grid.ts +++ b/src/aria/private/grid/grid.ts @@ -53,6 +53,11 @@ export class GridPattern { /** Whether the grid is disabled. */ readonly disabled = computed(() => this.gridBehavior.gridDisabled()); + /** Whether the grid is multi-selectable. */ + readonly multiSelectable = computed(() => + this.inputs.enableSelection() ? this.inputs.multi() : undefined, + ); + /** The ID of the currently active descendant cell. */ readonly activeDescendant = computed(() => this.gridBehavior.activeDescendant()); @@ -61,9 +66,7 @@ export class GridPattern { /** The current selection anchor cell. */ readonly anchorCell: SignalLike = computed(() => - this.inputs.enableSelection() && this.inputs.multi() - ? this.gridBehavior.selectionAnchorCell() - : undefined, + this.multiSelectable() ? this.gridBehavior.selectionAnchorCell() : undefined, ); /** Whether to pause grid navigation and give the keyboard control to cell or widget. */ diff --git a/src/aria/private/grid/widget.ts b/src/aria/private/grid/widget.ts index b5e810b35f7a..f51278638e71 100644 --- a/src/aria/private/grid/widget.ts +++ b/src/aria/private/grid/widget.ts @@ -58,7 +58,9 @@ export class GridCellWidgetPattern implements ListNavigationItem { readonly tabIndex: SignalLike<-1 | 0> = computed(() => this.inputs.cell().widgetTabIndex()); /** Whether the widget is the active item in the widget list. */ - readonly active: SignalLike = computed(() => this.inputs.cell().activeWidget() === this); + readonly active: SignalLike = computed( + () => this.inputs.cell().active() && this.inputs.cell().activeWidget() === this, + ); /** Whether the widget is currently activated. */ readonly isActivated: WritableSignalLike = signal(false); From ef607a6271b63c5fe9fb166aed57f091274382fc Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Fri, 6 Mar 2026 07:54:38 +0100 Subject: [PATCH 026/123] ci: add issue labeling and refactor jobs (#32890) Clean ups (cherry picked from commit 8912b00cc5bd383c577033b2a68e167545786e2a) --- .github/workflows/dev-infra.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/dev-infra.yml b/.github/workflows/dev-infra.yml index 3fedefd8be35..1123806799d9 100644 --- a/.github/workflows/dev-infra.yml +++ b/.github/workflows/dev-infra.yml @@ -3,22 +3,33 @@ name: DevInfra on: pull_request_target: types: [opened, synchronize, reopened] + issues: + types: [opened, reopened] # Declare default permissions as read only. -permissions: read-all +permissions: + contents: read jobs: labels: + if: github.event_name == 'pull_request_target' runs-on: ubuntu-latest steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: angular/dev-infra/github-actions/pull-request-labeling@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 + - uses: angular/dev-infra/github-actions/labeling/pull-request@63fd18d4726829e65f6abe6f15c0fe79f63f1dec with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} post_approval_changes: + if: github.event_name == 'pull_request_target' runs-on: ubuntu-latest steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: angular/dev-infra/github-actions/pull-request-labeling@e006a332028a4c3cb24e9d92437fac7ae99e2ed5 + - uses: angular/dev-infra/github-actions/post-approval-changes@63fd18d4726829e65f6abe6f15c0fe79f63f1dec with: angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} + issue_labels: + if: github.event_name == 'issues' + runs-on: ubuntu-latest + steps: + - uses: angular/dev-infra/github-actions/labeling/issue@c4344a4e20dbdf9cb8eeb7a7eb91431b98eabd99 + with: + angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }} + google-generative-ai-key: ${{ secrets.GOOGLE_GENERATIVE_AI_KEY }} From 2a330b89e8b2e4694fb9c9cc2764f767ecb2d75c Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 9 Mar 2026 17:26:11 +0100 Subject: [PATCH 027/123] refactor(material/menu): switch tests away from fakeAsync (#32909) Reworks the menu tests not to depend on `fakeAsync` anymore. (cherry picked from commit 60ad14c1a25aa57d10e8755168bc90b2b3cb4f4d) --- src/material/menu/menu.spec.ts | 691 +++++++++++++-------------------- 1 file changed, 277 insertions(+), 414 deletions(-) diff --git a/src/material/menu/menu.spec.ts b/src/material/menu/menu.spec.ts index 14c1ecb99d97..c7bf74fdfad4 100644 --- a/src/material/menu/menu.spec.ts +++ b/src/material/menu/menu.spec.ts @@ -28,7 +28,7 @@ import { ViewChild, ViewChildren, } from '@angular/core'; -import {ComponentFixture, fakeAsync, flush, TestBed, tick} from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import {Subject} from 'rxjs'; import { @@ -59,6 +59,10 @@ const MENU_PANEL_TOP_PADDING = 8; describe('MatMenu', () => { let overlayContainerElement: HTMLElement; + function wait(milliseconds: number) { + return new Promise(resolve => setTimeout(resolve, milliseconds)); + } + beforeEach(() => { TestBed.configureTestingModule({ providers: [{provide: MATERIAL_ANIMATIONS, useValue: {animationsDisabled: true}}], @@ -72,18 +76,17 @@ describe('MatMenu', () => { window.scroll(0, 0); }); - it('should aria-controls the menu panel', fakeAsync(() => { + it('should aria-controls the menu panel', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); expect(fixture.componentInstance.triggerEl.nativeElement.getAttribute('aria-controls')).toBe( fixture.componentInstance.menu.panelId, ); - })); + }); - it('should set aria-haspopup based on whether a menu is assigned', fakeAsync(() => { + it('should set aria-haspopup based on whether a menu is assigned', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const triggerElement = fixture.componentInstance.triggerEl.nativeElement; @@ -95,9 +98,9 @@ describe('MatMenu', () => { fixture.detectChanges(); expect(triggerElement.hasAttribute('aria-haspopup')).toBe(false); - })); + }); - it('should open the menu as an idempotent operation', fakeAsync(() => { + it('should open the menu as an idempotent operation', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); expect(overlayContainerElement.textContent).toBe(''); @@ -105,14 +108,13 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.openMenu(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); expect(overlayContainerElement.textContent).toContain('Item'); expect(overlayContainerElement.textContent).toContain('Disabled'); }).not.toThrowError(); - })); + }); - it('should close the menu when a click occurs outside the menu', fakeAsync(() => { + it('should close the menu when a click occurs outside the menu', async () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); @@ -120,45 +122,44 @@ describe('MatMenu', () => { const backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop'); backdrop.click(); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlayContainerElement.textContent).toBe(''); - })); + }); - it('should be able to remove the backdrop', fakeAsync(() => { + it('should be able to remove the backdrop', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.menu.hasBackdrop = false; fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeFalsy(); - })); + }); - it('should set the correct aria-haspopup value on the trigger element', fakeAsync(() => { + it('should set the correct aria-haspopup value on the trigger element', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const triggerElement = fixture.componentInstance.triggerEl.nativeElement; expect(triggerElement.getAttribute('aria-haspopup')).toBe('menu'); - })); + }); - it('should be able to remove the backdrop on repeat openings', fakeAsync(() => { + it('should be able to remove the backdrop on repeat openings', async () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); // Start off with a backdrop. expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeTruthy(); fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); + await wait(200); // Change `hasBackdrop` after the first open. fixture.componentInstance.menu.hasBackdrop = false; @@ -167,12 +168,12 @@ describe('MatMenu', () => { // Reopen the menu. fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop')).toBeFalsy(); - })); + }); - it('should restore focus to the trigger when the menu was opened by keyboard', fakeAsync(() => { + it('should restore focus to the trigger when the menu was opened by keyboard', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const triggerEl = fixture.componentInstance.triggerEl.nativeElement; @@ -185,12 +186,11 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); expect(document.activeElement).toBe(triggerEl); - })); + }); - it('should not restore focus to the trigger if focus restoration is disabled', fakeAsync(() => { + it('should not restore focus to the trigger if focus restoration is disabled', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const triggerEl = fixture.componentInstance.triggerEl.nativeElement; @@ -207,12 +207,11 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); expect(document.activeElement).not.toBe(triggerEl); - })); + }); - it('should be able to move focus in the closed event', fakeAsync(() => { + it('should be able to move focus in the closed event', () => { const fixture = TestBed.createComponent(SimpleMenu); const instance = fixture.componentInstance; fixture.detectChanges(); @@ -227,14 +226,13 @@ describe('MatMenu', () => { const subscription = instance.trigger.menuClosed.subscribe(() => button.focus()); instance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); expect(document.activeElement).toBe(button); button.remove(); subscription.unsubscribe(); - })); + }); - it('should restore focus to the trigger immediately once the menu is closed', fakeAsync(() => { + it('should restore focus to the trigger immediately once the menu is closed', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const triggerEl = fixture.componentInstance.triggerEl.nativeElement; @@ -242,27 +240,24 @@ describe('MatMenu', () => { // A click without a mousedown before it is considered a keyboard open. triggerEl.click(); fixture.detectChanges(); - tick(500); expect(overlayContainerElement.querySelector('.mat-mdc-menu-panel')).toBeTruthy(); fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - // Note: don't add a `tick` here since we're testing + // Note: don't add a `whenStable` here since we're testing // that focus is restored before the animation is done. expect(document.activeElement).toBe(triggerEl); - tick(500); - })); + }); - it('should move focus to another item if the active item is destroyed', fakeAsync(() => { + it('should move focus to another item if the active item is destroyed', () => { const fixture = TestBed.createComponent(MenuWithRepeatedItems); fixture.detectChanges(); const triggerEl = fixture.componentInstance.triggerEl.nativeElement; triggerEl.click(); fixture.detectChanges(); - tick(500); const items = overlayContainerElement.querySelectorAll( '.mat-mdc-menu-panel .mat-mdc-menu-item', @@ -274,26 +269,24 @@ describe('MatMenu', () => { fixture.componentInstance.items.shift(); fixture.detectChanges(); - tick(500); expect(spy).toHaveBeenCalled(); - })); + }); - it('should be able to set a custom class on the backdrop', fakeAsync(() => { + it('should be able to set a custom class on the backdrop', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.componentInstance.backdropClass = 'custom-backdrop'; fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop'); expect(backdrop.classList).toContain('custom-backdrop'); - })); + }); - it('should be able to set a custom class on the overlay panel', fakeAsync(() => { + it('should be able to set a custom class on the overlay panel', () => { TestBed.resetTestingModule().configureTestingModule({ providers: [ { @@ -308,14 +301,13 @@ describe('MatMenu', () => { fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane'); expect(overlayPane.classList).toContain('custom-panel-class'); - })); + }); - it('should be able to set a custom classes on the overlay panel', fakeAsync(() => { + it('should be able to set a custom classes on the overlay panel', () => { TestBed.resetTestingModule().configureTestingModule({ providers: [ { @@ -329,15 +321,14 @@ describe('MatMenu', () => { fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane'); expect(overlayPane.classList).toContain('custom-panel-class-1'); expect(overlayPane.classList).toContain('custom-panel-class-2'); - })); + }); - it('should restore focus to the root trigger when the menu was opened by mouse', fakeAsync(() => { + it('should restore focus to the root trigger when the menu was opened by mouse', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -350,12 +341,11 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); expect(document.activeElement).toBe(triggerEl); - })); + }); - it('should restore focus to the root trigger when the menu was opened by touch', fakeAsync(() => { + it('should restore focus to the root trigger when the menu was opened by touch', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -368,12 +358,11 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - flush(); expect(document.activeElement).toBe(triggerEl); - })); + }); - it('should scroll the panel to the top on open, when it is scrollable', fakeAsync(() => { + it('should scroll the panel to the top on open, when it is scrollable', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -387,13 +376,10 @@ describe('MatMenu', () => { triggerEl.click(); fixture.detectChanges(); - // Flush due to the additional tick that is necessary for the FocusMonitor. - flush(); - expect(overlayContainerElement.querySelector('.mat-mdc-menu-panel')!.scrollTop).toBe(0); - })); + }); - it('should set the proper focus origin when restoring focus after opening by keyboard', fakeAsync(() => { + it('should set the proper focus origin when restoring focus after opening by keyboard', () => { const focusMonitor = TestBed.inject(FocusMonitor); const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -405,14 +391,13 @@ describe('MatMenu', () => { fixture.detectChanges(); fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); fixture.detectChanges(); expect(triggerEl.classList).toContain('cdk-program-focused'); focusMonitor.stopMonitoring(triggerEl); - })); + }); - it('should set the proper focus origin when restoring focus after opening by mouse', fakeAsync(() => { + it('should set the proper focus origin when restoring focus after opening by mouse', () => { const focusMonitor = TestBed.inject(FocusMonitor); const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -425,14 +410,13 @@ describe('MatMenu', () => { focusMonitor.monitor(triggerEl, false); fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); fixture.detectChanges(); expect(triggerEl.classList).toContain('cdk-mouse-focused'); focusMonitor.stopMonitoring(triggerEl); - })); + }); - it('should set proper focus origin when right clicking on trigger, before opening by keyboard', fakeAsync(() => { + it('should set proper focus origin when right clicking on trigger, before opening by keyboard', () => { const focusMonitor = TestBed.inject(FocusMonitor); const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -450,14 +434,13 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); fixture.detectChanges(); expect(triggerEl.classList).toContain('cdk-program-focused'); focusMonitor.stopMonitoring(triggerEl); - })); + }); - it('should set the proper focus origin when restoring focus after opening by touch', fakeAsync(() => { + it('should set the proper focus origin when restoring focus after opening by touch', () => { const focusMonitor = TestBed.inject(FocusMonitor); const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -470,15 +453,13 @@ describe('MatMenu', () => { focusMonitor.monitor(triggerEl, false); fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); fixture.detectChanges(); - flush(); expect(triggerEl.classList).toContain('cdk-touch-focused'); focusMonitor.stopMonitoring(triggerEl); - })); + }); - it('should close the menu when pressing ESCAPE', fakeAsync(() => { + it('should close the menu when pressing ESCAPE', async () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); @@ -487,13 +468,13 @@ describe('MatMenu', () => { const event = dispatchKeyboardEvent(panel, 'keydown', ESCAPE); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlayContainerElement.textContent).toBe(''); expect(event.defaultPrevented).toBe(true); - })); + }); - it('should not close the menu when pressing ESCAPE with a modifier', fakeAsync(() => { + it('should not close the menu when pressing ESCAPE with a modifier', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); @@ -503,11 +484,10 @@ describe('MatMenu', () => { dispatchEvent(panel, event); fixture.detectChanges(); - tick(500); expect(overlayContainerElement.textContent).toBeTruthy(); expect(event.defaultPrevented).toBe(false); - })); + }); it('should open a custom menu', () => { const fixture = TestBed.createComponent(CustomMenu); @@ -522,7 +502,7 @@ describe('MatMenu', () => { }).not.toThrowError(); }); - it('should set the panel direction based on the trigger direction', fakeAsync(() => { + it('should set the panel direction based on the trigger direction', () => { TestBed.resetTestingModule().configureTestingModule({ providers: [provideFakeDirectionality('rtl')], }); @@ -531,15 +511,14 @@ describe('MatMenu', () => { fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const boundingBox = overlayContainerElement.querySelector( '.cdk-overlay-connected-position-bounding-box', )!; expect(boundingBox.getAttribute('dir')).toEqual('rtl'); - })); + }); - it('should update the panel direction if the trigger direction changes', fakeAsync(() => { + it('should update the panel direction if the trigger direction changes', async () => { const dir = signal('rtl'); TestBed.resetTestingModule().configureTestingModule({ providers: [provideFakeDirectionality(dir)], @@ -549,7 +528,7 @@ describe('MatMenu', () => { fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); let boundingBox = overlayContainerElement.querySelector( '.cdk-overlay-connected-position-bounding-box', @@ -558,27 +537,26 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); + await wait(200); dir.set('ltr'); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); boundingBox = overlayContainerElement.querySelector( '.cdk-overlay-connected-position-bounding-box', )!; expect(boundingBox.getAttribute('dir')).toEqual('ltr'); - })); + }); - it('should transfer any custom classes from the host to the overlay', fakeAsync(() => { + it('should transfer any custom classes from the host to the overlay', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.componentInstance.panelClass = 'custom-one custom-two'; fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const menuEl = fixture.debugElement.query(By.css('mat-menu'))!.nativeElement; const panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel')!; @@ -588,14 +566,13 @@ describe('MatMenu', () => { expect(panel.classList).toContain('custom-one'); expect(panel.classList).toContain('custom-two'); - })); + }); - it('should set the "menu" role on the overlay panel', fakeAsync(() => { + it('should set the "menu" role on the overlay panel', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const menuPanel = overlayContainerElement.querySelector('.mat-mdc-menu-panel'); @@ -603,15 +580,14 @@ describe('MatMenu', () => { const role = menuPanel ? menuPanel.getAttribute('role') : ''; expect(role).withContext('Expected panel to have the "menu" role.').toBe('menu'); - })); + }); - it('should forward ARIA attributes to the menu panel', fakeAsync(() => { + it('should forward ARIA attributes to the menu panel', () => { const fixture = TestBed.createComponent(SimpleMenu); const instance = fixture.componentInstance; fixture.detectChanges(); instance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const menuPanel = overlayContainerElement.querySelector('.mat-mdc-menu-panel')!; expect(menuPanel.hasAttribute('aria-label')).toBe(false); @@ -638,40 +614,37 @@ describe('MatMenu', () => { expect(menuPanel.hasAttribute('aria-label')).toBe(false); expect(menuPanel.hasAttribute('aria-labelledby')).toBe(false); expect(menuPanel.hasAttribute('aria-describedby')).toBe(false); - })); + }); - it('should set the "menuitem" role on the items by default', fakeAsync(() => { + it('should set the "menuitem" role on the items by default', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const items = Array.from(overlayContainerElement.querySelectorAll('.mat-mdc-menu-item')); expect(items.length).toBeGreaterThan(0); expect(items.every(item => item.getAttribute('role') === 'menuitem')).toBe(true); - })); + }); - it('should be able to set an alternate role on the menu items', fakeAsync(() => { + it('should be able to set an alternate role on the menu items', () => { const fixture = TestBed.createComponent(MenuWithCheckboxItems); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const items = Array.from(overlayContainerElement.querySelectorAll('.mat-mdc-menu-item')); expect(items.length).toBeGreaterThan(0); expect(items.every(item => item.getAttribute('role') === 'menuitemcheckbox')).toBe(true); - })); + }); - it('should not change focus origin if origin not specified for menu items', fakeAsync(() => { + it('should not change focus origin if origin not specified for menu items', () => { const fixture = TestBed.createComponent(MenuWithCheckboxItems); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); let [firstMenuItemDebugEl, secondMenuItemDebugEl] = fixture.debugElement.queryAll( By.css('.mat-mdc-menu-item'), @@ -684,11 +657,10 @@ describe('MatMenu', () => { firstMenuItemInstance.focus('mouse'); secondMenuItemDebugEl.nativeElement.blur(); secondMenuItemInstance.focus(); - tick(500); expect(secondMenuItemDebugEl.nativeElement.classList).toContain('cdk-focused'); expect(secondMenuItemDebugEl.nativeElement.classList).toContain('cdk-mouse-focused'); - })); + }); it('should not throw an error on destroy', () => { const fixture = TestBed.createComponent(SimpleMenu); @@ -701,21 +673,21 @@ describe('MatMenu', () => { expect(fixture.componentInstance.items.first.getLabel()).toBe('Item'); }); - it('should filter out icon nodes when figuring out the label', fakeAsync(() => { + it('should filter out icon nodes when figuring out the label', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const items = fixture.componentInstance.items.toArray(); expect(items[2].getLabel()).toBe('Item with an icon'); - })); + }); - it('should get the label of an item if the text is not in a direct descendant node', fakeAsync(() => { + it('should get the label of an item if the text is not in a direct descendant node', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const items = fixture.componentInstance.items.toArray(); expect(items[3].getLabel()).toBe('Item with text inside span'); - })); + }); - it('should set the proper focus origin when opening by mouse', fakeAsync(() => { + it('should set the proper focus origin when opening by mouse', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); spyOn(fixture.componentInstance.items.first, 'focus').and.callThrough(); @@ -725,12 +697,11 @@ describe('MatMenu', () => { dispatchMouseEvent(triggerEl, 'mousedown'); triggerEl.click(); fixture.detectChanges(); - tick(500); expect(fixture.componentInstance.items.first.focus).toHaveBeenCalledWith('mouse'); - })); + }); - it('should set the proper focus origin when opening by touch', fakeAsync(() => { + it('should set the proper focus origin when opening by touch', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); spyOn(fixture.componentInstance.items.first, 'focus').and.callThrough(); @@ -740,10 +711,9 @@ describe('MatMenu', () => { dispatchMouseEvent(triggerEl, 'touchstart'); triggerEl.click(); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.items.first.focus).toHaveBeenCalledWith('touch'); - })); + }); it('should set the proper origin when calling focusFirstItem after the opening sequence has started', () => { const fixture = TestBed.createComponent(SimpleMenu); @@ -758,7 +728,7 @@ describe('MatMenu', () => { expect(fixture.componentInstance.items.first.focus).toHaveBeenCalledOnceWith('touch'); }); - it('should close the menu when using the CloseScrollStrategy', fakeAsync(() => { + it('should close the menu when using the CloseScrollStrategy', () => { const scrolledSubject = new Subject(); TestBed.resetTestingModule().configureTestingModule({ providers: [ @@ -781,12 +751,11 @@ describe('MatMenu', () => { expect(trigger.menuOpen).toBe(true); scrolledSubject.next(); - tick(500); expect(trigger.menuOpen).toBe(false); - })); + }); - it('should switch to keyboard focus when using the keyboard after opening using the mouse', fakeAsync(() => { + it('should switch to keyboard focus when using the keyboard after opening using the mouse', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -800,23 +769,18 @@ describe('MatMenu', () => { items.forEach(item => patchElementFocus(item)); - tick(500); - tick(); fixture.detectChanges(); expect(items.some(item => item.classList.contains('cdk-keyboard-focused'))).toBe(false); dispatchKeyboardEvent(panel, 'keydown', DOWN_ARROW); fixture.detectChanges(); - // Flush due to the additional tick that is necessary for the FocusMonitor. - flush(); - // We skip to the third item, because the second one is disabled. expect(items[2].classList).toContain('cdk-focused'); expect(items[2].classList).toContain('cdk-keyboard-focused'); - })); + }); - it('should set the keyboard focus origin when opened using the keyboard', fakeAsync(() => { + it('should set the keyboard focus origin when opened using the keyboard', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const trigger = fixture.componentInstance.triggerEl.nativeElement; @@ -831,14 +795,12 @@ describe('MatMenu', () => { ); items.forEach(item => patchElementFocus(item)); - tick(500); - tick(); fixture.detectChanges(); expect(items[0].classList).toContain('cdk-keyboard-focused'); - })); + }); - it('should toggle the aria-expanded attribute on the trigger', fakeAsync(() => { + it('should toggle the aria-expanded attribute on the trigger', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const triggerEl = fixture.componentInstance.triggerEl.nativeElement; @@ -847,18 +809,16 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); expect(triggerEl.getAttribute('aria-expanded')).toBe('true'); fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); expect(triggerEl.getAttribute('aria-expanded')).toBe('false'); - })); + }); - it('should toggle aria-expanded on the trigger in an OnPush component', fakeAsync(() => { + it('should toggle aria-expanded on the trigger in an OnPush component', () => { const fixture = TestBed.createComponent(SimpleMenuOnPush); fixture.detectChanges(); const triggerEl = fixture.componentInstance.triggerEl.nativeElement; @@ -867,26 +827,23 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); expect(triggerEl.getAttribute('aria-expanded')).toBe('true'); fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); expect(triggerEl.getAttribute('aria-expanded')).toBe('false'); - })); + }); - it('should throw if assigning a menu that contains the trigger', fakeAsync(() => { + it('should throw if assigning a menu that contains the trigger', async () => { expect(() => { const fixture = TestBed.createComponent(InvalidRecursiveMenu); fixture.detectChanges(); - tick(500); }).toThrowError(/menu cannot contain its own trigger/); - })); + }); - it('should be able to swap out a menu after the first time it is opened', fakeAsync(() => { + it('should be able to swap out a menu after the first time it is opened', async () => { const fixture = TestBed.createComponent(DynamicPanelMenu); fixture.detectChanges(); expect(overlayContainerElement.textContent).toBe(''); @@ -899,7 +856,7 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); + await wait(200); fixture.detectChanges(); expect(overlayContainerElement.textContent).toBe(''); @@ -913,13 +870,13 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); + await wait(200); fixture.detectChanges(); expect(overlayContainerElement.textContent).toBe(''); - })); + }); - it('should focus the first item when pressing home', fakeAsync(() => { + it('should focus the first item when pressing home', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -944,10 +901,9 @@ describe('MatMenu', () => { expect(items[0].focus).toHaveBeenCalled(); expect(event.defaultPrevented).toBe(true); - flush(); - })); + }); - it('should not focus the first item when pressing home with a modifier key', fakeAsync(() => { + it('should not focus the first item when pressing home with a modifier key', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -971,10 +927,9 @@ describe('MatMenu', () => { expect(items[0].focus).not.toHaveBeenCalled(); expect(event.defaultPrevented).toBe(false); - flush(); - })); + }); - it('should focus the last item when pressing end', fakeAsync(() => { + it('should focus the last item when pressing end', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -992,10 +947,9 @@ describe('MatMenu', () => { expect(items[items.length - 1].focus).toHaveBeenCalled(); expect(event.defaultPrevented).toBe(true); - flush(); - })); + }); - it('should not focus the last item when pressing end with a modifier key', fakeAsync(() => { + it('should not focus the last item when pressing end with a modifier key', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -1015,16 +969,14 @@ describe('MatMenu', () => { expect(items[items.length - 1].focus).not.toHaveBeenCalled(); expect(event.defaultPrevented).toBe(false); - flush(); - })); + }); - it('should respect the DOM order, rather than insertion order, when moving focus using the arrow keys', fakeAsync(() => { + it('should respect the DOM order, rather than insertion order, when moving focus using the arrow keys', () => { let fixture = TestBed.createComponent(SimpleMenuWithRepeater); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); let menuPanel = document.querySelector('.mat-mdc-menu-panel')!; let items = menuPanel.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]'); @@ -1041,13 +993,11 @@ describe('MatMenu', () => { items = menuPanel.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]'); dispatchKeyboardEvent(menuPanel, 'keydown', DOWN_ARROW); fixture.detectChanges(); - tick(); expect(document.activeElement).withContext('Expected second item to be focused').toBe(items[1]); - flush(); - })); + }); - it('should sync the focus order when an item is focused programmatically', fakeAsync(() => { + it('should sync the focus order when an item is focused programmatically', () => { const fixture = TestBed.createComponent(SimpleMenuWithRepeater); // Add some more items to work with. @@ -1058,7 +1008,6 @@ describe('MatMenu', () => { fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const menuPanel = document.querySelector('.mat-mdc-menu-panel')!; const items = menuPanel.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]'); @@ -1074,81 +1023,75 @@ describe('MatMenu', () => { dispatchKeyboardEvent(menuPanel, 'keydown', DOWN_ARROW); fixture.detectChanges(); - tick(); expect(document.activeElement).withContext('Expected fifth item to be focused').toBe(items[4]); - flush(); - })); + }); - it('should open submenus when the menu is inside an OnPush component', fakeAsync(() => { + it('should open submenus when the menu is inside an OnPush component', () => { const fixture = TestBed.createComponent(LazyMenuWithOnPush); fixture.detectChanges(); // Open the top-level menu fixture.componentInstance.rootTrigger.nativeElement.click(); fixture.detectChanges(); - flush(); // Dispatch a `mouseenter` on the menu item to open the submenu. // This will only work if the top-level menu is aware the this menu item exists. dispatchMouseEvent(fixture.componentInstance.menuItemWithSubmenu.nativeElement, 'mouseenter'); fixture.detectChanges(); - flush(); expect(overlayContainerElement.querySelectorAll('.mat-mdc-menu-item').length) .withContext('Expected two open menus') .toBe(2); - })); + }); - it('should focus the menu panel if all items are disabled', fakeAsync(() => { + it('should focus the menu panel if all items are disabled', () => { const fixture = TestBed.createComponent(SimpleMenuWithRepeater); fixture.componentInstance.items.forEach(item => (item.disabled = true)); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); expect(document.activeElement).toBe( overlayContainerElement.querySelector('.mat-mdc-menu-panel'), ); - })); + }); - it('should focus the menu panel if all items are disabled inside lazy content', fakeAsync(() => { + it('should focus the menu panel if all items are disabled inside lazy content', () => { const fixture = TestBed.createComponent(SimpleMenuWithRepeaterInLazyContent); fixture.componentInstance.items.forEach(item => (item.disabled = true)); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); expect(document.activeElement).toBe( overlayContainerElement.querySelector('.mat-mdc-menu-panel'), ); - })); + }); - it('should clear the static aria-label from the menu host', fakeAsync(() => { + it('should clear the static aria-label from the menu host', () => { const fixture = TestBed.createComponent(StaticAriaLabelMenu); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('mat-menu').hasAttribute('aria-label')).toBe(false); - })); + }); - it('should clear the static aria-labelledby from the menu host', fakeAsync(() => { + it('should clear the static aria-labelledby from the menu host', () => { const fixture = TestBed.createComponent(StaticAriaLabelledByMenu); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('mat-menu').hasAttribute('aria-labelledby')).toBe( false, ); - })); + }); - it('should clear the static aria-describedby from the menu host', fakeAsync(() => { + it('should clear the static aria-describedby from the menu host', () => { const fixture = TestBed.createComponent(StaticAriaDescribedbyMenu); fixture.detectChanges(); expect(fixture.nativeElement.querySelector('mat-menu').hasAttribute('aria-describedby')).toBe( false, ); - })); + }); - it('should be able to move focus inside the `open` event', fakeAsync(() => { + it('should be able to move focus inside the `open` event', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); @@ -1157,23 +1100,21 @@ describe('MatMenu', () => { }); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const items = document.querySelectorAll('.mat-mdc-menu-panel [mat-menu-item]'); expect(document.activeElement).withContext('Expected fourth item to be focused').toBe(items[3]); - })); + }); - it('should default to the "below" and "after" positions', fakeAsync(() => { + it('should default to the "below" and "after" positions', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel') as HTMLElement; expect(panel.classList).toContain('mat-menu-below'); expect(panel.classList).toContain('mat-menu-after'); - })); + }); it('should keep the panel in the viewport when more items are added while open', () => { const viewportRuler = TestBed.inject(ViewportRuler); @@ -1200,12 +1141,11 @@ describe('MatMenu', () => { }); describe('lazy rendering', () => { - it('should be able to render the menu content lazily', fakeAsync(() => { + it('should be able to render the menu content lazily', () => { const fixture = TestBed.createComponent(SimpleLazyMenu); fixture.detectChanges(); fixture.componentInstance.triggerEl.nativeElement.click(); fixture.detectChanges(); - tick(500); const panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel')!; @@ -1216,14 +1156,14 @@ describe('MatMenu', () => { expect(fixture.componentInstance.trigger.menuOpen) .withContext('Expected menu to be open') .toBe(true); - })); + }); - it('should detach the lazy content when the menu is closed', fakeAsync(() => { + it('should detach the lazy content when the menu is closed', async () => { const fixture = TestBed.createComponent(SimpleLazyMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); fixture.detectChanges(); const checkers = fixture.componentInstance.destroyCheckers.toArray(); @@ -1232,7 +1172,7 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); + await wait(200); fixture.detectChanges(); expect(fixture.componentInstance.items.length) @@ -1241,7 +1181,7 @@ describe('MatMenu', () => { expect(checkers.map(d => d.destroyed)) .withContext('Expected ngOnDestroy to have been called') .toEqual([true, true]); - })); + }); it('should focus the first menu item when opening a lazy menu via keyboard', () => { const fixture = TestBed.createComponent(SimpleLazyMenu); @@ -1256,12 +1196,11 @@ describe('MatMenu', () => { expect(document.activeElement).withContext('Expected first item to be focused').toBe(item); }); - it('should be able to open the same menu with a different context', fakeAsync(() => { + it('should be able to open the same menu with a different context', () => { const fixture = TestBed.createComponent(LazyMenuWithContext); fixture.detectChanges(); fixture.componentInstance.triggerOne.openMenu(); fixture.detectChanges(); - tick(500); let item = overlayContainerElement.querySelector('.mat-mdc-menu-panel [mat-menu-item]')!; @@ -1269,39 +1208,35 @@ describe('MatMenu', () => { fixture.componentInstance.triggerOne.closeMenu(); fixture.detectChanges(); - tick(500); fixture.componentInstance.triggerTwo.openMenu(); fixture.detectChanges(); - tick(500); item = overlayContainerElement.querySelector('.mat-mdc-menu-panel [mat-menu-item]')!; expect(item.textContent!.trim()).toBe('two'); - })); + }); }); - it('does not open if the trigger element is disabled (including disabledInteractive)', fakeAsync(() => { + it('does not open if the trigger element is disabled (including disabledInteractive)', () => { const fixture = TestBed.createComponent(DisabledMenu); fixture.detectChanges(); const trigger = fixture.componentInstance.triggerEl.nativeElement; trigger.click(); fixture.detectChanges(); - tick(500); expect(overlayContainerElement.querySelector('.mat-mdc-menu-panel [mat-menu-item]')).toBeNull(); dispatchKeyboardEvent(trigger, 'keydown', ENTER); trigger.click(); fixture.detectChanges(); - tick(500); expect(overlayContainerElement.querySelector('.mat-mdc-menu-panel [mat-menu-item]')).toBeNull(); - })); + }); describe('positions', () => { let fixture: ComponentFixture; let trigger: HTMLElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(PositionedMenu); fixture.detectChanges(); @@ -1313,12 +1248,11 @@ describe('MatMenu', () => { // Push trigger to the right, so it has space to open "before" trigger.style.left = '100px'; - })); + }); - it('should append mat-menu-before if the x position is changed', fakeAsync(() => { + it('should append mat-menu-before if the x position is changed', () => { fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel') as HTMLElement; @@ -1331,12 +1265,11 @@ describe('MatMenu', () => { expect(panel.classList).toContain('mat-menu-after'); expect(panel.classList).not.toContain('mat-menu-before'); - })); + }); - it('should append mat-menu-above if the y position is changed', fakeAsync(() => { + it('should append mat-menu-above if the y position is changed', () => { fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel') as HTMLElement; @@ -1349,15 +1282,15 @@ describe('MatMenu', () => { expect(panel.classList).toContain('mat-menu-below'); expect(panel.classList).not.toContain('mat-menu-above'); - })); + }); - it('should update the position classes if the window is resized', fakeAsync(() => { + it('should update the position classes if the window is resized', async () => { trigger.style.position = 'fixed'; trigger.style.top = '300px'; fixture.componentInstance.yPosition = 'above'; fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); const panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel') as HTMLElement; @@ -1367,14 +1300,14 @@ describe('MatMenu', () => { trigger.style.top = '0'; dispatchFakeEvent(window, 'resize'); fixture.detectChanges(); - tick(500); + await wait(200); fixture.detectChanges(); expect(panel.classList).not.toContain('mat-menu-above'); expect(panel.classList).toContain('mat-menu-below'); - })); + }); - it('should be able to update the position after the first open', fakeAsync(() => { + it('should be able to update the position after the first open', async () => { trigger.style.position = 'fixed'; trigger.style.top = '200px'; @@ -1384,7 +1317,7 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); let panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel') as HTMLElement; @@ -1394,7 +1327,7 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.closeMenu(); fixture.detectChanges(); - tick(500); + await wait(200); fixture.componentInstance.yPosition = 'below'; fixture.changeDetectorRef.markForCheck(); @@ -1402,13 +1335,13 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel') as HTMLElement; expect(Math.floor(panel.getBoundingClientRect().top)) .withContext('Expected menu to open below') .toBe(Math.floor(trigger.getBoundingClientRect().bottom)); - })); + }); it('should not throw if a menu reposition is requested while the menu is closed', () => { expect(() => fixture.componentInstance.trigger.updatePosition()).not.toThrow(); @@ -1416,7 +1349,7 @@ describe('MatMenu', () => { }); describe('fallback positions', () => { - it('should fall back to "before" mode if "after" mode would not fit on screen', fakeAsync(() => { + it('should fall back to "before" mode if "after" mode would not fit on screen', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const trigger = fixture.componentInstance.triggerEl.nativeElement; @@ -1429,7 +1362,6 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const overlayPane = getOverlayPane(); const triggerRect = trigger.getBoundingClientRect(); const overlayRect = overlayPane.getBoundingClientRect(); @@ -1448,9 +1380,9 @@ describe('MatMenu', () => { expect(Math.floor(overlayRect.top)) .withContext(`Expected menu top position to be unchanged if it can fit in the viewport.`) .toBe(Math.floor(triggerRect.bottom)); - })); + }); - it('should fall back to "above" mode if "below" mode would not fit on screen', fakeAsync(() => { + it('should fall back to "above" mode if "below" mode would not fit on screen', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const trigger = fixture.componentInstance.triggerEl.nativeElement; @@ -1462,7 +1394,6 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const overlayPane = getOverlayPane(); const triggerRect = trigger.getBoundingClientRect(); const overlayRect = overlayPane.getBoundingClientRect(); @@ -1476,9 +1407,9 @@ describe('MatMenu', () => { expect(Math.floor(overlayRect.left)) .withContext(`Expected menu x position to be unchanged if it can fit in the viewport.`) .toBe(Math.floor(triggerRect.left)); - })); + }); - it('should re-position menu on both axes if both defaults would not fit', fakeAsync(() => { + it('should re-position menu on both axes if both defaults would not fit', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const trigger = fixture.componentInstance.triggerEl.nativeElement; @@ -1491,7 +1422,6 @@ describe('MatMenu', () => { fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const overlayPane = getOverlayPane(); const triggerRect = trigger.getBoundingClientRect(); const overlayRect = overlayPane.getBoundingClientRect(); @@ -1505,16 +1435,15 @@ describe('MatMenu', () => { expect(Math.floor(overlayRect.bottom)) .withContext(`Expected menu to open in "above" position if "below" position wouldn't fit.`) .toBe(Math.floor(triggerRect.top)); - })); + }); - it('should re-position a menu with custom position set', fakeAsync(() => { + it('should re-position a menu with custom position set', () => { const fixture = TestBed.createComponent(PositionedMenu); fixture.detectChanges(); const trigger = fixture.componentInstance.triggerEl.nativeElement; fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const overlayPane = getOverlayPane(); const triggerRect = trigger.getBoundingClientRect(); const overlayRect = overlayPane.getBoundingClientRect(); @@ -1534,7 +1463,7 @@ describe('MatMenu', () => { expect(Math.floor(overlayRect.top)) .withContext(`Expected menu to open in "below" position if "above" position wouldn't fit.`) .toBe(Math.floor(triggerRect.bottom)); - })); + }); function getOverlayPane(): HTMLElement { return overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement; @@ -1568,7 +1497,6 @@ describe('MatMenu', () => { openMenu() { this.fixture.componentInstance.trigger.openMenu(); this.fixture.detectChanges(); - tick(500); } get overlayRect() { @@ -1590,162 +1518,151 @@ describe('MatMenu', () => { let subject: OverlapSubject; describe('explicitly overlapping', () => { - beforeEach(fakeAsync(() => { + beforeEach(() => { subject = new OverlapSubject(OverlapMenu, {overlapTrigger: true}); - })); + }); - it('positions the overlay below the trigger', fakeAsync(() => { + it('positions the overlay below the trigger', () => { subject.openMenu(); - // Since the menu is overlaying the trigger, the overlay top should be the trigger top. // Since the menu is overlaying the trigger, the overlay top should be the trigger top. expect(Math.floor(subject.overlayRect.top)) .withContext(`Expected menu to open in default "below" position.`) .toBe(Math.floor(subject.triggerRect.top)); - })); + }); }); describe('not overlapping', () => { - beforeEach(fakeAsync(() => { + beforeEach(() => { subject = new OverlapSubject(OverlapMenu, {overlapTrigger: false}); - })); + }); - it('positions the overlay below the trigger', fakeAsync(() => { + it('positions the overlay below the trigger', () => { subject.openMenu(); - // Since the menu is below the trigger, the overlay top should be the trigger bottom. // Since the menu is below the trigger, the overlay top should be the trigger bottom. expect(Math.floor(subject.overlayRect.top)) .withContext(`Expected menu to open directly below the trigger.`) .toBe(Math.floor(subject.triggerRect.bottom)); - })); + }); - it('supports above position fall back', fakeAsync(() => { + it('supports above position fall back', () => { // Push trigger to the bottom part of viewport, so it doesn't have space to open // in its default "below" position below the trigger. subject.trigger.style.position = 'fixed'; subject.trigger.style.bottom = '0'; subject.openMenu(); - // Since the menu is above the trigger, the overlay bottom should be the trigger top. // Since the menu is above the trigger, the overlay bottom should be the trigger top. expect(Math.floor(subject.overlayRect.bottom)) .withContext( `Expected menu to open in "above" position if "below" position ` + `wouldn't fit.`, ) .toBe(Math.floor(subject.triggerRect.top)); - })); + }); - it('repositions the origin to be below, so the menu opens from the trigger', fakeAsync(() => { + it('repositions the origin to be below, so the menu opens from the trigger', () => { subject.openMenu(); subject.fixture.detectChanges(); expect(subject.menuPanel!.classList).toContain('mat-menu-below'); expect(subject.menuPanel!.classList).not.toContain('mat-menu-above'); - })); + }); }); }); describe('animations', () => { - it('should enable ripples on items by default', fakeAsync(() => { + it('should enable ripples on items by default', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const item = fixture.debugElement.query(By.css('.mat-mdc-menu-item'))!; const ripple = item.query(By.css('.mat-ripple'))!.injector.get(MatRipple); expect(ripple.disabled).toBe(false); - })); + }); - it('should disable ripples on disabled items', fakeAsync(() => { + it('should disable ripples on disabled items', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const items = fixture.debugElement.queryAll(By.css('.mat-mdc-menu-item')); const ripple = items[1].query(By.css('.mat-ripple'))!.injector.get(MatRipple); expect(ripple.disabled).toBe(true); - })); + }); - it('should disable ripples if disableRipple is set', fakeAsync(() => { + it('should disable ripples if disableRipple is set', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); // The third menu item in the `SimpleMenu` component has ripples disabled. const items = fixture.debugElement.queryAll(By.css('.mat-mdc-menu-item')); const ripple = items[2].query(By.css('.mat-ripple'))!.injector.get(MatRipple); expect(ripple.disabled).toBe(true); - })); + }); }); describe('close event', () => { let fixture: ComponentFixture; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); - })); + }); - it('should emit an event when a menu item is clicked', fakeAsync(() => { + it('should emit an event when a menu item is clicked', () => { const menuItem = overlayContainerElement.querySelector('[mat-menu-item]') as HTMLElement; menuItem.click(); fixture.detectChanges(); - tick(500); expect(fixture.componentInstance.closeCallback).toHaveBeenCalledWith('click'); expect(fixture.componentInstance.closeCallback).toHaveBeenCalledTimes(1); - })); + }); - it('should emit a close event when the backdrop is clicked', fakeAsync(() => { + it('should emit a close event when the backdrop is clicked', () => { const backdrop = overlayContainerElement.querySelector( '.cdk-overlay-backdrop', ) as HTMLElement; backdrop.click(); fixture.detectChanges(); - tick(500); expect(fixture.componentInstance.closeCallback).toHaveBeenCalledWith(undefined); expect(fixture.componentInstance.closeCallback).toHaveBeenCalledTimes(1); - })); + }); - it('should emit an event when pressing ESCAPE', fakeAsync(() => { + it('should emit an event when pressing ESCAPE', () => { const menu = overlayContainerElement.querySelector('.mat-mdc-menu-panel') as HTMLElement; dispatchKeyboardEvent(menu, 'keydown', ESCAPE); fixture.detectChanges(); - tick(500); expect(fixture.componentInstance.closeCallback).toHaveBeenCalledWith('keydown'); expect(fixture.componentInstance.closeCallback).toHaveBeenCalledTimes(1); - })); + }); - it('should complete the callback when the menu is destroyed', fakeAsync(() => { + it('should complete the callback when the menu is destroyed', () => { const completeCallback = jasmine.createSpy('complete callback'); fixture.componentInstance.menu.closed.subscribe(null, null, completeCallback); fixture.destroy(); - tick(500); expect(completeCallback).toHaveBeenCalled(); - })); + }); }); describe('nested menu', () => { @@ -1775,52 +1692,46 @@ describe('MatMenu', () => { overlay = overlayContainerElement; }); - it('should set the `triggersSubmenu` flags on the triggers', fakeAsync(() => { + it('should set the `triggersSubmenu` flags on the triggers', () => { expect(instance.rootTrigger.triggersSubmenu()).toBe(false); expect(instance.levelOneTrigger.triggersSubmenu()).toBe(true); expect(instance.levelTwoTrigger.triggersSubmenu()).toBe(true); - })); + }); - it('should set the `parentMenu` on the sub-menu instances', fakeAsync(() => { + it('should set the `parentMenu` on the sub-menu instances', () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); - tick(500); instance.levelOneTrigger.openMenu(); fixture.detectChanges(); - tick(500); instance.levelTwoTrigger.openMenu(); fixture.detectChanges(); - tick(500); expect(instance.rootMenu.parentMenu).toBeFalsy(); expect(instance.levelOneMenu.parentMenu).toBe(instance.rootMenu); expect(instance.levelTwoMenu.parentMenu).toBe(instance.levelOneMenu); - })); + }); - it('should pass the layout direction the nested menus', fakeAsync(() => { + it('should pass the layout direction the nested menus', () => { direction = 'rtl'; instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); instance.levelOneTrigger.openMenu(); fixture.detectChanges(); - tick(500); instance.levelTwoTrigger.openMenu(); fixture.detectChanges(); - tick(500); expect(instance.rootMenu.direction).toBe('rtl'); expect(instance.levelOneMenu.direction).toBe('rtl'); expect(instance.levelTwoMenu.direction).toBe('rtl'); - })); + }); - it('should emit an event when the hover state of the menu items changes', fakeAsync(() => { + it('should emit an event when the hover state of the menu items changes', () => { instance.rootTrigger.openMenu(); fixture.detectChanges(); - tick(500); const spy = jasmine.createSpy('hover spy'); const subscription = instance.rootMenu._hovered().subscribe(spy); @@ -1828,20 +1739,18 @@ describe('MatMenu', () => { dispatchMouseEvent(menuItems[0], 'mouseenter'); fixture.detectChanges(); - tick(500); expect(spy).toHaveBeenCalledTimes(1); dispatchMouseEvent(menuItems[1], 'mouseenter'); fixture.detectChanges(); - tick(500); expect(spy).toHaveBeenCalledTimes(2); subscription.unsubscribe(); - })); + }); - it('should toggle a nested menu when its trigger is hovered', fakeAsync(() => { + it('should toggle a nested menu when its trigger is hovered', async () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) @@ -1853,7 +1762,6 @@ describe('MatMenu', () => { dispatchMouseEvent(levelOneTrigger, 'mouseenter'); fixture.detectChanges(); - tick(); fixture.detectChanges(); expect(levelOneTrigger.classList) @@ -1865,7 +1773,7 @@ describe('MatMenu', () => { dispatchMouseEvent(items[items.indexOf(levelOneTrigger) + 1], 'mouseenter'); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') @@ -1874,9 +1782,9 @@ describe('MatMenu', () => { 'mat-mdc-menu-item-highlighted', 'Expected the trigger to not be highlighted', ); - })); + }); - it('should close all the open sub-menus when the hover state is changed at the root', fakeAsync(() => { + it('should close all the open sub-menus when the hover state is changed at the root', async () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); @@ -1885,12 +1793,10 @@ describe('MatMenu', () => { dispatchMouseEvent(levelOneTrigger, 'mouseenter'); fixture.detectChanges(); - tick(); const levelTwoTrigger = overlay.querySelector('#level-two-trigger')! as HTMLElement; dispatchMouseEvent(levelTwoTrigger, 'mouseenter'); fixture.detectChanges(); - tick(); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected three open menus') @@ -1898,23 +1804,23 @@ describe('MatMenu', () => { dispatchMouseEvent(items[items.indexOf(levelOneTrigger) + 1], 'mouseenter'); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') .toBe(1); - })); + }); - it('should close submenu when hovering over disabled sibling item', fakeAsync(() => { + it('should close submenu when hovering over disabled sibling item', async () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); - tick(500); + await wait(200); const items = fixture.debugElement.queryAll(By.directive(MatMenuItem)); dispatchFakeEvent(items[0].nativeElement, 'mouseenter'); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') @@ -1927,17 +1833,16 @@ describe('MatMenu', () => { // Invoke the handler directly since the fake events are flaky on disabled elements. items[1].componentInstance._handleMouseEnter(); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') .toBe(1); - })); + }); - it('should not open submenu when hovering over disabled trigger', fakeAsync(() => { + it('should not open submenu when hovering over disabled trigger', () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') @@ -1952,17 +1857,15 @@ describe('MatMenu', () => { // Invoke the handler directly since the fake events are flaky on disabled elements. item.componentInstance._handleMouseEnter(); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected to remain at one open menu') .toBe(1); - })); + }); - it('should open a nested menu when its trigger is clicked', fakeAsync(() => { + it('should open a nested menu when its trigger is clicked', () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') .toBe(1); @@ -1971,7 +1874,6 @@ describe('MatMenu', () => { levelOneTrigger.click(); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') .toBe(2); @@ -1981,9 +1883,9 @@ describe('MatMenu', () => { expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected repeat clicks not to close the menu.') .toBe(2); - })); + }); - it('should open and close a nested menu with arrow keys in ltr', fakeAsync(() => { + it('should open and close a nested menu with arrow keys in ltr', async () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) @@ -2000,12 +1902,12 @@ describe('MatMenu', () => { expect(panels.length).withContext('Expected two open menus').toBe(2); dispatchKeyboardEvent(panels[1], 'keydown', LEFT_ARROW); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length).toBe(1); - })); + }); - it('should open and close a nested menu with the arrow keys in rtl', fakeAsync(() => { + it('should open and close a nested menu with the arrow keys in rtl', async () => { direction = 'rtl'; instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); @@ -2023,45 +1925,42 @@ describe('MatMenu', () => { expect(panels.length).withContext('Expected two open menus').toBe(2); dispatchKeyboardEvent(panels[1], 'keydown', RIGHT_ARROW); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length).toBe(1); - })); + }); - it('should not do anything with the arrow keys for a top-level menu', fakeAsync(() => { + it('should not do anything with the arrow keys for a top-level menu', () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); - tick(500); const menu = overlay.querySelector('.mat-mdc-menu-panel')!; dispatchKeyboardEvent(menu, 'keydown', RIGHT_ARROW); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one menu to remain open') .toBe(1); dispatchKeyboardEvent(menu, 'keydown', LEFT_ARROW); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one menu to remain open') .toBe(1); - })); + }); - it('should close all of the menus when the backdrop is clicked', fakeAsync(() => { + it('should close all of the menus when the backdrop is clicked', async () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); - tick(500); + await wait(200); instance.levelOneTrigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); instance.levelTwoTrigger.openMenu(); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected three open menus') @@ -2075,17 +1974,16 @@ describe('MatMenu', () => { (overlay.querySelector('.cdk-overlay-backdrop')! as HTMLElement).click(); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected no open menus') .toBe(0); - })); + }); - it('should shift focus between the sub-menus', fakeAsync(() => { + it('should shift focus between the sub-menus', () => { instance.rootTrigger.openMenu(); fixture.detectChanges(); - tick(500); expect(overlay.querySelector('.mat-mdc-menu-panel')!.contains(document.activeElement)) .withContext('Expected focus to be inside the root menu') @@ -2093,7 +1991,6 @@ describe('MatMenu', () => { instance.levelOneTrigger.openMenu(); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel')[1].contains(document.activeElement)) .withContext('Expected focus to be inside the first nested menu') @@ -2101,7 +1998,6 @@ describe('MatMenu', () => { instance.levelTwoTrigger.openMenu(); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel')[2].contains(document.activeElement)) .withContext('Expected focus to be inside the second nested menu') @@ -2109,7 +2005,6 @@ describe('MatMenu', () => { instance.levelTwoTrigger.closeMenu(); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel')[1].contains(document.activeElement)) .withContext('Expected focus to be back inside the first nested menu') @@ -2117,14 +2012,13 @@ describe('MatMenu', () => { instance.levelOneTrigger.closeMenu(); fixture.detectChanges(); - tick(500); expect(overlay.querySelector('.mat-mdc-menu-panel')!.contains(document.activeElement)) .withContext('Expected focus to be back inside the root menu') .toBe(true); - })); + }); - it('should restore focus to a nested trigger when navigating via the keyboard', fakeAsync(() => { + it('should restore focus to a nested trigger when navigating via the keyboard', () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); @@ -2139,88 +2033,79 @@ describe('MatMenu', () => { LEFT_ARROW, ); fixture.detectChanges(); - tick(500); expect(spy).toHaveBeenCalled(); - })); + }); - it('should position the sub-menu to the right edge of the trigger in ltr', fakeAsync(() => { + it('should position the sub-menu to the right edge of the trigger in ltr', () => { instance.rootTriggerEl.nativeElement.style.position = 'fixed'; instance.rootTriggerEl.nativeElement.style.left = '50px'; instance.rootTriggerEl.nativeElement.style.top = '200px'; instance.rootTrigger.openMenu(); fixture.detectChanges(); - tick(500); instance.levelOneTrigger.openMenu(); fixture.detectChanges(); - tick(500); const triggerRect = overlay.querySelector('#level-one-trigger')!.getBoundingClientRect(); const panelRect = overlay.querySelectorAll('.mat-mdc-menu-panel')[1].getBoundingClientRect(); expect(Math.round(triggerRect.right)).toBe(Math.round(panelRect.left)); expect(Math.round(triggerRect.top)).toBe(Math.round(panelRect.top) + MENU_PANEL_TOP_PADDING); - })); + }); - it('should fall back to aligning to the left edge of the trigger in ltr', fakeAsync(() => { + it('should fall back to aligning to the left edge of the trigger in ltr', () => { instance.rootTriggerEl.nativeElement.style.position = 'fixed'; instance.rootTriggerEl.nativeElement.style.right = '10px'; instance.rootTriggerEl.nativeElement.style.top = '200px'; instance.rootTrigger.openMenu(); fixture.detectChanges(); - tick(500); instance.levelOneTrigger.openMenu(); fixture.detectChanges(); - tick(500); const triggerRect = overlay.querySelector('#level-one-trigger')!.getBoundingClientRect(); const panelRect = overlay.querySelectorAll('.mat-mdc-menu-panel')[1].getBoundingClientRect(); expect(Math.round(triggerRect.left)).toBe(Math.round(panelRect.right)); expect(Math.round(triggerRect.top)).toBe(Math.round(panelRect.top) + MENU_PANEL_TOP_PADDING); - })); + }); - it('should position the sub-menu to the left edge of the trigger in rtl', fakeAsync(() => { + it('should position the sub-menu to the left edge of the trigger in rtl', () => { direction = 'rtl'; instance.rootTriggerEl.nativeElement.style.position = 'fixed'; instance.rootTriggerEl.nativeElement.style.left = '50%'; instance.rootTriggerEl.nativeElement.style.top = '200px'; instance.rootTrigger.openMenu(); fixture.detectChanges(); - tick(500); instance.levelOneTrigger.openMenu(); fixture.detectChanges(); - tick(500); const triggerRect = overlay.querySelector('#level-one-trigger')!.getBoundingClientRect(); const panelRect = overlay.querySelectorAll('.mat-mdc-menu-panel')[1].getBoundingClientRect(); expect(Math.round(triggerRect.left)).toBe(Math.round(panelRect.right)); expect(Math.round(triggerRect.top)).toBe(Math.round(panelRect.top) + MENU_PANEL_TOP_PADDING); - })); + }); - it('should fall back to aligning to the right edge of the trigger in rtl', fakeAsync(() => { + it('should fall back to aligning to the right edge of the trigger in rtl', () => { direction = 'rtl'; instance.rootTriggerEl.nativeElement.style.position = 'fixed'; instance.rootTriggerEl.nativeElement.style.left = '10px'; instance.rootTriggerEl.nativeElement.style.top = '200px'; instance.rootTrigger.openMenu(); fixture.detectChanges(); - tick(500); instance.levelOneTrigger.openMenu(); fixture.detectChanges(); - tick(500); const triggerRect = overlay.querySelector('#level-one-trigger')!.getBoundingClientRect(); const panelRect = overlay.querySelectorAll('.mat-mdc-menu-panel')[1].getBoundingClientRect(); expect(Math.round(triggerRect.right)).toBe(Math.round(panelRect.left)); expect(Math.round(triggerRect.top)).toBe(Math.round(panelRect.top) + MENU_PANEL_TOP_PADDING); - })); + }); it('should account for custom padding when offsetting the sub-menu', () => { instance.rootTriggerEl.nativeElement.style.position = 'fixed'; @@ -2241,7 +2126,7 @@ describe('MatMenu', () => { expect(Math.round(triggerRect.top)).toBe(Math.round(panelRect.top) + 15); }); - it('should close all of the menus when an item is clicked', fakeAsync(() => { + it('should close all of the menus when an item is clicked', async () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); @@ -2257,14 +2142,14 @@ describe('MatMenu', () => { (menus[2].querySelector('.mat-mdc-menu-item')! as HTMLElement).click(); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected no open menus') .toBe(0); - })); + }); - it('should close all of the menus when the user tabs away', fakeAsync(() => { + it('should close all of the menus when the user tabs away', async () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); @@ -2280,17 +2165,16 @@ describe('MatMenu', () => { dispatchKeyboardEvent(menus[menus.length - 1], 'keydown', TAB); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected no open menus') .toBe(0); - })); + }); - it('should set a class on the menu items that trigger a sub-menu', fakeAsync(() => { + it('should set a class on the menu items that trigger a sub-menu', () => { instance.rootTrigger.openMenu(); fixture.detectChanges(); - tick(500); const menuItems = overlay.querySelectorAll('[mat-menu-item]'); @@ -2304,26 +2188,24 @@ describe('MatMenu', () => { expect(menuItems[0].classList).not.toContain('mat-mdc-menu-item-submenu-trigger'); expect(menuItems[0].querySelector('.mat-mdc-menu-submenu-icon')).toBeFalsy(); - })); + }); - it('should not change focus origin if origin not specified for trigger', fakeAsync(() => { + it('should not change focus origin if origin not specified for trigger', () => { instance.levelOneTrigger.openMenu(); fixture.detectChanges(); - tick(500); instance.levelOneTrigger.focus('mouse'); fixture.detectChanges(); instance.levelTwoTrigger.focus(); fixture.detectChanges(); - tick(500); const levelTwoTrigger = overlay.querySelector('#level-two-trigger')! as HTMLElement; expect(levelTwoTrigger.classList).toContain('cdk-focused'); expect(levelTwoTrigger.classList).toContain('cdk-mouse-focused'); - })); + }); - it('should close all of the menus when the root is closed programmatically', fakeAsync(() => { + it('should close all of the menus when the root is closed programmatically', async () => { instance.rootTrigger.openMenu(); fixture.detectChanges(); @@ -2339,17 +2221,16 @@ describe('MatMenu', () => { instance.rootTrigger.closeMenu(); fixture.detectChanges(); - tick(500); + await wait(200); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected no open menus') .toBe(0); - })); + }); - it('should toggle a nested menu when its trigger is added after init', fakeAsync(() => { + it('should toggle a nested menu when its trigger is added after init', () => { instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') .toBe(1); @@ -2362,9 +2243,7 @@ describe('MatMenu', () => { dispatchMouseEvent(lazyTrigger, 'mouseenter'); fixture.detectChanges(); - tick(500); fixture.detectChanges(); - flush(); expect(lazyTrigger.classList) .withContext('Expected the trigger to be highlighted') @@ -2372,12 +2251,11 @@ describe('MatMenu', () => { expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') .toBe(2); - })); + }); - it('should prevent the default mousedown action if the menu item opens a sub-menu', fakeAsync(() => { + it('should prevent the default mousedown action if the menu item opens a sub-menu', () => { instance.rootTrigger.openMenu(); fixture.detectChanges(); - tick(500); const event = createMouseEvent('mousedown'); Object.defineProperty(event, 'buttons', {get: () => 1}); @@ -2385,12 +2263,11 @@ describe('MatMenu', () => { dispatchEvent(overlay.querySelector('[mat-menu-item]')!, event); fixture.detectChanges(); - tick(500); expect(event.preventDefault).toHaveBeenCalled(); - })); + }); - it('should handle the items being rendered in a repeater', fakeAsync(() => { + it('should handle the items being rendered in a repeater', () => { const repeaterFixture = TestBed.createComponent(NestedMenuRepeater); overlay = overlayContainerElement; @@ -2398,27 +2275,24 @@ describe('MatMenu', () => { repeaterFixture.componentInstance.rootTriggerEl.nativeElement.click(); repeaterFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') .toBe(1); dispatchMouseEvent(overlay.querySelector('.level-one-trigger')!, 'mouseenter'); repeaterFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') .toBe(2); - })); + }); - it('should be able to trigger the same nested menu from different triggers', fakeAsync(() => { + it('should be able to trigger the same nested menu from different triggers', () => { const repeaterFixture = TestBed.createComponent(NestedMenuRepeater); overlay = overlayContainerElement; repeaterFixture.detectChanges(); repeaterFixture.componentInstance.rootTriggerEl.nativeElement.click(); repeaterFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') .toBe(1); @@ -2427,28 +2301,25 @@ describe('MatMenu', () => { dispatchMouseEvent(triggers[0], 'mouseenter'); repeaterFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') .toBe(2); dispatchMouseEvent(triggers[1], 'mouseenter'); repeaterFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') .toBe(2); - })); + }); - it('should close the initial menu if the user moves away while animating', fakeAsync(() => { + it('should close the initial menu if the user moves away while animating', () => { const repeaterFixture = TestBed.createComponent(NestedMenuRepeater); overlay = overlayContainerElement; repeaterFixture.detectChanges(); repeaterFixture.componentInstance.rootTriggerEl.nativeElement.click(); repeaterFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') .toBe(1); @@ -2457,59 +2328,53 @@ describe('MatMenu', () => { dispatchMouseEvent(triggers[0], 'mouseenter'); repeaterFixture.detectChanges(); - tick(100); dispatchMouseEvent(triggers[1], 'mouseenter'); repeaterFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') .toBe(2); - })); + }); it( 'should be able to open a submenu through an item that is not a direct descendant ' + 'of the panel', - fakeAsync(() => { + () => { const nestedFixture = TestBed.createComponent(SubmenuDeclaredInsideParentMenu); overlay = overlayContainerElement; nestedFixture.detectChanges(); nestedFixture.componentInstance.rootTriggerEl.nativeElement.click(); nestedFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') .toBe(1); dispatchMouseEvent(overlay.querySelector('.level-one-trigger')!, 'mouseenter'); nestedFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') .toBe(2); - }), + }, ); it( 'should not close when hovering over a menu item inside a sub-menu panel that is declared' + 'inside the root menu', - fakeAsync(() => { + () => { const nestedFixture = TestBed.createComponent(SubmenuDeclaredInsideParentMenu); overlay = overlayContainerElement; nestedFixture.detectChanges(); nestedFixture.componentInstance.rootTriggerEl.nativeElement.click(); nestedFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected one open menu') .toBe(1); dispatchMouseEvent(overlay.querySelector('.level-one-trigger')!, 'mouseenter'); nestedFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') @@ -2517,15 +2382,14 @@ describe('MatMenu', () => { dispatchMouseEvent(overlay.querySelector('.level-two-item')!, 'mouseenter'); nestedFixture.detectChanges(); - tick(500); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus to remain') .toBe(2); - }), + }, ); - it('should preserve focus on a child menu trigger when hovering another trigger', fakeAsync(() => { + it('should preserve focus on a child menu trigger when hovering another trigger', () => { dispatchFakeEvent(instance.rootTriggerEl.nativeElement, 'mousedown'); instance.rootTriggerEl.nativeElement.click(); fixture.detectChanges(); @@ -2535,28 +2399,25 @@ describe('MatMenu', () => { dispatchMouseEvent(levelOneTrigger, 'mouseenter'); fixture.detectChanges(); - tick(); expect(overlay.querySelectorAll('.mat-mdc-menu-panel').length) .withContext('Expected two open menus') .toBe(2); dispatchMouseEvent(items[items.indexOf(levelOneTrigger) + 1], 'mouseenter'); fixture.detectChanges(); - tick(500); expect(document.activeElement).toBe( levelOneTrigger, 'Expected focus not to be returned to the initial trigger.', ); - })); + }); }); - it('should have a focus indicator', fakeAsync(() => { + it('should have a focus indicator', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); fixture.componentInstance.trigger.openMenu(); fixture.detectChanges(); - tick(500); const menuItemNativeElements = Array.from( overlayContainerElement.querySelectorAll('.mat-mdc-menu-item'), ); @@ -2564,11 +2425,11 @@ describe('MatMenu', () => { expect( menuItemNativeElements.every(element => element.classList.contains('mat-focus-indicator')), ).toBe(true); - })); + }); }); describe('MatMenu default overrides', () => { - beforeEach(fakeAsync(() => { + beforeEach(() => { TestBed.configureTestingModule({ providers: [ { @@ -2578,9 +2439,9 @@ describe('MatMenu default overrides', () => { {provide: MATERIAL_ANIMATIONS, useValue: {animationsDisabled: true}}, ], }); - })); + }); - it('should allow for the default menu options to be overridden', fakeAsync(() => { + it('should allow for the default menu options to be overridden', () => { const fixture = TestBed.createComponent(SimpleMenu); fixture.detectChanges(); const menu = fixture.componentInstance.menu; @@ -2588,7 +2449,7 @@ describe('MatMenu default overrides', () => { expect(menu.overlapTrigger).toBe(true); expect(menu.xPosition).toBe('before'); expect(menu.yPosition).toBe('above'); - })); + }); }); const SIMPLE_MENU_TEMPLATE = ` @@ -2629,6 +2490,7 @@ class FakeIcon {} @Component({ template: SIMPLE_MENU_TEMPLATE, imports: [MatMenuTrigger, MatMenu, MatMenuItem, FakeIcon], + selector: 'simple-menu', }) class SimpleMenu { @ViewChild(MatMenuTrigger) trigger!: MatMenuTrigger; @@ -2649,6 +2511,7 @@ class SimpleMenu { template: SIMPLE_MENU_TEMPLATE, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatMenuTrigger, MatMenu, MatMenuItem, FakeIcon], + selector: 'simple-menu-on-push', }) class SimpleMenuOnPush extends SimpleMenu {} From 2851147187fa9779369a3c552d063c1cbd817a12 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 9 Mar 2026 17:26:58 +0100 Subject: [PATCH 028/123] refactor(material/datepicker): switch tests away from fakeAsync (#32903) Reworks the datepicker tests not to depend on `fakeAsync`. (cherry picked from commit 0affe5aaa704fa0bf923b1be3266515e41d5e350) --- .../datepicker/date-range-input.spec.ts | 89 +-- .../datepicker/datepicker-actions.spec.ts | 64 +- src/material/datepicker/datepicker.spec.ts | 704 +++++++----------- 3 files changed, 322 insertions(+), 535 deletions(-) diff --git a/src/material/datepicker/date-range-input.spec.ts b/src/material/datepicker/date-range-input.spec.ts index 2eee25e8b69b..02622e34ef93 100644 --- a/src/material/datepicker/date-range-input.spec.ts +++ b/src/material/datepicker/date-range-input.spec.ts @@ -7,7 +7,7 @@ import { provideFakeDirectionality, } from '@angular/cdk/testing/private'; import {Component, Directive, ElementRef, Provider, Type, ViewChild} from '@angular/core'; -import {ComponentFixture, fakeAsync, flush, TestBed, tick} from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import { FormControl, FormGroup, @@ -183,7 +183,7 @@ describe('MatDateRangeInput', () => { expect(rangeInput.getAttribute('aria-describedby')).toBe(labelId); }); - it('should preserve aria-describedby set directly in the DOM', fakeAsync(() => { + it('should preserve aria-describedby set directly in the DOM', () => { const fixture = createComponent(StandardRangePicker); const rangeInput = fixture.nativeElement.querySelector('.mat-date-range-input'); @@ -193,7 +193,7 @@ describe('MatDateRangeInput', () => { const hint = fixture.nativeElement.querySelector('.mat-mdc-form-field-hint'); expect(rangeInput.getAttribute('aria-describedby')).toBe(`${hint.getAttribute('id')} custom`); - })); + }); it('should not set aria-labelledby if the form field does not have a label', () => { const fixture = createComponent(RangePickerNoLabel); @@ -204,7 +204,7 @@ describe('MatDateRangeInput', () => { expect(end.nativeElement.getAttribute('aria-labelledby')).toBeFalsy(); }); - it('should set aria-labelledby of the overlay to the form field label', fakeAsync(() => { + it('should set aria-labelledby of the overlay to the form field label', () => { const fixture = createComponent(StandardRangePicker); fixture.detectChanges(); @@ -214,12 +214,11 @@ describe('MatDateRangeInput', () => { fixture.componentInstance.rangePicker.open(); fixture.detectChanges(); - tick(); const popup = document.querySelector('.cdk-overlay-pane .mat-datepicker-content-container')!; expect(popup).toBeTruthy(); expect(popup.getAttribute('aria-labelledby')).toBe(label.getAttribute('id')); - })); + }); it('should float the form field label when either input is focused', () => { const fixture = createComponent(StandardRangePicker); @@ -262,10 +261,9 @@ describe('MatDateRangeInput', () => { expect(rangeInput.empty).toBe(false); }); - it('should mark the range controls as invalid if the start value is after the end value', fakeAsync(() => { + it('should mark the range controls as invalid if the start value is after the end value', () => { const fixture = createComponent(StandardRangePicker); fixture.detectChanges(); - tick(); const {start, end} = fixture.componentInstance.range.controls; // The default error state matcher only checks if the controls have been touched. @@ -289,7 +287,7 @@ describe('MatDateRangeInput', () => { expect(fixture.componentInstance.rangeInput.errorState).toBe(false); expect(start.errors?.['matStartDateInvalid']).toBeFalsy(); expect(end.errors?.['matEndDateInvalid']).toBeFalsy(); - })); + }); it('should pass the minimum date from the range input to the inner inputs', () => { const fixture = createComponent(StandardRangePicker); @@ -434,10 +432,9 @@ describe('MatDateRangeInput', () => { expect(startInput.focus).toHaveBeenCalled(); }); - it('should focus the end input when clicking on the form field when start has a value', fakeAsync(() => { + it('should focus the end input when clicking on the form field when start has a value', () => { const fixture = createComponent(StandardRangePicker); fixture.detectChanges(); - tick(); const endInput = fixture.componentInstance.end.nativeElement; const formFieldContainer = fixture.nativeElement.querySelector('.mat-mdc-text-field-wrapper'); @@ -448,10 +445,9 @@ describe('MatDateRangeInput', () => { formFieldContainer.click(); fixture.detectChanges(); - tick(); expect(endInput.focus).toHaveBeenCalled(); - })); + }); it('should revalidate if a validation field changes', () => { const fixture = createComponent(StandardRangePicker); @@ -526,18 +522,16 @@ describe('MatDateRangeInput', () => { expect(end.nativeElement.getAttribute('max')).toContain('2020'); }); - it('should pass the range input value through to the calendar', fakeAsync(() => { + it('should pass the range input value through to the calendar', () => { const fixture = createComponent(StandardRangePicker); const {start, end} = fixture.componentInstance.range.controls; const overlayContainerElement = TestBed.inject(OverlayContainer).getContainerElement(); start.setValue(new Date(2020, 1, 2)); end.setValue(new Date(2020, 1, 5)); fixture.detectChanges(); - tick(); fixture.componentInstance.rangePicker.open(); fixture.detectChanges(); - tick(); const rangeTexts = Array.from( overlayContainerElement!.querySelectorAll( @@ -550,9 +544,9 @@ describe('MatDateRangeInput', () => { ).map(cell => cell.textContent!.trim()); expect(rangeTexts).toEqual(['2', '3', '4', '5']); - })); + }); - it("should have aria-desciredby on start and end date cells that point to the 's accessible name", fakeAsync(() => { + it("should have aria-desciredby on start and end date cells that point to the 's accessible name", () => { const fixture = createComponent(StandardRangePicker); const {start, end} = fixture.componentInstance.range.controls; const overlayContainerElement = TestBed.inject(OverlayContainer).getContainerElement(); @@ -560,11 +554,9 @@ describe('MatDateRangeInput', () => { start.setValue(new Date(2020, 1, 2)); end.setValue(new Date(2020, 1, 5)); fixture.detectChanges(); - tick(); fixture.componentInstance.rangePicker.open(); fixture.detectChanges(); - tick(); const rangeStart = overlayContainerElement!.querySelector('.mat-calendar-body-range-start'); const rangeEnd = overlayContainerElement!.querySelector('.mat-calendar-body-range-end'); @@ -607,9 +599,9 @@ describe('MatDateRangeInput', () => { .join(' ') .trim(), ).toEqual('End date'); - })); + }); - it('should pass the comparison range through to the calendar', fakeAsync(() => { + it('should pass the comparison range through to the calendar', () => { const fixture = createComponent(StandardRangePicker); const overlayContainerElement = TestBed.inject(OverlayContainer).getContainerElement(); @@ -625,7 +617,6 @@ describe('MatDateRangeInput', () => { fixture.componentInstance.rangePicker.open(); fixture.detectChanges(); - tick(); const rangeTexts = Array.from( overlayContainerElement!.querySelectorAll( @@ -638,9 +629,9 @@ describe('MatDateRangeInput', () => { ).map(cell => cell.textContent!.trim()); expect(rangeTexts).toEqual(['2', '3', '4', '5']); - })); + }); - it('should preserve the preselected values when assigning through ngModel', fakeAsync(() => { + it('should preserve the preselected values when assigning through ngModel', () => { const start = new Date(2020, 1, 2); const end = new Date(2020, 1, 2); const fixture = createComponent(RangePickerNgModel); @@ -648,21 +639,17 @@ describe('MatDateRangeInput', () => { fixture.componentInstance.end = end; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - tick(); - fixture.detectChanges(); expect(fixture.componentInstance.start).toBe(start); expect(fixture.componentInstance.end).toBe(end); - })); + }); - it('should preserve the values when assigning both together through ngModel', fakeAsync(() => { + it('should preserve the values when assigning both together through ngModel', () => { const assignAndAssert = (start: Date, end: Date) => { fixture.componentInstance.start = start; fixture.componentInstance.end = end; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - tick(); - fixture.detectChanges(); expect(fixture.componentInstance.start).toBe(start); expect(fixture.componentInstance.end).toBe(end); }; @@ -672,42 +659,39 @@ describe('MatDateRangeInput', () => { assignAndAssert(new Date(2020, 1, 2), new Date(2020, 1, 5)); assignAndAssert(new Date(2020, 2, 2), new Date(2020, 2, 5)); - })); + }); - it('should not be dirty on init when there is no value', fakeAsync(() => { + it('should not be dirty on init when there is no value', () => { const fixture = createComponent(RangePickerNgModel); fixture.detectChanges(); - flush(); const {startModel, endModel} = fixture.componentInstance; expect(startModel.dirty).toBe(false); expect(startModel.touched).toBe(false); expect(endModel.dirty).toBe(false); expect(endModel.touched).toBe(false); - })); + }); - it('should not be dirty on init when there is a value', fakeAsync(() => { + it('should not be dirty on init when there is a value', () => { const fixture = createComponent(RangePickerNgModel); fixture.componentInstance.start = new Date(2020, 1, 2); fixture.componentInstance.end = new Date(2020, 2, 2); fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); const {startModel, endModel} = fixture.componentInstance; expect(startModel.dirty).toBe(false); expect(startModel.touched).toBe(false); expect(endModel.dirty).toBe(false); expect(endModel.touched).toBe(false); - })); + }); - it('should mark the input as dirty once the user types in it', fakeAsync(() => { + it('should mark the input as dirty once the user types in it', () => { const fixture = createComponent(RangePickerNgModel); fixture.componentInstance.start = new Date(2020, 1, 2); fixture.componentInstance.end = new Date(2020, 2, 2); fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); const {startModel, endModel, startInput, endInput} = fixture.componentInstance; expect(startModel.dirty).toBe(false); @@ -716,8 +700,6 @@ describe('MatDateRangeInput', () => { endInput.nativeElement.value = '30/12/2020'; dispatchFakeEvent(endInput.nativeElement, 'input'); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(startModel.dirty).toBe(false); expect(endModel.dirty).toBe(true); @@ -725,17 +707,14 @@ describe('MatDateRangeInput', () => { startInput.nativeElement.value = '12/12/2020'; dispatchFakeEvent(startInput.nativeElement, 'input'); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(startModel.dirty).toBe(true); expect(endModel.dirty).toBe(true); - })); + }); - it('should mark both inputs as touched when the range picker is closed', fakeAsync(() => { + it('should mark both inputs as touched when the range picker is closed', () => { const fixture = createComponent(RangePickerNgModel); fixture.detectChanges(); - flush(); const {startModel, endModel, rangePicker} = fixture.componentInstance; expect(startModel.dirty).toBe(false); @@ -745,8 +724,6 @@ describe('MatDateRangeInput', () => { rangePicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(startModel.dirty).toBe(false); expect(startModel.touched).toBe(false); @@ -755,13 +732,12 @@ describe('MatDateRangeInput', () => { rangePicker.close(); fixture.detectChanges(); - flush(); expect(startModel.dirty).toBe(false); expect(startModel.touched).toBe(true); expect(endModel.dirty).toBe(false); expect(endModel.touched).toBe(true); - })); + }); it('should move focus to the start input when pressing backspace on an empty end input', () => { const fixture = createComponent(StandardRangePicker); @@ -1050,24 +1026,21 @@ describe('MatDateRangeInput', () => { expect(endInput.errorStateMatcher).toBe(matcher); }); - it('should only update model for input that changed', fakeAsync(() => { + it('should only update model for input that changed', () => { const fixture = createComponent(RangePickerNgModel); fixture.detectChanges(); - tick(); expect(fixture.componentInstance.startDateModelChangeCount).toBe(0); expect(fixture.componentInstance.endDateModelChangeCount).toBe(0); fixture.componentInstance.rangePicker.open(); fixture.detectChanges(); - tick(); const fromDate = new Date(2020, 0, 1); const toDate = new Date(2020, 0, 2); fixture.componentInstance.rangePicker.select(fromDate); fixture.detectChanges(); - tick(); expect(fixture.componentInstance.startDateModelChangeCount) .withContext('Start Date set once') @@ -1078,7 +1051,6 @@ describe('MatDateRangeInput', () => { fixture.componentInstance.rangePicker.select(toDate); fixture.detectChanges(); - tick(); expect(fixture.componentInstance.startDateModelChangeCount) .withContext('Start Date unchanged (set once)') @@ -1089,13 +1061,11 @@ describe('MatDateRangeInput', () => { fixture.componentInstance.rangePicker.open(); fixture.detectChanges(); - tick(); const fromDate2 = new Date(2021, 0, 1); const toDate2 = new Date(2021, 0, 2); fixture.componentInstance.rangePicker.select(fromDate2); fixture.detectChanges(); - tick(); expect(fixture.componentInstance.startDateModelChangeCount) .withContext('Start Date set twice') @@ -1106,7 +1076,6 @@ describe('MatDateRangeInput', () => { fixture.componentInstance.rangePicker.select(toDate2); fixture.detectChanges(); - tick(); expect(fixture.componentInstance.startDateModelChangeCount) .withContext('Start Date unchanged (set twice)') @@ -1114,7 +1083,7 @@ describe('MatDateRangeInput', () => { expect(fixture.componentInstance.endDateModelChangeCount) .withContext('End date set three times') .toBe(3); - })); + }); it('should mark the range picker as required when the entire group has the required validator', () => { const fixture = createComponent(StandardRangePicker); diff --git a/src/material/datepicker/datepicker-actions.spec.ts b/src/material/datepicker/datepicker-actions.spec.ts index e160ffb4fc34..03c55306cd95 100644 --- a/src/material/datepicker/datepicker-actions.spec.ts +++ b/src/material/datepicker/datepicker-actions.spec.ts @@ -1,5 +1,5 @@ import {Component, ElementRef, Type, ViewChild} from '@angular/core'; -import {ComponentFixture, TestBed, fakeAsync, flush, tick} from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FormControl, ReactiveFormsModule} from '@angular/forms'; import {MATERIAL_ANIMATIONS, provideNativeDateAdapter} from '../core'; import {MatInputModule} from '../input'; @@ -19,43 +19,38 @@ describe('MatDatepickerActions', () => { return TestBed.createComponent(component); } - it('should render the actions inside calendar panel in popup mode', fakeAsync(() => { + it('should render the actions inside calendar panel in popup mode', () => { const fixture = createComponent(DatepickerWithActions); fixture.detectChanges(); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const actions = document.querySelector('.mat-datepicker-content .mat-datepicker-actions'); expect(actions).toBeTruthy(); expect(actions?.querySelector('.cancel')).toBeTruthy(); expect(actions?.querySelector('.apply')).toBeTruthy(); - })); + }); - it('should render the actions inside calendar panel in touch UI mode', fakeAsync(() => { + it('should render the actions inside calendar panel in touch UI mode', () => { const fixture = createComponent(DatepickerWithActions); fixture.componentInstance.touchUi = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const actions = document.querySelector('.mat-datepicker-content .mat-datepicker-actions'); expect(actions).toBeTruthy(); expect(actions?.querySelector('.cancel')).toBeTruthy(); expect(actions?.querySelector('.apply')).toBeTruthy(); - })); + }); - it('should not assign the value or close the datepicker when a value is selected', fakeAsync(() => { + it('should not assign the value or close the datepicker when a value is selected', () => { const fixture = createComponent(DatepickerWithActions); fixture.detectChanges(); const {control, datepicker, onDateChange, input} = fixture.componentInstance; datepicker.open(); fixture.detectChanges(); - tick(); const content = document.querySelector('.mat-datepicker-content')!; const cells = content.querySelectorAll('.mat-calendar-body-cell'); @@ -68,23 +63,20 @@ describe('MatDatepickerActions', () => { cells[10].click(); fixture.detectChanges(); - flush(); expect(datepicker.opened).toBe(true); expect(input.nativeElement.value).toBeFalsy(); expect(control.value).toBeFalsy(); expect(onDateChange).not.toHaveBeenCalled(); expect(content.querySelector('.mat-calendar-body-selected')).toBeTruthy(); - })); + }); - it('should close without changing the value when clicking on the cancel button', fakeAsync(() => { + it('should close without changing the value when clicking on the cancel button', () => { const fixture = createComponent(DatepickerWithActions); fixture.detectChanges(); const {control, datepicker, onDateChange, input} = fixture.componentInstance; datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const content = document.querySelector('.mat-datepicker-content')!; const cells = content.querySelectorAll('.mat-calendar-body-cell'); @@ -97,8 +89,6 @@ describe('MatDatepickerActions', () => { cells[10].click(); fixture.detectChanges(); - tick(); - flush(); expect(datepicker.opened).toBe(true); expect(input.nativeElement.value).toBeFalsy(); @@ -108,15 +98,14 @@ describe('MatDatepickerActions', () => { (content.querySelector('.cancel') as HTMLElement).click(); fixture.detectChanges(); - flush(); expect(datepicker.opened).toBe(false); expect(input.nativeElement.value).toBeFalsy(); expect(control.value).toBeFalsy(); expect(onDateChange).not.toHaveBeenCalled(); - })); + }); - it('should close while keeping the previous control value when clicking on cancel', fakeAsync(() => { + it('should close while keeping the previous control value when clicking on cancel', () => { const fixture = createComponent(DatepickerWithActions); fixture.detectChanges(); const {control, datepicker, onDateChange} = fixture.componentInstance; @@ -125,8 +114,6 @@ describe('MatDatepickerActions', () => { fixture.detectChanges(); datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const content = document.querySelector('.mat-datepicker-content')!; const cells = content.querySelectorAll('.mat-calendar-body-cell'); @@ -137,8 +124,6 @@ describe('MatDatepickerActions', () => { cells[10].click(); fixture.detectChanges(); - tick(); - flush(); expect(datepicker.opened).toBe(true); expect(control.value).toBe(value); @@ -146,21 +131,18 @@ describe('MatDatepickerActions', () => { (content.querySelector('.cancel') as HTMLElement).click(); fixture.detectChanges(); - flush(); expect(datepicker.opened).toBe(false); expect(control.value).toBe(value); expect(onDateChange).not.toHaveBeenCalled(); - })); + }); - it('should close and accept the value when clicking on the apply button', fakeAsync(() => { + it('should close and accept the value when clicking on the apply button', () => { const fixture = createComponent(DatepickerWithActions); fixture.detectChanges(); const {control, datepicker, onDateChange, input} = fixture.componentInstance; datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const content = document.querySelector('.mat-datepicker-content')!; const cells = content.querySelectorAll('.mat-calendar-body-cell'); @@ -173,8 +155,6 @@ describe('MatDatepickerActions', () => { cells[10].click(); fixture.detectChanges(); - tick(); - flush(); expect(datepicker.opened).toBe(true); expect(input.nativeElement.value).toBeFalsy(); @@ -184,22 +164,19 @@ describe('MatDatepickerActions', () => { (content.querySelector('.apply') as HTMLElement).click(); fixture.detectChanges(); - flush(); expect(datepicker.opened).toBe(false); expect(input.nativeElement.value).toBeTruthy(); expect(control.value).toBeTruthy(); expect(onDateChange).toHaveBeenCalledTimes(1); - })); + }); - it('should revert to the default behavior if the actions are removed', fakeAsync(() => { + it('should revert to the default behavior if the actions are removed', () => { const fixture = createComponent(DatepickerWithActions); fixture.detectChanges(); const {control, datepicker, onDateChange} = fixture.componentInstance; datepicker.open(); fixture.detectChanges(); - tick(); - flush(); let content = document.querySelector('.mat-datepicker-content')!; let actions = content.querySelector('.mat-datepicker-actions')!; @@ -212,8 +189,6 @@ describe('MatDatepickerActions', () => { cells[10].click(); fixture.detectChanges(); - tick(); - flush(); expect(datepicker.opened).toBe(true); expect(control.value).toBeFalsy(); @@ -221,7 +196,6 @@ describe('MatDatepickerActions', () => { (actions.querySelector('.cancel') as HTMLElement).click(); fixture.detectChanges(); - flush(); expect(datepicker.opened).toBe(false); expect(control.value).toBeFalsy(); @@ -243,15 +217,13 @@ describe('MatDatepickerActions', () => { cells[10].click(); fixture.detectChanges(); - tick(); - flush(); expect(datepicker.opened).toBe(false); expect(control.value).toBeTruthy(); expect(onDateChange).toHaveBeenCalledTimes(1); - })); + }); - it('should be able to toggle the actions while the datepicker is open', fakeAsync(() => { + it('should be able to toggle the actions while the datepicker is open', () => { const fixture = createComponent(DatepickerWithActions); fixture.componentInstance.renderActions = false; fixture.changeDetectorRef.markForCheck(); @@ -259,8 +231,6 @@ describe('MatDatepickerActions', () => { fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const content = document.querySelector('.mat-datepicker-content')!; expect(content.querySelector('.mat-datepicker-actions')).toBeFalsy(); @@ -274,7 +244,7 @@ describe('MatDatepickerActions', () => { fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(content.querySelector('.mat-datepicker-actions')).toBeFalsy(); - })); + }); }); @Component({ diff --git a/src/material/datepicker/datepicker.spec.ts b/src/material/datepicker/datepicker.spec.ts index 0392c35af15c..356b7f764fb6 100644 --- a/src/material/datepicker/datepicker.spec.ts +++ b/src/material/datepicker/datepicker.spec.ts @@ -31,7 +31,7 @@ import { ViewEncapsulation, signal, } from '@angular/core'; -import {ComponentFixture, TestBed, fakeAsync, flush, tick} from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import { FormControl, FormsModule, @@ -72,13 +72,17 @@ describe('MatDatepicker', () => { return TestBed.createComponent(component); } + function wait(milliseconds: number) { + return new Promise(resolve => setTimeout(resolve, milliseconds)); + } + describe('with native adapter', () => { describe('standard datepicker', () => { let fixture: ComponentFixture; let testComponent: StandardDatepicker; let model: MatDateSelectionModel; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(StandardDatepicker, [provideNativeDateAdapter()]); fixture.detectChanges(); @@ -86,13 +90,12 @@ describe('MatDatepicker', () => { model = fixture.debugElement .query(By.directive(MatDatepicker)) .injector.get(MatDateSelectionModel); - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); - })); + }); it('should initialize with correct value shown in input', () => { if (SUPPORTS_INTL) { @@ -100,18 +103,16 @@ describe('MatDatepicker', () => { } }); - it('open non-touch should open popup', fakeAsync(() => { + it('open non-touch should open popup', () => { expect(document.querySelector('.cdk-overlay-pane.mat-datepicker-popup')).toBeNull(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(document.querySelector('.cdk-overlay-pane.mat-datepicker-popup')).not.toBeNull(); - })); + }); - it('touch should open dialog', fakeAsync(() => { + it('touch should open dialog', () => { testComponent.touch = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); @@ -120,13 +121,11 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(document.querySelector('.mat-datepicker-dialog')).not.toBeNull(); - })); + }); - it('should not be able to open more than one dialog', fakeAsync(() => { + it('should not be able to open more than one dialog', () => { testComponent.touch = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); @@ -135,39 +134,31 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(500); - fixture.detectChanges(); dispatchKeyboardEvent(document.querySelector('.mat-calendar-body')!, 'keydown', ENTER); fixture.detectChanges(); - tick(100); testComponent.datepicker.open(); - tick(500); fixture.detectChanges(); - flush(); expect(document.querySelectorAll('.mat-datepicker-dialog').length).toBe(1); - })); + }); - it('should open datepicker if opened input is set to true', fakeAsync(() => { + it('should open datepicker if opened input is set to true', () => { testComponent.opened = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - tick(); - flush(); expect(document.querySelector('.mat-datepicker-content')).not.toBeNull(); testComponent.opened = false; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); expect(document.querySelector('.mat-datepicker-content')).toBeNull(); - })); + }); - it('open in disabled mode should not open the calendar', fakeAsync(() => { + it('open in disabled mode should not open the calendar', () => { testComponent.disabled = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); @@ -176,15 +167,13 @@ describe('MatDatepicker', () => { expect(document.querySelector('.mat-datepicker-dialog')).toBeNull(); testComponent.datepicker.open(); - tick(); fixture.detectChanges(); - flush(); expect(document.querySelector('.cdk-overlay-pane')).toBeNull(); expect(document.querySelector('.mat-datepicker-dialog')).toBeNull(); - })); + }); - it('disabled datepicker input should open the calendar if datepicker is enabled', fakeAsync(() => { + it('disabled datepicker input should open the calendar if datepicker is enabled', () => { testComponent.datepicker.disabled = false; testComponent.datepickerInput.disabled = true; fixture.changeDetectorRef.markForCheck(); @@ -194,17 +183,13 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(document.querySelector('.cdk-overlay-pane')).not.toBeNull(); - })); + }); - it('close should close popup', fakeAsync(() => { + it('close should close popup', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const popup = document.querySelector('.cdk-overlay-pane')!; expect(popup).not.toBeNull(); @@ -212,16 +197,13 @@ describe('MatDatepicker', () => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); expect(popup.getBoundingClientRect().height).toBe(0); - })); + }); - it('should close the popup when pressing ESCAPE', fakeAsync(() => { + it('should close the popup when pressing ESCAPE', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(testComponent.datepicker.opened) .withContext('Expected datepicker to be open.') @@ -229,18 +211,16 @@ describe('MatDatepicker', () => { const event = dispatchKeyboardEvent(document.body, 'keydown', ESCAPE); fixture.detectChanges(); - flush(); expect(testComponent.datepicker.opened) .withContext('Expected datepicker to be closed.') .toBe(false); expect(event.defaultPrevented).toBe(true); - })); + }); - it('should not close the popup when pressing ESCAPE with a modifier key', fakeAsync(() => { + it('should not close the popup when pressing ESCAPE with a modifier key', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); expect(testComponent.datepicker.opened) .withContext('Expected datepicker to be open.') @@ -250,26 +230,23 @@ describe('MatDatepicker', () => { alt: true, }); fixture.detectChanges(); - flush(); expect(testComponent.datepicker.opened) .withContext('Expected datepicker to stay open.') .toBe(true); expect(event.defaultPrevented).toBe(false); - })); + }); - it('should set the proper role on the popup', fakeAsync(() => { + it('should set the proper role on the popup', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const popup = document.querySelector('.mat-datepicker-content-container')!; expect(popup).toBeTruthy(); expect(popup.getAttribute('role')).toBe('dialog'); - })); + }); - it('should set aria-labelledby to the one from the input, if not placed inside a mat-form-field', fakeAsync(() => { + it('should set aria-labelledby to the one from the input, if not placed inside a mat-form-field', () => { expect(fixture.nativeElement.querySelector('mat-form-field')).toBeFalsy(); const input: HTMLInputElement = fixture.nativeElement.querySelector('input'); @@ -277,43 +254,37 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const popup = document.querySelector( '.cdk-overlay-pane .mat-datepicker-content-container', )!; expect(popup).toBeTruthy(); expect(popup.getAttribute('aria-labelledby')).toBe('test-label'); - })); + }); - it('close should close dialog', fakeAsync(() => { + it('close should close dialog', () => { testComponent.touch = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); expect(document.querySelector('.mat-datepicker-dialog')).not.toBeNull(); testComponent.datepicker.close(); fixture.detectChanges(); - flush(); expect(document.querySelector('.mat-datepicker-dialog')).toBeNull(); - })); + }); - it('setting selected via click should update input and close calendar', fakeAsync(() => { + it('setting selected via click should update input and close calendar', () => { testComponent.touch = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(document.querySelector('.mat-datepicker-dialog')).not.toBeNull(); expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1)); @@ -321,21 +292,18 @@ describe('MatDatepicker', () => { let cells = document.querySelectorAll('.mat-calendar-body-cell'); dispatchMouseEvent(cells[1], 'click'); fixture.detectChanges(); - flush(); expect(document.querySelector('.mat-datepicker-dialog')).toBeNull(); expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 2)); - })); + }); - it('setting selected via enter press should update input and close calendar', fakeAsync(() => { + it('setting selected via enter press should update input and close calendar', () => { testComponent.touch = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(document.querySelector('.mat-datepicker-dialog')).not.toBeNull(); expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1)); @@ -344,22 +312,19 @@ describe('MatDatepicker', () => { dispatchKeyboardEvent(calendarBodyEl, 'keydown', RIGHT_ARROW); fixture.detectChanges(); - tick(); - flush(); dispatchKeyboardEvent(calendarBodyEl, 'keydown', ENTER); fixture.detectChanges(); dispatchKeyboardEvent(calendarBodyEl, 'keyup', ENTER); fixture.detectChanges(); - flush(); expect(document.querySelector('.mat-datepicker-dialog')).toBeNull(); expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 2)); - })); + }); it( 'clicking the currently selected date should close the calendar ' + 'without firing selectedChanged', - fakeAsync(() => { + () => { const spy = jasmine.createSpy('selectionChanged spy'); const selectedSubscription = model.selectionChanged.subscribe(spy); @@ -367,7 +332,6 @@ describe('MatDatepicker', () => { const currentDay = changeCount; testComponent.datepicker.open(); fixture.detectChanges(); - tick(); expect(document.querySelector('mat-datepicker-content')).not.toBeNull(); expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, currentDay)); @@ -375,24 +339,21 @@ describe('MatDatepicker', () => { let cells = document.querySelectorAll('.mat-calendar-body-cell'); dispatchMouseEvent(cells[1], 'click'); fixture.detectChanges(); - flush(); } expect(spy).toHaveBeenCalledTimes(1); expect(document.querySelector('.mat-datepicker-dialog')).toBeNull(); expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 2)); selectedSubscription.unsubscribe(); - }), + }, ); - it('pressing enter on the currently selected date should close the calendar without firing selectedChanged', fakeAsync(() => { + it('pressing enter on the currently selected date should close the calendar without firing selectedChanged', () => { const spy = jasmine.createSpy('selectionChanged spy'); const selectedSubscription = model.selectionChanged.subscribe(spy); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); let calendarBodyEl = document.querySelector('.mat-calendar-body') as HTMLElement; expect(calendarBodyEl).not.toBeNull(); @@ -400,13 +361,12 @@ describe('MatDatepicker', () => { dispatchKeyboardEvent(calendarBodyEl, 'keydown', ENTER); fixture.detectChanges(); - flush(); expect(spy).not.toHaveBeenCalled(); expect(document.querySelector('.mat-datepicker-dialog')).toBeNull(); expect(testComponent.datepickerInput.value).toEqual(new Date(2020, JAN, 1)); selectedSubscription.unsubscribe(); - })); + }); it('startAt should fallback to input value', () => { expect(testComponent.datepicker.startAt).toEqual(new Date(2020, JAN, 1)); @@ -419,14 +379,12 @@ describe('MatDatepicker', () => { .toBe('input'); }); - it('input should aria-owns calendar after opened in non-touch mode', fakeAsync(() => { + it('input should aria-owns calendar after opened in non-touch mode', () => { let inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; expect(inputEl.getAttribute('aria-owns')).toBeNull(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); let ownedElementId = inputEl.getAttribute('aria-owns'); expect(ownedElementId).not.toBeNull(); @@ -434,9 +392,9 @@ describe('MatDatepicker', () => { let ownedElement = document.getElementById(ownedElementId); expect(ownedElement).not.toBeNull(); expect((ownedElement as Element).tagName.toLowerCase()).toBe('mat-calendar'); - })); + }); - it('input should aria-owns calendar after opened in touch mode', fakeAsync(() => { + it('input should aria-owns calendar after opened in touch mode', () => { testComponent.touch = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); @@ -446,8 +404,6 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); let ownedElementId = inputEl.getAttribute('aria-owns'); expect(ownedElementId).not.toBeNull(); @@ -455,7 +411,7 @@ describe('MatDatepicker', () => { let ownedElement = document.getElementById(ownedElementId); expect(ownedElement).not.toBeNull(); expect((ownedElement as Element).tagName.toLowerCase()).toBe('mat-calendar'); - })); + }); it('should not throw when given wrong data type', () => { testComponent.date = '1/1/2017' as any; @@ -464,7 +420,7 @@ describe('MatDatepicker', () => { expect(() => fixture.detectChanges()).not.toThrow(); }); - it('should clear out the backdrop subscriptions on close', fakeAsync(() => { + it('should clear out the backdrop subscriptions on close', () => { for (let i = 0; i < 3; i++) { testComponent.datepicker.open(); fixture.detectChanges(); @@ -486,9 +442,9 @@ describe('MatDatepicker', () => { expect(spy).toHaveBeenCalledTimes(1); expect(testComponent.datepicker.opened).toBe(false); subscription.unsubscribe(); - })); + }); - it('should reset the datepicker when it is closed externally', fakeAsync(() => { + it('should reset the datepicker when it is closed externally', async () => { TestBed.resetTestingModule(); const scrolledSubject = new Subject(); @@ -511,22 +467,20 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); expect(testComponent.datepicker.opened).toBe(true); scrolledSubject.next(); - flush(); + // The scroll strategy has some debouncing we need to wait for. + await wait(50); fixture.detectChanges(); expect(testComponent.datepicker.opened).toBe(false); - })); + }); - it('should close the datepicker using ALT + UP_ARROW', fakeAsync(() => { + it('should close the datepicker using ALT + UP_ARROW', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(testComponent.datepicker.opened).toBe(true); @@ -534,16 +488,13 @@ describe('MatDatepicker', () => { dispatchEvent(document.body, event); fixture.detectChanges(); - flush(); expect(testComponent.datepicker.opened).toBe(false); - })); + }); - it('should not close the datepicker when using CTRL + SHIFT + ALT + UP_ARROW', fakeAsync(() => { + it('should not close the datepicker when using CTRL + SHIFT + ALT + UP_ARROW', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(testComponent.datepicker.opened).toBe(true); @@ -555,26 +506,23 @@ describe('MatDatepicker', () => { dispatchEvent(document.body, event); fixture.detectChanges(); - flush(); expect(testComponent.datepicker.opened).toBe(true); - })); + }); - it('should open the datepicker using ALT + DOWN_ARROW', fakeAsync(() => { + it('should open the datepicker using ALT + DOWN_ARROW', () => { expect(testComponent.datepicker.opened).toBe(false); const event = createKeyboardEvent('keydown', DOWN_ARROW, undefined, {alt: true}); dispatchEvent(fixture.nativeElement.querySelector('input'), event); fixture.detectChanges(); - tick(); - flush(); expect(testComponent.datepicker.opened).toBe(true); expect(event.defaultPrevented).toBe(true); - })); + }); - it('should not open for ALT + DOWN_ARROW on readonly input', fakeAsync(() => { + it('should not open for ALT + DOWN_ARROW on readonly input', () => { const input = fixture.nativeElement.querySelector('input'); expect(testComponent.datepicker.opened).toBe(false); @@ -585,13 +533,12 @@ describe('MatDatepicker', () => { dispatchEvent(input, event); fixture.detectChanges(); - flush(); expect(testComponent.datepicker.opened).toBe(false); expect(event.defaultPrevented).toBe(false); - })); + }); - it('should not open the datepicker using SHIFT + CTRL + ALT + DOWN_ARROW', fakeAsync(() => { + it('should not open the datepicker using SHIFT + CTRL + ALT + DOWN_ARROW', () => { expect(testComponent.datepicker.opened).toBe(false); const event = createKeyboardEvent('keydown', DOWN_ARROW, undefined, { @@ -602,19 +549,15 @@ describe('MatDatepicker', () => { dispatchEvent(fixture.nativeElement.querySelector('input'), event); fixture.detectChanges(); - tick(); - flush(); expect(testComponent.datepicker.opened).toBe(false); expect(event.defaultPrevented).toBe(false); - })); + }); - it('should show the invisible close button on focus', fakeAsync(() => { + it('should show the invisible close button on focus', () => { testComponent.opened = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - tick(); - flush(); const button = document.querySelector('.mat-datepicker-close-button') as HTMLButtonElement; expect(button.classList).toContain('cdk-visually-hidden'); @@ -626,26 +569,23 @@ describe('MatDatepicker', () => { dispatchFakeEvent(button, 'blur'); fixture.detectChanges(); expect(button.classList).toContain('cdk-visually-hidden'); - })); + }); - it('should close the overlay when clicking on the invisible close button', fakeAsync(() => { + it('should close the overlay when clicking on the invisible close button', () => { testComponent.opened = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - tick(); - flush(); const button = document.querySelector('.mat-datepicker-close-button') as HTMLButtonElement; expect(document.querySelector('.mat-datepicker-content')).not.toBeNull(); button.click(); fixture.detectChanges(); - flush(); expect(document.querySelector('.mat-datepicker-content')).toBeNull(); - })); + }); - it('should prevent the default action of navigation keys before the focus timeout has elapsed', fakeAsync(() => { + it('should prevent the default action of navigation keys before the focus timeout has elapsed', () => { testComponent.datepicker.open(); fixture.detectChanges(); @@ -658,21 +598,18 @@ describe('MatDatepicker', () => { .withContext(`Expected default action to be prevented for key code ${keyCode}`) .toBe(true); }); - - tick(); - flush(); - })); + }); }); describe('datepicker with too many inputs', () => { - it('should throw when multiple inputs registered', fakeAsync(() => { + it('should throw when multiple inputs registered', () => { const fixture = createComponent(MultiInputDatepicker, [provideNativeDateAdapter()]); expect(() => fixture.detectChanges()).toThrow(); - })); + }); }); describe('datepicker that is assigned to input at a later point', () => { - it('should not throw on ALT + DOWN_ARROW for input without datepicker', fakeAsync(() => { + it('should not throw on ALT + DOWN_ARROW for input without datepicker', () => { const fixture = createComponent(DelayedDatepicker, [provideNativeDateAdapter()]); fixture.detectChanges(); @@ -680,11 +617,10 @@ describe('MatDatepicker', () => { const event = createKeyboardEvent('keydown', DOWN_ARROW, undefined, {alt: true}); dispatchEvent(fixture.nativeElement.querySelector('input'), event); fixture.detectChanges(); - flush(); }).not.toThrow(); - })); + }); - it('should handle value changes when a datepicker is assigned after init', fakeAsync(() => { + it('should handle value changes when a datepicker is assigned after init', () => { const fixture = createComponent(DelayedDatepicker, [provideNativeDateAdapter()]); const testComponent: DelayedDatepicker = fixture.componentInstance; const toSelect = new Date(2017, JAN, 1); @@ -703,54 +639,52 @@ describe('MatDatepicker', () => { testComponent.assignedDatepicker.select(toSelect); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(testComponent.datepickerInput.value).toEqual(toSelect); expect(model.selection).toEqual(toSelect); - })); + }); }); describe('datepicker with no inputs', () => { let fixture: ComponentFixture; let testComponent: NoInputDatepicker; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(NoInputDatepicker, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - })); + }); it('should not throw when accessing disabled property', () => { expect(() => testComponent.datepicker.disabled).not.toThrow(); }); - it('should throw when opened with no registered inputs', fakeAsync(() => { + it('should throw when opened with no registered inputs', () => { expect(() => testComponent.datepicker.open()).toThrow(); - })); + }); }); describe('datepicker with startAt', () => { let fixture: ComponentFixture; let testComponent: DatepickerWithStartAt; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithStartAt, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - })); + }); it('explicit startAt should override input value', () => { expect(testComponent.datepicker.startAt).toEqual(new Date(2010, JAN, 1)); @@ -761,23 +695,21 @@ describe('MatDatepicker', () => { let fixture: ComponentFixture; let testComponent: DatepickerWithStartViewYear; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithStartViewYear, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); - })); + }); - it('should start at the specified view', fakeAsync(() => { + it('should start at the specified view', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const firstCalendarCell = document.querySelector('.mat-calendar-body-cell')!; @@ -788,51 +720,45 @@ describe('MatDatepicker', () => { expect(firstCalendarCell.textContent!.trim()) .withContext('Expected the calendar to be in year-view') .toBe('JAN'); - })); + }); - it('should fire yearSelected when user selects calendar year in year view', fakeAsync(() => { + it('should fire yearSelected when user selects calendar year in year view', () => { spyOn(testComponent, 'onYearSelection'); expect(testComponent.onYearSelection).not.toHaveBeenCalled(); testComponent.datepicker.open(); - tick(); fixture.detectChanges(); - flush(); const cells = document.querySelectorAll('.mat-calendar-body-cell'); dispatchMouseEvent(cells[0], 'click'); fixture.detectChanges(); - tick(); - flush(); expect(testComponent.onYearSelection).toHaveBeenCalled(); - })); + }); }); describe('datepicker with startView set to multiyear', () => { let fixture: ComponentFixture; let testComponent: DatepickerWithStartViewMultiYear; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithStartViewMultiYear, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; spyOn(testComponent, 'onMultiYearSelection'); - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); - })); + }); - it('should start at the specified view', fakeAsync(() => { + it('should start at the specified view', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const firstCalendarCell = document.querySelector('.mat-calendar-body-cell')!; @@ -843,24 +769,21 @@ describe('MatDatepicker', () => { expect(firstCalendarCell.textContent!.trim()) .withContext('Expected the calendar to be in multi-year-view') .toBe('2016'); - })); + }); - it('should fire yearSelected when user selects calendar year in multiyear view', fakeAsync(() => { + it('should fire yearSelected when user selects calendar year in multiyear view', () => { expect(testComponent.onMultiYearSelection).not.toHaveBeenCalled(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const cells = document.querySelectorAll('.mat-calendar-body-cell'); dispatchMouseEvent(cells[0], 'click'); fixture.detectChanges(); - tick(); - flush(); expect(testComponent.onMultiYearSelection).toHaveBeenCalled(); - })); + }); }); describe('datepicker with ngModel', () => { @@ -868,21 +791,21 @@ describe('MatDatepicker', () => { let testComponent: DatepickerWithNgModel; let model: MatDateSelectionModel; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithNgModel, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; model = fixture.debugElement .query(By.directive(MatDatepicker)) .injector.get(MatDateSelectionModel); - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - })); + }); - it('should update datepicker when model changes', fakeAsync(() => { + it('should update datepicker when model changes', async () => { expect(testComponent.datepickerInput.value).toBeNull(); expect(model.selection).toBeNull(); @@ -890,26 +813,24 @@ describe('MatDatepicker', () => { testComponent.selected = selected; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); fixture.detectChanges(); expect(testComponent.datepickerInput.value).toEqual(selected); expect(model.selection).toEqual(selected); - })); + }); - it('should update model when date is selected', fakeAsync(() => { + it('should update model when date is selected', () => { expect(testComponent.selected).toBeNull(); expect(testComponent.datepickerInput.value).toBeNull(); let selected = new Date(2017, JAN, 1); testComponent.datepicker.select(selected); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(testComponent.selected).toEqual(selected); expect(testComponent.datepickerInput.value).toEqual(selected); - })); + }); it('should mark input dirty after input event', () => { let inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; @@ -923,18 +844,16 @@ describe('MatDatepicker', () => { expect(inputEl.classList).toContain('ng-dirty'); }); - it('should mark input dirty after date selected', fakeAsync(() => { + it('should mark input dirty after date selected', () => { let inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; expect(inputEl.classList).toContain('ng-pristine'); testComponent.datepicker.select(new Date(2017, JAN, 1)); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(inputEl.classList).toContain('ng-dirty'); - })); + }); it('should mark input dirty after invalid value is typed in', () => { let inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; @@ -948,7 +867,7 @@ describe('MatDatepicker', () => { expect(inputEl.classList).toContain('ng-dirty'); }); - it('should not mark dirty after model change', fakeAsync(() => { + it('should not mark dirty after model change', () => { let inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; expect(inputEl.classList).toContain('ng-pristine'); @@ -956,11 +875,9 @@ describe('MatDatepicker', () => { testComponent.selected = new Date(2017, JAN, 1); fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(inputEl.classList).toContain('ng-pristine'); - })); + }); it('should mark input touched on blur', () => { let inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; @@ -978,26 +895,21 @@ describe('MatDatepicker', () => { expect(inputEl.classList).toContain('ng-touched'); }); - it('should mark input as touched when the datepicker is closed', fakeAsync(() => { + it('should mark input as touched when the datepicker is closed', () => { let inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; expect(inputEl.classList).toContain('ng-untouched'); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); - fixture.detectChanges(); expect(inputEl.classList).toContain('ng-untouched'); fixture.componentInstance.datepicker.close(); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(inputEl.classList).toContain('ng-touched'); - })); + }); it('should reformat the input value on blur', () => { if (SUPPORTS_INTL) { @@ -1031,18 +943,16 @@ describe('MatDatepicker', () => { expect(inputEl.value).toBe('very-valid-date'); }); - it('should mark input touched on calendar selection', fakeAsync(() => { + it('should mark input touched on calendar selection', () => { let inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; expect(inputEl.classList).toContain('ng-untouched'); testComponent.datepicker.select(new Date(2017, JAN, 1)); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(inputEl.classList).toContain('ng-touched'); - })); + }); }); describe('datepicker with formControl', () => { @@ -1050,7 +960,7 @@ describe('MatDatepicker', () => { let testComponent: DatepickerWithFormControl; let model: MatDateSelectionModel; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithFormControl, [provideNativeDateAdapter()]); fixture.detectChanges(); @@ -1058,12 +968,12 @@ describe('MatDatepicker', () => { model = fixture.debugElement .query(By.directive(MatDatepicker)) .injector.get(MatDateSelectionModel); - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - })); + }); it('should update datepicker when formControl changes', () => { expect(testComponent.datepickerInput.value).toBeNull(); @@ -1112,7 +1022,7 @@ describe('MatDatepicker', () => { it( 'should not dispatch FormControl change event for invalid values on input when set ' + 'to update on blur', - fakeAsync(() => { + () => { const formControl = new FormControl({value: null} as unknown as Date, {updateOn: 'blur'}); const spy = jasmine.createSpy('change spy'); const subscription = formControl.valueChanges.subscribe(spy); @@ -1121,7 +1031,6 @@ describe('MatDatepicker', () => { inputEl.value = value; dispatchFakeEvent(inputEl, 'input'); fixture.detectChanges(); - flush(); fixture.detectChanges(); }; @@ -1142,12 +1051,11 @@ describe('MatDatepicker', () => { dispatchFakeEvent(inputEl, 'blur'); fixture.detectChanges(); - flush(); fixture.detectChanges(); expect(spy).toHaveBeenCalledTimes(1); subscription.unsubscribe(); - }), + }, ); it('should set the matDatepickerParse error when an invalid value is typed for the first time', () => { @@ -1197,18 +1105,17 @@ describe('MatDatepicker', () => { let fixture: ComponentFixture; let testComponent: DatepickerWithToggle; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithToggle, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); - })); + }); it('should set `aria-haspopup` on the toggle button', () => { const button = fixture.debugElement.query(By.css('button'))!; @@ -1286,7 +1193,7 @@ describe('MatDatepicker', () => { expect(icon.getAttribute('focusable')).toBe('false'); }); - it('should restore focus to the toggle after the calendar is closed', fakeAsync(() => { + it('should restore focus to the toggle after the calendar is closed', async () => { let toggle = fixture.debugElement.query(By.css('button'))!.nativeElement; fixture.componentInstance.touchUI = false; @@ -1298,25 +1205,22 @@ describe('MatDatepicker', () => { fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); + await wait(50); // Wait for focus to move to calendar + fixture.detectChanges(); let pane = document.querySelector('.cdk-overlay-pane')!; - - expect(pane).withContext('Expected calendar to be open.').toBeTruthy(); expect(pane.contains(document.activeElement)) .withContext('Expected focus to be inside the calendar.') .toBe(true); fixture.componentInstance.datepicker.close(); fixture.detectChanges(); - flush(); + await wait(200); - expect(document.activeElement) - .withContext('Expected focus to be restored to toggle.') - .toBe(toggle); - })); + expect(document.activeElement).toBe(toggle, 'Expected focus to be restored to the toggle.'); + }); - it('should restore focus when placed inside a shadow root', fakeAsync(() => { + it('should restore focus when placed inside a shadow root', () => { if (!_supportsShadowDom()) { return; } @@ -1336,17 +1240,15 @@ describe('MatDatepicker', () => { spyOn(toggle, 'focus').and.callThrough(); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); fixture.componentInstance.datepicker.close(); fixture.detectChanges(); - flush(); // We have to assert by looking at the `focus` method, because // `document.activeElement` will return the shadow root. expect(toggle.focus).toHaveBeenCalled(); - })); + }); - it('should allow for focus restoration to be disabled', fakeAsync(() => { + it('should allow for focus restoration to be disabled', async () => { let toggle = fixture.debugElement.query(By.css('button'))!.nativeElement; fixture.componentInstance.touchUI = false; @@ -1359,25 +1261,25 @@ describe('MatDatepicker', () => { fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); + await wait(50); // Wait for focus to move to calendar + fixture.detectChanges(); let pane = document.querySelector('.cdk-overlay-pane')!; - - expect(pane).withContext('Expected calendar to be open.').toBeTruthy(); expect(pane.contains(document.activeElement)) .withContext('Expected focus to be inside the calendar.') .toBe(true); fixture.componentInstance.datepicker.close(); fixture.detectChanges(); - flush(); + await wait(200); - expect(document.activeElement) - .not.withContext('Expected focus not to be restored to toggle.') - .toBe(toggle); - })); + expect(document.activeElement).not.toBe( + toggle, + 'Expected focus not to be restored to the toggle.', + ); + }); - it('should not override focus if it was moved inside the closed event in touchUI mode', fakeAsync(() => { + it('should not override focus if it was moved inside the closed event in touchUI mode', async () => { const focusTarget = document.createElement('button'); const datepicker = fixture.componentInstance.datepicker; const subscription = datepicker.closedStream.subscribe(() => focusTarget.focus()); @@ -1400,7 +1302,7 @@ describe('MatDatepicker', () => { datepicker.open(); fixture.detectChanges(); - tick(500); + await wait(500); fixture.detectChanges(); expect(document.activeElement).not.toBe( @@ -1410,7 +1312,7 @@ describe('MatDatepicker', () => { datepicker.close(); fixture.detectChanges(); - tick(500); + await wait(500); fixture.detectChanges(); expect(document.activeElement) @@ -1419,7 +1321,7 @@ describe('MatDatepicker', () => { focusTarget.remove(); subscription.unsubscribe(); - })); + }); it('should re-render when the i18n labels change', () => { const intl = TestBed.inject(MatDatepickerIntl); @@ -1432,49 +1334,41 @@ describe('MatDatepicker', () => { expect(toggle.getAttribute('aria-label')).toBe('Open the calendar, perhaps?'); }); - it('should toggle the active state of the datepicker toggle', fakeAsync(() => { + it('should toggle the active state of the datepicker toggle', () => { const toggle = fixture.debugElement.query(By.css('mat-datepicker-toggle'))!.nativeElement; expect(toggle.classList).not.toContain('mat-datepicker-toggle-active'); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(toggle.classList).toContain('mat-datepicker-toggle-active'); fixture.componentInstance.datepicker.close(); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(toggle.classList).not.toContain('mat-datepicker-toggle-active'); - })); + }); - it('should set aria-expanded on the toggle', fakeAsync(() => { + it('should set aria-expanded on the toggle', () => { const button = fixture.nativeElement.querySelector('mat-datepicker-toggle button'); expect(button.getAttribute('aria-expanded')).toBe('false'); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(button.getAttribute('aria-expanded')).toBe('true'); fixture.componentInstance.datepicker.close(); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(button.getAttribute('aria-expanded')).toBe('false'); - })); + }); }); describe('datepicker with custom mat-datepicker-toggle icon', () => { - it('should be able to override the mat-datepicker-toggle icon', fakeAsync(() => { + it('should be able to override the mat-datepicker-toggle icon', () => { const fixture = createComponent(DatepickerWithCustomIcon, [provideNativeDateAdapter()]); fixture.detectChanges(); @@ -1485,7 +1379,7 @@ describe('MatDatepicker', () => { expect(fixture.nativeElement.querySelector('.mat-datepicker-toggle mat-icon')) .withContext('Expected default icon to be removed.') .toBeFalsy(); - })); + }); }); describe('datepicker with tabindex on mat-datepicker-toggle', () => { @@ -1516,17 +1410,16 @@ describe('MatDatepicker', () => { let fixture: ComponentFixture; let testComponent: FormFieldDatepicker; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(FormFieldDatepicker, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); - })); + }); it('should float the placeholder when an invalid value is entered', () => { testComponent.datepickerInput.value = 'totally-not-a-date' as any; @@ -1539,13 +1432,11 @@ describe('MatDatepicker', () => { ); }); - it('should pass the form field theme color to the overlay', fakeAsync(() => { + it('should pass the form field theme color to the overlay', () => { testComponent.formField.color = 'primary'; fixture.changeDetectorRef.markForCheck(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); let contentEl = document.querySelector('.mat-datepicker-content')!; @@ -1553,7 +1444,6 @@ describe('MatDatepicker', () => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); testComponent.formField.color = 'warn'; fixture.changeDetectorRef.markForCheck(); @@ -1561,29 +1451,25 @@ describe('MatDatepicker', () => { contentEl = document.querySelector('.mat-datepicker-content')!; fixture.detectChanges(); - tick(); - flush(); expect(contentEl.classList).toContain('mat-warn'); expect(contentEl.classList).not.toContain('mat-primary'); - })); + }); - it('should prefer the datepicker color over the form field one', fakeAsync(() => { + it('should prefer the datepicker color over the form field one', () => { testComponent.datepicker.color = 'accent'; testComponent.formField.color = 'warn'; fixture.changeDetectorRef.markForCheck(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const contentEl = document.querySelector('.mat-datepicker-content')!; expect(contentEl.classList).toContain('mat-accent'); expect(contentEl.classList).not.toContain('mat-warn'); - })); + }); - it('should set aria-labelledby of the overlay to the form field label', fakeAsync(() => { + it('should set aria-labelledby of the overlay to the form field label', () => { const label: HTMLElement = fixture.nativeElement.querySelector('label'); expect(label).toBeTruthy(); @@ -1591,128 +1477,124 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); const popup = document.querySelector( '.cdk-overlay-pane .mat-datepicker-content-container', )!; expect(popup).toBeTruthy(); expect(popup.getAttribute('aria-labelledby')).toBe(label.getAttribute('id')); - })); + }); }); describe('datepicker with min and max dates and validation', () => { let fixture: ComponentFixture; let testComponent: DatepickerWithMinAndMaxValidation; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithMinAndMaxValidation, [provideNativeDateAdapter()]); fixture.detectChanges(); - flush(); testComponent = fixture.componentInstance; - })); + }); - function revalidate() { + async function revalidate() { fixture.detectChanges(); - flush(); + await fixture.whenStable(); fixture.detectChanges(); } - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); - })); + }); it('should use min and max dates specified by the input', () => { expect(testComponent.datepicker._getMinDate()).toEqual(new Date(2010, JAN, 1)); expect(testComponent.datepicker._getMaxDate()).toEqual(new Date(2020, JAN, 1)); }); - it('should mark invalid when value is before min', fakeAsync(() => { + it('should mark invalid when value is before min', async () => { testComponent.date = new Date(2009, DEC, 31); fixture.changeDetectorRef.markForCheck(); - revalidate(); + await revalidate(); expect(fixture.debugElement.query(By.css('input'))!.nativeElement.classList).toContain( 'ng-invalid', ); - })); + }); - it('should mark invalid when value is after max', fakeAsync(() => { + it('should mark invalid when value is after max', async () => { testComponent.date = new Date(2020, JAN, 2); fixture.changeDetectorRef.markForCheck(); - revalidate(); + await revalidate(); expect(fixture.debugElement.query(By.css('input'))!.nativeElement.classList).toContain( 'ng-invalid', ); - })); + }); - it('should not mark invalid when value equals min', fakeAsync(() => { + it('should not mark invalid when value equals min', async () => { testComponent.date = testComponent.datepicker._getMinDate(); fixture.changeDetectorRef.markForCheck(); - revalidate(); + await revalidate(); expect(fixture.debugElement.query(By.css('input'))!.nativeElement.classList).not.toContain( 'ng-invalid', ); - })); + }); - it('should not mark invalid when value equals max', fakeAsync(() => { + it('should not mark invalid when value equals max', async () => { testComponent.date = testComponent.datepicker._getMaxDate(); fixture.changeDetectorRef.markForCheck(); - revalidate(); + await revalidate(); expect(fixture.debugElement.query(By.css('input'))!.nativeElement.classList).not.toContain( 'ng-invalid', ); - })); + }); - it('should not mark invalid when value is between min and max', fakeAsync(() => { + it('should not mark invalid when value is between min and max', async () => { testComponent.date = new Date(2010, JAN, 2); fixture.changeDetectorRef.markForCheck(); - revalidate(); + await revalidate(); expect(fixture.debugElement.query(By.css('input'))!.nativeElement.classList).not.toContain( 'ng-invalid', ); - })); + }); - it('should update validity when switching between null and invalid', fakeAsync(() => { + it('should update validity when switching between null and invalid', async () => { const inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; inputEl.value = ''; dispatchFakeEvent(inputEl, 'input'); - revalidate(); + await revalidate(); expect(testComponent.model.valid).toBe(true); inputEl.value = 'abcdefg'; dispatchFakeEvent(inputEl, 'input'); - revalidate(); + await revalidate(); expect(testComponent.model.valid).toBe(false); inputEl.value = ''; dispatchFakeEvent(inputEl, 'input'); - revalidate(); + await revalidate(); expect(testComponent.model.valid).toBe(true); - })); + }); - it('should update validity when a value is assigned', fakeAsync(() => { + it('should update validity when a value is assigned', async () => { const inputEl = fixture.debugElement.query(By.css('input'))!.nativeElement; inputEl.value = ''; dispatchFakeEvent(inputEl, 'input'); - revalidate(); + await revalidate(); expect(testComponent.model.valid).toBe(true); inputEl.value = 'abcdefg'; dispatchFakeEvent(inputEl, 'input'); - revalidate(); + await revalidate(); expect(testComponent.model.valid).toBe(false); @@ -1723,13 +1605,13 @@ describe('MatDatepicker', () => { .query(By.directive(MatDatepicker)) .injector.get>(MatDateSelectionModel); model.updateSelection(validDate, null); - revalidate(); + await revalidate(); expect(testComponent.model.valid).toBe(true); expect(testComponent.date).toBe(validDate); - })); + }); - it('should update the calendar when the min/max dates change', fakeAsync(() => { + it('should update the calendar when the min/max dates change', () => { const getDisabledCells = () => { return document.querySelectorAll('.mat-calendar-body-disabled').length; }; @@ -1745,8 +1627,6 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); let disabledCellCount = getDisabledCells(); expect(disabledCellCount).not.toBe(0); @@ -1754,7 +1634,6 @@ describe('MatDatepicker', () => { testComponent.minDate = new Date(2020, JAN, 1); fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); expect(getDisabledCells()).not.toBe(disabledCellCount); disabledCellCount = getDisabledCells(); @@ -1762,10 +1641,9 @@ describe('MatDatepicker', () => { testComponent.maxDate = new Date(2020, JAN, 10); fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); expect(getDisabledCells()).not.toBe(disabledCellCount); - })); + }); }); describe('datepicker with filter and validation', () => { @@ -1779,17 +1657,16 @@ describe('MatDatepicker', () => { testComponent = fixture.componentInstance; }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); - })); + }); - it('should mark input invalid', fakeAsync(() => { + it('should mark input invalid', async () => { testComponent.date = new Date(2017, JAN, 1); fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); fixture.detectChanges(); expect(fixture.debugElement.query(By.css('input'))!.nativeElement.classList).toContain( @@ -1799,36 +1676,34 @@ describe('MatDatepicker', () => { testComponent.date = new Date(2017, JAN, 2); fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); fixture.detectChanges(); expect(fixture.debugElement.query(By.css('input'))!.nativeElement.classList).not.toContain( 'ng-invalid', ); - })); + }); - it('should disable filtered calendar cells', fakeAsync(() => { + it('should disable filtered calendar cells', () => { fixture.detectChanges(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); expect(document.querySelector('.mat-datepicker-dialog')).not.toBeNull(); let cells = document.querySelectorAll('.mat-calendar-body-cell'); expect(cells[0].classList).toContain('mat-calendar-body-disabled'); expect(cells[1].classList).not.toContain('mat-calendar-body-disabled'); - })); + }); - it('should revalidate when a new function is assigned', fakeAsync(() => { + it('should revalidate when a new function is assigned', async () => { const classList = fixture.debugElement.query(By.css('input'))!.nativeElement.classList; testComponent.date = new Date(2017, JAN, 1); testComponent.filter = () => true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); fixture.detectChanges(); expect(classList).not.toContain('ng-invalid'); @@ -1836,19 +1711,19 @@ describe('MatDatepicker', () => { testComponent.filter = () => false; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); fixture.detectChanges(); expect(classList).toContain('ng-invalid'); - })); + }); - it('should not dispatch the change event if a new function with the same result is assigned', fakeAsync(() => { + it('should not dispatch the change event if a new function with the same result is assigned', () => { const spy = jasmine.createSpy('change spy'); const subscription = fixture.componentInstance.model.valueChanges?.subscribe(spy); testComponent.filter = () => false; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); + fixture.detectChanges(); expect(spy).toHaveBeenCalledTimes(1); @@ -1856,12 +1731,10 @@ describe('MatDatepicker', () => { testComponent.filter = () => false; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); - fixture.detectChanges(); expect(spy).toHaveBeenCalledTimes(1); subscription?.unsubscribe(); - })); + }); }); describe('datepicker with change and input events', () => { @@ -1869,7 +1742,7 @@ describe('MatDatepicker', () => { let testComponent: DatepickerWithChangeAndInputEvents; let inputEl: HTMLInputElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithChangeAndInputEvents, [provideNativeDateAdapter()]); fixture.detectChanges(); @@ -1880,12 +1753,12 @@ describe('MatDatepicker', () => { spyOn(testComponent, 'onInput'); spyOn(testComponent, 'onDateChange'); spyOn(testComponent, 'onDateInput'); - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - })); + }); it('should fire input and dateInput events when user types input', () => { expect(testComponent.onChange).not.toHaveBeenCalled(); @@ -1918,7 +1791,7 @@ describe('MatDatepicker', () => { expect(testComponent.onDateInput).not.toHaveBeenCalled(); }); - it('should fire dateChange and dateInput events when user selects calendar date', fakeAsync(() => { + it('should fire dateChange and dateInput events when user selects calendar date', () => { expect(testComponent.onChange).not.toHaveBeenCalled(); expect(testComponent.onDateChange).not.toHaveBeenCalled(); expect(testComponent.onInput).not.toHaveBeenCalled(); @@ -1926,20 +1799,18 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); expect(document.querySelector('.mat-datepicker-dialog')).not.toBeNull(); const cells = document.querySelectorAll('.mat-calendar-body-cell'); dispatchMouseEvent(cells[0], 'click'); fixture.detectChanges(); - flush(); expect(testComponent.onChange).not.toHaveBeenCalled(); expect(testComponent.onDateChange).toHaveBeenCalled(); expect(testComponent.onInput).not.toHaveBeenCalled(); expect(testComponent.onDateInput).toHaveBeenCalled(); - })); + }); it('should not fire the dateInput event if the value has not changed', () => { expect(testComponent.onDateInput).not.toHaveBeenCalled(); @@ -1992,59 +1863,54 @@ describe('MatDatepicker', () => { let fixture: ComponentFixture; let testComponent: DatepickerWithISOStrings; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithISOStrings, [provideNativeDateAdapter()]); - flush(); testComponent = fixture.componentInstance; - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - })); + }); - it('should coerce ISO strings', fakeAsync(() => { + it('should coerce ISO strings', async () => { expect(() => fixture.detectChanges()).not.toThrow(); - flush(); + await fixture.whenStable(); fixture.detectChanges(); expect(testComponent.datepicker.startAt).toEqual(new Date(2017, JUL, 1)); expect(testComponent.datepickerInput.value).toEqual(new Date(2017, JUN, 1)); expect(testComponent.datepickerInput.min).toEqual(new Date(2017, JAN, 1)); expect(testComponent.datepickerInput.max).toEqual(new Date(2017, DEC, 31)); - })); + }); }); describe('with events', () => { let fixture: ComponentFixture; let testComponent: DatepickerWithEvents; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithEvents, [provideNativeDateAdapter()]); fixture.detectChanges(); - flush(); testComponent = fixture.componentInstance; - })); + }); - it('should dispatch an event when a datepicker is opened', fakeAsync(() => { + it('should dispatch an event when a datepicker is opened', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); expect(testComponent.openedSpy).toHaveBeenCalled(); - })); + }); - it('should dispatch an event when a datepicker is closed', fakeAsync(() => { + it('should dispatch an event when a datepicker is closed', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); testComponent.datepicker.close(); - flush(); fixture.detectChanges(); expect(testComponent.closedSpy).toHaveBeenCalled(); - })); + }); }); describe('datepicker that opens on focus', () => { @@ -2052,31 +1918,30 @@ describe('MatDatepicker', () => { let testComponent: DatepickerOpeningOnFocus; let input: HTMLInputElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerOpeningOnFocus, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; input = fixture.debugElement.query(By.css('input'))!.nativeElement; - })); + }); - it('should not reopen if the browser fires the focus event asynchronously', fakeAsync(() => { + it('should not reopen if the browser fires the focus event asynchronously', async () => { // Stub out the real focus method so we can call it reliably. spyOn(input, 'focus').and.callFake(() => { - // Dispatch the event handler async to simulate the IE11 behavior. + // Dispatch the event handler to simulate the IE11 behavior. Promise.resolve().then(() => dispatchFakeEvent(input, 'focus')); }); // Open initially by focusing. input.focus(); fixture.detectChanges(); - tick(); - flush(); + await fixture.whenStable(); + fixture.detectChanges(); // Due to some browser limitations we can't install a stub on `document.activeElement` // so instead we have to override the previously-focused element manually. (fixture.componentInstance.datepicker as any)._focusedElementBeforeOpen = input; - // Ensure that the datepicker is actually open. // Ensure that the datepicker is actually open. expect(testComponent.datepicker.opened) .withContext('Expected datepicker to be open.') @@ -2089,19 +1954,19 @@ describe('MatDatepicker', () => { // Schedule the input to be focused asynchronously. input.focus(); fixture.detectChanges(); - tick(); // Flush out the scheduled tasks. - flush(); + await wait(200); + fixture.detectChanges(); expect(testComponent.datepicker.opened) .withContext('Expected datepicker to be closed.') .toBe(false); - })); + }); }); describe('datepicker directionality', () => { - it('should pass along the directionality to the popup', fakeAsync(() => { + it('should pass along the directionality to the popup', () => { const fixture = createComponent(StandardDatepicker, [ provideNativeDateAdapter(), provideFakeDirectionality('rtl'), @@ -2110,14 +1975,13 @@ describe('MatDatepicker', () => { fixture.detectChanges(); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); const overlay = document.querySelector('.cdk-overlay-connected-position-bounding-box')!; expect(overlay.getAttribute('dir')).toBe('rtl'); - })); + }); - it('should update the popup direction if the directionality value changes', fakeAsync(() => { + it('should update the popup direction if the directionality value changes', () => { const dir = signal('ltr'); const fixture = createComponent(StandardDatepicker, [ provideNativeDateAdapter(), @@ -2127,7 +1991,6 @@ describe('MatDatepicker', () => { fixture.detectChanges(); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); let overlay = document.querySelector('.cdk-overlay-connected-position-bounding-box')!; @@ -2135,19 +1998,17 @@ describe('MatDatepicker', () => { fixture.componentInstance.datepicker.close(); fixture.detectChanges(); - flush(); dir.set('rtl'); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); overlay = document.querySelector('.cdk-overlay-connected-position-bounding-box')!; expect(overlay.getAttribute('dir')).toBe('rtl'); - })); + }); - it('should pass along the directionality to the dialog in touch mode', fakeAsync(() => { + it('should pass along the directionality to the dialog in touch mode', () => { const fixture = createComponent(StandardDatepicker, [ provideNativeDateAdapter(), provideFakeDirectionality('rtl'), @@ -2158,12 +2019,11 @@ describe('MatDatepicker', () => { fixture.detectChanges(); fixture.componentInstance.datepicker.open(); fixture.detectChanges(); - tick(); const overlay = document.querySelector('.cdk-global-overlay-wrapper')!; expect(overlay.getAttribute('dir')).toBe('rtl'); - })); + }); }); }); @@ -2230,19 +2090,18 @@ describe('MatDatepicker', () => { let testComponent: StandardDatepicker; let input: HTMLElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(StandardDatepicker, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; input = fixture.debugElement.query(By.css('input'))!.nativeElement; input.style.position = 'fixed'; - })); + }); - it('should be below and to the right when there is plenty of space', fakeAsync(() => { + it('should be below and to the right when there is plenty of space', () => { input.style.top = input.style.left = '20px'; testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const overlayRect = document.querySelector('.cdk-overlay-pane')!.getBoundingClientRect(); const inputRect = input.getBoundingClientRect(); @@ -2253,13 +2112,12 @@ describe('MatDatepicker', () => { expect(Math.floor(overlayRect.left)) .withContext('Expected popup to align to input left.') .toBe(Math.floor(inputRect.left)); - })); + }); - it('should be above and to the right when there is no space below', fakeAsync(() => { + it('should be above and to the right when there is no space below', () => { input.style.bottom = input.style.left = '20px'; testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const overlayRect = document.querySelector('.cdk-overlay-pane')!.getBoundingClientRect(); const inputRect = input.getBoundingClientRect(); @@ -2270,13 +2128,12 @@ describe('MatDatepicker', () => { expect(Math.floor(overlayRect.left)) .withContext('Expected popup to align to input left.') .toBe(Math.floor(inputRect.left)); - })); + }); - it('should be below and to the left when there is no space on the right', fakeAsync(() => { + it('should be below and to the left when there is no space on the right', () => { input.style.top = input.style.right = '20px'; testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const overlayRect = document.querySelector('.cdk-overlay-pane')!.getBoundingClientRect(); const inputRect = input.getBoundingClientRect(); @@ -2287,13 +2144,12 @@ describe('MatDatepicker', () => { expect(Math.floor(overlayRect.right)) .withContext('Expected popup to align to input right.') .toBe(Math.floor(inputRect.right)); - })); + }); - it('should be above and to the left when there is no space on the bottom', fakeAsync(() => { + it('should be above and to the left when there is no space on the bottom', () => { input.style.bottom = input.style.right = '20px'; testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const overlayRect = document.querySelector('.cdk-overlay-pane')!.getBoundingClientRect(); const inputRect = input.getBoundingClientRect(); @@ -2304,9 +2160,9 @@ describe('MatDatepicker', () => { expect(Math.floor(overlayRect.right)) .withContext('Expected popup to align to input right.') .toBe(Math.floor(inputRect.right)); - })); + }); - it('should be able to customize the calendar position along the X axis', fakeAsync(() => { + it('should be able to customize the calendar position along the X axis', () => { input.style.top = input.style.left = '200px'; testComponent.xPosition = 'end'; fixture.changeDetectorRef.markForCheck(); @@ -2314,7 +2170,6 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const overlayRect = document.querySelector('.cdk-overlay-pane')!.getBoundingClientRect(); const inputRect = input.getBoundingClientRect(); @@ -2322,9 +2177,9 @@ describe('MatDatepicker', () => { expect(Math.floor(overlayRect.right)) .withContext('Expected popup to align to input right.') .toBe(Math.floor(inputRect.right)); - })); + }); - it('should be able to customize the calendar position along the Y axis', fakeAsync(() => { + it('should be able to customize the calendar position along the Y axis', () => { input.style.bottom = input.style.left = '100px'; testComponent.yPosition = 'above'; fixture.changeDetectorRef.markForCheck(); @@ -2332,7 +2187,6 @@ describe('MatDatepicker', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const overlayRect = document.querySelector('.cdk-overlay-pane')!.getBoundingClientRect(); const inputRect = input.getBoundingClientRect(); @@ -2340,7 +2194,7 @@ describe('MatDatepicker', () => { expect(Math.floor(overlayRect.bottom)) .withContext('Expected popup to align to input top.') .toBe(Math.floor(inputRect.top)); - })); + }); }); describe('internationalization', () => { @@ -2358,7 +2212,7 @@ describe('MatDatepicker', () => { input = fixture.nativeElement.querySelector('input') as HTMLInputElement; }); - it('should have the correct input value even when inverted date format', fakeAsync(() => { + it('should have the correct input value even when inverted date format', async () => { if (typeof Intl === 'undefined') { // Skip this test if the internationalization API is not supported in the current // browser. Browsers like Safari 9 do not support the "Intl" API. @@ -2369,49 +2223,45 @@ describe('MatDatepicker', () => { testComponent.date = selected; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); + await fixture.whenStable(); fixture.detectChanges(); // Normally the proper date format would 01.09.2017, but some browsers seem format the // date without the leading zero. (e.g. 1.9.2017). expect(input.value).toMatch(/0?1\.0?9\.2017/); expect(testComponent.datepickerInput.value).toBe(selected); - })); + }); }); describe('datepicker with custom header', () => { let fixture: ComponentFixture; let testComponent: DatepickerWithCustomHeader; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(DatepickerWithCustomHeader, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; - })); + }); - it('should instantiate a datepicker with a custom header', fakeAsync(() => { + it('should instantiate a datepicker with a custom header', () => { expect(testComponent).toBeTruthy(); - })); + }); - it('should find the standard header element', fakeAsync(() => { + it('should find the standard header element', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); fixture.detectChanges(); expect(document.querySelector('mat-calendar-header')).toBeTruthy(); - })); + }); - it('should find the custom element', fakeAsync(() => { + it('should find the custom element', () => { testComponent.datepicker.open(); fixture.detectChanges(); - tick(); - flush(); fixture.detectChanges(); expect(document.querySelector('.custom-element')).toBeTruthy(); - })); + }); }); it('should not trigger validators if new date object for same date is set for `min`', () => { @@ -2502,18 +2352,17 @@ describe('MatDatepicker', () => { let fixture: ComponentFixture; let testComponent: PanelClassDatepicker; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = createComponent(PanelClassDatepicker, [provideNativeDateAdapter()]); fixture.detectChanges(); testComponent = fixture.componentInstance; - })); + }); - afterEach(fakeAsync(() => { + afterEach(() => { testComponent.datepicker.close(); fixture.detectChanges(); - flush(); - })); + }); it('should accept a single class', () => { testComponent.panelClass = 'foobar'; @@ -2529,19 +2378,18 @@ describe('MatDatepicker', () => { expect(testComponent.datepicker.panelClass).toEqual(['foo', 'bar']); }); - it('should work with ngClass', fakeAsync(() => { + it('should work with ngClass', () => { testComponent.panelClass = ['foo', 'bar']; fixture.changeDetectorRef.markForCheck(); testComponent.datepicker.open(); fixture.detectChanges(); - tick(); const actualClasses = document.querySelector( '.mat-datepicker-content .mat-calendar', )!.classList; expect(actualClasses.contains('foo')).toBe(true); expect(actualClasses.contains('bar')).toBe(true); - })); + }); }); }); From efa2f4f898598b0f9e216d93faaf489f17884f68 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 9 Mar 2026 17:27:18 +0100 Subject: [PATCH 029/123] refactor(material/select): move tests away from fakeAsync (#32901) Reworks the select tests so they don't use `fakeAsync` anymore. (cherry picked from commit 1597a2d85049e53e67eabdaa7f37efd1cfaad93e) --- src/material/select/select.spec.ts | 915 ++++++++++++----------------- 1 file changed, 369 insertions(+), 546 deletions(-) diff --git a/src/material/select/select.spec.ts b/src/material/select/select.spec.ts index 07fe510d67ee..a64e1c68eb27 100644 --- a/src/material/select/select.spec.ts +++ b/src/material/select/select.spec.ts @@ -40,7 +40,7 @@ import { inject, signal, } from '@angular/core'; -import {ComponentFixture, TestBed, fakeAsync, flush, tick} from '@angular/core/testing'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; import { ControlValueAccessor, FormBuilder, @@ -103,6 +103,10 @@ describe('MatSelect', () => { return fixture.nativeElement.querySelector('.cdk-overlay-backdrop'); } + function wait(milliseconds: number) { + return new Promise(resolve => setTimeout(resolve, milliseconds)); + } + describe('core', () => { describe('accessibility', () => { describe('for select', () => { @@ -120,27 +124,25 @@ describe('MatSelect', () => { expect(select.getAttribute('aria-haspopup')).toBe('listbox'); }); - it('should point the aria-controls attribute to the listbox', fakeAsync(() => { + it('should point the aria-controls attribute to the listbox', () => { expect(select.hasAttribute('aria-controls')).toBe(false); fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); const ariaControls = select.getAttribute('aria-controls'); expect(ariaControls).toBeTruthy(); expect(ariaControls).toBe(document.querySelector('.mat-mdc-select-panel')!.id); - })); + }); - it('should set aria-expanded based on the select open state', fakeAsync(() => { + it('should set aria-expanded based on the select open state', () => { expect(select.getAttribute('aria-expanded')).toBe('false'); fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); expect(select.getAttribute('aria-expanded')).toBe('true'); - })); + }); it('should support setting a custom aria-label', () => { fixture.componentInstance.ariaLabel = 'Custom Label'; @@ -190,7 +192,7 @@ describe('MatSelect', () => { expect(select.getAttribute('aria-describedby')).toBe('test'); }); - it('should preserve aria-describedby set directly in the DOM', fakeAsync(() => { + it('should preserve aria-describedby set directly in the DOM', () => { select.setAttribute('aria-describedby', 'custom'); fixture.componentInstance.hint = 'test'; fixture.changeDetectorRef.markForCheck(); @@ -198,7 +200,7 @@ describe('MatSelect', () => { const hint = fixture.debugElement.query(By.css('mat-hint')).nativeElement; expect(select.getAttribute('aria-describedby')).toBe(`${hint.getAttribute('id')} custom`); - })); + }); it('should be able to override the tabindex', () => { fixture.componentInstance.tabIndexOverride = 3; @@ -272,7 +274,7 @@ describe('MatSelect', () => { expect(select.getAttribute('tabindex')).toEqual('0'); }); - it('should select options via the UP/DOWN arrow keys on a closed select', fakeAsync(() => { + it('should select options via the UP/DOWN arrow keys on a closed select', () => { const formControl = fixture.componentInstance.control; const options = fixture.componentInstance.options.toArray(); @@ -307,18 +309,15 @@ describe('MatSelect', () => { expect(formControl.value) .withContext('Expected value from second option to have been set on the model.') .toBe(options[1].value); + }); - flush(); - })); - - it('should go back to first option if value is reset after interacting using the arrow keys on a closed select', fakeAsync(() => { + it('should go back to first option if value is reset after interacting using the arrow keys on a closed select', () => { const formControl = fixture.componentInstance.control; const options = fixture.componentInstance.options.toArray(); expect(formControl.value).withContext('Expected no initial value.').toBeFalsy(); dispatchKeyboardEvent(select, 'keydown', DOWN_ARROW); - flush(); expect(options[0].selected) .withContext('Expected first option to be selected.') @@ -336,7 +335,6 @@ describe('MatSelect', () => { expect(formControl.value).withContext('Expected value to be reset.').toBeFalsy(); dispatchKeyboardEvent(select, 'keydown', DOWN_ARROW); - flush(); expect(options[0].selected) .withContext('Expected first option to be selected again.') @@ -344,9 +342,9 @@ describe('MatSelect', () => { expect(formControl.value) .withContext('Expected value from first option to have been set on the model again.') .toBe(options[0].value); - })); + }); - it('should select first/last options via the HOME/END keys on a closed select', fakeAsync(() => { + it('should select first/last options via the HOME/END keys on a closed select', () => { const formControl = fixture.componentInstance.control; const firstOption = fixture.componentInstance.options.first; const lastOption = fixture.componentInstance.options.last; @@ -372,11 +370,9 @@ describe('MatSelect', () => { expect(formControl.value) .withContext('Expected value from first option to have been set on the model.') .toBe(firstOption.value); + }); - flush(); - })); - - it('should select first/last options via the PAGE_DOWN/PAGE_UP keys on a closed select with less than 10 options', fakeAsync(() => { + it('should select first/last options via the PAGE_DOWN/PAGE_UP keys on a closed select with less than 10 options', () => { const formControl = fixture.componentInstance.control; const firstOption = fixture.componentInstance.options.first; const lastOption = fixture.componentInstance.options.last; @@ -405,11 +401,9 @@ describe('MatSelect', () => { expect(formControl.value) .withContext('Expected value from first option to have been set on the model.') .toBe(firstOption.value); + }); - flush(); - })); - - it('should resume focus from selected item after selecting via click', fakeAsync(() => { + it('should resume focus from selected item after selecting via click', () => { const formControl = fixture.componentInstance.control; const options = fixture.componentInstance.options.toArray(); @@ -417,11 +411,9 @@ describe('MatSelect', () => { fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); (getOverlayHost(fixture)?.querySelectorAll('mat-option')[3] as HTMLElement).click(); fixture.detectChanges(); - flush(); expect(formControl.value).toBe(options[3].value); @@ -429,10 +421,9 @@ describe('MatSelect', () => { fixture.detectChanges(); expect(formControl.value).toBe(options[4].value); - flush(); - })); + }); - it('should select options via LEFT/RIGHT arrow keys on a closed select', fakeAsync(() => { + it('should select options via LEFT/RIGHT arrow keys on a closed select', () => { const formControl = fixture.componentInstance.control; const options = fixture.componentInstance.options.toArray(); @@ -467,21 +458,18 @@ describe('MatSelect', () => { expect(formControl.value) .withContext('Expected value from second option to have been set on the model.') .toBe(options[1].value); - flush(); - })); + }); - it('should announce changes via the keyboard on a closed select', fakeAsync(() => { + it('should announce changes via the keyboard on a closed select', () => { const liveAnnouncer = TestBed.inject(LiveAnnouncer); spyOn(liveAnnouncer, 'announce'); dispatchKeyboardEvent(select, 'keydown', RIGHT_ARROW); expect(liveAnnouncer.announce).toHaveBeenCalledWith('Steak', jasmine.any(Number)); + }); - flush(); - })); - - it('should not throw when reaching a reset option using the arrow keys on a closed select', fakeAsync(() => { + it('should not throw when reaching a reset option using the arrow keys on a closed select', () => { fixture.componentInstance.foods = [ {value: 'steak-0', viewValue: 'Steak'}, {value: null, viewValue: 'None'}, @@ -494,9 +482,7 @@ describe('MatSelect', () => { dispatchKeyboardEvent(select, 'keydown', DOWN_ARROW); fixture.detectChanges(); }).not.toThrow(); - - flush(); - })); + }); it('should open a single-selection select using ALT + DOWN_ARROW', () => { const {control: formControl, select: selectInstance} = fixture.componentInstance; @@ -562,14 +548,14 @@ describe('MatSelect', () => { .toBe(true); }); - it('should be able to select options by typing on a closed select', fakeAsync(() => { + it('should be able to select options by typing on a closed select', async () => { const formControl = fixture.componentInstance.control; const options = fixture.componentInstance.options.toArray(); expect(formControl.value).withContext('Expected no initial value.').toBeFalsy(); dispatchEvent(select, createKeyboardEvent('keydown', 80, 'p')); - tick(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); + await wait(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); expect(options[1].selected) .withContext('Expected second option to be selected.') @@ -579,7 +565,7 @@ describe('MatSelect', () => { .toBe(options[1].value); dispatchEvent(select, createKeyboardEvent('keydown', 69, 'e')); - tick(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); + await wait(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); expect(options[5].selected) .withContext('Expected sixth option to be selected.') @@ -587,9 +573,9 @@ describe('MatSelect', () => { expect(formControl.value) .withContext('Expected value from sixth option to have been set on the model.') .toBe(options[5].value); - })); + }); - it('should not open the select when pressing space while typing', fakeAsync(() => { + it('should not open the select when pressing space while typing', async () => { const selectInstance = fixture.componentInstance.select; fixture.componentInstance.typeaheadDebounceInterval = DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL; @@ -601,7 +587,7 @@ describe('MatSelect', () => { .toBe(false); dispatchEvent(select, createKeyboardEvent('keydown', 80, 'p')); - tick(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL / 2); + await wait(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL / 2); fixture.detectChanges(); dispatchKeyboardEvent(select, 'keydown', SPACE); @@ -611,15 +597,15 @@ describe('MatSelect', () => { .withContext('Expected select to remain closed after space was pressed.') .toBe(false); - tick(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL / 2); + await wait(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL / 2); fixture.detectChanges(); expect(selectInstance.panelOpen) .withContext('Expected select to be closed when the timer runs out.') .toBe(false); - })); + }); - it('should be able to customize the typeahead debounce interval', fakeAsync(() => { + it('should be able to customize the typeahead debounce interval', async () => { const formControl = fixture.componentInstance.control; const options = fixture.componentInstance.options.toArray(); @@ -630,13 +616,13 @@ describe('MatSelect', () => { expect(formControl.value).withContext('Expected no initial value.').toBeFalsy(); dispatchEvent(select, createKeyboardEvent('keydown', 80, 'p')); - tick(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); + await wait(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); expect(formControl.value) .withContext('Expected no value after a bit of time has passed.') .toBeFalsy(); - tick(1337); + await wait(1337); expect(options[1].selected) .withContext('Expected second option to be selected after all the time has passed.') @@ -644,9 +630,9 @@ describe('MatSelect', () => { expect(formControl.value) .withContext('Expected value from second option to have been set on the model.') .toBe(options[1].value); - })); + }); - it('should cancel the typeahead selection on blur', fakeAsync(() => { + it('should cancel the typeahead selection on blur', async () => { const formControl = fixture.componentInstance.control; const options = fixture.componentInstance.options.toArray(); @@ -654,13 +640,13 @@ describe('MatSelect', () => { dispatchEvent(select, createKeyboardEvent('keydown', 80, 'p')); dispatchFakeEvent(select, 'blur'); - tick(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); + await wait(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); expect(options.some(o => o.selected)) .withContext('Expected no options to be selected.') .toBe(false); expect(formControl.value).withContext('Expected no value to be assigned.').toBeFalsy(); - })); + }); it('should open the panel when pressing a vertical arrow key on a closed multiple select', () => { fixture.destroy(); @@ -751,7 +737,7 @@ describe('MatSelect', () => { .toBe(true); }); - it('should continue from the selected option when the value is set programmatically', fakeAsync(() => { + it('should continue from the selected option when the value is set programmatically', () => { const formControl = fixture.componentInstance.control; formControl.setValue('eggs-5'); @@ -761,8 +747,7 @@ describe('MatSelect', () => { expect(formControl.value).toBe('pasta-6'); expect(fixture.componentInstance.options.toArray()[6].selected).toBe(true); - flush(); - })); + }); it('should not shift focus when the selected options are updated programmatically in a multi select', () => { fixture.destroy(); @@ -851,7 +836,7 @@ describe('MatSelect', () => { .toBe(false); }); - it('should toggle the next option when pressing shift + DOWN_ARROW on a multi-select', fakeAsync(() => { + it('should toggle the next option when pressing shift + DOWN_ARROW on a multi-select', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -862,7 +847,6 @@ describe('MatSelect', () => { multiFixture.componentInstance.select.open(); multiFixture.detectChanges(); - flush(); expect(multiFixture.componentInstance.select.value).toBeFalsy(); @@ -875,9 +859,9 @@ describe('MatSelect', () => { multiFixture.detectChanges(); expect(multiFixture.componentInstance.select.value).toEqual(['pizza-1', 'tacos-2']); - })); + }); - it('should toggle the previous option when pressing shift + UP_ARROW on a multi-select', fakeAsync(() => { + it('should toggle the previous option when pressing shift + UP_ARROW on a multi-select', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -888,7 +872,6 @@ describe('MatSelect', () => { multiFixture.componentInstance.select.open(); multiFixture.detectChanges(); - flush(); // Move focus down first. for (let i = 0; i < 5; i++) { @@ -907,7 +890,7 @@ describe('MatSelect', () => { multiFixture.detectChanges(); expect(multiFixture.componentInstance.select.value).toEqual(['sandwich-3', 'chips-4']); - })); + }); it('should prevent the default action when pressing space', () => { const event = dispatchKeyboardEvent(select, 'keydown', SPACE); @@ -926,7 +909,7 @@ describe('MatSelect', () => { }); }); - it('should consider the selection a result of a user action when closed', fakeAsync(() => { + it('should consider the selection a result of a user action when closed', () => { const option = fixture.componentInstance.options.first; const spy = jasmine.createSpy('option selection spy'); const subscription = option.onSelectionChange @@ -937,8 +920,7 @@ describe('MatSelect', () => { expect(spy).toHaveBeenCalledWith(true); subscription.unsubscribe(); - flush(); - })); + }); it('should be able to focus the select trigger', () => { document.body.focus(); // ensure that focus isn't on the trigger already @@ -950,7 +932,7 @@ describe('MatSelect', () => { .toBe(select); }); - it('should set `aria-multiselectable` to true on the listbox inside multi select', fakeAsync(() => { + it('should set `aria-multiselectable` to true on the listbox inside multi select', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -958,22 +940,20 @@ describe('MatSelect', () => { select = multiFixture.debugElement.query(By.css('mat-select'))!.nativeElement; multiFixture.componentInstance.select.open(); multiFixture.detectChanges(); - flush(); const panel = document.querySelector('.mat-mdc-select-panel')!; expect(panel.getAttribute('aria-multiselectable')).toBe('true'); - })); + }); - it('should set aria-multiselectable false on single-selection instances', fakeAsync(() => { + it('should set aria-multiselectable false on single-selection instances', () => { fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); const panel = document.querySelector('.mat-mdc-select-panel')!; expect(panel.getAttribute('aria-multiselectable')).toBe('false'); - })); + }); - it('should set aria-activedescendant only while the panel is open', fakeAsync(() => { + it('should set aria-activedescendant only while the panel is open', () => { fixture.componentInstance.control.setValue('chips-4'); fixture.detectChanges(); @@ -985,7 +965,6 @@ describe('MatSelect', () => { fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); const options = getOverlayHost(fixture)!.querySelectorAll('mat-option'); @@ -995,19 +974,17 @@ describe('MatSelect', () => { fixture.componentInstance.select.close(); fixture.detectChanges(); - flush(); expect(host.hasAttribute('aria-activedescendant')) .withContext('Expected no aria-activedescendant when closed.') .toBe(false); - })); + }); - it('should set aria-activedescendant based on the focused option', fakeAsync(() => { + it('should set aria-activedescendant based on the focused option', () => { const host = fixture.debugElement.query(By.css('mat-select'))!.nativeElement; fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); const options = getOverlayHost(fixture)!.querySelectorAll('mat-option'); @@ -1024,14 +1001,13 @@ describe('MatSelect', () => { fixture.detectChanges(); expect(host.getAttribute('aria-activedescendant')).toBe(options[2].id); - })); + }); - it('should not change the aria-activedescendant using the horizontal arrow keys', fakeAsync(() => { + it('should not change the aria-activedescendant using the horizontal arrow keys', () => { const host = fixture.debugElement.query(By.css('mat-select'))!.nativeElement; fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); const options = getOverlayHost(fixture)!.querySelectorAll('mat-option'); @@ -1043,7 +1019,7 @@ describe('MatSelect', () => { }); expect(host.getAttribute('aria-activedescendant')).toBe(options[0].id); - })); + }); it('should restore focus to the trigger after selecting an option in multi-select mode', () => { fixture.destroy(); @@ -1069,61 +1045,56 @@ describe('MatSelect', () => { .toBe(select); }); - it('should set a role of listbox on the select panel', fakeAsync(() => { + it('should set a role of listbox on the select panel', () => { fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); const panel = document.querySelector('.mat-mdc-select-panel')!; expect(panel.getAttribute('role')).toBe('listbox'); - })); + }); - it('should point the aria-labelledby of the panel to the field label', fakeAsync(() => { + it('should point the aria-labelledby of the panel to the field label', () => { fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); const labelId = fixture.nativeElement.querySelector('label').id; const panel = document.querySelector('.mat-mdc-select-panel')!; expect(panel.getAttribute('aria-labelledby')).toBe(labelId); - })); + }); - it('should add a custom aria-labelledby to the panel', fakeAsync(() => { + it('should add a custom aria-labelledby to the panel', () => { fixture.componentInstance.ariaLabelledby = 'myLabelId'; fixture.changeDetectorRef.markForCheck(); fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); const labelId = fixture.nativeElement.querySelector('label').id; const panel = document.querySelector('.mat-mdc-select-panel')!; expect(panel.getAttribute('aria-labelledby')).toBe(`${labelId} myLabelId`); - })); + }); - it('should trim the custom panel aria-labelledby when there is no label', fakeAsync(() => { + it('should trim the custom panel aria-labelledby when there is no label', () => { fixture.componentInstance.hasLabel = false; fixture.componentInstance.ariaLabelledby = 'myLabelId'; fixture.changeDetectorRef.markForCheck(); fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); // Note that we assert that there are no spaces around the value. const panel = document.querySelector('.mat-mdc-select-panel')!; expect(panel.getAttribute('aria-labelledby')).toBe(`myLabelId`); - })); + }); - it('should clear aria-labelledby from the panel if an aria-label is set', fakeAsync(() => { + it('should clear aria-labelledby from the panel if an aria-label is set', () => { fixture.componentInstance.ariaLabel = 'My label'; fixture.changeDetectorRef.markForCheck(); fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); const panel = document.querySelector('.mat-mdc-select-panel')!; expect(panel.getAttribute('aria-label')).toBe('My label'); expect(panel.hasAttribute('aria-labelledby')).toBe(false); - })); + }); }); describe('for select inside a modal', () => { @@ -1164,13 +1135,13 @@ describe('MatSelect', () => { ); }); - it('should set the role of mat-option to option', fakeAsync(() => { + it('should set the role of mat-option to option', () => { expect(options[0].getAttribute('role')).toEqual('option'); expect(options[1].getAttribute('role')).toEqual('option'); expect(options[2].getAttribute('role')).toEqual('option'); - })); + }); - it('should set aria-selected on each option for single select', fakeAsync(() => { + it('should set aria-selected on each option for single select', () => { expect(options.every(option => option.getAttribute('aria-selected') === 'false')) .withContext( 'Expected all unselected single-select options to have ' + 'aria-selected="false".', @@ -1182,7 +1153,6 @@ describe('MatSelect', () => { trigger.click(); fixture.detectChanges(); - flush(); expect(options[1].getAttribute('aria-selected')) .withContext( @@ -1195,9 +1165,9 @@ describe('MatSelect', () => { 'Expected all unselected single-select options to have ' + 'aria-selected="false".', ) .toBe(true); - })); + }); - it('should set aria-selected on each option for multi-select', fakeAsync(() => { + it('should set aria-selected on each option for multi-select', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -1230,7 +1200,6 @@ describe('MatSelect', () => { trigger.click(); multiFixture.detectChanges(); - flush(); expect(options[1].getAttribute('aria-selected')) .withContext('Expected selected multi-select option to have aria-selected="true".') @@ -1247,15 +1216,15 @@ describe('MatSelect', () => { 'Expected all unselected multi-select options to have ' + 'aria-selected="false".', ) .toBe(true); - })); + }); - it('should omit the tabindex attribute on each option', fakeAsync(() => { + it('should omit the tabindex attribute on each option', () => { expect(options[0].hasAttribute('tabindex')).toBeFalse(); expect(options[1].hasAttribute('tabindex')).toBeFalse(); expect(options[2].hasAttribute('tabindex')).toBeFalse(); - })); + }); - it('should set aria-disabled for disabled options', fakeAsync(() => { + it('should set aria-disabled for disabled options', () => { expect(options[0].getAttribute('aria-disabled')).toEqual('false'); expect(options[1].getAttribute('aria-disabled')).toEqual('false'); expect(options[2].getAttribute('aria-disabled')).toEqual('true'); @@ -1267,9 +1236,9 @@ describe('MatSelect', () => { expect(options[0].getAttribute('aria-disabled')).toEqual('false'); expect(options[1].getAttribute('aria-disabled')).toEqual('false'); expect(options[2].getAttribute('aria-disabled')).toEqual('false'); - })); + }); - it('should remove the active state from options that have been deselected while closed', fakeAsync(() => { + it('should remove the active state from options that have been deselected while closed', () => { let activeOptions = options.filter(option => { return option.classList.contains('mat-mdc-option-active'); }); @@ -1279,9 +1248,10 @@ describe('MatSelect', () => { options[1].click(); fixture.detectChanges(); + fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); + fixture.detectChanges(); activeOptions = options.filter(option => { return option.classList.contains('mat-mdc-option-active'); @@ -1296,11 +1266,9 @@ describe('MatSelect', () => { fixture.detectChanges(); fixture.componentInstance.select.close(); fixture.detectChanges(); - flush(); fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); activeOptions = options.filter(option => { return option.classList.contains('mat-mdc-option-active'); @@ -1311,15 +1279,14 @@ describe('MatSelect', () => { 'value has changed.', ) .toEqual([options[7]]); - })); + }); - it('should render a checkmark on selected option', fakeAsync(() => { + it('should render a checkmark on selected option', () => { fixture.componentInstance.control.setValue(fixture.componentInstance.foods[2].value); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); const pseudoCheckboxes = options .map(option => option.querySelector('.mat-pseudo-checkbox-minimal')) @@ -1328,9 +1295,9 @@ describe('MatSelect', () => { expect(selectedOption.querySelector('.mat-pseudo-checkbox-minimal')).not.toBeNull(); expect(pseudoCheckboxes.length).toBe(1); - })); + }); - it('should render checkboxes for multi-select', fakeAsync(() => { + it('should render checkboxes for multi-select', () => { fixture.destroy(); const multiFixture = TestBed.createComponent(MultiSelect); @@ -1347,7 +1314,6 @@ describe('MatSelect', () => { trigger.click(); multiFixture.detectChanges(); - flush(); options = Array.from( getOverlayHost(multiFixture)!.querySelectorAll('mat-option'), @@ -1363,7 +1329,7 @@ describe('MatSelect', () => { expect(selectedPseudoCheckbox.classList) .withContext('expecting selected pseudo-checkbox to be checked') .toContain('mat-pseudo-checkbox-checked'); - })); + }); }); describe('for option groups', () => { @@ -1382,11 +1348,11 @@ describe('MatSelect', () => { ) as NodeListOf; }); - it('should set the appropriate role', fakeAsync(() => { + it('should set the appropriate role', () => { expect(groups[0].getAttribute('role')).toBe('group'); - })); + }); - it('should set the `aria-labelledby` attribute', fakeAsync(() => { + it('should set the `aria-labelledby` attribute', () => { let group = groups[0]; let label = group.querySelector('.mat-mdc-optgroup-label') as HTMLElement; @@ -1396,11 +1362,11 @@ describe('MatSelect', () => { expect(group.getAttribute('aria-labelledby')) .withContext('Expected `aria-labelledby` to match the label id.') .toBe(label.getAttribute('id')); - })); + }); - it('should set the `aria-disabled` attribute if the group is disabled', fakeAsync(() => { + it('should set the `aria-disabled` attribute if the group is disabled', () => { expect(groups[1].getAttribute('aria-disabled')).toBe('true'); - })); + }); }); }); @@ -1437,62 +1403,55 @@ describe('MatSelect', () => { expect(select.panelOpen).toBe(false); }); - it('should open the panel when trigger is clicked', fakeAsync(() => { + it('should open the panel when trigger is clicked', () => { trigger.click(); fixture.detectChanges(); - flush(); const overlay = getOverlayHost(fixture)!; expect(fixture.componentInstance.select.panelOpen).toBe(true); expect(overlay.textContent).toContain('Steak'); expect(overlay.textContent).toContain('Pizza'); expect(overlay.textContent).toContain('Tacos'); - })); + }); - it('should close the panel when an item is clicked', fakeAsync(() => { + it('should close the panel when an item is clicked', () => { trigger.click(); fixture.detectChanges(); - flush(); const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement; option.click(); fixture.detectChanges(); - flush(); expect(getOverlayHost(fixture)!).toBeFalsy(); expect(fixture.componentInstance.select.panelOpen).toBe(false); - })); + }); - it('should close the panel when a click occurs outside the panel', fakeAsync(() => { + it('should close the panel when a click occurs outside the panel', () => { trigger.click(); fixture.detectChanges(); - flush(); getBackdrop(fixture)!.click(); fixture.detectChanges(); - flush(); expect(getOverlayHost(fixture)!).toBeFalsy(); expect(fixture.componentInstance.select.panelOpen).toBe(false); - })); + }); - it('should set the width of the overlay based on the trigger', fakeAsync(() => { + it('should set the width of the overlay based on the trigger', () => { formField.style.width = '200px'; trigger.click(); fixture.detectChanges(); - flush(); const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement; expect(pane.style.width).toBe('200px'); - })); + }); - it('should update the width of the panel on resize', fakeAsync(() => { + it('should update the width of the panel on resize', async () => { formField.style.width = '300px'; trigger.click(); fixture.detectChanges(); - flush(); const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement; const initialWidth = parseInt(pane.style.width || '0'); @@ -1502,50 +1461,47 @@ describe('MatSelect', () => { formField.style.width = '400px'; dispatchFakeEvent(window, 'resize'); fixture.detectChanges(); - tick(1000); + await wait(1000); fixture.detectChanges(); expect(parseInt(pane.style.width || '0')).toBeGreaterThan(initialWidth); - })); + }); - it('should be able to set a custom width on the select panel', fakeAsync(() => { + it('should be able to set a custom width on the select panel', () => { fixture.componentInstance.panelWidth = '42px'; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement; expect(pane.style.width).toBe('42px'); - })); + }); - it('should not set a width on the panel if panelWidth is null', fakeAsync(() => { + it('should not set a width on the panel if panelWidth is null', () => { fixture.componentInstance.panelWidth = null; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement; expect(pane.style.width).toBeFalsy(); - })); + }); - it('should not set a width on the panel if panelWidth is an empty string', fakeAsync(() => { + it('should not set a width on the panel if panelWidth is an empty string', () => { fixture.componentInstance.panelWidth = ''; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); const pane = getOverlayHost(fixture)?.querySelector('.cdk-overlay-pane') as HTMLElement; expect(pane.style.width).toBeFalsy(); - })); + }); it('should not attempt to open a select that does not have any options', () => { fixture.componentInstance.foods = []; @@ -1558,26 +1514,23 @@ describe('MatSelect', () => { expect(fixture.componentInstance.select.panelOpen).toBe(false); }); - it('should close the panel when tabbing out', fakeAsync(() => { + it('should close the panel when tabbing out', () => { trigger.click(); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.select.panelOpen).toBe(true); dispatchKeyboardEvent(trigger, 'keydown', TAB); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.select.panelOpen).toBe(false); - })); + }); - it('should restore focus to the host before tabbing away', fakeAsync(() => { + it('should restore focus to the host before tabbing away', () => { const select = fixture.nativeElement.querySelector('.mat-mdc-select'); trigger.click(); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.select.panelOpen).toBe(true); @@ -1586,78 +1539,71 @@ describe('MatSelect', () => { dispatchKeyboardEvent(trigger, 'keydown', TAB); fixture.detectChanges(); - flush(); expect(select.focus).toHaveBeenCalled(); - })); + }); - it('should close when tabbing out from inside the panel', fakeAsync(() => { + it('should close when tabbing out from inside the panel', () => { trigger.click(); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.select.panelOpen).toBe(true); const panel = getOverlayHost(fixture)!.querySelector('.mat-mdc-select-panel')!; dispatchKeyboardEvent(panel, 'keydown', TAB); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.select.panelOpen).toBe(false); - })); + }); - it('should focus the first option when pressing HOME', fakeAsync(() => { + it('should focus the first option when pressing HOME', () => { fixture.componentInstance.control.setValue('pizza-1'); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); const event = dispatchKeyboardEvent(trigger, 'keydown', HOME); fixture.detectChanges(); expect(fixture.componentInstance.select._keyManager.activeItemIndex).toBe(0); expect(event.defaultPrevented).toBe(true); - })); + }); - it('should focus the last option when pressing END', fakeAsync(() => { + it('should focus the last option when pressing END', () => { fixture.componentInstance.control.setValue('pizza-1'); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); const event = dispatchKeyboardEvent(trigger, 'keydown', END); fixture.detectChanges(); expect(fixture.componentInstance.select._keyManager.activeItemIndex).toBe(7); expect(event.defaultPrevented).toBe(true); - })); + }); - it('should focus the last option when pressing PAGE_DOWN with less than 10 options', fakeAsync(() => { + it('should focus the last option when pressing PAGE_DOWN with less than 10 options', () => { fixture.componentInstance.control.setValue('pizza-1'); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); const event = dispatchKeyboardEvent(trigger, 'keydown', PAGE_DOWN); fixture.detectChanges(); expect(fixture.componentInstance.select._keyManager.activeItemIndex).toBe(7); expect(event.defaultPrevented).toBe(true); - })); + }); - it('should focus the first option when pressing PAGE_UP with index < 10', fakeAsync(() => { + it('should focus the first option when pressing PAGE_UP with index < 10', () => { fixture.componentInstance.control.setValue('pizza-1'); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.select._keyManager.activeItemIndex).toBeLessThan(10); const event = dispatchKeyboardEvent(trigger, 'keydown', PAGE_UP); @@ -1665,7 +1611,7 @@ describe('MatSelect', () => { expect(fixture.componentInstance.select._keyManager.activeItemIndex).toBe(0); expect(event.defaultPrevented).toBe(true); - })); + }); it('should be able to set extra classes on the panel', () => { trigger.click(); @@ -1695,14 +1641,13 @@ describe('MatSelect', () => { .toBeTruthy(); }); - it('should not show ripples if they were disabled', fakeAsync(() => { + it('should not show ripples if they were disabled', () => { fixture.componentInstance.disableRipple = true; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); const option = getOverlayHost(fixture)!.querySelector('mat-option')!; @@ -1710,7 +1655,7 @@ describe('MatSelect', () => { dispatchFakeEvent(option, 'mouseup'); expect(option.querySelectorAll('.mat-ripple-element').length).toBe(0); - })); + }); it('should be able to render options inside groups with an ng-container', () => { fixture.destroy(); @@ -1726,7 +1671,7 @@ describe('MatSelect', () => { .toBeGreaterThan(0); }); - it('should not consider itself as blurred if the trigger loses focus while the panel is still open', fakeAsync(() => { + it('should not consider itself as blurred if the trigger loses focus while the panel is still open', () => { const selectElement = fixture.nativeElement.querySelector('.mat-mdc-select'); const selectInstance = fixture.componentInstance.select; @@ -1737,16 +1682,15 @@ describe('MatSelect', () => { selectInstance.open(); fixture.detectChanges(); - flush(); dispatchFakeEvent(selectElement, 'blur'); fixture.detectChanges(); expect(selectInstance.focused) .withContext('Expected select element to remain focused.') .toBe(true); - })); + }); - it('should close the panel on scroll event when MAT_SELECT_SCROLL_STRATEGY token was defined with CloseScrollStrategy', fakeAsync(() => { + it('should close the panel on scroll event when MAT_SELECT_SCROLL_STRATEGY token was defined with CloseScrollStrategy', () => { // Need to recreate the testing module, because the issue we're // testing for only the MAT_SELECT_SCROLL_STRATEGY is defined with thw // is defined with the CloseScrollStrategy @@ -1775,10 +1719,9 @@ describe('MatSelect', () => { scrolledSubject.next(); fixture.detectChanges(); - flush(); expect(select.panelOpen).toBe(false); - })); + }); }); describe('selection logic', () => { @@ -1801,27 +1744,23 @@ describe('MatSelect', () => { .toBe(false); }); - it('should focus the first option if no option is selected', fakeAsync(() => { + it('should focus the first option if no option is selected', () => { trigger.click(); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.select._keyManager.activeItemIndex).toEqual(0); - })); + }); - it('should select an option when it is clicked', fakeAsync(() => { + it('should select an option when it is clicked', () => { trigger.click(); fixture.detectChanges(); - flush(); let option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement; option.click(); fixture.detectChanges(); - flush(); trigger.click(); fixture.detectChanges(); - flush(); option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement; @@ -1830,12 +1769,11 @@ describe('MatSelect', () => { expect(fixture.componentInstance.select.selected).toBe( fixture.componentInstance.options.first, ); - })); + }); - it('should be able to select an option using the MatOption API', fakeAsync(() => { + it('should be able to select an option using the MatOption API', () => { trigger.click(); fixture.detectChanges(); - flush(); const optionInstances = fixture.componentInstance.options.toArray(); const optionNodes: NodeListOf = @@ -1847,12 +1785,11 @@ describe('MatSelect', () => { expect(optionNodes[1].classList).toContain('mdc-list-item--selected'); expect(optionInstances[1].selected).toBe(true); expect(fixture.componentInstance.select.selected).toBe(optionInstances[1]); - })); + }); - it('should deselect other options when one is selected', fakeAsync(() => { + it('should deselect other options when one is selected', () => { trigger.click(); fixture.detectChanges(); - flush(); let options = getOverlayHost(fixture)!.querySelectorAll( 'mat-option', @@ -1860,11 +1797,9 @@ describe('MatSelect', () => { options[0].click(); fixture.detectChanges(); - flush(); trigger.click(); fixture.detectChanges(); - flush(); options = getOverlayHost(fixture)!.querySelectorAll( 'mat-option', @@ -1875,15 +1810,14 @@ describe('MatSelect', () => { const optionInstances = fixture.componentInstance.options.toArray(); expect(optionInstances[1].selected).toBe(false); expect(optionInstances[2].selected).toBe(false); - })); + }); - it('should deselect other options when one is programmatically selected', fakeAsync(() => { + it('should deselect other options when one is programmatically selected', () => { let control = fixture.componentInstance.control; let foods = fixture.componentInstance.foods; trigger.click(); fixture.detectChanges(); - flush(); let options = getOverlayHost(fixture)!.querySelectorAll( 'mat-option', @@ -1891,14 +1825,12 @@ describe('MatSelect', () => { options[0].click(); fixture.detectChanges(); - flush(); control.setValue(foods[1].value); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); options = getOverlayHost(fixture)!.querySelectorAll( 'mat-option', @@ -1920,14 +1852,14 @@ describe('MatSelect', () => { expect(optionInstances[1].selected) .withContext('Expected second option to be selected') .toBe(true); - })); + }); - it('should remove selection if option has been removed', fakeAsync(() => { + it('should remove selection if option has been removed', async () => { let select = fixture.componentInstance.select; trigger.click(); fixture.detectChanges(); - flush(); + await fixture.whenRenderingDone(); let firstOption = getOverlayHost(fixture)!.querySelectorAll('mat-option')[0] as HTMLElement; @@ -1941,22 +1873,20 @@ describe('MatSelect', () => { fixture.componentInstance.foods = []; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - flush(); + await fixture.whenRenderingDone(); expect(select.selected) .withContext('Expected selection to be removed when option no longer exists.') .toBeUndefined(); - })); + }); - it('should display the selected option in the trigger', fakeAsync(() => { + it('should display the selected option in the trigger', () => { trigger.click(); fixture.detectChanges(); - flush(); const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement; option.click(); fixture.detectChanges(); - flush(); const value = fixture.debugElement.query(By.css('.mat-mdc-select-value'))!.nativeElement; @@ -1964,44 +1894,40 @@ describe('MatSelect', () => { .withContext('Label should be floating') .toBe(true); expect(value.textContent).toContain('Steak'); - })); + }); - it('should focus the selected option if an option is selected', fakeAsync(() => { + it('should focus the selected option if an option is selected', () => { // must wait for initial writeValue promise to finish - flush(); fixture.componentInstance.control.setValue('pizza-1'); fixture.detectChanges(); trigger.click(); fixture.detectChanges(); - flush(); // must wait for animation to finish fixture.detectChanges(); expect(fixture.componentInstance.select._keyManager.activeItemIndex).toEqual(1); - })); + }); - it('should select an option that was added after initialization', fakeAsync(() => { + it('should select an option that was added after initialization', () => { fixture.componentInstance.foods.push({viewValue: 'Potatoes', value: 'potatoes-8'}); trigger.click(); fixture.detectChanges(); - flush(); const options = getOverlayHost(fixture)!.querySelectorAll( 'mat-option', ) as NodeListOf; options[8].click(); fixture.detectChanges(); - flush(); expect(trigger.textContent).toContain('Potatoes'); expect(fixture.componentInstance.select.selected).toBe( fixture.componentInstance.options.last, ); - })); + }); - it('should update the trigger when the selected option label is changed', fakeAsync(() => { + it('should update the trigger when the selected option label is changed', () => { fixture.componentInstance.control.setValue('pizza-1'); fixture.detectChanges(); @@ -2012,9 +1938,9 @@ describe('MatSelect', () => { fixture.detectChanges(); expect(trigger.textContent!.trim()).toBe('Calzone'); - })); + }); - it('should update the trigger value if the text as a result of an expression change', fakeAsync(() => { + it('should update the trigger value if the text as a result of an expression change', () => { fixture.componentInstance.control.setValue('pizza-1'); fixture.detectChanges(); @@ -2026,7 +1952,7 @@ describe('MatSelect', () => { fixture.checkNoChanges(); expect(trigger.textContent!.trim()).toBe('PIZZA'); - })); + }); it('should not select disabled options', () => { trigger.click(); @@ -2062,28 +1988,26 @@ describe('MatSelect', () => { expect(groupFixture.componentInstance.select.selected).toBeUndefined(); }); - it('should not throw if triggerValue accessed with no selected value', fakeAsync(() => { + it('should not throw if triggerValue accessed with no selected value', () => { expect(() => fixture.componentInstance.select.triggerValue).not.toThrow(); - })); + }); - it('should emit to `optionSelectionChanges` when an option is selected', fakeAsync(() => { + it('should emit to `optionSelectionChanges` when an option is selected', () => { trigger.click(); fixture.detectChanges(); - flush(); const spy = jasmine.createSpy('option selection spy'); const subscription = fixture.componentInstance.select.optionSelectionChanges.subscribe(spy); const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement; option.click(); fixture.detectChanges(); - flush(); expect(spy).toHaveBeenCalledWith(jasmine.any(MatOptionSelectionChange)); subscription.unsubscribe(); - })); + }); - it('should handle accessing `optionSelectionChanges` before the options are initialized', fakeAsync(() => { + it('should handle accessing `optionSelectionChanges` before the options are initialized', () => { fixture.destroy(); fixture = TestBed.createComponent(BasicSelect); @@ -2100,48 +2024,46 @@ describe('MatSelect', () => { trigger.click(); fixture.detectChanges(); - flush(); const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement; option.click(); fixture.detectChanges(); - flush(); expect(spy).toHaveBeenCalledWith(jasmine.any(MatOptionSelectionChange)); subscription!.unsubscribe(); - })); + }); - it('should emit to `optionSelectionChanges` after the list of options has changed', fakeAsync(() => { + it('should emit to `optionSelectionChanges` after the list of options has changed', async () => { let spy = jasmine.createSpy('option selection spy'); let subscription = fixture.componentInstance.select.optionSelectionChanges.subscribe(spy); - let selectFirstOption = () => { + let selectFirstOption = async () => { trigger.click(); fixture.detectChanges(); - flush(); + await fixture.whenRenderingDone(); const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement; option.click(); fixture.detectChanges(); - flush(); + await fixture.whenRenderingDone(); }; fixture.componentInstance.foods = [{value: 'salad-8', viewValue: 'Salad'}]; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - selectFirstOption(); + await selectFirstOption(); expect(spy).toHaveBeenCalledTimes(1); fixture.componentInstance.foods = [{value: 'fruit-9', viewValue: 'Fruit'}]; fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); - selectFirstOption(); + await selectFirstOption(); expect(spy).toHaveBeenCalledTimes(2); subscription!.unsubscribe(); - })); + }); it('should not indicate programmatic value changes as user interactions', () => { const events: MatOptionSelectionChange[] = []; @@ -2168,7 +2090,7 @@ describe('MatSelect', () => { trigger = fixture.debugElement.query(By.css('.mat-mdc-select-trigger'))!.nativeElement; }); - it('should take an initial view value with reactive forms', fakeAsync(() => { + it('should take an initial view value with reactive forms', () => { fixture.componentInstance.control = new FormControl('pizza-1'); fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); @@ -2181,7 +2103,6 @@ describe('MatSelect', () => { trigger = fixture.debugElement.query(By.css('.mat-mdc-select-trigger'))!.nativeElement; trigger.click(); fixture.detectChanges(); - flush(); const options = getOverlayHost(fixture)!.querySelectorAll( 'mat-option', @@ -2189,9 +2110,9 @@ describe('MatSelect', () => { expect(options[1].classList) .withContext(`Expected option with the control's initial value to be selected.`) .toContain('mdc-list-item--selected'); - })); + }); - it('should set the view value from the form', fakeAsync(() => { + it('should set the view value from the form', () => { let value = fixture.debugElement.query(By.css('.mat-mdc-select-value'))!; expect(value.nativeElement.textContent.trim()).toBe('Food'); @@ -2205,7 +2126,6 @@ describe('MatSelect', () => { trigger.click(); fixture.detectChanges(); - flush(); const options = getOverlayHost(fixture)!.querySelectorAll( 'mat-option', @@ -2213,28 +2133,26 @@ describe('MatSelect', () => { expect(options[1].classList) .withContext(`Expected option with the control's new value to be selected.`) .toContain('mdc-list-item--selected'); - })); + }); - it('should update the form value when the view changes', fakeAsync(() => { + it('should update the form value when the view changes', () => { expect(fixture.componentInstance.control.value) .withContext(`Expected the control's value to be empty initially.`) .toEqual(null); trigger.click(); fixture.detectChanges(); - flush(); const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement; option.click(); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.control.value) .withContext(`Expected control's value to be set to the new option.`) .toEqual('steak-0'); - })); + }); - it('should clear the selection when a nonexistent option value is selected', fakeAsync(() => { + it('should clear the selection when a nonexistent option value is selected', () => { fixture.componentInstance.control.setValue('pizza-1'); fixture.detectChanges(); @@ -2252,7 +2170,6 @@ describe('MatSelect', () => { trigger.click(); fixture.detectChanges(); - flush(); const options = getOverlayHost(fixture)!.querySelectorAll( 'mat-option', @@ -2261,9 +2178,9 @@ describe('MatSelect', () => { 'mdc-list-item--selected', `Expected option w/ the old value not to be selected.`, ); - })); + }); - it('should clear the selection when the control is reset', fakeAsync(() => { + it('should clear the selection when the control is reset', () => { fixture.componentInstance.control.setValue('pizza-1'); fixture.detectChanges(); @@ -2281,7 +2198,6 @@ describe('MatSelect', () => { trigger.click(); fixture.detectChanges(); - flush(); const options = getOverlayHost(fixture)!.querySelectorAll( 'mat-option', @@ -2290,9 +2206,9 @@ describe('MatSelect', () => { 'mdc-list-item--selected', `Expected option w/ the old value not to be selected.`, ); - })); + }); - it('should set the control to touched when the select is blurred', fakeAsync(() => { + it('should set the control to touched when the select is blurred', () => { expect(fixture.componentInstance.control.touched) .withContext(`Expected the control to start off as untouched.`) .toEqual(false); @@ -2300,7 +2216,6 @@ describe('MatSelect', () => { trigger.click(); dispatchFakeEvent(trigger, 'blur'); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.control.touched) .withContext(`Expected the control to stay untouched when menu opened.`) @@ -2309,14 +2224,13 @@ describe('MatSelect', () => { getBackdrop(fixture)!.click(); dispatchFakeEvent(trigger, 'blur'); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.control.touched) .withContext(`Expected the control to be touched as soon as focus left the select.`) .toEqual(true); - })); + }); - it('should set the control to touched when the panel is closed', fakeAsync(() => { + it('should set the control to touched when the panel is closed', () => { expect(fixture.componentInstance.control.touched) .withContext('Expected the control to start off as untouched.') .toBe(false); @@ -2324,7 +2238,6 @@ describe('MatSelect', () => { trigger.click(); dispatchFakeEvent(trigger, 'blur'); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.control.touched) .withContext('Expected the control to stay untouched when menu opened.') @@ -2332,12 +2245,11 @@ describe('MatSelect', () => { fixture.componentInstance.select.close(); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.control.touched) .withContext('Expected the control to be touched when the panel was closed.') .toBe(true); - })); + }); it('should not set touched when a disabled select is touched', () => { expect(fixture.componentInstance.control.touched) @@ -2352,24 +2264,22 @@ describe('MatSelect', () => { .toBe(false); }); - it('should set the control to dirty when the select value changes in DOM', fakeAsync(() => { + it('should set the control to dirty when the select value changes in DOM', () => { expect(fixture.componentInstance.control.dirty) .withContext(`Expected control to start out pristine.`) .toEqual(false); trigger.click(); fixture.detectChanges(); - flush(); const option = getOverlayHost(fixture)?.querySelector('mat-option') as HTMLElement; option.click(); fixture.detectChanges(); - flush(); expect(fixture.componentInstance.control.dirty) .withContext(`Expected control to be dirty after value was changed by user.`) .toEqual(true); - })); + }); it('should not set the control to dirty when the value changes programmatically', () => { expect(fixture.componentInstance.control.dirty) @@ -2383,7 +2293,7 @@ describe('MatSelect', () => { .toEqual(false); }); - it('should set an asterisk after the label if control is required', fakeAsync(() => { + it('should set an asterisk after the label if control is required', () => { const label = fixture.nativeElement.querySelector('.mat-mdc-form-field label'); expect(label.querySelector('.mat-mdc-form-field-required-marker')) @@ -2397,9 +2307,9 @@ describe('MatSelect', () => { expect(label.querySelector('.mat-mdc-form-field-required-marker')) .withContext(`Expected label to have an asterisk, as control was required.`) .toBeTruthy(); - })); + }); - it('should propagate the value set through the `value` property to the form field', fakeAsync(() => { + it('should propagate the value set through the `value` property to the form field', () => { const control = fixture.componentInstance.control; expect(control.value).toBeFalsy(); @@ -2409,11 +2319,11 @@ describe('MatSelect', () => { fixture.detectChanges(); expect(control.value).toBe('pizza-1'); - })); + }); }); describe('disabled behavior', () => { - it('should disable itself when control is disabled programmatically', fakeAsync(() => { + it('should disable itself when control is disabled programmatically', () => { const fixture = TestBed.createComponent(BasicSelect); fixture.detectChanges(); @@ -2426,7 +2336,6 @@ describe('MatSelect', () => { trigger.click(); fixture.detectChanges(); - flush(); expect(getOverlayHost(fixture)?.querySelector('.mat-mdc-select-panel')) .withContext(`Expected select panel to stay closed.`) @@ -2443,7 +2352,6 @@ describe('MatSelect', () => { trigger.click(); fixture.detectChanges(); - flush(); expect(getOverlayHost(fixture)?.querySelector('.mat-mdc-select-panel')?.textContent) .withContext(`Expected select panel to open normally on re-enabled control`) @@ -2451,7 +2359,7 @@ describe('MatSelect', () => { expect(fixture.componentInstance.select.panelOpen) .withContext(`Expected select panelOpen property to become true.`) .toBe(true); - })); + }); it('should keep the disabled state in sync if the form group is swapped and disabled at the same time', () => { const fixture = TestBed.createComponent(SelectInsideDynamicFormGroup); @@ -2472,7 +2380,7 @@ describe('MatSelect', () => { let host: HTMLElement; let panel: HTMLElement; - beforeEach(fakeAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(BasicSelect); fixture.componentInstance.foods = []; @@ -2485,12 +2393,11 @@ describe('MatSelect', () => { fixture.detectChanges(); fixture.componentInstance.select.open(); fixture.detectChanges(); - flush(); fixture.detectChanges(); host = fixture.debugElement.query(By.css('mat-select'))!.nativeElement; panel = getOverlayHost(fixture)!.querySelector('.mat-mdc-select-panel')! as HTMLElement; - })); + }); it('should not scroll to options that are completely in the view', () => { const initialScrollPosition = panel.scrollTop; @@ -2527,7 +2434,7 @@ describe('MatSelect', () => { expect(panel.scrollTop).withContext('Expected scroll to be at the 9th option.').toBe(440); }); - it('should skip option group labels', fakeAsync(() => { + it('should skip option group labels', () => { fixture.destroy(); const groupFixture = TestBed.createComponent(SelectWithGroups); @@ -2535,7 +2442,6 @@ describe('MatSelect', () => { groupFixture.detectChanges(); groupFixture.componentInstance.select.open(); groupFixture.detectChanges(); - flush(); host = groupFixture.debugElement.query(By.css('mat-select'))!.nativeElement; panel = getOverlayHost(groupFixture)!.querySelector( @@ -2544,13 +2450,12 @@ describe('MatSelect', () => { for (let i = 0; i < 8; i++) { dispatchKeyboardEvent(host, 'keydown', DOWN_ARROW); - flush(); } // + <(option index + group labels) * height> - = // 8 + (8 + 3) * 48 - 275 = 309 expect(panel.scrollTop).withContext('Expected scroll to be at the 9th option.').toBe(309); - })); + }); it('should scroll to the top when pressing HOME', () => { for (let i = 0; i < 20; i++) { @@ -2640,26 +2545,24 @@ describe('MatSelect', () => { expect(fixture.componentInstance.select._keyManager.activeItemIndex).toBe(29); }); - it('should scroll to the active option when typing', fakeAsync(() => { + it('should scroll to the active option when typing', async () => { for (let i = 0; i < 15; i++) { // Press the letter 'o' 15 times since all the options are named 'Option ' dispatchEvent(host, createKeyboardEvent('keydown', 79, 'o')); fixture.detectChanges(); - tick(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); + await wait(DEFAULT_TYPEAHEAD_DEBOUNCE_INTERVAL); } - flush(); // +