diff --git a/.claude/commands/create-hotfix-release.md b/.claude/commands/create-hotfix-release.md index de314309d..f35a8ad23 100644 --- a/.claude/commands/create-hotfix-release.md +++ b/.claude/commands/create-hotfix-release.md @@ -1,30 +1,85 @@ # Create Hotfix Release -This command guides you through creating a patch/hotfix release for ComfyUI Frontend with comprehensive safety checks and human confirmations at each step. +This command creates patch/hotfix releases for ComfyUI Frontend by backporting fixes to stable core branches. It handles both automated backports (preferred) and manual cherry-picking (fallback). + +**Process Overview:** +1. **Check automated backports first** (via labels) +2. **Skip to version bump** if backports already merged +3. **Manual cherry-picking** if automation failed +4. **Create patch release** with version bump +5. **Publish GitHub release** (manually uncheck "latest") +6. **Update ComfyUI requirements.txt** via PR -Create a hotfix release by cherry-picking commits or PR commits from main to a core branch: $ARGUMENTS +Create a hotfix release by backporting commits/PRs from main to a core branch: $ARGUMENTS Expected format: Comma-separated list of commits or PR numbers Examples: -- `abc123,def456,ghi789` (commits) -- `#1234,#5678` (PRs) -- `abc123,#1234,def456` (mixed) +- `#1234,#5678` (PRs - preferred) +- `abc123,def456` (commit hashes) +- `#1234,abc123` (mixed) -If no arguments provided, the command will help identify the correct core branch and guide you through selecting commits/PRs. +If no arguments provided, the command will guide you through identifying commits/PRs to backport. ## Prerequisites -Before starting, ensure: -- You have push access to the repository -- GitHub CLI (`gh`) is authenticated -- You're on a clean working tree -- You understand the commits/PRs you're cherry-picking +- Push access to repository +- GitHub CLI (`gh`) authenticated +- Clean working tree +- Understanding of what fixes need backporting ## Hotfix Release Process -### Step 1: Identify Target Core Branch +### Step 1: Try Automated Backports First + +**Check if automated backports were attempted:** + +1. **For each PR, check existing backport labels:** + ```bash + gh pr view #1234 --json labels | jq -r '.labels[].name' + ``` + +2. **If no backport labels exist, add them now:** + ```bash + # Add backport labels (this triggers automated backports) + gh pr edit #1234 --add-label "needs-backport" + gh pr edit #1234 --add-label "1.24" # Replace with target version + ``` + +3. **Check for existing backport PRs:** + ```bash + # Check for backport PRs created by automation + PR_NUMBER=${ARGUMENTS%%,*} # Extract first PR number from arguments + PR_NUMBER=${PR_NUMBER#\#} # Remove # prefix + gh pr list --search "backport-${PR_NUMBER}-to" --json number,title,state,baseRefName + ``` + +4. **Handle existing backport scenarios:** + + **Scenario A: Automated backports already merged** + ```bash + # Check if backport PRs were merged to core branches + gh pr list --search "backport-${PR_NUMBER}-to" --state merged + ``` + - If backport PRs are merged → Skip to Step 10 (Version Bump) + - **CONFIRMATION**: Automated backports completed, proceeding to version bump? + + **Scenario B: Automated backport PRs exist but not merged** + ```bash + # Show open backport PRs that need merging + gh pr list --search "backport-${PR_NUMBER}-to" --state open + ``` + - **ACTION REQUIRED**: Merge the existing backport PRs first + - Use: `gh pr merge [PR_NUMBER] --merge` for each backport PR + - After merging, return to this command and skip to Step 10 (Version Bump) + - **CONFIRMATION**: Have you merged all backport PRs? Ready to proceed to version bump? + + **Scenario C: No automated backports or they failed** + - Continue to Step 2 for manual cherry-picking + - **CONFIRMATION**: Proceeding with manual cherry-picking because automation failed? + +### Step 2: Identify Target Core Branch 1. Fetch the current ComfyUI requirements.txt from master branch: ```bash @@ -36,7 +91,7 @@ Before starting, ensure: 5. Verify the core branch exists: `git ls-remote origin refs/heads/core/*` 6. **CONFIRMATION REQUIRED**: Is `core/X.Y` the correct target branch? -### Step 2: Parse and Validate Arguments +### Step 3: Parse and Validate Arguments 1. Parse the comma-separated list of commits/PRs 2. For each item: @@ -49,7 +104,7 @@ Before starting, ensure: - **CONFIRMATION REQUIRED**: Use merge commit or cherry-pick individual commits? 4. Validate all commit hashes exist in the repository -### Step 3: Analyze Target Changes +### Step 4: Analyze Target Changes 1. For each commit/PR to cherry-pick: - Display commit hash, author, date @@ -60,7 +115,7 @@ Before starting, ensure: 2. Identify potential conflicts by checking changed files 3. **CONFIRMATION REQUIRED**: Proceed with these commits? -### Step 4: Create Hotfix Branch +### Step 5: Create Hotfix Branch 1. Checkout the core branch (e.g., `core/1.23`) 2. Pull latest changes: `git pull origin core/X.Y` @@ -69,7 +124,7 @@ Before starting, ensure: - Example: `hotfix/1.23.4-20241120` 5. **CONFIRMATION REQUIRED**: Created branch correctly? -### Step 5: Cherry-pick Changes +### Step 6: Cherry-pick Changes For each commit: 1. Attempt cherry-pick: `git cherry-pick ` @@ -83,7 +138,7 @@ For each commit: - Run validation: `pnpm typecheck && pnpm lint` 4. **CONFIRMATION REQUIRED**: Cherry-pick successful and valid? -### Step 6: Create PR to Core Branch +### Step 7: Create PR to Core Branch 1. Push the hotfix branch: `git push origin hotfix/-` 2. Create PR using gh CLI: @@ -100,7 +155,7 @@ For each commit: - Impact assessment 5. **CONFIRMATION REQUIRED**: PR created correctly? -### Step 7: Wait for Tests +### Step 8: Wait for Tests 1. Monitor PR checks: `gh pr checks` 2. Display test results as they complete @@ -111,7 +166,7 @@ For each commit: 4. Wait for all required checks to pass 5. **CONFIRMATION REQUIRED**: All tests passing? -### Step 8: Merge Hotfix PR +### Step 9: Merge Hotfix PR 1. Verify all checks have passed 2. Check for required approvals @@ -119,7 +174,7 @@ For each commit: 4. Delete the hotfix branch 5. **CONFIRMATION REQUIRED**: PR merged successfully? -### Step 9: Create Version Bump +### Step 10: Create Version Bump 1. Checkout the core branch: `git checkout core/X.Y` 2. Pull latest changes: `git pull origin core/X.Y` @@ -131,7 +186,7 @@ For each commit: 7. Commit: `git commit -m "[release] Bump version to 1.23.5"` 8. **CONFIRMATION REQUIRED**: Version bump correct? -### Step 10: Create Release PR +### Step 11: Create Release PR 1. Push release branch: `git push origin release/1.23.5` 2. Create PR with Release label: @@ -184,7 +239,7 @@ For each commit: ``` 5. **CONFIRMATION REQUIRED**: Release PR has "Release" label? -### Step 11: Monitor Release Process +### Step 12: Monitor Release Process 1. Wait for PR checks to pass 2. **FINAL CONFIRMATION**: Ready to trigger release by merging? @@ -199,7 +254,102 @@ For each commit: - PyPI upload - pnpm types publication -### Step 12: Post-Release Verification +### Step 13: Manually Publish Draft Release + +**CRITICAL**: The release workflow creates a DRAFT release. You must manually publish it: + +1. **Go to GitHub Releases:** https://github.com/Comfy-Org/ComfyUI_frontend/releases +2. **Find the DRAFT release** (e.g., "v1.23.5 Draft") +3. **Click "Edit release"** +4. **UNCHECK "Set as the latest release"** ⚠️ **CRITICAL** + - This prevents the hotfix from showing as "latest" + - Main branch should always be "latest release" +5. **Click "Publish release"** +6. **CONFIRMATION REQUIRED**: Draft release published with "latest" unchecked? + +### Step 14: Create ComfyUI Requirements.txt Update PR + +**IMPORTANT**: Create PR to update ComfyUI's requirements.txt via fork: + +1. **Setup fork (if needed):** + ```bash + # Check if fork already exists + if gh repo view ComfyUI --json owner | jq -r '.owner.login' | grep -q "$(gh api user --jq .login)"; then + echo "Fork already exists" + else + # Fork the ComfyUI repository + gh repo fork comfyanonymous/ComfyUI --clone=false + echo "Created fork of ComfyUI" + fi + ``` + +2. **Clone fork and create branch:** + ```bash + # Clone your fork (or use existing clone) + GITHUB_USER=$(gh api user --jq .login) + if [ ! -d "ComfyUI-fork" ]; then + gh repo clone ${GITHUB_USER}/ComfyUI ComfyUI-fork + fi + + cd ComfyUI-fork + git checkout master + git pull origin master + + # Create update branch + BRANCH_NAME="update-frontend-${NEW_VERSION}" + git checkout -b ${BRANCH_NAME} + ``` + +3. **Update requirements.txt:** + ```bash + # Update the version in requirements.txt + sed -i "s/comfyui-frontend-package==[0-9].*$/comfyui-frontend-package==${NEW_VERSION}/" requirements.txt + + # Verify the change + grep "comfyui-frontend-package" requirements.txt + + # Commit the change + git add requirements.txt + git commit -m "Bump frontend to ${NEW_VERSION}" + git push origin ${BRANCH_NAME} + ``` + +4. **Create PR from fork:** + ```bash + # Create PR using gh CLI from fork + gh pr create \ + --repo comfyanonymous/ComfyUI \ + --title "Bump frontend to ${NEW_VERSION}" \ + --body "$(cat <> $GITHUB_OUTPUT + exit 0 + fi + + echo "Found existing backport PRs:" + echo "$EXISTING_BACKPORTS" + echo "skip=true" >> $GITHUB_OUTPUT + echo "::warning::Backport PRs already exist for PR #${PR_NUMBER}, skipping to avoid duplicates" + - name: Extract version labels + if: steps.check-existing.outputs.skip != 'true' id: versions run: | # Extract version labels (e.g., "1.24", "1.22") @@ -52,6 +72,7 @@ jobs: echo "Found version labels: ${VERSIONS}" - name: Backport commits + if: steps.check-existing.outputs.skip != 'true' id: backport env: PR_NUMBER: ${{ github.event.pull_request.number }} @@ -109,7 +130,7 @@ jobs: fi - name: Create PR for each successful backport - if: steps.backport.outputs.success + if: steps.check-existing.outputs.skip != 'true' && steps.backport.outputs.success env: GH_TOKEN: ${{ secrets.PR_GH_TOKEN }} run: | @@ -141,7 +162,7 @@ jobs: done - name: Comment on failures - if: failure() && steps.backport.outputs.failed + if: steps.check-existing.outputs.skip != 'true' && failure() && steps.backport.outputs.failed env: GH_TOKEN: ${{ github.token }} run: | diff --git a/.github/workflows/claude-pr-review.yml b/.github/workflows/claude-pr-review.yml index 3ec61cb3c..d1eecafe3 100644 --- a/.github/workflows/claude-pr-review.yml +++ b/.github/workflows/claude-pr-review.yml @@ -47,6 +47,7 @@ jobs: needs: wait-for-ci if: needs.wait-for-ci.outputs.should-proceed == 'true' runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout repository uses: actions/checkout@v4 @@ -69,19 +70,17 @@ jobs: pnpm install -g typescript @vue/compiler-sfc - name: Run Claude PR Review - uses: anthropics/claude-code-action@main + uses: anthropics/claude-code-action@v1.0.6 with: label_trigger: "claude-review" - direct_prompt: | + prompt: | Read the file .claude/commands/comprehensive-pr-review.md and follow ALL the instructions exactly. CRITICAL: You must post individual inline comments using the gh api commands shown in the file. DO NOT create a summary comment. Each issue must be posted as a separate inline comment on the specific line of code. anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - max_turns: 256 - timeout_minutes: 30 - allowed_tools: "Bash(git:*),Bash(gh api:*),Bash(gh pr:*),Bash(gh repo:*),Bash(jq:*),Bash(echo:*),Read,Write,Edit,Glob,Grep,WebFetch" + claude_args: "--max-turns 256 --allowedTools 'Bash(git:*),Bash(gh api:*),Bash(gh pr:*),Bash(gh repo:*),Bash(jq:*),Bash(echo:*),Read,Write,Edit,Glob,Grep,WebFetch'" env: PR_NUMBER: ${{ github.event.pull_request.number }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/create-release-candidate-branch.yaml b/.github/workflows/create-release-candidate-branch.yaml index 84b545478..e3fcd9e2b 100644 --- a/.github/workflows/create-release-candidate-branch.yaml +++ b/.github/workflows/create-release-candidate-branch.yaml @@ -128,45 +128,6 @@ jobs: echo "- Critical security patches" echo "- Documentation updates" - - name: Create branch protection rules - if: steps.check_version.outputs.is_minor_bump == 'true' && env.branch_exists != 'true' - env: - GITHUB_TOKEN: ${{ secrets.PR_GH_TOKEN || secrets.GITHUB_TOKEN }} - run: | - BRANCH_NAME="${{ steps.check_version.outputs.branch_name }}" - - # Create branch protection using GitHub API - echo "Setting up branch protection for $BRANCH_NAME..." - - RESPONSE=$(curl -s -w "\n%{http_code}" -X PUT \ - -H "Authorization: token $GITHUB_TOKEN" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/${{ github.repository }}/branches/$BRANCH_NAME/protection" \ - -d '{ - "required_status_checks": { - "strict": true, - "contexts": ["lint-and-format", "test", "playwright-tests"] - }, - "enforce_admins": false, - "required_pull_request_reviews": { - "required_approving_review_count": 1, - "dismiss_stale_reviews": true - }, - "restrictions": null, - "allow_force_pushes": false, - "allow_deletions": false - }') - - HTTP_CODE=$(echo "$RESPONSE" | tail -n 1) - BODY=$(echo "$RESPONSE" | sed '$d') - - if [[ "$HTTP_CODE" -eq 200 ]] || [[ "$HTTP_CODE" -eq 201 ]]; then - echo "✅ Branch protection successfully applied" - else - echo "⚠️ Failed to apply branch protection (HTTP $HTTP_CODE)" - echo "Response: $BODY" - # Don't fail the workflow, just warn - fi - name: Post summary if: steps.check_version.outputs.is_minor_bump == 'true' diff --git a/.github/workflows/pr-playwright-deploy.yaml b/.github/workflows/pr-playwright-deploy.yaml index 12051fa99..19bb28253 100644 --- a/.github/workflows/pr-playwright-deploy.yaml +++ b/.github/workflows/pr-playwright-deploy.yaml @@ -1,4 +1,4 @@ -name: PR Playwright Deploy and Comment +name: PR Playwright Deploy (Forks) on: workflow_run: @@ -9,272 +9,84 @@ env: DATE_FORMAT: '+%m/%d/%Y, %I:%M:%S %p' jobs: - deploy-reports: + deploy-and-comment-forked-pr: runs-on: ubuntu-latest - if: github.repository == 'Comfy-Org/ComfyUI_frontend' && github.event.workflow_run.event == 'pull_request' && github.event.action == 'completed' + if: | + github.repository == 'Comfy-Org/ComfyUI_frontend' && + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.head_repository != null && + github.event.workflow_run.repository != null && + github.event.workflow_run.head_repository.full_name != github.event.workflow_run.repository.full_name permissions: + pull-requests: write actions: read - strategy: - fail-fast: false - matrix: - browser: [chromium, chromium-2x, chromium-0.5x, mobile-chrome] steps: - - name: Get PR info - id: pr-info + - name: Log workflow trigger info + run: | + echo "Repository: ${{ github.repository }}" + echo "Event: ${{ github.event.workflow_run.event }}" + echo "Head repo: ${{ github.event.workflow_run.head_repository.full_name || 'null' }}" + echo "Base repo: ${{ github.event.workflow_run.repository.full_name || 'null' }}" + echo "Is forked: ${{ github.event.workflow_run.head_repository.full_name != github.event.workflow_run.repository.full_name }}" + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get PR Number + id: pr uses: actions/github-script@v7 with: script: | - const { data: pullRequests } = await github.rest.pulls.list({ + const { data: prs } = await github.rest.pulls.list({ owner: context.repo.owner, repo: context.repo.repo, state: 'open', - head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`, }); - if (pullRequests.length === 0) { - console.log('No open PR found for this branch'); - return { number: null, sanitized_branch: null }; + const pr = prs.find(p => p.head.sha === context.payload.workflow_run.head_sha); + + if (!pr) { + console.log('No PR found for SHA:', context.payload.workflow_run.head_sha); + return null; } - const pr = pullRequests[0]; - const branchName = context.payload.workflow_run.head_branch; - const sanitizedBranch = branchName.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/--+/g, '-').replace(/^-|-$/g, ''); - - return { - number: pr.number, - sanitized_branch: sanitizedBranch - }; + console.log(`Found PR #${pr.number} from fork: ${context.payload.workflow_run.head_repository.full_name}`); + return pr.number; - - name: Set project name - if: fromJSON(steps.pr-info.outputs.result).number != null - id: project-name + - name: Handle Test Start + if: steps.pr.outputs.result != 'null' && github.event.action == 'requested' + env: + GITHUB_TOKEN: ${{ github.token }} run: | - if [ "${{ matrix.browser }}" = "chromium-0.5x" ]; then - echo "name=comfyui-playwright-chromium-0-5x" >> $GITHUB_OUTPUT - else - echo "name=comfyui-playwright-${{ matrix.browser }}" >> $GITHUB_OUTPUT - fi - echo "branch=${{ fromJSON(steps.pr-info.outputs.result).sanitized_branch }}" >> $GITHUB_OUTPUT + chmod +x scripts/cicd/pr-playwright-deploy-and-comment.sh + ./scripts/cicd/pr-playwright-deploy-and-comment.sh \ + "${{ steps.pr.outputs.result }}" \ + "${{ github.event.workflow_run.head_branch }}" \ + "starting" \ + "$(date -u '${{ env.DATE_FORMAT }}')" - - name: Download playwright report - if: fromJSON(steps.pr-info.outputs.result).number != null + - name: Download and Deploy Reports + if: steps.pr.outputs.result != 'null' && github.event.action == 'completed' uses: actions/download-artifact@v4 with: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} - name: playwright-report-${{ matrix.browser }} - path: playwright-report - - - name: Install Wrangler - if: fromJSON(steps.pr-info.outputs.result).number != null - run: npm install -g wrangler - - - name: Deploy to Cloudflare Pages (${{ matrix.browser }}) - if: fromJSON(steps.pr-info.outputs.result).number != null - id: cloudflare-deploy - continue-on-error: true - run: | - # Retry logic for wrangler deploy (3 attempts) - RETRY_COUNT=0 - MAX_RETRIES=3 - SUCCESS=false + pattern: playwright-report-* + path: reports - while [ $RETRY_COUNT -lt $MAX_RETRIES ] && [ $SUCCESS = false ]; do - RETRY_COUNT=$((RETRY_COUNT + 1)) - echo "Deployment attempt $RETRY_COUNT of $MAX_RETRIES..." - - if npx wrangler pages deploy playwright-report --project-name=${{ steps.project-name.outputs.name }} --branch=${{ steps.project-name.outputs.branch }}; then - SUCCESS=true - echo "Deployment successful on attempt $RETRY_COUNT" - else - echo "Deployment failed on attempt $RETRY_COUNT" - if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then - echo "Retrying in 10 seconds..." - sleep 10 - fi - fi - done - - if [ $SUCCESS = false ]; then - echo "All deployment attempts failed" - exit 1 - fi + - name: Handle Test Completion + if: steps.pr.outputs.result != 'null' && github.event.action == 'completed' env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - - comment-tests-starting: - runs-on: ubuntu-latest - if: github.repository == 'Comfy-Org/ComfyUI_frontend' && github.event.workflow_run.event == 'pull_request' && github.event.action == 'requested' - permissions: - pull-requests: write - actions: read - steps: - - name: Get PR number - id: pr - uses: actions/github-script@v7 - with: - script: | - const { data: pullRequests } = await github.rest.pulls.list({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`, - }); - - if (pullRequests.length === 0) { - console.log('No open PR found for this branch'); - return null; - } - - return pullRequests[0].number; - - - name: Get completion time - id: completion-time - run: echo "time=$(date -u '${{ env.DATE_FORMAT }}')" >> $GITHUB_OUTPUT - - - name: Generate comment body for start - if: steps.pr.outputs.result != 'null' - id: comment-body-start + GITHUB_TOKEN: ${{ github.token }} run: | - echo "" > comment.md - echo "## 🎭 Playwright Test Results" >> comment.md - echo "" >> comment.md - echo "comfy-loading-gif **Tests are starting...** " >> comment.md - echo "" >> comment.md - echo "⏰ Started at: ${{ steps.completion-time.outputs.time }} UTC" >> comment.md - echo "" >> comment.md - echo "### 🚀 Running Tests" >> comment.md - echo "- 🧪 **chromium**: Running tests..." >> comment.md - echo "- 🧪 **chromium-0.5x**: Running tests..." >> comment.md - echo "- 🧪 **chromium-2x**: Running tests..." >> comment.md - echo "- 🧪 **mobile-chrome**: Running tests..." >> comment.md - echo "" >> comment.md - echo "---" >> comment.md - echo "⏱️ Please wait while tests are running across all browsers..." >> comment.md - - - name: Comment PR - Tests Started - if: steps.pr.outputs.result != 'null' - uses: edumserrano/find-create-or-update-comment@82880b65c8a3a6e4c70aa05a204995b6c9696f53 # v3.0.0 - with: - issue-number: ${{ steps.pr.outputs.result }} - body-includes: '' - comment-author: 'github-actions[bot]' - edit-mode: replace - body-path: comment.md - - comment-tests-completed: - runs-on: ubuntu-latest - needs: deploy-reports - if: github.repository == 'Comfy-Org/ComfyUI_frontend' && github.event.workflow_run.event == 'pull_request' && github.event.action == 'completed' && always() - permissions: - pull-requests: write - actions: read - steps: - - name: Get PR number - id: pr - uses: actions/github-script@v7 - with: - script: | - const { data: pullRequests } = await github.rest.pulls.list({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`, - }); - - if (pullRequests.length === 0) { - console.log('No open PR found for this branch'); - return null; - } - - return pullRequests[0].number; - - - name: Download all deployment info - if: steps.pr.outputs.result != 'null' - uses: actions/download-artifact@v4 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ github.event.workflow_run.id }} - pattern: deployment-info-* - merge-multiple: true - path: deployment-info - - - name: Get completion time - id: completion-time - run: echo "time=$(date -u '${{ env.DATE_FORMAT }}')" >> $GITHUB_OUTPUT - - - name: Generate comment body for completion - if: steps.pr.outputs.result != 'null' - id: comment-body-completed - run: | - echo "" > comment.md - echo "## 🎭 Playwright Test Results" >> comment.md - echo "" >> comment.md - - # Check if all tests passed - ALL_PASSED=true - for file in deployment-info/*.txt; do - if [ -f "$file" ]; then - browser=$(basename "$file" .txt) - info=$(cat "$file") - exit_code=$(echo "$info" | cut -d'|' -f2) - if [ "$exit_code" != "0" ]; then - ALL_PASSED=false - break - fi - fi - done - - if [ "$ALL_PASSED" = "true" ]; then - echo "✅ **All tests passed across all browsers!**" >> comment.md - else - echo "❌ **Some tests failed!**" >> comment.md - fi - - echo "" >> comment.md - echo "⏰ Completed at: ${{ steps.completion-time.outputs.time }} UTC" >> comment.md - echo "" >> comment.md - echo "### 📊 Test Reports by Browser" >> comment.md - - for file in deployment-info/*.txt; do - if [ -f "$file" ]; then - browser=$(basename "$file" .txt) - info=$(cat "$file") - exit_code=$(echo "$info" | cut -d'|' -f2) - url=$(echo "$info" | cut -d'|' -f3) - - # Validate URLs before using them in comments - sanitized_url=$(echo "$url" | grep -E '^https://[a-z0-9.-]+\.pages\.dev(/.*)?$' || echo "INVALID_URL") - if [ "$sanitized_url" = "INVALID_URL" ]; then - echo "Invalid deployment URL detected: $url" - url="#" # Use safe fallback - fi - - if [ "$exit_code" = "0" ]; then - status="✅" - else - status="❌" - fi - - echo "- $status **$browser**: [View Report]($url)" >> comment.md - fi - done - - echo "" >> comment.md - echo "---" >> comment.md - if [ "$ALL_PASSED" = "true" ]; then - echo "🎉 Your tests are passing across all browsers!" >> comment.md - else - echo "⚠️ Please check the test reports for details on failures." >> comment.md - fi - - - name: Comment PR - Tests Complete - if: steps.pr.outputs.result != 'null' - uses: edumserrano/find-create-or-update-comment@82880b65c8a3a6e4c70aa05a204995b6c9696f53 # v3.0.0 - with: - issue-number: ${{ steps.pr.outputs.result }} - body-includes: '' - comment-author: 'github-actions[bot]' - edit-mode: replace - body-path: comment.md \ No newline at end of file + # Rename merged report if exists + [ -d "reports/playwright-report-chromium-merged" ] && \ + mv reports/playwright-report-chromium-merged reports/playwright-report-chromium + + chmod +x scripts/cicd/pr-playwright-deploy-and-comment.sh + ./scripts/cicd/pr-playwright-deploy-and-comment.sh \ + "${{ steps.pr.outputs.result }}" \ + "${{ github.event.workflow_run.head_branch }}" \ + "completed" \ No newline at end of file diff --git a/.github/workflows/test-ui.yaml b/.github/workflows/test-ui.yaml index 451c4b903..f8f6cf955 100644 --- a/.github/workflows/test-ui.yaml +++ b/.github/workflows/test-ui.yaml @@ -284,3 +284,65 @@ jobs: name: playwright-report-chromium path: ComfyUI_frontend/playwright-report/ retention-days: 30 + + #### BEGIN Deployment and commenting (non-forked PRs only) + # when using pull_request event, we have permission to comment directly + # if its a forked repo, we need to use workflow_run event in a separate workflow (pr-playwright-deploy.yaml) + + # Post starting comment for non-forked PRs + comment-on-pr-start: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false + permissions: + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get start time + id: start-time + run: echo "time=$(date -u '+%m/%d/%Y, %I:%M:%S %p')" >> $GITHUB_OUTPUT + + - name: Post starting comment + env: + GITHUB_TOKEN: ${{ github.token }} + run: | + chmod +x scripts/cicd/pr-playwright-deploy-and-comment.sh + ./scripts/cicd/pr-playwright-deploy-and-comment.sh \ + "${{ github.event.pull_request.number }}" \ + "${{ github.head_ref }}" \ + "starting" \ + "${{ steps.start-time.outputs.time }}" + + # Deploy and comment for non-forked PRs only + deploy-and-comment: + needs: [playwright-tests, merge-reports] + runs-on: ubuntu-latest + if: always() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false + permissions: + pull-requests: write + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download all playwright reports + uses: actions/download-artifact@v4 + with: + pattern: playwright-report-* + path: reports + + - name: Make deployment script executable + run: chmod +x scripts/cicd/pr-playwright-deploy-and-comment.sh + + - name: Deploy reports and comment on PR + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + GITHUB_TOKEN: ${{ github.token }} + run: | + ./scripts/cicd/pr-playwright-deploy-and-comment.sh \ + "${{ github.event.pull_request.number }}" \ + "${{ github.head_ref }}" \ + "completed" + #### END Deployment and commenting (non-forked PRs only) \ No newline at end of file diff --git a/.gitignore b/.gitignore index db0b8454c..100bcd13e 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ tests-ui/workflows/examples /blob-report/ /playwright/.cache/ browser_tests/**/*-win32.png +browser-tests/local/ .env diff --git a/.husky/pre-commit b/.husky/pre-commit index 6b8a399e4..578271509 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/usr/bin/env bash -npx lint-staged -npx tsx scripts/check-unused-i18n-keys.ts \ No newline at end of file +pnpm exec lint-staged +pnpm exec tsx scripts/check-unused-i18n-keys.ts diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 000000000..ec1fc17d0 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +# Run Knip with cache via package script +pnpm knip + diff --git a/.mcp.json b/.mcp.json deleted file mode 100644 index 82e215be0..000000000 --- a/.mcp.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "mcpServers": { - "playwright": { - "command": "npx", - "args": ["-y", "@executeautomation/playwright-mcp-server"] - }, - "context7": { - "command": "npx", - "args": ["-y", "@upstash/context7-mcp"] - } - } -} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 2ac2ab06e..68be11a12 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -127,3 +127,6 @@ const value = api.getServerFeature('config_name', defaultValue) // Get config - NEVER use `--no-verify` flag when committing - NEVER delete or disable tests to make them pass - NEVER circumvent quality checks +- NEVER use `dark:` prefix - always use `dark-theme:` for dark mode styles, for example: `dark-theme:text-white dark-theme:bg-black` +- NEVER use `:class="[]"` to merge class names - always use `import { cn } from '@/utils/tailwindUtil'`, for example: `
` + diff --git a/browser_tests/fixtures/ComfyMouse.ts b/browser_tests/fixtures/ComfyMouse.ts index 306f4352b..dfb0281eb 100644 --- a/browser_tests/fixtures/ComfyMouse.ts +++ b/browser_tests/fixtures/ComfyMouse.ts @@ -10,7 +10,7 @@ import type { Position } from './types' * - {@link Mouse.move} * - {@link Mouse.up} */ -export interface DragOptions { +interface DragOptions { button?: 'left' | 'right' | 'middle' clickCount?: number steps?: number diff --git a/browser_tests/fixtures/ComfyPage.ts b/browser_tests/fixtures/ComfyPage.ts index f64ca5c94..c32dd3937 100644 --- a/browser_tests/fixtures/ComfyPage.ts +++ b/browser_tests/fixtures/ComfyPage.ts @@ -453,6 +453,32 @@ export class ComfyPage { await workflowsTab.close() } + /** + * Attach a screenshot to the test report. + * By default, screenshots are only taken in non-CI environments. + * @param name - Name for the screenshot attachment + * @param options - Optional configuration + * @param options.runInCI - Whether to take screenshot in CI (default: false) + * @param options.fullPage - Whether to capture full page (default: false) + */ + async attachScreenshot( + name: string, + options: { runInCI?: boolean; fullPage?: boolean } = {} + ) { + const { runInCI = false, fullPage = false } = options + + // Skip in CI unless explicitly requested + if (process.env.CI && !runInCI) { + return + } + + const testInfo = comfyPageFixture.info() + await testInfo.attach(name, { + body: await this.page.screenshot({ fullPage }), + contentType: 'image/png' + }) + } + async resetView() { if (await this.resetViewButton.isVisible()) { await this.resetViewButton.click() diff --git a/browser_tests/fixtures/components/Topbar.ts b/browser_tests/fixtures/components/Topbar.ts index f2c9dfa16..04a9117ce 100644 --- a/browser_tests/fixtures/components/Topbar.ts +++ b/browser_tests/fixtures/components/Topbar.ts @@ -1,7 +1,13 @@ -import { Locator, Page } from '@playwright/test' +import { Locator, Page, expect } from '@playwright/test' export class Topbar { - constructor(public readonly page: Page) {} + private readonly menuLocator: Locator + private readonly menuTrigger: Locator + + constructor(public readonly page: Page) { + this.menuLocator = page.locator('.comfy-command-menu') + this.menuTrigger = page.locator('.comfyui-logo-wrapper') + } async getTabNames(): Promise { return await this.page @@ -15,10 +21,33 @@ export class Topbar { .innerText() } - getMenuItem(itemLabel: string): Locator { + /** + * Get a menu item by its label, optionally within a specific parent container + */ + getMenuItem(itemLabel: string, parent?: Locator): Locator { + if (parent) { + return parent.locator(`.p-tieredmenu-item:has-text("${itemLabel}")`) + } + return this.page.locator(`.p-menubar-item-label:text-is("${itemLabel}")`) } + /** + * Get the visible submenu (last visible submenu in case of nested menus) + */ + getVisibleSubmenu(): Locator { + return this.page.locator('.p-tieredmenu-submenu:visible').last() + } + + /** + * Check if a menu item has an active checkmark + */ + async isMenuItemActive(menuItem: Locator): Promise { + const checkmark = menuItem.locator('.pi-check') + const classes = await checkmark.getAttribute('class') + return classes ? !classes.includes('invisible') : false + } + getWorkflowTab(tabName: string): Locator { return this.page .locator(`.workflow-tabs .workflow-label:has-text("${tabName}")`) @@ -66,10 +95,50 @@ export class Topbar { async openTopbarMenu() { await this.page.waitForTimeout(1000) - await this.page.locator('.comfyui-logo-wrapper').click() - const menu = this.page.locator('.comfy-command-menu') - await menu.waitFor({ state: 'visible' }) - return menu + await this.menuTrigger.click() + await this.menuLocator.waitFor({ state: 'visible' }) + return this.menuLocator + } + + /** + * Close the topbar menu by clicking outside + */ + async closeTopbarMenu() { + await this.page.locator('body').click({ position: { x: 10, y: 10 } }) + await expect(this.menuLocator).not.toBeVisible() + } + + /** + * Navigate to a submenu by hovering over a menu item + */ + async openSubmenu(menuItemLabel: string): Promise { + const menuItem = this.getMenuItem(menuItemLabel) + await menuItem.hover() + const submenu = this.getVisibleSubmenu() + await submenu.waitFor({ state: 'visible' }) + return submenu + } + + /** + * Get theme menu items and interact with theme switching + */ + async getThemeMenuItems() { + const themeSubmenu = await this.openSubmenu('Theme') + return { + submenu: themeSubmenu, + darkTheme: this.getMenuItem('Dark (Default)', themeSubmenu), + lightTheme: this.getMenuItem('Light', themeSubmenu) + } + } + + /** + * Switch to a specific theme + */ + async switchTheme(theme: 'dark' | 'light') { + const { darkTheme, lightTheme } = await this.getThemeMenuItems() + const themeItem = theme === 'dark' ? darkTheme : lightTheme + const themeLabel = themeItem.locator('.p-menubar-item-label') + await themeLabel.click() } async triggerTopbarCommand(path: string[]) { @@ -79,9 +148,7 @@ export class Topbar { const menu = await this.openTopbarMenu() const tabName = path[0] - const topLevelMenuItem = this.page.locator( - `.p-menubar-item-label:text-is("${tabName}")` - ) + const topLevelMenuItem = this.getMenuItem(tabName) const topLevelMenu = menu .locator('.p-tieredmenu-item') .filter({ has: topLevelMenuItem }) diff --git a/browser_tests/fixtures/utils/litegraphUtils.ts b/browser_tests/fixtures/utils/litegraphUtils.ts index 8a52d8b66..c9bf88a91 100644 --- a/browser_tests/fixtures/utils/litegraphUtils.ts +++ b/browser_tests/fixtures/utils/litegraphUtils.ts @@ -134,7 +134,7 @@ export class SubgraphSlotReference { } } -export class NodeSlotReference { +class NodeSlotReference { constructor( readonly type: 'input' | 'output', readonly index: number, @@ -201,7 +201,7 @@ export class NodeSlotReference { } } -export class NodeWidgetReference { +class NodeWidgetReference { constructor( readonly index: number, readonly node: NodeReference diff --git a/browser_tests/fixtures/utils/vueNodeFixtures.ts b/browser_tests/fixtures/utils/vueNodeFixtures.ts new file mode 100644 index 000000000..5c4541b92 --- /dev/null +++ b/browser_tests/fixtures/utils/vueNodeFixtures.ts @@ -0,0 +1,131 @@ +import type { Locator, Page } from '@playwright/test' + +import type { NodeReference } from './litegraphUtils' + +/** + * VueNodeFixture provides Vue-specific testing utilities for interacting with + * Vue node components. It bridges the gap between litegraph node references + * and Vue UI components. + */ +export class VueNodeFixture { + constructor( + private readonly nodeRef: NodeReference, + private readonly page: Page + ) {} + + /** + * Get the node's header element using data-testid + */ + async getHeader(): Promise { + const nodeId = this.nodeRef.id + return this.page.locator(`[data-testid="node-header-${nodeId}"]`) + } + + /** + * Get the node's title element + */ + async getTitleElement(): Promise { + const header = await this.getHeader() + return header.locator('[data-testid="node-title"]') + } + + /** + * Get the current title text + */ + async getTitle(): Promise { + const titleElement = await this.getTitleElement() + return (await titleElement.textContent()) || '' + } + + /** + * Set a new title by double-clicking and entering text + */ + async setTitle(newTitle: string): Promise { + const titleElement = await this.getTitleElement() + await titleElement.dblclick() + + const input = (await this.getHeader()).locator( + '[data-testid="node-title-input"]' + ) + await input.fill(newTitle) + await input.press('Enter') + } + + /** + * Cancel title editing + */ + async cancelTitleEdit(): Promise { + const titleElement = await this.getTitleElement() + await titleElement.dblclick() + + const input = (await this.getHeader()).locator( + '[data-testid="node-title-input"]' + ) + await input.press('Escape') + } + + /** + * Check if the title is currently being edited + */ + async isEditingTitle(): Promise { + const header = await this.getHeader() + const input = header.locator('[data-testid="node-title-input"]') + return await input.isVisible() + } + + /** + * Get the collapse/expand button + */ + async getCollapseButton(): Promise { + const header = await this.getHeader() + return header.locator('[data-testid="node-collapse-button"]') + } + + /** + * Toggle the node's collapsed state + */ + async toggleCollapse(): Promise { + const button = await this.getCollapseButton() + await button.click() + } + + /** + * Get the collapse icon element + */ + async getCollapseIcon(): Promise { + const button = await this.getCollapseButton() + return button.locator('i') + } + + /** + * Get the collapse icon's CSS classes + */ + async getCollapseIconClass(): Promise { + const icon = await this.getCollapseIcon() + return (await icon.getAttribute('class')) || '' + } + + /** + * Check if the collapse button is visible + */ + async isCollapseButtonVisible(): Promise { + const button = await this.getCollapseButton() + return await button.isVisible() + } + + /** + * Get the node's body/content element + */ + async getBody(): Promise { + const nodeId = this.nodeRef.id + return this.page.locator(`[data-testid="node-body-${nodeId}"]`) + } + + /** + * Check if the node body is visible (not collapsed) + */ + async isBodyVisible(): Promise { + const body = await this.getBody() + return await body.isVisible() + } +} diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png index 1ba61954e..423859696 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-all-colors-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-all-colors-chromium-linux.png index 70c81dfbb..7751d090e 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-all-colors-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-all-colors-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-chromium-linux.png index 47083ae5c..22e014cff 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/default-color-palette-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/default-color-palette-chromium-linux.png index 722020a96..4a5c11c2b 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/default-color-palette-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/default-color-palette-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-lightened-colors-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-lightened-colors-chromium-linux.png index 1ba61954e..423859696 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-lightened-colors-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-lightened-colors-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-2-arc-theme-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-2-arc-theme-chromium-linux.png index ee50ed0c5..95ef93d47 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-2-arc-theme-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-2-arc-theme-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-changed-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-changed-chromium-linux.png index 3d490143e..ec52820b1 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-changed-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-changed-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-removed-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-removed-chromium-linux.png index f5eeaa61b..3702c5e46 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-removed-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-removed-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-5-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-5-chromium-linux.png index 6b0e3a30a..ba4591403 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-5-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-5-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-1-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-1-chromium-linux.png index 722020a96..4a5c11c2b 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-1-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-1-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-chromium-linux.png index 6f5edfd8f..acd3b340e 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-with-link-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-with-link-chromium-linux.png index 9a695eed8..bb6defb05 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-with-link-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-with-link-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-widget-value-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-widget-value-chromium-linux.png index 1c1a63047..1927ba4ae 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-widget-value-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-widget-value-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/drag-copy-copied-node-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/drag-copy-copied-node-chromium-linux.png index 164773278..1cd84c832 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/drag-copy-copied-node-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/drag-copy-copied-node-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/no-node-copied-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/no-node-copied-chromium-linux.png index be7214acf..b7bead810 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/no-node-copied-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/no-node-copied-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/paste-in-text-area-with-node-previously-copied-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/paste-in-text-area-with-node-previously-copied-chromium-linux.png index fdc151be1..241a48448 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/paste-in-text-area-with-node-previously-copied-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/paste-in-text-area-with-node-previously-copied-chromium-linux.png differ diff --git a/browser_tests/tests/domWidget.spec.ts-snapshots/focus-mode-on-chromium-linux.png b/browser_tests/tests/domWidget.spec.ts-snapshots/focus-mode-on-chromium-linux.png index 3acc073ff..4d4bd7c57 100644 Binary files a/browser_tests/tests/domWidget.spec.ts-snapshots/focus-mode-on-chromium-linux.png and b/browser_tests/tests/domWidget.spec.ts-snapshots/focus-mode-on-chromium-linux.png differ diff --git a/browser_tests/tests/execution.spec.ts-snapshots/execution-error-unconnected-slot-chromium-linux.png b/browser_tests/tests/execution.spec.ts-snapshots/execution-error-unconnected-slot-chromium-linux.png index 8b8287a40..109c5436a 100644 Binary files a/browser_tests/tests/execution.spec.ts-snapshots/execution-error-unconnected-slot-chromium-linux.png and b/browser_tests/tests/execution.spec.ts-snapshots/execution-error-unconnected-slot-chromium-linux.png differ diff --git a/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-hidden-links-chromium-linux.png b/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-hidden-links-chromium-linux.png index f5ca69e54..b0c849b88 100644 Binary files a/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-hidden-links-chromium-linux.png and b/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-hidden-links-chromium-linux.png differ diff --git a/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-visible-links-chromium-linux.png b/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-visible-links-chromium-linux.png index af9081d0a..cbf2b4f08 100644 Binary files a/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-visible-links-chromium-linux.png and b/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-visible-links-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png index e2e2f2206..ed5712f00 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/batch-disconnect-links-disconnected-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/batch-disconnect-links-disconnected-chromium-linux.png index 27c987620..8a387cb47 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/batch-disconnect-links-disconnected-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/batch-disconnect-links-disconnected-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-chromium-linux.png index 5732eea2b..e1c4fe01a 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-moved-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-moved-chromium-linux.png index 3ebdeb306..98027277e 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-moved-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-moved-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-2x-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-2x-linux.png index ba16c1a37..36be4e4fc 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-2x-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-2x-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-linux.png index 2006231c7..c0112a796 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/deleted-all-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/deleted-all-chromium-linux.png index fd4b5a115..fa37a19a8 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/deleted-all-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/deleted-all-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/disconnected-edge-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/disconnected-edge-chromium-linux.png index c07494c21..a73a56622 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/disconnected-edge-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/disconnected-edge-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/dragged-node1-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/dragged-node1-chromium-linux.png index a3d7a8443..86c45da4d 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/dragged-node1-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/dragged-node1-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link1-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link1-chromium-linux.png index b8e5cdab9..ce0c454eb 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link1-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link1-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link2-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link2-chromium-linux.png index e425d88e8..7fe839d52 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link2-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link2-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/group-fit-to-contents-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/group-fit-to-contents-chromium-linux.png index 99bd797a8..351b73b99 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/group-fit-to-contents-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/group-fit-to-contents-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png index 3e8474a2b..046886851 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/group-title-edited-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/group-title-edited-chromium-linux.png index 082281496..b36ec42fd 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/group-title-edited-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/group-title-edited-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-alt-shift-drag-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-alt-shift-drag-chromium-linux.png index 750d15c1b..6eb2b1ac1 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-alt-shift-drag-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-alt-shift-drag-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-click-node-select-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-click-node-select-chromium-linux.png index d0bd046ad..e2e04c7e7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-click-node-select-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-click-node-select-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-left-drag-pan-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-left-drag-pan-chromium-linux.png index 750d15c1b..6eb2b1ac1 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-left-drag-pan-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-left-drag-pan-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-middle-drag-pan-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-middle-drag-pan-chromium-linux.png index 750d15c1b..6eb2b1ac1 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-middle-drag-pan-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-middle-drag-pan-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-in-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-in-chromium-linux.png index c457dea5c..2d944759e 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-in-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-in-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-out-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-out-chromium-linux.png index 2006231c7..c0112a796 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-out-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-out-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/moved-link-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/moved-link-chromium-linux.png index 7a631a02f..391228994 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/moved-link-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/moved-link-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/node-title-edited-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/node-title-edited-chromium-linux.png index 8255f0f5a..117d4bb8a 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/node-title-edited-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/node-title-edited-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-bypassed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-bypassed-chromium-linux.png index 7181cdcfc..099a0b05b 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-bypassed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-bypassed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-pinned-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-pinned-chromium-linux.png index f6b135cb6..23f5e9c7e 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-pinned-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-pinned-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unbypassed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unbypassed-chromium-linux.png index a6d09ff18..349014360 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unbypassed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unbypassed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unpinned-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unpinned-chromium-linux.png index a6d09ff18..349014360 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unpinned-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unpinned-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-from-far-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-from-far-chromium-linux.png index 7445cc3f9..892b43b72 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-from-far-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-from-far-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-one-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-one-chromium-linux.png index 2006231c7..c0112a796 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-one-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-one-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-two-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-two-chromium-linux.png index 5b2380510..1648d9e8f 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-two-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-two-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-chromium-linux.png index 02d3823e4..788a96295 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-far-away-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-far-away-chromium-linux.png index fd4b5a115..fa37a19a8 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-far-away-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-far-away-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-one-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-one-chromium-linux.png index 5b2380510..1648d9e8f 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-one-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-one-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-two-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-two-chromium-linux.png index 7445cc3f9..892b43b72 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-two-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-two-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-touch-mobile-chrome-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-touch-mobile-chrome-linux.png index 89cdd22d2..d0798275d 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-touch-mobile-chrome-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-touch-mobile-chrome-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panning-when-dragging-link-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panning-when-dragging-link-chromium-linux.png index 6d06644e3..e2984d5c3 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panning-when-dragging-link-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panning-when-dragging-link-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/pinned-all-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/pinned-all-chromium-linux.png index 51f5fc50e..1b221cac9 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/pinned-all-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/pinned-all-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png index 2006231c7..c0112a796 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png index a8fed2ac0..0ba6e8df2 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-chromium-linux.png index 6811cb646..d23f7108a 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-text-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-text-chromium-linux.png index 6ce3ce119..1f5fd61ed 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-text-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-text-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-all-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-all-chromium-linux.png index a149cb8ef..336d7526d 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-all-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-all-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-2x-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-2x-linux.png index f57ca3be8..a9f182581 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-2x-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-2x-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png index d0bd046ad..e2e04c7e7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-2x-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-2x-linux.png index 9e998d26f..8590a08d8 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-2x-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-2x-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png index f76d1945d..9c5c9677b 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-chromium-linux.png index 797b10f6f..869a1c4b6 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-fit-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-fit-chromium-linux.png index 797b10f6f..869a1c4b6 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-fit-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-fit-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-modified-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-modified-chromium-linux.png index 1dfcfa4fe..764f05410 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-modified-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-modified-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-chromium-linux.png index dc1258e21..71dcfaed8 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-linked-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-linked-chromium-linux.png index 2a80227ab..6640f4f38 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-linked-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-linked-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/snapped-highlighted-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/snapped-highlighted-chromium-linux.png index 37866d892..7f0f6f24f 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/snapped-highlighted-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/snapped-highlighted-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-click-node-select-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-click-node-select-chromium-linux.png index d0bd046ad..e2e04c7e7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-click-node-select-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-click-node-select-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-in-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-in-chromium-linux.png index c457dea5c..2d944759e 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-in-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-in-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-out-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-out-chromium-linux.png index 2006231c7..c0112a796 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-out-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-out-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-initial-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-initial-chromium-linux.png index a9d0efb74..2f5526019 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-initial-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-initial-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-left-drag-select-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-left-drag-select-chromium-linux.png index a6d09ff18..349014360 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-left-drag-select-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-left-drag-select-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-middle-drag-pan-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-middle-drag-pan-chromium-linux.png index 750d15c1b..6eb2b1ac1 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-middle-drag-pan-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-middle-drag-pan-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-center-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-center-chromium-linux.png index 57b6438ae..1c8538715 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-center-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-center-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-left-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-left-chromium-linux.png index a9d0efb74..2f5526019 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-left-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-left-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-right-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-right-chromium-linux.png index 57b6438ae..1c8538715 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-right-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-right-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-space-drag-pan-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-space-drag-pan-chromium-linux.png index 3db5f8a8c..a6baaa6ad 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-space-drag-pan-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-space-drag-pan-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/string-input-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/string-input-chromium-linux.png index 2c3343f6b..51725b7e7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/string-input-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/string-input-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/string-node-id-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/string-node-id-chromium-linux.png index 7b7b8f84a..a727dce70 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/string-node-id-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/string-node-id-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-back-open-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-back-open-chromium-linux.png index 67a37ae57..56e147eba 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-back-open-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-back-open-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-off-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-off-chromium-linux.png index dfd279b57..3744ac657 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-off-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-off-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/unpinned-all-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/unpinned-all-chromium-linux.png index a149cb8ef..336d7526d 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/unpinned-all-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/unpinned-all-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-back-in-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-back-in-chromium-linux.png index 2006231c7..c0112a796 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-back-in-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-back-in-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-default-ctrl-shift-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-default-ctrl-shift-chromium-linux.png index 3d891b985..96ed23cf5 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-default-ctrl-shift-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-default-ctrl-shift-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png index 39ec12552..3ecf7ebb2 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png index ef8c2d9b2..759d66b50 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-high-zoom-speed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-high-zoom-speed-chromium-linux.png index 4be78a0bd..6b3c9f349 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-high-zoom-speed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-high-zoom-speed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-low-zoom-speed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-low-zoom-speed-chromium-linux.png index a3f68aaf7..5b60237c3 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-low-zoom-speed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-low-zoom-speed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png index 2006231c7..c0112a796 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-ctrl-shift-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-ctrl-shift-chromium-linux.png index 910bf98e6..aa411c13c 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-ctrl-shift-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-ctrl-shift-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-high-zoom-speed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-high-zoom-speed-chromium-linux.png index 27b3ff339..73cc47ffa 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-high-zoom-speed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-high-zoom-speed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-low-zoom-speed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-low-zoom-speed-chromium-linux.png index a135084e8..bc5a9c57c 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-low-zoom-speed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-low-zoom-speed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-very-far-out-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-very-far-out-chromium-linux.png index e807682d3..a39ae0d7d 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-very-far-out-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-very-far-out-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/dropped-workflow-url-hidream-dev-example-png-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/dropped-workflow-url-hidream-dev-example-png-chromium-linux.png index eb4903bf8..15b1e0f14 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/dropped-workflow-url-hidream-dev-example-png-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/dropped-workflow-url-hidream-dev-example-png-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/edited-workflow-webp-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/edited-workflow-webp-chromium-linux.png index 2e327dff0..c1a5b4340 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/edited-workflow-webp-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/edited-workflow-webp-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/large-workflow-webp-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/large-workflow-webp-chromium-linux.png index 2ff59b391..082c4a0c6 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/large-workflow-webp-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/large-workflow-webp-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/no-workflow-webp-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/no-workflow-webp-chromium-linux.png index 8f347b607..1464d93a2 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/no-workflow-webp-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/no-workflow-webp-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-m4v-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-m4v-chromium-linux.png index 65446a6c7..37ccbb323 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-m4v-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-m4v-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mov-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mov-chromium-linux.png index 65446a6c7..37ccbb323 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mov-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mov-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mp4-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mp4-chromium-linux.png index 65446a6c7..37ccbb323 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mp4-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mp4-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-svg-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-svg-chromium-linux.png index 2e327dff0..c1a5b4340 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-svg-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-svg-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webm-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webm-chromium-linux.png index 58e7be2ea..662eefd90 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webm-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webm-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webp-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webp-chromium-linux.png index 2e327dff0..c1a5b4340 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webp-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webp-chromium-linux.png differ diff --git a/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-high-quality-chromium-linux.png b/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-high-quality-chromium-linux.png index 0b2859d12..8d69066c2 100644 Binary files a/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-high-quality-chromium-linux.png and b/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-high-quality-chromium-linux.png differ diff --git a/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-low-quality-chromium-linux.png b/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-low-quality-chromium-linux.png index a6d8fe852..ea86cb4e1 100644 Binary files a/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-low-quality-chromium-linux.png and b/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-low-quality-chromium-linux.png differ diff --git a/browser_tests/tests/menu.spec.ts b/browser_tests/tests/menu.spec.ts index 355acb590..fa46778a4 100644 --- a/browser_tests/tests/menu.spec.ts +++ b/browser_tests/tests/menu.spec.ts @@ -178,6 +178,72 @@ test.describe('Menu', () => { await comfyPage.menu.topbar.triggerTopbarCommand(['ext', 'foo-command']) expect(await comfyPage.getVisibleToastCount()).toBe(1) }) + + test('Can navigate Theme menu and switch between Dark and Light themes', async ({ + comfyPage + }) => { + const { topbar } = comfyPage.menu + + // Take initial screenshot with default theme + await comfyPage.attachScreenshot('theme-initial') + + // Open the topbar menu + const menu = await topbar.openTopbarMenu() + await expect(menu).toBeVisible() + + // Get theme menu items + const { + submenu: themeSubmenu, + darkTheme: darkThemeItem, + lightTheme: lightThemeItem + } = await topbar.getThemeMenuItems() + + await expect(darkThemeItem).toBeVisible() + await expect(lightThemeItem).toBeVisible() + + // Switch to Light theme + await topbar.switchTheme('light') + + // Verify menu stays open and Light theme shows as active + await expect(menu).toBeVisible() + await expect(themeSubmenu).toBeVisible() + + // Check that Light theme is active + expect(await topbar.isMenuItemActive(lightThemeItem)).toBe(true) + + // Screenshot with light theme active + await comfyPage.attachScreenshot('theme-menu-light-active') + + // Verify ColorPalette setting is set to "light" + expect(await comfyPage.getSetting('Comfy.ColorPalette')).toBe('light') + + // Close menu to see theme change + await topbar.closeTopbarMenu() + + // Re-open menu and get theme items again + await topbar.openTopbarMenu() + const themeItems2 = await topbar.getThemeMenuItems() + + // Switch back to Dark theme + await topbar.switchTheme('dark') + + // Verify menu stays open and Dark theme shows as active + await expect(menu).toBeVisible() + await expect(themeItems2.submenu).toBeVisible() + + // Check that Dark theme is active and Light theme is not + expect(await topbar.isMenuItemActive(themeItems2.darkTheme)).toBe(true) + expect(await topbar.isMenuItemActive(themeItems2.lightTheme)).toBe(false) + + // Screenshot with dark theme active + await comfyPage.attachScreenshot('theme-menu-dark-active') + + // Verify ColorPalette setting is set to "dark" + expect(await comfyPage.getSetting('Comfy.ColorPalette')).toBe('dark') + + // Close menu + await topbar.closeTopbarMenu() + }) }) // Only test 'Top' to reduce test time. diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png index eaf2a528c..68985db05 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png index 8b8c993c3..eec02ef30 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png index 97a24c6dc..ca68ad258 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png index 3e28c594a..57c5199b1 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png index b81e9e785..7bde04b28 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-light-color-palette-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-light-color-palette-chromium-linux.png index 7b5a380fc..d64c6c93b 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-light-color-palette-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-light-color-palette-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png index 1c2e2e274..6d7c32276 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-unknown-color-palette-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-unknown-color-palette-chromium-linux.png index 6975bdeae..942bbf724 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-unknown-color-palette-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-unknown-color-palette-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/default-input-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/default-input-chromium-linux.png index 415531498..196990019 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/default-input-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/default-input-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/dynamically-added-input-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/dynamically-added-input-chromium-linux.png index 5ae61ea03..aff3b2012 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/dynamically-added-input-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/dynamically-added-input-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/force-input-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/force-input-chromium-linux.png index f76546805..5d97d949b 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/force-input-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/force-input-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/missing-nodes-converted-widget-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/missing-nodes-converted-widget-chromium-linux.png index 84ed95b0d..9d086a2e7 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/missing-nodes-converted-widget-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/missing-nodes-converted-widget-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/optional-input-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/optional-input-chromium-linux.png index 10c5870f3..b58d1cd5b 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/optional-input-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/optional-input-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/simple-slider-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/simple-slider-chromium-linux.png index ecea34922..e5855068f 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/simple-slider-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/simple-slider-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-chromium-linux.png index 1202e34d9..17e2e13e2 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-no-connection-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-no-connection-chromium-linux.png index f4bd4d3f9..0ca779dc6 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-no-connection-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-no-connection-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-batch-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-batch-chromium-linux.png index 0d57dcd25..ac61db5cd 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-batch-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-batch-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-chromium-linux.png index 127e5be05..aacd4d499 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-context-menu-search-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-context-menu-search-chromium-linux.png index 127e5be05..aacd4d499 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-context-menu-search-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-context-menu-search-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-release-context-menu-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-release-context-menu-chromium-linux.png index ade1f674d..84ee3f655 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-release-context-menu-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-release-context-menu-chromium-linux.png differ diff --git a/browser_tests/tests/noteNode.spec.ts-snapshots/note-nodes-chromium-linux.png b/browser_tests/tests/noteNode.spec.ts-snapshots/note-nodes-chromium-linux.png index 509067e9f..789f31c5a 100644 Binary files a/browser_tests/tests/noteNode.spec.ts-snapshots/note-nodes-chromium-linux.png and b/browser_tests/tests/noteNode.spec.ts-snapshots/note-nodes-chromium-linux.png differ diff --git a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-chromium-linux.png b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-chromium-linux.png index d64126266..b09ed4e59 100644 Binary files a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-chromium-linux.png and b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-chromium-linux.png differ diff --git a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-chromium-linux.png b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-chromium-linux.png index 40d877ff9..76c6e3bd2 100644 Binary files a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-chromium-linux.png and b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-chromium-linux.png differ diff --git a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-dom-widget-chromium-linux.png b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-dom-widget-chromium-linux.png index ff50afcd4..d2c15dc6b 100644 Binary files a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-dom-widget-chromium-linux.png and b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-dom-widget-chromium-linux.png differ diff --git a/browser_tests/tests/primitiveNode.spec.ts-snapshots/static-primitive-connected-chromium-linux.png b/browser_tests/tests/primitiveNode.spec.ts-snapshots/static-primitive-connected-chromium-linux.png index b8c243f0b..f6b317330 100644 Binary files a/browser_tests/tests/primitiveNode.spec.ts-snapshots/static-primitive-connected-chromium-linux.png and b/browser_tests/tests/primitiveNode.spec.ts-snapshots/static-primitive-connected-chromium-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-0-5x-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-0-5x-linux.png index 75c7dd2b3..91ff758aa 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-0-5x-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-0-5x-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-2x-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-2x-linux.png index be8c019f3..ef29bdd8e 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-2x-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-2x-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-linux.png index d7ee9ff26..7a2f59080 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-chromium-linux.png index 30b9a3894..aac33499e 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-chromium-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-context-menu-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-context-menu-chromium-linux.png index 8723985d2..694049cdd 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-context-menu-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-context-menu-chromium-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-delete-from-midpoint-context-menu-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-delete-from-midpoint-context-menu-chromium-linux.png index c07494c21..a73a56622 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-delete-from-midpoint-context-menu-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-delete-from-midpoint-context-menu-chromium-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/reroute-inserted-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/reroute-inserted-chromium-linux.png index d14a6e132..38c957f06 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/reroute-inserted-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/reroute-inserted-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-group-group-added-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-group-group-added-chromium-linux.png index d141d9912..8d2b7c63f 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-group-group-added-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-group-group-added-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-node-node-added-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-node-node-added-chromium-linux.png index 9443182e3..a44032d6d 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-node-node-added-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-node-node-added-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/node-pinned-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/node-pinned-chromium-linux.png index fbadb08da..ce3c5ac6b 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/node-pinned-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/node-pinned-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-menu-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-menu-chromium-linux.png index a73ca4c33..520dfbb51 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-menu-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-menu-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-bypassed-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-bypassed-chromium-linux.png index 238946afa..dc82953e1 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-bypassed-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-bypassed-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png index 1635e4e89..2ae5c3ff2 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-badge-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-badge-chromium-linux.png index 4c1ed8d69..5241f3517 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-badge-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-badge-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png index ea0156109..31ac480af 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png index 4910f554a..b92e9b1aa 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png index f381be240..26e017ff5 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-pinned-node-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-pinned-node-chromium-linux.png index 4440ef029..fc30c3368 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-pinned-node-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-pinned-node-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-chromium-linux.png index 1635e4e89..2ae5c3ff2 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-moved-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-moved-chromium-linux.png index 700e9d2c5..59ea157f9 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-moved-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-moved-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png index a6d09ff18..349014360 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-pinned-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-pinned-chromium-linux.png index c0b91f3ec..5e26ed857 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-pinned-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-pinned-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-unpinned-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-unpinned-chromium-linux.png index a80e1ad38..a3c584b32 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-unpinned-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-unpinned-chromium-linux.png differ diff --git a/browser_tests/tests/selectionToolbox.spec.ts b/browser_tests/tests/selectionToolbox.spec.ts index ce45eb3fb..a9a5fc9c2 100644 --- a/browser_tests/tests/selectionToolbox.spec.ts +++ b/browser_tests/tests/selectionToolbox.spec.ts @@ -149,7 +149,7 @@ test.describe('Selection Toolbox', () => { // Node should have the selected color class/style // Note: Exact verification method depends on how color is applied to nodes const selectedNode = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] - expect(selectedNode.getProperty('color')).not.toBeNull() + expect(await selectedNode.getProperty('color')).not.toBeNull() }) test('color picker shows current color of selected nodes', async ({ diff --git a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-nodes-border-chromium-linux.png b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-nodes-border-chromium-linux.png index e638f12ce..0d9878344 100644 Binary files a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-nodes-border-chromium-linux.png and b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-nodes-border-chromium-linux.png differ diff --git a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-selections-border-chromium-linux.png b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-selections-border-chromium-linux.png index e638f12ce..7c454dd81 100644 Binary files a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-selections-border-chromium-linux.png and b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-selections-border-chromium-linux.png differ diff --git a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-node-no-border-chromium-linux.png b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-node-no-border-chromium-linux.png index 3cec1c675..8973c1ed3 100644 Binary files a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-node-no-border-chromium-linux.png and b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-node-no-border-chromium-linux.png differ diff --git a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-selection-no-border-chromium-linux.png b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-selection-no-border-chromium-linux.png index 3cec1c675..c0112a796 100644 Binary files a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-selection-no-border-chromium-linux.png and b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-selection-no-border-chromium-linux.png differ diff --git a/browser_tests/tests/templates.spec.ts-snapshots/template-card-after-hover-chromium-linux.png b/browser_tests/tests/templates.spec.ts-snapshots/template-card-after-hover-chromium-linux.png index 5e105418c..719ec65e4 100644 Binary files a/browser_tests/tests/templates.spec.ts-snapshots/template-card-after-hover-chromium-linux.png and b/browser_tests/tests/templates.spec.ts-snapshots/template-card-after-hover-chromium-linux.png differ diff --git a/browser_tests/tests/templates.spec.ts-snapshots/template-card-before-hover-chromium-linux.png b/browser_tests/tests/templates.spec.ts-snapshots/template-card-before-hover-chromium-linux.png index 4bafa8784..b880fca84 100644 Binary files a/browser_tests/tests/templates.spec.ts-snapshots/template-card-before-hover-chromium-linux.png and b/browser_tests/tests/templates.spec.ts-snapshots/template-card-before-hover-chromium-linux.png differ diff --git a/browser_tests/tests/templates.spec.ts-snapshots/template-grid-desktop-chromium-linux.png b/browser_tests/tests/templates.spec.ts-snapshots/template-grid-desktop-chromium-linux.png index ff6a6c017..0c34b0607 100644 Binary files a/browser_tests/tests/templates.spec.ts-snapshots/template-grid-desktop-chromium-linux.png and b/browser_tests/tests/templates.spec.ts-snapshots/template-grid-desktop-chromium-linux.png differ diff --git a/browser_tests/tests/templates.spec.ts-snapshots/template-grid-mobile-chromium-linux.png b/browser_tests/tests/templates.spec.ts-snapshots/template-grid-mobile-chromium-linux.png index fadb02348..54f14ea0d 100644 Binary files a/browser_tests/tests/templates.spec.ts-snapshots/template-grid-mobile-chromium-linux.png and b/browser_tests/tests/templates.spec.ts-snapshots/template-grid-mobile-chromium-linux.png differ diff --git a/browser_tests/tests/templates.spec.ts-snapshots/template-grid-tablet-chromium-linux.png b/browser_tests/tests/templates.spec.ts-snapshots/template-grid-tablet-chromium-linux.png index 350b01a28..a5cf133cb 100644 Binary files a/browser_tests/tests/templates.spec.ts-snapshots/template-grid-tablet-chromium-linux.png and b/browser_tests/tests/templates.spec.ts-snapshots/template-grid-tablet-chromium-linux.png differ diff --git a/browser_tests/tests/templates.spec.ts-snapshots/template-grid-varying-content-chromium-linux.png b/browser_tests/tests/templates.spec.ts-snapshots/template-grid-varying-content-chromium-linux.png index cabfe9a20..6c330c2f4 100644 Binary files a/browser_tests/tests/templates.spec.ts-snapshots/template-grid-varying-content-chromium-linux.png and b/browser_tests/tests/templates.spec.ts-snapshots/template-grid-varying-content-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/NodeHeader.spec.ts b/browser_tests/tests/vueNodes/NodeHeader.spec.ts new file mode 100644 index 000000000..7a8ae5dd2 --- /dev/null +++ b/browser_tests/tests/vueNodes/NodeHeader.spec.ts @@ -0,0 +1,134 @@ +import { + comfyExpect as expect, + comfyPageFixture as test +} from '../../fixtures/ComfyPage' +import { VueNodeFixture } from '../../fixtures/utils/vueNodeFixtures' + +test.describe('NodeHeader', () => { + test.beforeEach(async ({ comfyPage }) => { + await comfyPage.setSetting('Comfy.UseNewMenu', 'Enabled') + await comfyPage.setSetting('Comfy.Graph.CanvasMenu', false) + await comfyPage.setSetting('Comfy.EnableTooltips', true) + await comfyPage.setSetting('Comfy.VueNodes.Enabled', true) + await comfyPage.setup() + }) + + test('displays node title', async ({ comfyPage }) => { + // Get the KSampler node from the default workflow + const nodes = await comfyPage.getNodeRefsByType('KSampler') + expect(nodes.length).toBeGreaterThanOrEqual(1) + + const node = nodes[0] + const vueNode = new VueNodeFixture(node, comfyPage.page) + + const title = await vueNode.getTitle() + expect(title).toBe('KSampler') + + // Verify title is visible in the header + const header = await vueNode.getHeader() + await expect(header).toContainText('KSampler') + }) + + test('allows title renaming', async ({ comfyPage }) => { + const nodes = await comfyPage.getNodeRefsByType('KSampler') + const node = nodes[0] + const vueNode = new VueNodeFixture(node, comfyPage.page) + + // Test renaming with Enter + await vueNode.setTitle('My Custom Sampler') + const newTitle = await vueNode.getTitle() + expect(newTitle).toBe('My Custom Sampler') + + // Verify the title is displayed + const header = await vueNode.getHeader() + await expect(header).toContainText('My Custom Sampler') + + // Test cancel with Escape + const titleElement = await vueNode.getTitleElement() + await titleElement.dblclick() + await comfyPage.nextFrame() + + // Type a different value but cancel + const input = (await vueNode.getHeader()).locator( + '[data-testid="node-title-input"]' + ) + await input.fill('This Should Be Cancelled') + await input.press('Escape') + await comfyPage.nextFrame() + + // Title should remain as the previously saved value + const titleAfterCancel = await vueNode.getTitle() + expect(titleAfterCancel).toBe('My Custom Sampler') + }) + + test('handles node collapsing', async ({ comfyPage }) => { + // Get the KSampler node from the default workflow + const nodes = await comfyPage.getNodeRefsByType('KSampler') + const node = nodes[0] + const vueNode = new VueNodeFixture(node, comfyPage.page) + + // Initially should not be collapsed + expect(await node.isCollapsed()).toBe(false) + const body = await vueNode.getBody() + await expect(body).toBeVisible() + + // Collapse the node + await vueNode.toggleCollapse() + expect(await node.isCollapsed()).toBe(true) + + // Verify node content is hidden + const collapsedSize = await node.getSize() + await expect(body).not.toBeVisible() + + // Expand again + await vueNode.toggleCollapse() + expect(await node.isCollapsed()).toBe(false) + await expect(body).toBeVisible() + + // Size should be restored + const expandedSize = await node.getSize() + expect(expandedSize.height).toBeGreaterThanOrEqual(collapsedSize.height) + }) + + test('shows collapse/expand icon state', async ({ comfyPage }) => { + const nodes = await comfyPage.getNodeRefsByType('KSampler') + const node = nodes[0] + const vueNode = new VueNodeFixture(node, comfyPage.page) + + // Check initial expanded state icon + let iconClass = await vueNode.getCollapseIconClass() + expect(iconClass).toContain('pi-chevron-down') + + // Collapse and check icon + await vueNode.toggleCollapse() + iconClass = await vueNode.getCollapseIconClass() + expect(iconClass).toContain('pi-chevron-right') + + // Expand and check icon + await vueNode.toggleCollapse() + iconClass = await vueNode.getCollapseIconClass() + expect(iconClass).toContain('pi-chevron-down') + }) + + test('preserves title when collapsing/expanding', async ({ comfyPage }) => { + const nodes = await comfyPage.getNodeRefsByType('KSampler') + const node = nodes[0] + const vueNode = new VueNodeFixture(node, comfyPage.page) + + // Set custom title + await vueNode.setTitle('Test Sampler') + expect(await vueNode.getTitle()).toBe('Test Sampler') + + // Collapse + await vueNode.toggleCollapse() + expect(await vueNode.getTitle()).toBe('Test Sampler') + + // Expand + await vueNode.toggleCollapse() + expect(await vueNode.getTitle()).toBe('Test Sampler') + + // Verify title is still displayed + const header = await vueNode.getHeader() + await expect(header).toContainText('Test Sampler') + }) +}) diff --git a/browser_tests/tests/widget.spec.ts-snapshots/animated-image-preview-saved-webp-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/animated-image-preview-saved-webp-chromium-linux.png index 3f3d831bb..b2fe8bb40 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/animated-image-preview-saved-webp-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/animated-image-preview-saved-webp-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-chromium-linux.png index 05764b532..2879c3d15 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-toggled-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-toggled-chromium-linux.png index fb055e8c8..d882ba9fb 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-toggled-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-toggled-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/empty-latent-resized-80-percent-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/empty-latent-resized-80-percent-chromium-linux.png index 745e69148..4bd504117 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/empty-latent-resized-80-percent-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/empty-latent-resized-80-percent-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/image-preview-changed-by-combo-value-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/image-preview-changed-by-combo-value-chromium-linux.png index 0b7cb495d..39bd0fd14 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/image-preview-changed-by-combo-value-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/image-preview-changed-by-combo-value-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/image-preview-drag-and-dropped-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/image-preview-drag-and-dropped-chromium-linux.png index 0b7cb495d..39bd0fd14 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/image-preview-drag-and-dropped-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/image-preview-drag-and-dropped-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/ksampler-resized-min-width-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/ksampler-resized-min-width-chromium-linux.png index 520576df1..2d95e6dd1 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/ksampler-resized-min-width-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/ksampler-resized-min-width-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/ksampler-widget-added-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/ksampler-widget-added-chromium-linux.png index 1b01d4972..52f20bbce 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/ksampler-widget-added-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/ksampler-widget-added-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/load-audio-widget-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/load-audio-widget-chromium-linux.png index fde5a2de9..9fd907f38 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/load-audio-widget-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/load-audio-widget-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/load-checkpoint-resized-min-width-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/load-checkpoint-resized-min-width-chromium-linux.png index 538e0b460..5af9039e0 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/load-checkpoint-resized-min-width-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/load-checkpoint-resized-min-width-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/load-image-widget-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/load-image-widget-chromium-linux.png index b631cd32d..843ebacc7 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/load-image-widget-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/load-image-widget-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/resized-to-original-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/resized-to-original-chromium-linux.png index d5e10e061..566ab88e8 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/resized-to-original-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/resized-to-original-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/seed-widget-dragged-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/seed-widget-dragged-chromium-linux.png index b356214e8..ff3fdcbfb 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/seed-widget-dragged-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/seed-widget-dragged-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/slider-widget-dragged-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/slider-widget-dragged-chromium-linux.png index 2c82d9c8d..6fe4d1e2b 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/slider-widget-dragged-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/slider-widget-dragged-chromium-linux.png differ diff --git a/docs/adr/0003-crdt-based-layout-system.md b/docs/adr/0003-crdt-based-layout-system.md new file mode 100644 index 000000000..1eceb2a1f --- /dev/null +++ b/docs/adr/0003-crdt-based-layout-system.md @@ -0,0 +1,156 @@ +# 3. Centralized Layout Management with CRDT + +Date: 2025-08-27 + +## Status + +Proposed + +## Context + +ComfyUI's node graph editor currently suffers from fundamental architectural limitations around spatial data management that prevent us from achieving key product goals. + +### Current Architecture Problems + +The existing system allows each node to directly mutate its position within LiteGraph's canvas renderer. This creates several critical issues: + +1. **Performance Bottlenecks**: UI updates require full graph traversals to detect position changes. Large workflows (100+ nodes) can create bottlenecks during interactions due to this O(n) polling approach. + +2. **Position Conflicts**: Multiple systems (LiteGraph canvas, DOMwidgets.ts overlays) currently compete to control node positions. Future Vue widget overlays will compound this maintenance burden. + +3. **No Collaboration Foundation**: Direct position mutations make concurrent editing impossible—there's no mechanism to merge conflicting position updates from multiple users. + +4. **Renderer Lock-in**: Spatial data is tightly coupled to LiteGraph's canvas implementation, preventing alternative rendering approaches (WebGL, DOM, other libraries, hybrid approaches). + +5. **Inefficient Change Detection**: While LiteGraph provides some events, many operations require polling via changeTracker.ts. The current undo/redo system performs expensive diffs on every interaction rather than using reactive push/pull signals, creating performance bottlenecks and blocking efficient animations and viewport culling. + + This represents a fundamental architectural limitation: diff-based systems scale O(n) with graph complexity (traverse entire structure to detect changes), while signal-based reactive systems scale O(1) with actual changes (data mutations automatically notify subscribers). Modern frameworks (Vue 3, Angular signals, SolidJS) have moved to reactive approaches for precisely this performance reason. + +### Business Context + +- Performance issues emerge with workflow complexity (100+ nodes) +- The AI workflow community increasingly expects collaborative features (similar to Figma, Miro) +- Accessibility requirements will necessitate DOM-based rendering options +- Technical debt compounds with each new spatial feature + +This decision builds on [ADR-0001 (Merge LiteGraph)](0001-merge-litegraph-into-frontend.md), which enables the architectural restructuring proposed here. + +## Decision + +We will implement a centralized layout management system using CRDT (Conflict-free Replicated Data Types) with command pattern architecture to separate spatial data from rendering behavior. + +### Centralized State Management Foundation + +This solution applies proven centralized state management patterns: + +- **Centralized Store**: All spatial data (position, size, bounds, transform) managed in a single CRDT-backed store +- **Command Interface**: All mutations flow through explicit commands rather than direct property access +- **Observer Pattern**: Independent systems (rendering, interaction, layout) subscribe to state changes +- **Domain Separation**: Layout logic completely separated from rendering and UI concerns + +This provides single source of truth, predictable state updates, and natural system decoupling—solving our core architectural problems. + +### Core Architecture + +1. **Centralized Layout Store**: A Yjs CRDT maintains all spatial data in a single authoritative store: + ```typescript + // Instead of: node.position = {x, y} + layoutStore.moveNode(nodeId, {x, y}) + ``` + +2. **Command Pattern**: All spatial mutations flow through explicit commands: + ``` + User Input → Commands → Layout Store → Observer Notifications → Renderers + ``` + +3. **Observer-Based Systems**: Multiple independent systems subscribe to layout changes: + - **Rendering Systems**: LiteGraph canvas, WebGL, DOM accessibility renderers + - **Interaction Systems**: Drag handlers, selection, hover states + - **Layout Systems**: Auto-layout, alignment, distribution + - **Animation Systems**: Smooth transitions, physics simulations + +4. **Reactive Updates**: Store changes propagate through observers, eliminating polling and enabling efficient system coordination. + +### Implementation Strategy + +**Phase 1: Parallel System** +- Build CRDT layout store alongside existing system +- Layout store initially mirrors LiteGraph changes via observers +- Gradually migrate user interactions to use command interface +- Maintain full backward compatibility + +**Phase 2: Inversion of Control** +- CRDT store becomes single source of truth +- LiteGraph receives position updates via reactive subscriptions +- Enable alternative renderers and advanced features + +### Why Centralized State + CRDT? + +This combination provides both architectural and technical benefits: + +**Centralized State Benefits:** +- **Single Source of Truth**: All layout data managed in one place, eliminating conflicts +- **System Decoupling**: Rendering, interaction, and layout systems operate independently +- **Predictable Updates**: Clear data flow makes debugging and testing easier +- **Extensibility**: Easy to add new layout behaviors without modifying existing systems + +**CRDT Benefits:** +- **Conflict Resolution**: Automatic merging eliminates position conflicts between systems +- **Collaboration-Ready**: Built-in support for multi-user editing +- **Eventual Consistency**: Guaranteed convergence to same state across all clients + +**Yjs-Specific Benefits:** +- **Event-Driven**: Native observer pattern removes need for polling +- **Selective Updates**: Only changed nodes trigger system updates +- **Fine-Grained Changes**: Efficient delta synchronization + +## Consequences + +### Positive + +- **Eliminates Polling**: Observer pattern removes O(n) graph traversals, improving performance +- **System Modularity**: Independent systems can be developed, tested, and optimized separately +- **Renderer Flexibility**: Easy to add WebGL, DOM accessibility, or hybrid rendering systems +- **Rich Interactions**: Command pattern enables robust undo/redo, macros, and interaction history +- **Collaboration-Ready**: CRDT foundation enables real-time multi-user editing +- **Conflict Resolution**: Eliminates position "snap-back" behavior between competing systems +- **Better Developer Experience**: Clear separation of concerns and predictable data flow patterns + +### Negative + +- **Learning Curve**: Team must understand CRDT concepts and centralized state management +- **Migration Complexity**: Gradual migration of existing direct property access requires careful coordination +- **Memory Overhead**: Yjs library (~30KB) plus operation history storage +- **CRDT Performance**: CRDTs have computational overhead compared to direct property access +- **Increased Abstraction**: Additional layer between user interactions and visual updates + +### Risk Mitigations + +- Provide comprehensive migration documentation and examples +- Build compatibility layer for gradual, low-risk migration +- Implement operation history pruning for long-running sessions +- Phase implementation to validate approach before full migration + +## Notes + +This centralized state + CRDT architecture follows patterns from modern collaborative applications: + +**Centralized State Management**: Similar to Redux/Vuex patterns in complex web applications, but with CRDT backing for collaboration. This provides predictable state updates while enabling real-time multi-user features. + +**CRDT in Collaboration**: Tools like Figma, Linear, and Notion use similar approaches for real-time collaboration, demonstrating the effectiveness of separating authoritative data from presentation logic. + +**Future Capabilities**: This foundation enables advanced features that would be difficult with the current architecture: +- Macro recording and workflow automation +- Programmatic layout optimization and constraints +- API-driven workflow construction +- Multiple simultaneous renderers (canvas + accessibility DOM) +- Real-time collaborative editing +- Advanced spatial features (physics, animations, auto-layout) + +The architecture provides immediate single-user benefits while creating infrastructure for collaborative and advanced spatial features. + +## References + +- [Yjs Documentation](https://docs.yjs.dev/) +- [CRDTs: The Hard Parts](https://martin.kleppmann.com/2020/07/06/crdt-hard-parts-hydra.html) by Martin Kleppmann +- [Figma's Multiplayer Technology](https://www.figma.com/blog/how-figmas-multiplayer-technology-works/) diff --git a/docs/adr/README.md b/docs/adr/README.md index 3ebf340d5..00e50a639 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -11,7 +11,8 @@ An Architecture Decision Record captures an important architectural decision mad | ADR | Title | Status | Date | |-----|-------|--------|------| | [0001](0001-merge-litegraph-into-frontend.md) | Merge LiteGraph.js into ComfyUI Frontend | Accepted | 2025-08-05 | -| [0002](0002-monorepo-conversion.md) | Restructure as a Monorepo | Proposed | 2025-08-25 | +| [0002](0002-monorepo-conversion.md) | Restructure as a Monorepo | Accepted | 2025-08-25 | +| [0003](0003-crdt-based-layout-system.md) | Centralized Layout Management with CRDT | Proposed | 2025-08-27 | ## Creating a New ADR @@ -77,4 +78,4 @@ Optional section for additional information, references, or clarifications. ## Further Reading - [Documenting Architecture Decisions](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions) by Michael Nygard -- [Architecture Decision Records](https://adr.github.io/) - Collection of ADR resources \ No newline at end of file +- [Architecture Decision Records](https://adr.github.io/) - Collection of ADR resources diff --git a/eslint.config.js b/eslint.config.js index 59c5f46df..7e3248b20 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -62,6 +62,41 @@ export default [ '@typescript-eslint/prefer-as-const': 'off', 'unused-imports/no-unused-imports': 'error', 'vue/no-v-html': 'off', + // Enforce dark-theme: instead of dark: prefix + 'vue/no-restricted-class': ['error', '/^dark:/'], + // Restrict deprecated PrimeVue components + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'primevue/calendar', + message: + 'Calendar is deprecated in PrimeVue 4+. Use DatePicker instead: import DatePicker from "primevue/datepicker"' + }, + { + name: 'primevue/dropdown', + message: + 'Dropdown is deprecated in PrimeVue 4+. Use Select instead: import Select from "primevue/select"' + }, + { + name: 'primevue/inputswitch', + message: + 'InputSwitch is deprecated in PrimeVue 4+. Use ToggleSwitch instead: import ToggleSwitch from "primevue/toggleswitch"' + }, + { + name: 'primevue/overlaypanel', + message: + 'OverlayPanel is deprecated in PrimeVue 4+. Use Popover instead: import Popover from "primevue/popover"' + }, + { + name: 'primevue/sidebar', + message: + 'Sidebar is deprecated in PrimeVue 4+. Use Drawer instead: import Drawer from "primevue/drawer"' + } + ] + } + ], // i18n rules '@intlify/vue-i18n/no-raw-text': [ 'error', diff --git a/knip.config.ts b/knip.config.ts index 556ec5bc4..64e836f08 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -2,30 +2,22 @@ import type { KnipConfig } from 'knip' const config: KnipConfig = { entry: [ - 'build/**/*.ts', - 'scripts/**/*.{js,ts}', + '{build,scripts}/**/*.{js,ts}', + 'src/assets/css/style.css', 'src/main.ts', - 'vite.electron.config.mts', - 'vite.types.config.mts' - ], - project: [ - 'browser_tests/**/*.{js,ts}', - 'build/**/*.{js,ts,vue}', - 'scripts/**/*.{js,ts}', - 'src/**/*.{js,ts,vue}', - 'tests-ui/**/*.{js,ts,vue}', - '*.{js,ts,mts}' + 'src/scripts/ui/menu/index.ts', + 'src/types/index.ts' ], + project: ['**/*.{js,ts,vue}', '*.{js,ts,mts}'], + ignoreBinaries: ['only-allow', 'openapi-typescript'], ignoreDependencies: [ + // Weird importmap things + '@iconify/json', '@primeuix/forms', '@primeuix/styled', '@primeuix/utils', '@primevue/icons', - '@iconify/json', - 'tailwindcss', - 'tailwindcss-primeui', // Need to figure out why tailwind plugin isn't applying // Dev - '@executeautomation/playwright-mcp-server', '@trivago/prettier-plugin-sort-imports' ], ignore: [ @@ -56,32 +48,35 @@ const config: KnipConfig = { 'vite.types.config.mts', // Auto generated manager types 'src/types/generatedManagerTypes.ts', - // Design system components (may not be used immediately) - 'src/components/button/IconGroup.vue', - 'src/components/button/MoreButton.vue', - 'src/components/button/TextButton.vue', - 'src/components/card/CardTitle.vue', - 'src/components/card/CardDescription.vue', - 'src/components/input/SingleSelect.vue' + 'src/types/comfyRegistryTypes.ts', + // Used by a custom node (that should move off of this) + 'src/scripts/ui/components/splitButton.ts' ], - ignoreExportsUsedInFile: true, - // Vue-specific configuration - vue: true, - tailwind: true, - // Only check for unused files, disable all other rules - // TODO: Gradually enable other rules - see https://github.com/Comfy-Org/ComfyUI_frontend/issues/4888 - rules: { - binaries: 'off', - classMembers: 'off', - duplicates: 'off', - enumMembers: 'off', - exports: 'off', - nsExports: 'off', - nsTypes: 'off', - types: 'off' + compilers: { + // https://github.com/webpro-nl/knip/issues/1008#issuecomment-3207756199 + css: (text: string) => + [ + ...text.replaceAll('plugin', 'import').matchAll(/(?<=@)import[^;]+/g) + ].join('\n') }, - // Include dependencies analysis - includeEntryExports: true + vite: { + config: ['vite?(.*).config.mts'] + }, + vitest: { + config: ['vitest?(.*).config.ts'], + entry: [ + '**/*.{bench,test,test-d,spec}.?(c|m)[jt]s?(x)', + '**/__mocks__/**/*.[jt]s?(x)' + ] + }, + playwright: { + config: ['playwright?(.*).config.ts'], + entry: ['**/*.@(spec|test).?(c|m)[jt]s?(x)', 'browser_tests/**/*.ts'] + }, + tags: [ + '-knipIgnoreUnusedButUsedByCustomNodes', + '-knipIgnoreUnusedButUsedByVueNodesBranch' + ] } export default config diff --git a/package.json b/package.json index c7acbf645..63a28a2dc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@comfyorg/comfyui-frontend", "private": true, - "version": "1.27.0", + "version": "1.27.2", "type": "module", "repository": "https://github.com/Comfy-Org/ComfyUI_frontend", "homepage": "https://comfy.org", @@ -25,10 +25,10 @@ "preinstall": "npx only-allow pnpm", "prepare": "husky || true && git config blame.ignoreRevsFile .git-blame-ignore-revs || true", "preview": "nx preview", - "lint": "eslint src --cache", - "lint:fix": "eslint src --cache --fix", - "lint:no-cache": "eslint src", - "lint:fix:no-cache": "eslint src --fix", + "lint": "eslint src --cache --concurrency=$npm_package_config_eslint_concurrency", + "lint:fix": "eslint src --fix --cache --concurrency=$npm_package_config_eslint_concurrency", + "lint:no-cache": "eslint src --concurrency=$npm_package_config_eslint_concurrency", + "lint:fix:no-cache": "eslint src --fix --concurrency=$npm_package_config_eslint_concurrency", "knip": "knip --cache", "knip:no-cache": "knip", "locale": "lobe-i18n locale", @@ -37,9 +37,12 @@ "storybook": "nx storybook -p 6006", "build-storybook": "storybook build" }, + "config": { + "eslint_concurrency": "4" + }, "devDependencies": { "@eslint/js": "^9.8.0", - "@executeautomation/playwright-mcp-server": "^1.0.6", + "@iconify-json/lucide": "^1.2.66", "@iconify/tailwind": "^1.2.0", "@intlify/eslint-plugin-vue-i18n": "^3.2.0", "@lobehub/i18n-cli": "^1.25.1", @@ -63,7 +66,7 @@ "@vitest/coverage-v8": "^3.2.4", "@vitest/ui": "^3.0.0", "@vue/test-utils": "^2.4.6", - "eslint": "^9.12.0", + "eslint": "^9.34.0", "eslint-config-prettier": "^10.1.2", "eslint-plugin-prettier": "^5.2.6", "eslint-plugin-storybook": "^9.1.1", @@ -77,7 +80,6 @@ "jsdom": "^26.1.0", "knip": "^5.62.0", "lint-staged": "^15.2.7", - "lucide-vue-next": "^0.540.0", "nx": "21.4.1", "prettier": "^3.3.2", "storybook": "^9.1.1", @@ -85,7 +87,7 @@ "tailwindcss-primeui": "^0.6.1", "tsx": "^4.15.6", "typescript": "^5.4.5", - "typescript-eslint": "^8.0.0", + "typescript-eslint": "^8.42.0", "unplugin-icons": "^0.22.0", "unplugin-vue-components": "^0.28.0", "uuid": "^11.1.0", @@ -124,6 +126,8 @@ "@xterm/xterm": "^5.5.0", "algoliasearch": "^5.21.0", "axios": "^1.8.2", + "chart.js": "^4.5.0", + "clsx": "^2.1.1", "dompurify": "^3.2.5", "dotenv": "^16.4.5", "es-toolkit": "^1.39.9", @@ -140,12 +144,14 @@ "primeicons": "^7.0.0", "primevue": "^4.2.5", "semver": "^7.7.2", + "tailwind-merge": "^3.3.1", "three": "^0.170.0", "tiptap-markdown": "^0.8.10", "vue": "^3.5.13", "vue-i18n": "^9.14.3", "vue-router": "^4.4.3", "vuefire": "^3.2.1", + "yjs": "^13.6.27", "zod": "^3.23.8", "zod-validation-error": "^3.3.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4784c4b53..903a6c551 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -83,6 +83,12 @@ importers: axios: specifier: ^1.8.2 version: 1.11.0 + chart.js: + specifier: ^4.5.0 + version: 4.5.0 + clsx: + specifier: ^2.1.1 + version: 2.1.1 dompurify: specifier: ^3.2.5 version: 3.2.5 @@ -131,6 +137,9 @@ importers: semver: specifier: ^7.7.2 version: 7.7.2 + tailwind-merge: + specifier: ^3.3.1 + version: 3.3.1 three: specifier: ^0.170.0 version: 0.170.0 @@ -149,6 +158,9 @@ importers: vuefire: specifier: ^3.2.1 version: 3.2.1(consola@3.4.2)(firebase@11.6.0)(vue@3.5.13(typescript@5.9.2)) + yjs: + specifier: ^13.6.27 + version: 13.6.27 zod: specifier: ^3.23.8 version: 3.24.1 @@ -159,27 +171,27 @@ importers: '@eslint/js': specifier: ^9.8.0 version: 9.12.0 - '@executeautomation/playwright-mcp-server': - specifier: ^1.0.6 - version: 1.0.6(react@19.1.1)(ws@8.18.3)(zod@3.24.1) + '@iconify-json/lucide': + specifier: ^1.2.66 + version: 1.2.66 '@iconify/tailwind': specifier: ^1.2.0 version: 1.2.0 '@intlify/eslint-plugin-vue-i18n': specifier: ^3.2.0 - version: 3.2.0(eslint@9.12.0(jiti@2.4.2)) + version: 3.2.0(eslint@9.35.0(jiti@2.4.2)) '@lobehub/i18n-cli': specifier: ^1.25.1 version: 1.25.1(@types/react@19.1.9)(typescript@5.9.2)(use-sync-external-store@1.5.0(react@19.1.1))(ws@8.18.3)(zod@3.24.1) '@nx/eslint': specifier: 21.4.1 - version: 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1) + version: 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1) '@nx/playwright': specifier: 21.4.1 - version: 21.4.1(@babel/traverse@7.28.3)(@playwright/test@1.52.0)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1)(typescript@5.9.2) + version: 21.4.1(@babel/traverse@7.28.3)(@playwright/test@1.52.0)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1)(typescript@5.9.2) '@nx/storybook': specifier: 21.4.1 - version: 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1)(storybook@9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2) + version: 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1)(storybook@9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2) '@nx/vite': specifier: 21.4.1 version: 21.4.1(@babel/traverse@7.28.3)(nx@21.4.1)(typescript@5.9.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2))(vitest@3.2.4) @@ -232,23 +244,23 @@ importers: specifier: ^2.4.6 version: 2.4.6 eslint: - specifier: ^9.12.0 - version: 9.12.0(jiti@2.4.2) + specifier: ^9.34.0 + version: 9.35.0(jiti@2.4.2) eslint-config-prettier: specifier: ^10.1.2 - version: 10.1.2(eslint@9.12.0(jiti@2.4.2)) + version: 10.1.2(eslint@9.35.0(jiti@2.4.2)) eslint-plugin-prettier: specifier: ^5.2.6 - version: 5.2.6(eslint-config-prettier@10.1.2(eslint@9.12.0(jiti@2.4.2)))(eslint@9.12.0(jiti@2.4.2))(prettier@3.3.2) + version: 5.2.6(eslint-config-prettier@10.1.2(eslint@9.35.0(jiti@2.4.2)))(eslint@9.35.0(jiti@2.4.2))(prettier@3.3.2) eslint-plugin-storybook: specifier: ^9.1.1 - version: 9.1.1(eslint@9.12.0(jiti@2.4.2))(storybook@9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2) + version: 9.1.1(eslint@9.35.0(jiti@2.4.2))(storybook@9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2) eslint-plugin-unused-imports: specifier: ^4.1.4 - version: 4.1.4(@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.12.0(jiti@2.4.2)) + version: 4.1.4(@typescript-eslint/eslint-plugin@8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2)) eslint-plugin-vue: specifier: ^9.27.0 - version: 9.27.0(eslint@9.12.0(jiti@2.4.2)) + version: 9.27.0(eslint@9.35.0(jiti@2.4.2)) fs-extra: specifier: ^11.2.0 version: 11.2.0 @@ -273,9 +285,6 @@ importers: lint-staged: specifier: ^15.2.7 version: 15.2.7 - lucide-vue-next: - specifier: ^0.540.0 - version: 0.540.0(vue@3.5.13(typescript@5.9.2)) nx: specifier: 21.4.1 version: 21.4.1 @@ -298,8 +307,8 @@ importers: specifier: ^5.4.5 version: 5.9.2 typescript-eslint: - specifier: ^8.0.0 - version: 8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) + specifier: ^8.42.0 + version: 8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) unplugin-icons: specifier: ^0.22.0 version: 0.22.0(@vue/compiler-sfc@3.5.13) @@ -336,53 +345,9 @@ importers: packages: - '@actions/core@1.11.1': - resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==} - - '@actions/exec@1.1.1': - resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} - - '@actions/http-client@2.2.3': - resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==} - - '@actions/io@1.1.3': - resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} - '@adobe/css-tools@4.4.3': resolution: {integrity: sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==} - '@ai-sdk/openai@1.3.24': - resolution: {integrity: sha512-GYXnGJTHRTZc4gJMSmFRgEQudjqd4PUN0ZjQhPwOAYH1yOAvQoG/Ikqs+HyISRbLPCrhbZnPKCNHuRU4OfpW0Q==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.0.0 - - '@ai-sdk/provider-utils@2.2.8': - resolution: {integrity: sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.23.8 - - '@ai-sdk/provider@1.1.3': - resolution: {integrity: sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==} - engines: {node: '>=18'} - - '@ai-sdk/react@1.2.12': - resolution: {integrity: sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g==} - engines: {node: '>=18'} - peerDependencies: - react: ^18 || ^19 || ^19.0.0-rc - zod: ^3.23.8 - peerDependenciesMeta: - zod: - optional: true - - '@ai-sdk/ui-utils@1.2.11': - resolution: {integrity: sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.23.8 - '@alcalzone/ansi-tokenize@0.2.0': resolution: {integrity: sha512-qI/5TaaaCZE4yeSZ83lu0+xi1r88JSxUjnH4OP/iZF7+KKZ75u3ee5isd0LxX+6N8U0npL61YrpbthILHB6BnA==} engines: {node: '>=18'} @@ -459,9 +424,6 @@ packages: '@antfu/utils@8.1.1': resolution: {integrity: sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==} - '@anthropic-ai/sdk@0.8.1': - resolution: {integrity: sha512-59etePenCizVx1O8Qhi1T1ruE04ISfNzCnyhZNcsss1QljsLmYS83jttarMNEvGYcsUF7rwxw2lzcC3Zbxao7g==} - '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} @@ -1004,8 +966,8 @@ packages: resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==} engines: {node: '>=6.9.0'} - '@babel/runtime@7.28.3': - resolution: {integrity: sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==} + '@babel/runtime@7.28.4': + resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} '@babel/template@7.27.2': @@ -1358,41 +1320,51 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.11.0': - resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + '@eslint-community/eslint-utils@4.8.0': + resolution: {integrity: sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.18.0': - resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.6.0': - resolution: {integrity: sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==} + '@eslint/config-helpers@0.3.1': + resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.2': + resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.1.0': resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@9.12.0': resolution: {integrity: sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.4': - resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + '@eslint/js@9.35.0': + resolution: {integrity: sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.2.3': - resolution: {integrity: sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==} + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@executeautomation/playwright-mcp-server@1.0.6': - resolution: {integrity: sha512-Yq5dM5XCzWTc2hjC0mYJPbGaNPn3giGS9XR47bRGSQIF1t3zcjrH4i/z0Fc4PfJj/6kaPMFzp/7N49LDZBJlzA==} - hasBin: true - - '@fastify/busboy@2.1.1': - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} + '@eslint/plugin-kit@0.3.5': + resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@firebase/analytics-compat@0.2.18': resolution: {integrity: sha512-Hw9mzsSMZaQu6wrTbi3kYYwGw9nBqOHr47pVLxfr5v8CalsdrG5gfs9XUlPOZjHRVISp3oQrh1j7d3E+ulHPjQ==} @@ -1613,22 +1585,25 @@ packages: engines: {node: '>=6'} hasBin: true - '@humanfs/core@0.19.0': - resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==} + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.5': - resolution: {integrity: sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==} + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@iconify-json/lucide@1.2.66': + resolution: {integrity: sha512-TrhmfThWY2FHJIckjz7g34gUx3+cmja61DcHNdmu0rVDBQHIjPMYO1O8mMjoDSqIXEllz9wDZxCqT3lFuI+f/A==} + '@iconify/json@2.2.380': resolution: {integrity: sha512-+Al/Q+mMB/nLz/tawmJEOkCs6+RKKVUS/Yg9I80h2yRpu0kIzxVLQRfF0NifXz/fH92vDVXbS399wio4lMVF4Q==} @@ -1713,6 +1688,9 @@ packages: '@jridgewell/trace-mapping@0.3.30': resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} + '@kurkle/color@0.3.4': + resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==} + '@lobehub/cli-ui@1.13.0': resolution: {integrity: sha512-7kXm84dc6yiniEFb/KRZv5H4g43n+xKTSpKSczlv54DY3tHSuZjBARyI/UDxFVgn7ezWYAIFuphzs0hSdhs6hw==} engines: {node: '>=18'} @@ -1741,10 +1719,6 @@ packages: '@microsoft/tsdoc@0.15.1': resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==} - '@modelcontextprotocol/sdk@1.11.1': - resolution: {integrity: sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ==} - engines: {node: '>=18'} - '@napi-rs/wasm-runtime@0.2.4': resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} @@ -1868,10 +1842,6 @@ packages: '@one-ini/wasm@0.1.1': resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} - '@opentelemetry/api@1.9.0': - resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} - engines: {node: '>=8.0.0'} - '@oxc-resolver/binding-android-arm-eabi@11.6.1': resolution: {integrity: sha512-Ma/kg29QJX1Jzelv0Q/j2iFuUad1WnjgPjpThvjqPjpOyLjCUaiFCCnshhmWjyS51Ki1Iol3fjf1qAzObf8GIA==} cpu: [arm] @@ -1989,28 +1959,11 @@ packages: resolution: {integrity: sha512-25L86MyPvnlQoX2MTIV2OiUcb6vJ6aRbFa9pbwByn95INKD5mFH2smgjDhq+fwJoqAgvgbdJLj6Tz7V9X5CFAQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@playwright/browser-chromium@1.53.1': - resolution: {integrity: sha512-xsujbzJAgn3A0RVV00cT/XekdPUOqsJoy8WWyKdqhQnuA7A88m/x0MnbcaCeZcs2M5JVRqpbsFKRos+IIeZLjw==} - engines: {node: '>=18'} - - '@playwright/browser-firefox@1.53.1': - resolution: {integrity: sha512-1+jAvoMYrh8rT/7VJQZ+J4+3/sFEx+/TPesdKjITmLlia2NrdxEnB2jvu5N2bhuPluFccZBWTUibPkULpva0YA==} - engines: {node: '>=18'} - - '@playwright/browser-webkit@1.53.1': - resolution: {integrity: sha512-6z0KsU1A6hppMSkVVstEoQhK/tjMTf8ZIaegTTDD/bKIq7osUcgkVdGKt4cd2gFvjxZH4HqV6wKGmuWcdWmmQQ==} - engines: {node: '>=18'} - '@playwright/test@1.52.0': resolution: {integrity: sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==} engines: {node: '>=18'} hasBin: true - '@playwright/test@1.55.0': - resolution: {integrity: sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==} - engines: {node: '>=18'} - hasBin: true - '@pnpm/config.env-replace@1.1.0': resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} engines: {node: '>=12.22.0'} @@ -2584,9 +2537,6 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -2668,26 +2618,20 @@ packages: '@types/webxr@0.5.20': resolution: {integrity: sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==} - '@typescript-eslint/eslint-plugin@8.0.0': - resolution: {integrity: sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==} + '@typescript-eslint/eslint-plugin@8.42.0': + resolution: {integrity: sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + '@typescript-eslint/parser': ^8.42.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.0.0': - resolution: {integrity: sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==} + '@typescript-eslint/parser@8.42.0': + resolution: {integrity: sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/project-service@8.39.0': resolution: {integrity: sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew==} @@ -2695,45 +2639,46 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.0.0': - resolution: {integrity: sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==} + '@typescript-eslint/project-service@8.42.0': + resolution: {integrity: sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/scope-manager@8.39.0': resolution: {integrity: sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.42.0': + resolution: {integrity: sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.39.0': resolution: {integrity: sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.0.0': - resolution: {integrity: sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==} + '@typescript-eslint/tsconfig-utils@8.42.0': + resolution: {integrity: sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.0.0': - resolution: {integrity: sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==} + '@typescript-eslint/type-utils@8.42.0': + resolution: {integrity: sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/types@8.39.0': resolution: {integrity: sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.0.0': - resolution: {integrity: sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==} + '@typescript-eslint/types@8.42.0': + resolution: {integrity: sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true '@typescript-eslint/typescript-estree@8.39.0': resolution: {integrity: sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw==} @@ -2741,11 +2686,11 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.0.0': - resolution: {integrity: sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==} + '@typescript-eslint/typescript-estree@8.42.0': + resolution: {integrity: sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/utils@8.39.0': resolution: {integrity: sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ==} @@ -2754,14 +2699,21 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.0.0': - resolution: {integrity: sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==} + '@typescript-eslint/utils@8.42.0': + resolution: {integrity: sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' '@typescript-eslint/visitor-keys@8.39.0': resolution: {integrity: sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.42.0': + resolution: {integrity: sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vitejs/plugin-vue@5.1.4': resolution: {integrity: sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==} engines: {node: ^18.0.0 || >=20.0.0} @@ -2957,10 +2909,6 @@ packages: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} - accepts@2.0.0: - resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} - engines: {node: '>= 0.6'} - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -2976,6 +2924,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + address@1.2.2: resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} engines: {node: '>= 10.0.0'} @@ -2988,16 +2941,6 @@ packages: resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} engines: {node: '>= 8.0.0'} - ai@4.3.19: - resolution: {integrity: sha512-dIE2bfNpqHN3r6IINp9znguYdhIOheKW2LDigAMrgt/upT3B8eBGPSCblENvaZGoq+hxaN9fSMzjWpbqloP+7Q==} - engines: {node: '>=18'} - peerDependencies: - react: ^18 || ^19 || ^19.0.0-rc - zod: ^3.23.8 - peerDependenciesMeta: - react: - optional: true - ajv-draft-04@1.0.0: resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} peerDependencies: @@ -3088,10 +3031,6 @@ packages: resolution: {integrity: sha512-yOzOZcR9Tn7enTF66bqKorGGH0F36vcPaSWg8fO0c0UYb3LX3VMXj5ZxEqQLNOecAhlRJ7wYZja5i4jTlnbIfQ==} engines: {node: '>=4'} - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} @@ -3172,9 +3111,6 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - base-64@0.1.0: - resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==} - base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -3195,10 +3131,6 @@ packages: bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - body-parser@2.2.0: - resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} - engines: {node: '>=18'} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -3234,10 +3166,6 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -3293,8 +3221,9 @@ packages: character-parser@2.2.0: resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==} - charenc@0.0.2: - resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + chart.js@4.5.0: + resolution: {integrity: sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==} + engines: {pnpm: '>=8'} check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} @@ -3348,6 +3277,10 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + code-excerpt@4.0.0: resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3429,14 +3362,6 @@ packages: constantinople@4.0.1: resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==} - content-disposition@1.0.0: - resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} - engines: {node: '>= 0.6'} - - content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -3444,14 +3369,6 @@ packages: resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - cookie-signature@1.2.2: - resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} - engines: {node: '>=6.6.0'} - - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} - copy-anything@3.0.5: resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} engines: {node: '>=12.13'} @@ -3462,10 +3379,6 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - cosmiconfig@7.1.0: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} @@ -3486,9 +3399,6 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - crypt@0.0.2: - resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} - css-select@4.3.0: resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} @@ -3588,10 +3498,6 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -3611,13 +3517,6 @@ packages: diff-match-patch@1.0.5: resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} - digest-fetch@1.3.0: - resolution: {integrity: sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==} - - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dirty-json@0.9.2: resolution: {integrity: sha512-7SCDfnQtBObcngVXNPZcnxGxqqPTK4UqeXeKAch+RGH5qpqadWbV9FmN71x9Bb4tTs0TNFb4FT/4Kz4P4Cjqcw==} engines: {node: '>=6.0.0'} @@ -3682,9 +3581,6 @@ packages: engines: {node: '>=14'} hasBin: true - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} @@ -3702,10 +3598,6 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} - end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} @@ -3794,9 +3686,6 @@ packages: resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} engines: {node: '>=12'} - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} @@ -3865,8 +3754,8 @@ packages: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-scope@8.1.0: - resolution: {integrity: sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==} + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: @@ -3877,8 +3766,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.12.0: - resolution: {integrity: sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==} + eslint@9.35.0: + resolution: {integrity: sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -3894,6 +3783,10 @@ packages: resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3925,10 +3818,6 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -3936,14 +3825,6 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - eventsource-parser@3.0.5: - resolution: {integrity: sha512-bSRG85ZrMdmWtm7qkF9He9TNRzc/Bm99gEJMaQoHJ9E6Kv9QBbsldh2oMj7iXmYNEAVvNgvv5vPorG6W+XtBhQ==} - engines: {node: '>=20.0.0'} - - eventsource@3.0.7: - resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} - engines: {node: '>=18.0.0'} - execa@8.0.1: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} @@ -3956,16 +3837,6 @@ packages: resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} engines: {node: '>=12.0.0'} - express-rate-limit@7.5.1: - resolution: {integrity: sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==} - engines: {node: '>= 16'} - peerDependencies: - express: '>= 4.11' - - express@5.1.0: - resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} - engines: {node: '>= 18'} - exsolve@1.0.7: resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==} @@ -4055,10 +3926,6 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - finalhandler@2.1.0: - resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} - engines: {node: '>= 0.8'} - find-package-json@1.2.0: resolution: {integrity: sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw==} @@ -4077,9 +3944,6 @@ packages: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true - flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} @@ -4120,14 +3984,6 @@ packages: resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} engines: {node: '>= 12.20'} - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - - fresh@2.0.0: - resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} - engines: {node: '>= 0.8'} - front-matter@4.0.2: resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} @@ -4227,10 +4083,6 @@ packages: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -4300,10 +4152,6 @@ packages: engines: {node: '>=12'} hasBin: true - http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - http-parser-js@0.5.10: resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} @@ -4349,6 +4197,10 @@ packages: resolution: {integrity: sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==} engines: {node: '>= 4'} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} @@ -4399,10 +4251,6 @@ packages: react-devtools-core: optional: true - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -4410,9 +4258,6 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-buffer@1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - is-core-module@2.16.1: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} @@ -4502,9 +4347,6 @@ packages: is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} - is-promise@4.0.0: - resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -4546,6 +4388,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isomorphic.js@0.2.5: + resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} + istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -4653,9 +4498,6 @@ packages: json-schema-typed@8.0.1: resolution: {integrity: sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==} - json-schema@0.4.0: - resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -4732,6 +4574,11 @@ packages: resolution: {integrity: sha512-vzaalVBmFLnMaedq0QAsBAaXsWahzRpvnIBdBjj7y+7EKTS6lnziU2y/PsU2c6rV5qYj2B5IDw0uNJ9peXD0vw==} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + lib0@0.2.114: + resolution: {integrity: sha512-gcxmNFzA4hv8UYi8j43uPlQ7CGcyMJ2KQb5kZASw6SnAKAf10hK12i2fjrS3Cl/ugZa5Ui6WwIu1/6MIXiHttQ==} + engines: {node: '>=16'} + hasBin: true + lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} @@ -4898,11 +4745,6 @@ packages: resolution: {integrity: sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==} engines: {node: '>=16.14'} - lucide-vue-next@0.540.0: - resolution: {integrity: sha512-H7qhKVNKLyoFMo05pWcGSWBiLPiI3zJmWV65SuXWHlrIGIcvDer10xAyWcRJ0KLzIH5k5+yi7AGw/Xi1VF8Pbw==} - peerDependencies: - vue: '>=3.0.1' - lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -4939,15 +4781,6 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - mcp-evals@1.0.18: - resolution: {integrity: sha512-khDcEG0XWshdCRirqLXogNoDLmzFA86QyuKoi5ioXsbeRZ3XQra8Zsg7vD+C0K5vwkFIoB1vTuPjHEHMhdLFtQ==} - hasBin: true - peerDependencies: - react: ^19.1.0 - - md5@2.3.0: - resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} - mdast-util-find-and-replace@3.0.2: resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} @@ -4996,14 +4829,6 @@ packages: media-encoder-host@9.0.20: resolution: {integrity: sha512-IyEYxw6az97RNuETOAZV4YZqNAPOiF9GKIp5mVZb4HOyWd6mhkWQ34ydOzhqAWogMyc4W05kjN/VCgTtgyFmsw==} - media-typer@1.1.0: - resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} - engines: {node: '>= 0.8'} - - merge-descriptors@2.0.0: - resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} - engines: {node: '>=18'} - merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -5109,18 +4934,10 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - mime-db@1.54.0: - resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} - engines: {node: '>= 0.6'} - mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - mime-types@3.0.1: - resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} - engines: {node: '>= 0.6'} - mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -5199,11 +5016,6 @@ packages: resolution: {integrity: sha512-SsI/exkodHsh+ofCV7An2PZWRaJC7eFVl7gtHQlMWFEDmWtb7cELr/GK32Nhe/6dZQhbr81o+Moswx9aXN3RRg==} engines: {node: '>=18.2.0'} - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - nanoid@3.3.8: resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -5222,10 +5034,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - negotiator@1.0.0: - resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} - engines: {node: '>= 0.6'} - no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} @@ -5299,18 +5107,10 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} - object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -5409,10 +5209,6 @@ packages: parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - pascal-case@3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} @@ -5446,10 +5242,6 @@ packages: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} - path-to-regexp@8.2.0: - resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} - engines: {node: '>=16'} - path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -5502,10 +5294,6 @@ packages: typescript: optional: true - pkce-challenge@5.0.0: - resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==} - engines: {node: '>=16.20.0'} - pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -5517,31 +5305,11 @@ packages: engines: {node: '>=18'} hasBin: true - playwright-core@1.53.1: - resolution: {integrity: sha512-Z46Oq7tLAyT0lGoFx4DOuB1IA9D1TPj0QkYxpPVUnGDqHHvDpCftu1J2hM2PiWsNMoZh8+LQaarAWcDfPBc6zg==} - engines: {node: '>=18'} - hasBin: true - - playwright-core@1.55.0: - resolution: {integrity: sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==} - engines: {node: '>=18'} - hasBin: true - playwright@1.52.0: resolution: {integrity: sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==} engines: {node: '>=18'} hasBin: true - playwright@1.53.1: - resolution: {integrity: sha512-LJ13YLr/ocweuwxyGf1XNFWIU4M2zUSo149Qbp+A4cpwDjsxRPj7k6H25LBrEHiEwxvRbD8HdwvQmRMSvquhYw==} - engines: {node: '>=18'} - hasBin: true - - playwright@1.55.0: - resolution: {integrity: sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==} - engines: {node: '>=18'} - hasBin: true - postcss-selector-parser@6.1.0: resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==} engines: {node: '>=4'} @@ -5657,10 +5425,6 @@ packages: resolution: {integrity: sha512-Z2E/kOY1QjoMlCytmexzYfDm/w5fKAiRwpSzGtdnXW1zC88Z2yXazHHrOtwCzn+7wSxyE8PYM4rvVcMphF9sOA==} engines: {node: '>=12.0.0'} - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -5712,10 +5476,6 @@ packages: resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} engines: {node: '>=12.20'} - qs@6.14.0: - resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} - engines: {node: '>=0.6'} - quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} @@ -5725,14 +5485,6 @@ packages: raf-schd@4.0.3: resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==} - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - raw-body@3.0.0: - resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} - engines: {node: '>= 0.8'} - rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -5876,10 +5628,6 @@ packages: rope-sequence@1.3.4: resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} - router@2.2.0: - resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} - engines: {node: '>= 18'} - rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -5913,9 +5661,6 @@ packages: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} - secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -5930,14 +5675,6 @@ packages: engines: {node: '>=10'} hasBin: true - send@1.2.0: - resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} - engines: {node: '>= 18'} - - serve-static@2.2.0: - resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} - engines: {node: '>= 18'} - set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -5945,9 +5682,6 @@ packages: setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -5956,22 +5690,6 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -5986,10 +5704,6 @@ packages: resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} engines: {node: '>=18'} - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} @@ -6033,14 +5747,6 @@ packages: standardized-audio-context@25.3.77: resolution: {integrity: sha512-Ki9zNz6pKcC5Pi+QPjPyVsD9GwJIJWgryji0XL9cAJXMGyn+dPOf6Qik1AHei0+UNVcc4BOCa0hWLBzlwqsW/A==} - statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - - statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} - std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} @@ -6156,6 +5862,9 @@ packages: resolution: {integrity: sha512-JJoOEKTfL1urb1mDoEblhD9NhEbWmq9jHEMEnxoC4ujUaZ4itA8vKgwkFAyNClgxplLi9tsUKX+EduK0p/l7sg==} engines: {node: ^14.18.0 || >=16.0.0} + tailwind-merge@3.3.1: + resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} + tailwindcss-primeui@0.6.1: resolution: {integrity: sha512-T69Rylcrmnt8zy9ik+qZvsLuRIrS9/k6rYJSIgZ1trnbEzGDDQSCIdmfyZknevqiHwpSJHSmQ9XT2C+S/hJY4A==} peerDependencies: @@ -6185,16 +5894,9 @@ packages: resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} engines: {node: '>=18'} - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - three@0.170.0: resolution: {integrity: sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==} - throttleit@2.1.0: - resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} - engines: {node: '>=18'} - tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -6243,10 +5945,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - token-stream@1.0.0: resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==} @@ -6272,12 +5970,6 @@ packages: trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - ts-api-utils@1.3.0: - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - ts-api-utils@2.1.0: resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} @@ -6303,10 +5995,6 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - tunnel@0.0.6: - resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} - engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -6323,18 +6011,12 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} - type-is@2.0.1: - resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} - engines: {node: '>= 0.6'} - - typescript-eslint@8.0.0: - resolution: {integrity: sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==} + typescript-eslint@8.42.0: + resolution: {integrity: sha512-ozR/rQn+aQXQxh1YgbCzQWDFrsi9mcg+1PM3l/z5o1+20P7suOIaNg515bpr/OYt6FObz/NHcBstydDLHWeEKg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' typescript@5.4.2: resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} @@ -6364,10 +6046,6 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - undici@5.29.0: - resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} - engines: {node: '>=14.0'} - unescape-js@1.1.4: resolution: {integrity: sha512-42SD8NOQEhdYntEiUQdYq/1V/YHwr1HLwlHuTJB5InVVdOSbgI6xu8jK5q65yIzuFCfczzyDF/7hbGzVbyCw0g==} @@ -6414,10 +6092,6 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - unplugin-icons@0.22.0: resolution: {integrity: sha512-CP+iZq5U7doOifer5bcM0jQ9t3Is7EGybIYt3myVxceI8Zuk8EZEpe1NPtJvh7iqMs1VdbK0L41t9+um9VuuLw==} peerDependencies: @@ -6494,10 +6168,6 @@ packages: resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - vfile-message@4.0.3: resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} @@ -6712,10 +6382,6 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - web-streams-polyfill@3.3.3: - resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} - engines: {node: '>= 8'} - web-streams-polyfill@4.0.0-beta.3: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} @@ -6882,6 +6548,10 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yjs@13.6.27: + resolution: {integrity: sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==} + engines: {node: '>=16.0.0', npm: '>=8.0.0'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -6933,58 +6603,8 @@ packages: snapshots: - '@actions/core@1.11.1': - dependencies: - '@actions/exec': 1.1.1 - '@actions/http-client': 2.2.3 - - '@actions/exec@1.1.1': - dependencies: - '@actions/io': 1.1.3 - - '@actions/http-client@2.2.3': - dependencies: - tunnel: 0.0.6 - undici: 5.29.0 - - '@actions/io@1.1.3': {} - '@adobe/css-tools@4.4.3': {} - '@ai-sdk/openai@1.3.24(zod@3.24.1)': - dependencies: - '@ai-sdk/provider': 1.1.3 - '@ai-sdk/provider-utils': 2.2.8(zod@3.24.1) - zod: 3.24.1 - - '@ai-sdk/provider-utils@2.2.8(zod@3.24.1)': - dependencies: - '@ai-sdk/provider': 1.1.3 - nanoid: 3.3.11 - secure-json-parse: 2.7.0 - zod: 3.24.1 - - '@ai-sdk/provider@1.1.3': - dependencies: - json-schema: 0.4.0 - - '@ai-sdk/react@1.2.12(react@19.1.1)(zod@3.24.1)': - dependencies: - '@ai-sdk/provider-utils': 2.2.8(zod@3.24.1) - '@ai-sdk/ui-utils': 1.2.11(zod@3.24.1) - react: 19.1.1 - swr: 2.3.6(react@19.1.1) - throttleit: 2.1.0 - optionalDependencies: - zod: 3.24.1 - - '@ai-sdk/ui-utils@1.2.11(zod@3.24.1)': - dependencies: - '@ai-sdk/provider': 1.1.3 - '@ai-sdk/provider-utils': 2.2.8(zod@3.24.1) - zod: 3.24.1 - zod-to-json-schema: 3.24.1(zod@3.24.1) - '@alcalzone/ansi-tokenize@0.2.0': dependencies: ansi-styles: 6.2.1 @@ -7088,20 +6708,6 @@ snapshots: '@antfu/utils@8.1.1': {} - '@anthropic-ai/sdk@0.8.1': - dependencies: - '@types/node': 18.19.123 - '@types/node-fetch': 2.6.13 - abort-controller: 3.0.0 - agentkeepalive: 4.6.0 - digest-fetch: 1.3.0 - form-data-encoder: 1.7.2 - formdata-node: 4.4.1 - node-fetch: 2.7.0 - web-streams-polyfill: 3.3.3 - transitivePeerDependencies: - - encoding - '@asamuzakjp/css-color@3.2.0': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) @@ -7819,7 +7425,7 @@ snapshots: '@babel/runtime@7.27.6': {} - '@babel/runtime@7.28.3': {} + '@babel/runtime@7.28.4': {} '@babel/template@7.27.2': dependencies: @@ -8025,22 +7631,31 @@ snapshots: '@esbuild/win32-x64@0.25.5': optional: true - '@eslint-community/eslint-utils@4.7.0(eslint@9.12.0(jiti@2.4.2))': + '@eslint-community/eslint-utils@4.7.0(eslint@9.35.0(jiti@2.4.2))': dependencies: - eslint: 9.12.0(jiti@2.4.2) + eslint: 9.35.0(jiti@2.4.2) eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.11.0': {} - - '@eslint/config-array@0.18.0': + '@eslint-community/eslint-utils@4.8.0(eslint@9.35.0(jiti@2.4.2))': dependencies: - '@eslint/object-schema': 2.1.4 + eslint: 9.35.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 debug: 4.4.1 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - '@eslint/core@0.6.0': {} + '@eslint/config-helpers@0.3.1': {} + + '@eslint/core@0.15.2': + dependencies: + '@types/json-schema': 7.0.15 '@eslint/eslintrc@3.1.0': dependencies: @@ -8056,33 +7671,31 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.1 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + '@eslint/js@9.12.0': {} - '@eslint/object-schema@2.1.4': {} + '@eslint/js@9.35.0': {} - '@eslint/plugin-kit@0.2.3': + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.5': dependencies: + '@eslint/core': 0.15.2 levn: 0.4.1 - '@executeautomation/playwright-mcp-server@1.0.6(react@19.1.1)(ws@8.18.3)(zod@3.24.1)': - dependencies: - '@modelcontextprotocol/sdk': 1.11.1 - '@playwright/browser-chromium': 1.53.1 - '@playwright/browser-firefox': 1.53.1 - '@playwright/browser-webkit': 1.53.1 - '@playwright/test': 1.55.0 - mcp-evals: 1.0.18(react@19.1.1)(ws@8.18.3)(zod@3.24.1) - playwright: 1.53.1 - uuid: 11.1.0 - transitivePeerDependencies: - - encoding - - react - - supports-color - - ws - - zod - - '@fastify/busboy@2.1.1': {} - '@firebase/analytics-compat@0.2.18(@firebase/app-compat@0.2.53)(@firebase/app@0.11.4)': dependencies: '@firebase/analytics': 0.10.12(@firebase/app@0.11.4) @@ -8413,16 +8026,20 @@ snapshots: protobufjs: 7.5.0 yargs: 17.7.2 - '@humanfs/core@0.19.0': {} + '@humanfs/core@0.19.1': {} - '@humanfs/node@0.16.5': + '@humanfs/node@0.16.7': dependencies: - '@humanfs/core': 0.19.0 - '@humanwhocodes/retry': 0.3.1 + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/retry@0.3.1': {} + '@humanwhocodes/retry@0.4.3': {} + + '@iconify-json/lucide@1.2.66': + dependencies: + '@iconify/types': 2.0.0 '@iconify/json@2.2.380': dependencies: @@ -8453,14 +8070,14 @@ snapshots: '@intlify/message-compiler': 9.14.3 '@intlify/shared': 9.14.3 - '@intlify/eslint-plugin-vue-i18n@3.2.0(eslint@9.12.0(jiti@2.4.2))': + '@intlify/eslint-plugin-vue-i18n@3.2.0(eslint@9.35.0(jiti@2.4.2))': dependencies: '@eslint/eslintrc': 3.1.0 '@intlify/core-base': 9.14.3 '@intlify/message-compiler': 9.14.3 debug: 4.4.1 - eslint: 9.12.0(jiti@2.4.2) - eslint-compat-utils: 0.6.5(eslint@9.12.0(jiti@2.4.2)) + eslint: 9.35.0(jiti@2.4.2) + eslint-compat-utils: 0.6.5(eslint@9.35.0(jiti@2.4.2)) glob: 10.4.5 globals: 15.15.0 ignore: 6.0.2 @@ -8473,7 +8090,7 @@ snapshots: parse5: 7.1.2 semver: 7.7.2 synckit: 0.9.3 - vue-eslint-parser: 9.4.3(eslint@9.12.0(jiti@2.4.2)) + vue-eslint-parser: 9.4.3(eslint@9.35.0(jiti@2.4.2)) yaml-eslint-parser: 1.3.0 transitivePeerDependencies: - supports-color @@ -8540,6 +8157,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@kurkle/color@0.3.4': {} + '@lobehub/cli-ui@1.13.0(@types/react@19.1.9)': dependencies: arr-rotate: 1.0.0 @@ -8643,21 +8262,6 @@ snapshots: '@microsoft/tsdoc@0.15.1': {} - '@modelcontextprotocol/sdk@1.11.1': - dependencies: - content-type: 1.0.5 - cors: 2.8.5 - cross-spawn: 7.0.6 - eventsource: 3.0.7 - express: 5.1.0 - express-rate-limit: 7.5.1(express@5.1.0) - pkce-challenge: 5.0.0 - raw-body: 3.0.0 - zod: 3.24.1 - zod-to-json-schema: 3.24.1(zod@3.24.1) - transitivePeerDependencies: - - supports-color - '@napi-rs/wasm-runtime@0.2.4': dependencies: '@emnapi/core': 1.4.5 @@ -8683,10 +8287,10 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@nx/cypress@21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1)(typescript@5.9.2)': + '@nx/cypress@21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1)(typescript@5.9.2)': dependencies: '@nx/devkit': 21.4.1(nx@21.4.1) - '@nx/eslint': 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1) + '@nx/eslint': 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1) '@nx/js': 21.4.1(@babel/traverse@7.28.3)(nx@21.4.1) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.9.2) detect-port: 1.6.1 @@ -8717,11 +8321,11 @@ snapshots: tslib: 2.8.1 yargs-parser: 21.1.1 - '@nx/eslint@21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1)': + '@nx/eslint@21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1)': dependencies: '@nx/devkit': 21.4.1(nx@21.4.1) '@nx/js': 21.4.1(@babel/traverse@7.28.3)(nx@21.4.1) - eslint: 9.12.0(jiti@2.4.2) + eslint: 9.35.0(jiti@2.4.2) semver: 7.7.2 tslib: 2.8.1 typescript: 5.8.3 @@ -8805,10 +8409,10 @@ snapshots: '@nx/nx-win32-x64-msvc@21.4.1': optional: true - '@nx/playwright@21.4.1(@babel/traverse@7.28.3)(@playwright/test@1.52.0)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1)(typescript@5.9.2)': + '@nx/playwright@21.4.1(@babel/traverse@7.28.3)(@playwright/test@1.52.0)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1)(typescript@5.9.2)': dependencies: '@nx/devkit': 21.4.1(nx@21.4.1) - '@nx/eslint': 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1) + '@nx/eslint': 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1) '@nx/js': 21.4.1(@babel/traverse@7.28.3)(nx@21.4.1) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.9.2) minimatch: 9.0.3 @@ -8827,11 +8431,11 @@ snapshots: - typescript - verdaccio - '@nx/storybook@21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1)(storybook@9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2)': + '@nx/storybook@21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1)(storybook@9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2)': dependencies: - '@nx/cypress': 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1)(typescript@5.9.2) + '@nx/cypress': 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1)(typescript@5.9.2) '@nx/devkit': 21.4.1(nx@21.4.1) - '@nx/eslint': 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.12.0(jiti@2.4.2))(nx@21.4.1) + '@nx/eslint': 21.4.1(@babel/traverse@7.28.3)(@zkochan/js-yaml@0.0.7)(eslint@9.35.0(jiti@2.4.2))(nx@21.4.1) '@nx/js': 21.4.1(@babel/traverse@7.28.3)(nx@21.4.1) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.9.2) semver: 7.7.2 @@ -8891,8 +8495,6 @@ snapshots: '@one-ini/wasm@0.1.1': {} - '@opentelemetry/api@1.9.0': {} - '@oxc-resolver/binding-android-arm-eabi@11.6.1': optional: true @@ -8972,26 +8574,10 @@ snapshots: '@pkgr/core@0.2.2': {} - '@playwright/browser-chromium@1.53.1': - dependencies: - playwright-core: 1.53.1 - - '@playwright/browser-firefox@1.53.1': - dependencies: - playwright-core: 1.53.1 - - '@playwright/browser-webkit@1.53.1': - dependencies: - playwright-core: 1.53.1 - '@playwright/test@1.52.0': dependencies: playwright: 1.52.0 - '@playwright/test@1.55.0': - dependencies: - playwright: 1.55.0 - '@pnpm/config.env-replace@1.1.0': {} '@pnpm/network.ca-file@1.0.2': @@ -9337,7 +8923,7 @@ snapshots: '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.27.1 - '@babel/runtime': 7.28.3 + '@babel/runtime': 7.28.4 '@types/aria-query': 5.0.4 aria-query: 5.3.0 dom-accessibility-api: 0.5.16 @@ -9555,8 +9141,6 @@ snapshots: '@types/estree@1.0.5': {} - '@types/estree@1.0.6': {} - '@types/estree@1.0.8': {} '@types/fs-extra@11.0.4': @@ -9645,33 +9229,31 @@ snapshots: '@types/webxr@0.5.20': {} - '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2)': dependencies: - '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) - '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/type-utils': 8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) - '@typescript-eslint/utils': 8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.0.0 - eslint: 9.12.0(jiti@2.4.2) + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/scope-manager': 8.42.0 + '@typescript-eslint/type-utils': 8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/utils': 8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.42.0 + eslint: 9.35.0(jiti@2.4.2) graphemer: 1.4.0 - ignore: 5.3.1 + ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.9.2) - optionalDependencies: + ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2)': + '@typescript-eslint/parser@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2)': dependencies: - '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.0.0 + '@typescript-eslint/scope-manager': 8.42.0 + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.42.0 debug: 4.4.1 - eslint: 9.12.0(jiti@2.4.2) - optionalDependencies: + eslint: 9.35.0(jiti@2.4.2) typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -9685,50 +9267,48 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.0.0': + '@typescript-eslint/project-service@8.42.0(typescript@5.9.2)': dependencies: - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/visitor-keys': 8.0.0 + '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@5.9.2) + '@typescript-eslint/types': 8.42.0 + debug: 4.4.1 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color '@typescript-eslint/scope-manager@8.39.0': dependencies: '@typescript-eslint/types': 8.39.0 '@typescript-eslint/visitor-keys': 8.39.0 + '@typescript-eslint/scope-manager@8.42.0': + dependencies: + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/visitor-keys': 8.42.0 + '@typescript-eslint/tsconfig-utils@8.39.0(typescript@5.9.2)': dependencies: typescript: 5.9.2 - '@typescript-eslint/type-utils@8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2)': + '@typescript-eslint/tsconfig-utils@8.42.0(typescript@5.9.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) + typescript: 5.9.2 + + '@typescript-eslint/type-utils@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2)': + dependencies: + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) debug: 4.4.1 - ts-api-utils: 1.3.0(typescript@5.9.2) - optionalDependencies: + eslint: 9.35.0(jiti@2.4.2) + ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: - - eslint - supports-color - '@typescript-eslint/types@8.0.0': {} - '@typescript-eslint/types@8.39.0': {} - '@typescript-eslint/typescript-estree@8.0.0(typescript@5.9.2)': - dependencies: - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/visitor-keys': 8.0.0 - debug: 4.4.1 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.2 - ts-api-utils: 1.3.0(typescript@5.9.2) - optionalDependencies: - typescript: 5.9.2 - transitivePeerDependencies: - - supports-color + '@typescript-eslint/types@8.42.0': {} '@typescript-eslint/typescript-estree@8.39.0(typescript@5.9.2)': dependencies: @@ -9746,38 +9326,54 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2)': + '@typescript-eslint/typescript-estree@8.42.0(typescript@5.9.2)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.12.0(jiti@2.4.2)) - '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.9.2) - eslint: 9.12.0(jiti@2.4.2) - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/utils@8.39.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2)': - dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.12.0(jiti@2.4.2)) - '@typescript-eslint/scope-manager': 8.39.0 - '@typescript-eslint/types': 8.39.0 - '@typescript-eslint/typescript-estree': 8.39.0(typescript@5.9.2) - eslint: 9.12.0(jiti@2.4.2) + '@typescript-eslint/project-service': 8.42.0(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@5.9.2) + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/visitor-keys': 8.42.0 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.0.0': + '@typescript-eslint/utils@8.39.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2)': dependencies: - '@typescript-eslint/types': 8.0.0 - eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.35.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.39.0 + '@typescript-eslint/types': 8.39.0 + '@typescript-eslint/typescript-estree': 8.39.0(typescript@5.9.2) + eslint: 9.35.0(jiti@2.4.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.42.0 + '@typescript-eslint/types': 8.42.0 + '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2) + eslint: 9.35.0(jiti@2.4.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color '@typescript-eslint/visitor-keys@8.39.0': dependencies: '@typescript-eslint/types': 8.39.0 eslint-visitor-keys: 4.2.1 + '@typescript-eslint/visitor-keys@8.42.0': + dependencies: + '@typescript-eslint/types': 8.42.0 + eslint-visitor-keys: 4.2.1 + '@vitejs/plugin-vue@5.1.4(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2))(vue@3.5.13(typescript@5.9.2))': dependencies: vite: 5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2) @@ -10077,19 +9673,20 @@ snapshots: dependencies: event-target-shim: 5.0.1 - accepts@2.0.0: - dependencies: - mime-types: 3.0.1 - negotiator: 1.0.0 - acorn-jsx@5.3.2(acorn@8.14.1): dependencies: acorn: 8.14.1 + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + acorn@7.4.1: {} acorn@8.14.1: {} + acorn@8.15.0: {} + address@1.2.2: {} agent-base@7.1.4: {} @@ -10098,18 +9695,6 @@ snapshots: dependencies: humanize-ms: 1.2.1 - ai@4.3.19(react@19.1.1)(zod@3.24.1): - dependencies: - '@ai-sdk/provider': 1.1.3 - '@ai-sdk/provider-utils': 2.2.8(zod@3.24.1) - '@ai-sdk/react': 1.2.12(react@19.1.1)(zod@3.24.1) - '@ai-sdk/ui-utils': 1.2.11(zod@3.24.1) - '@opentelemetry/api': 1.9.0 - jsondiffpatch: 0.6.0 - zod: 3.24.1 - optionalDependencies: - react: 19.1.1 - ajv-draft-04@1.0.0(ajv@8.13.0): optionalDependencies: ajv: 8.13.0 @@ -10211,8 +9796,6 @@ snapshots: arr-rotate@1.0.0: {} - array-union@2.1.0: {} - asap@2.0.6: {} assert-never@1.4.0: {} @@ -10307,8 +9890,6 @@ snapshots: balanced-match@1.0.2: {} - base-64@0.1.0: {} - base64-js@1.5.1: {} better-opn@3.0.2: @@ -10327,20 +9908,6 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - body-parser@2.2.0: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 4.4.1 - http-errors: 2.0.0 - iconv-lite: 0.6.3 - on-finished: 2.4.1 - qs: 6.14.0 - raw-body: 3.0.0 - type-is: 2.0.1 - transitivePeerDependencies: - - supports-color - boolbase@1.0.0: {} boxen@8.0.1: @@ -10392,8 +9959,6 @@ snapshots: dependencies: run-applescript: 7.0.0 - bytes@3.1.2: {} - cac@6.7.14: {} call-bind-apply-helpers@1.0.2: @@ -10449,7 +10014,9 @@ snapshots: dependencies: is-regex: 1.2.1 - charenc@0.0.2: {} + chart.js@4.5.0: + dependencies: + '@kurkle/color': 0.3.4 check-error@2.1.1: {} @@ -10500,6 +10067,8 @@ snapshots: clone@1.0.4: {} + clsx@2.1.1: {} + code-excerpt@4.0.0: dependencies: convert-to-spaces: 2.0.1 @@ -10576,20 +10145,10 @@ snapshots: '@babel/parser': 7.28.3 '@babel/types': 7.28.2 - content-disposition@1.0.0: - dependencies: - safe-buffer: 5.2.1 - - content-type@1.0.5: {} - convert-source-map@2.0.0: {} convert-to-spaces@2.0.1: {} - cookie-signature@1.2.2: {} - - cookie@0.7.2: {} - copy-anything@3.0.5: dependencies: is-what: 4.1.16 @@ -10600,11 +10159,6 @@ snapshots: core-util-is@1.0.3: {} - cors@2.8.5: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - cosmiconfig@7.1.0: dependencies: '@types/parse-json': 4.0.2 @@ -10630,8 +10184,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - crypt@0.0.2: {} - css-select@4.3.0: dependencies: boolbase: 1.0.0 @@ -10709,8 +10261,6 @@ snapshots: delayed-stream@1.0.0: {} - depd@2.0.0: {} - dequal@2.0.3: {} detect-libc@2.0.4: {} @@ -10728,15 +10278,6 @@ snapshots: diff-match-patch@1.0.5: {} - digest-fetch@1.3.0: - dependencies: - base-64: 0.1.0 - md5: 2.3.0 - - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - dirty-json@0.9.2: dependencies: lex: 1.7.9 @@ -10805,8 +10346,6 @@ snapshots: minimatch: 9.0.1 semver: 7.7.2 - ee-first@1.1.1: {} - ejs@3.1.10: dependencies: jake: 10.9.2 @@ -10819,8 +10358,6 @@ snapshots: emoji-regex@9.2.2: {} - encodeurl@2.0.0: {} - end-of-stream@1.4.5: dependencies: once: 1.4.0 @@ -10938,8 +10475,6 @@ snapshots: escape-goat@4.0.0: {} - escape-html@1.0.3: {} - escape-string-regexp@1.0.5: {} escape-string-regexp@2.0.0: {} @@ -10948,49 +10483,49 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-compat-utils@0.6.5(eslint@9.12.0(jiti@2.4.2)): + eslint-compat-utils@0.6.5(eslint@9.35.0(jiti@2.4.2)): dependencies: - eslint: 9.12.0(jiti@2.4.2) + eslint: 9.35.0(jiti@2.4.2) semver: 7.7.2 - eslint-config-prettier@10.1.2(eslint@9.12.0(jiti@2.4.2)): + eslint-config-prettier@10.1.2(eslint@9.35.0(jiti@2.4.2)): dependencies: - eslint: 9.12.0(jiti@2.4.2) + eslint: 9.35.0(jiti@2.4.2) - eslint-plugin-prettier@5.2.6(eslint-config-prettier@10.1.2(eslint@9.12.0(jiti@2.4.2)))(eslint@9.12.0(jiti@2.4.2))(prettier@3.3.2): + eslint-plugin-prettier@5.2.6(eslint-config-prettier@10.1.2(eslint@9.35.0(jiti@2.4.2)))(eslint@9.35.0(jiti@2.4.2))(prettier@3.3.2): dependencies: - eslint: 9.12.0(jiti@2.4.2) + eslint: 9.35.0(jiti@2.4.2) prettier: 3.3.2 prettier-linter-helpers: 1.0.0 synckit: 0.11.3 optionalDependencies: - eslint-config-prettier: 10.1.2(eslint@9.12.0(jiti@2.4.2)) + eslint-config-prettier: 10.1.2(eslint@9.35.0(jiti@2.4.2)) - eslint-plugin-storybook@9.1.1(eslint@9.12.0(jiti@2.4.2))(storybook@9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2): + eslint-plugin-storybook@9.1.1(eslint@9.35.0(jiti@2.4.2))(storybook@9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2): dependencies: - '@typescript-eslint/utils': 8.39.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) - eslint: 9.12.0(jiti@2.4.2) + '@typescript-eslint/utils': 8.39.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) + eslint: 9.35.0(jiti@2.4.2) storybook: 9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.12.0(jiti@2.4.2)): + eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2)): dependencies: - eslint: 9.12.0(jiti@2.4.2) + eslint: 9.35.0(jiti@2.4.2) optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/eslint-plugin': 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) - eslint-plugin-vue@9.27.0(eslint@9.12.0(jiti@2.4.2)): + eslint-plugin-vue@9.27.0(eslint@9.35.0(jiti@2.4.2)): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.12.0(jiti@2.4.2)) - eslint: 9.12.0(jiti@2.4.2) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.35.0(jiti@2.4.2)) + eslint: 9.35.0(jiti@2.4.2) globals: 13.24.0 natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.0 semver: 7.7.2 - vue-eslint-parser: 9.4.3(eslint@9.12.0(jiti@2.4.2)) + vue-eslint-parser: 9.4.3(eslint@9.35.0(jiti@2.4.2)) xml-name-validator: 4.0.0 transitivePeerDependencies: - supports-color @@ -11000,7 +10535,7 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 - eslint-scope@8.1.0: + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 @@ -11009,28 +10544,29 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.12.0(jiti@2.4.2): + eslint@9.35.0(jiti@2.4.2): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.12.0(jiti@2.4.2)) - '@eslint-community/regexpp': 4.11.0 - '@eslint/config-array': 0.18.0 - '@eslint/core': 0.6.0 - '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.12.0 - '@eslint/plugin-kit': 0.2.3 - '@humanfs/node': 0.16.5 + '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.1 + '@eslint/core': 0.15.2 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.35.0 + '@eslint/plugin-kit': 0.3.5 + '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.3.1 - '@types/estree': 1.0.6 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.1 escape-string-regexp: 4.0.0 - eslint-scope: 8.1.0 + eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 - espree: 10.2.0 + espree: 10.4.0 esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -11045,7 +10581,6 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 - text-table: 0.2.0 optionalDependencies: jiti: 2.4.2 transitivePeerDependencies: @@ -11059,6 +10594,12 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.14.1) eslint-visitor-keys: 4.2.1 + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + espree@9.6.1: dependencies: acorn: 8.14.1 @@ -11085,18 +10626,10 @@ snapshots: esutils@2.0.3: {} - etag@1.8.1: {} - event-target-shim@5.0.1: {} eventemitter3@5.0.1: {} - eventsource-parser@3.0.5: {} - - eventsource@3.0.7: - dependencies: - eventsource-parser: 3.0.5 - execa@8.0.1: dependencies: cross-spawn: 7.0.6 @@ -11126,42 +10659,6 @@ snapshots: expect-type@1.2.2: {} - express-rate-limit@7.5.1(express@5.1.0): - dependencies: - express: 5.1.0 - - express@5.1.0: - dependencies: - accepts: 2.0.0 - body-parser: 2.2.0 - content-disposition: 1.0.0 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.2.2 - debug: 4.4.1 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 2.1.0 - fresh: 2.0.0 - http-errors: 2.0.0 - merge-descriptors: 2.0.0 - mime-types: 3.0.1 - on-finished: 2.4.1 - once: 1.4.0 - parseurl: 1.3.3 - proxy-addr: 2.0.7 - qs: 6.14.0 - range-parser: 1.2.1 - router: 2.2.0 - send: 1.2.0 - serve-static: 2.2.0 - statuses: 2.0.2 - type-is: 2.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - exsolve@1.0.7: {} extend-shallow@2.0.1: @@ -11265,17 +10762,6 @@ snapshots: dependencies: to-regex-range: 5.0.1 - finalhandler@2.1.0: - dependencies: - debug: 4.4.1 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - find-package-json@1.2.0: {} find-up@5.0.0: @@ -11318,13 +10804,11 @@ snapshots: flat-cache@4.0.1: dependencies: - flatted: 3.3.1 + flatted: 3.3.3 keyv: 4.5.4 flat@5.0.2: {} - flatted@3.3.1: {} - flatted@3.3.3: {} follow-redirects@1.15.6: {} @@ -11360,10 +10844,6 @@ snapshots: node-domexception: 1.0.0 web-streams-polyfill: 4.0.0-beta.3 - forwarded@0.2.0: {} - - fresh@2.0.0: {} - front-matter@4.0.2: dependencies: js-yaml: 3.14.1 @@ -11471,15 +10951,6 @@ snapshots: globals@15.15.0: {} - globby@11.1.0: - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.3 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 3.0.0 - gopd@1.2.0: {} gpt-tokenizer@2.9.0: {} @@ -11545,14 +11016,6 @@ snapshots: relateurl: 0.2.7 terser: 5.39.2 - http-errors@2.0.0: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - http-parser-js@0.5.10: {} http-proxy-agent@7.0.2: @@ -11591,6 +11054,8 @@ snapshots: ignore@6.0.2: {} + ignore@7.0.5: {} + immediate@3.0.6: {} import-fresh@3.3.0: @@ -11650,16 +11115,12 @@ snapshots: - bufferutil - utf-8-validate - ipaddr.js@1.9.1: {} - is-arrayish@0.2.1: {} is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 - is-buffer@1.1.6: {} - is-core-module@2.16.1: dependencies: hasown: 2.0.2 @@ -11720,8 +11181,6 @@ snapshots: is-promise@2.2.2: {} - is-promise@4.0.0: {} - is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -11753,6 +11212,8 @@ snapshots: isexe@2.0.0: {} + isomorphic.js@0.2.5: {} + istanbul-lib-coverage@3.2.2: {} istanbul-lib-report@3.0.1: @@ -11872,8 +11333,6 @@ snapshots: json-schema-typed@8.0.1: {} - json-schema@0.4.0: {} - json-stable-stringify-without-jsonify@1.0.1: {} json-stable-stringify@1.3.0: @@ -11966,6 +11425,10 @@ snapshots: lex@1.7.9: {} + lib0@0.2.114: + dependencies: + isomorphic.js: 0.2.5 + lie@3.3.0: dependencies: immediate: 3.0.6 @@ -12117,10 +11580,6 @@ snapshots: lru-cache@8.0.5: {} - lucide-vue-next@0.540.0(vue@3.5.13(typescript@5.9.2)): - dependencies: - vue: 3.5.13(typescript@5.9.2) - lz-string@1.5.0: {} magic-string@0.30.17: @@ -12158,30 +11617,6 @@ snapshots: math-intrinsics@1.1.0: {} - mcp-evals@1.0.18(react@19.1.1)(ws@8.18.3)(zod@3.24.1): - dependencies: - '@actions/core': 1.11.1 - '@ai-sdk/openai': 1.3.24(zod@3.24.1) - '@anthropic-ai/sdk': 0.8.1 - '@modelcontextprotocol/sdk': 1.11.1 - ai: 4.3.19(react@19.1.1)(zod@3.24.1) - chalk: 4.1.2 - dotenv: 16.4.5 - openai: 4.104.0(ws@8.18.3)(zod@3.24.1) - react: 19.1.1 - tsx: 4.19.4 - transitivePeerDependencies: - - encoding - - supports-color - - ws - - zod - - md5@2.3.0: - dependencies: - charenc: 0.0.2 - crypt: 0.0.2 - is-buffer: 1.1.6 - mdast-util-find-and-replace@3.0.2: dependencies: '@types/mdast': 4.0.4 @@ -12319,10 +11754,6 @@ snapshots: media-encoder-host-worker: 10.0.19 tslib: 2.8.1 - media-typer@1.1.0: {} - - merge-descriptors@2.0.0: {} - merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -12534,16 +11965,10 @@ snapshots: mime-db@1.52.0: {} - mime-db@1.54.0: {} - mime-types@2.1.35: dependencies: mime-db: 1.52.0 - mime-types@3.0.1: - dependencies: - mime-db: 1.54.0 - mimic-fn@2.1.0: {} mimic-fn@4.0.0: {} @@ -12610,8 +12035,6 @@ snapshots: '@babel/runtime': 7.27.6 tslib: 2.8.1 - nanoid@3.3.11: {} - nanoid@3.3.8: {} nanoid@5.1.5: {} @@ -12620,8 +12043,6 @@ snapshots: natural-compare@1.4.0: {} - negotiator@1.0.0: {} - no-case@3.0.4: dependencies: lower-case: 2.0.2 @@ -12727,14 +12148,8 @@ snapshots: object-assign@4.1.1: {} - object-inspect@1.13.4: {} - object-keys@1.1.1: {} - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 - once@1.4.0: dependencies: wrappy: 1.0.2 @@ -12876,8 +12291,6 @@ snapshots: dependencies: entities: 6.0.1 - parseurl@1.3.3: {} - pascal-case@3.1.2: dependencies: no-case: 3.0.4 @@ -12905,8 +12318,6 @@ snapshots: lru-cache: 11.1.0 minipass: 7.1.2 - path-to-regexp@8.2.0: {} - path-type@4.0.0: {} pathe@0.2.0: {} @@ -12937,8 +12348,6 @@ snapshots: optionalDependencies: typescript: 5.9.2 - pkce-challenge@5.0.0: {} - pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -12953,28 +12362,12 @@ snapshots: playwright-core@1.52.0: {} - playwright-core@1.53.1: {} - - playwright-core@1.55.0: {} - playwright@1.52.0: dependencies: playwright-core: 1.52.0 optionalDependencies: fsevents: 2.3.2 - playwright@1.53.1: - dependencies: - playwright-core: 1.53.1 - optionalDependencies: - fsevents: 2.3.2 - - playwright@1.55.0: - dependencies: - playwright-core: 1.55.0 - optionalDependencies: - fsevents: 2.3.2 - postcss-selector-parser@6.1.0: dependencies: cssesc: 3.0.0 @@ -13149,11 +12542,6 @@ snapshots: '@types/node': 20.14.10 long: 5.3.1 - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - proxy-from-env@1.1.0: {} pug-attrs@3.0.0: @@ -13231,25 +12619,12 @@ snapshots: dependencies: escape-goat: 4.0.0 - qs@6.14.0: - dependencies: - side-channel: 1.1.0 - quansync@0.2.11: {} queue-microtask@1.2.3: {} raf-schd@4.0.3: {} - range-parser@1.2.1: {} - - raw-body@3.0.0: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.6.3 - unpipe: 1.0.0 - rc@1.2.8: dependencies: deep-extend: 0.6.0 @@ -13448,16 +12823,6 @@ snapshots: rope-sequence@1.3.4: {} - router@2.2.0: - dependencies: - debug: 4.4.1 - depd: 2.0.0 - is-promise: 4.0.0 - parseurl: 1.3.3 - path-to-regexp: 8.2.0 - transitivePeerDependencies: - - supports-color - rrweb-cssom@0.8.0: {} run-applescript@7.0.0: {} @@ -13485,8 +12850,6 @@ snapshots: extend-shallow: 2.0.1 kind-of: 6.0.3 - secure-json-parse@2.7.0: {} - semver@6.3.1: {} semver@7.5.4: @@ -13495,31 +12858,6 @@ snapshots: semver@7.7.2: {} - send@1.2.0: - dependencies: - debug: 4.4.1 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 2.0.0 - http-errors: 2.0.0 - mime-types: 3.0.1 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - - serve-static@2.2.0: - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 1.2.0 - transitivePeerDependencies: - - supports-color - set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -13531,42 +12869,12 @@ snapshots: setimmediate@1.0.5: {} - setprototypeof@1.2.0: {} - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 shebang-regex@3.0.0: {} - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - siginfo@2.0.0: {} signal-exit@3.0.7: {} @@ -13579,8 +12887,6 @@ snapshots: mrmime: 2.0.1 totalist: 3.0.1 - slash@3.0.0: {} - slice-ansi@5.0.0: dependencies: ansi-styles: 6.2.1 @@ -13623,10 +12929,6 @@ snapshots: automation-events: 7.1.11 tslib: 2.8.1 - statuses@2.0.1: {} - - statuses@2.0.2: {} - std-env@3.9.0: {} storybook@9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)): @@ -13749,6 +13051,8 @@ snapshots: '@pkgr/core': 0.1.2 tslib: 2.8.1 + tailwind-merge@3.3.1: {} + tailwindcss-primeui@0.6.1(tailwindcss@4.1.12): dependencies: tailwindcss: 4.1.12 @@ -13787,12 +13091,8 @@ snapshots: glob: 10.4.5 minimatch: 9.0.5 - text-table@0.2.0: {} - three@0.170.0: {} - throttleit@2.1.0: {} - tiny-invariant@1.3.3: {} tinybench@2.9.0: {} @@ -13832,8 +13132,6 @@ snapshots: dependencies: is-number: 7.0.0 - toidentifier@1.0.1: {} - token-stream@1.0.0: {} totalist@3.0.1: {} @@ -13852,10 +13150,6 @@ snapshots: trough@2.2.0: {} - ts-api-utils@1.3.0(typescript@5.9.2): - dependencies: - typescript: 5.9.2 - ts-api-utils@2.1.0(typescript@5.9.2): dependencies: typescript: 5.9.2 @@ -13879,8 +13173,6 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - tunnel@0.0.6: {} - type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -13891,21 +13183,15 @@ snapshots: type-fest@4.41.0: {} - type-is@2.0.1: + typescript-eslint@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2): dependencies: - content-type: 1.0.5 - media-typer: 1.1.0 - mime-types: 3.0.1 - - typescript-eslint@8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2): - dependencies: - '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) - '@typescript-eslint/parser': 8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) - '@typescript-eslint/utils': 8.0.0(eslint@9.12.0(jiti@2.4.2))(typescript@5.9.2) - optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/parser': 8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) + '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2) + eslint: 9.35.0(jiti@2.4.2) typescript: 5.9.2 transitivePeerDependencies: - - eslint - supports-color typescript@5.4.2: {} @@ -13922,10 +13208,6 @@ snapshots: undici-types@5.26.5: {} - undici@5.29.0: - dependencies: - '@fastify/busboy': 2.1.1 - unescape-js@1.1.4: dependencies: string.fromcodepoint: 0.2.1 @@ -13976,8 +13258,6 @@ snapshots: universalify@2.0.1: {} - unpipe@1.0.0: {} - unplugin-icons@0.22.0(@vue/compiler-sfc@3.5.13): dependencies: '@antfu/install-pkg': 0.5.0 @@ -14057,8 +13337,6 @@ snapshots: validate-npm-package-name@5.0.1: {} - vary@1.1.2: {} - vfile-message@4.0.3: dependencies: '@types/unist': 3.0.3 @@ -14263,10 +13541,10 @@ snapshots: vue: 3.5.13(typescript@5.9.2) vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.13(typescript@5.9.2)) - vue-eslint-parser@9.4.3(eslint@9.12.0(jiti@2.4.2)): + vue-eslint-parser@9.4.3(eslint@9.35.0(jiti@2.4.2)): dependencies: debug: 4.4.1 - eslint: 9.12.0(jiti@2.4.2) + eslint: 9.35.0(jiti@2.4.2) eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 @@ -14329,8 +13607,6 @@ snapshots: dependencies: defaults: 1.0.4 - web-streams-polyfill@3.3.3: {} - web-streams-polyfill@4.0.0-beta.3: {} web-vitals@4.2.4: {} @@ -14460,6 +13736,10 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yjs@13.6.27: + dependencies: + lib0: 0.2.114 + yocto-queue@0.1.0: {} yoctocolors@2.1.1: {} diff --git a/scripts/cicd/pr-playwright-deploy-and-comment.sh b/scripts/cicd/pr-playwright-deploy-and-comment.sh new file mode 100755 index 000000000..767a7f514 --- /dev/null +++ b/scripts/cicd/pr-playwright-deploy-and-comment.sh @@ -0,0 +1,241 @@ +#!/bin/bash +set -e + +# Deploy Playwright test reports to Cloudflare Pages and comment on PR +# Usage: ./pr-playwright-deploy-and-comment.sh [start_time] + +# Input validation +# Validate PR number is numeric +case "$1" in + ''|*[!0-9]*) + echo "Error: PR_NUMBER must be numeric" >&2 + exit 1 + ;; +esac +PR_NUMBER="$1" + +# Sanitize and validate branch name (allow alphanumeric, dots, dashes, underscores, slashes) +BRANCH_NAME=$(echo "$2" | sed 's/[^a-zA-Z0-9._/-]//g') +if [ -z "$BRANCH_NAME" ]; then + echo "Error: Invalid or empty branch name" >&2 + exit 1 +fi + +# Validate status parameter +STATUS="${3:-completed}" +case "$STATUS" in + starting|completed) ;; + *) + echo "Error: STATUS must be 'starting' or 'completed'" >&2 + exit 1 + ;; +esac + +START_TIME="${4:-$(date -u '+%m/%d/%Y, %I:%M:%S %p')}" + +# Required environment variables +: "${GITHUB_TOKEN:?GITHUB_TOKEN is required}" +: "${GITHUB_REPOSITORY:?GITHUB_REPOSITORY is required}" + +# Cloudflare variables only required for deployment +if [ "$STATUS" = "completed" ]; then + : "${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN is required for deployment}" + : "${CLOUDFLARE_ACCOUNT_ID:?CLOUDFLARE_ACCOUNT_ID is required for deployment}" +fi + +# Configuration +COMMENT_MARKER="" +# Use dot notation for artifact names (as Playwright creates them) +BROWSERS="chromium chromium-2x chromium-0.5x mobile-chrome" + +# Install wrangler if not available (output to stderr for debugging) +if ! command -v wrangler > /dev/null 2>&1; then + echo "Installing wrangler v4..." >&2 + npm install -g wrangler@^4.0.0 >&2 || { + echo "Failed to install wrangler" >&2 + echo "failed" + return + } +fi + +# Deploy a single browser report, WARN: ensure inputs are sanitized before calling this function +deploy_report() { + dir="$1" + browser="$2" + branch="$3" + + [ ! -d "$dir" ] && echo "failed" && return + + + # Project name with dots converted to dashes for Cloudflare + sanitized_browser=$(echo "$browser" | sed 's/\./-/g') + project="comfyui-playwright-${sanitized_browser}" + + echo "Deploying $browser to project $project on branch $branch..." >&2 + + # Try deployment up to 3 times + i=1 + while [ $i -le 3 ]; do + echo "Deployment attempt $i of 3..." >&2 + # Branch and project are already sanitized, use them directly + # Branch was sanitized at script start, project uses sanitized_browser + if output=$(wrangler pages deploy "$dir" \ + --project-name="$project" \ + --branch="$branch" 2>&1); then + + # Extract URL from output (improved regex for valid URL characters) + url=$(echo "$output" | grep -oE 'https://[a-zA-Z0-9.-]+\.pages\.dev\S*' | head -1) + result="${url:-https://${branch}.${project}.pages.dev}" + echo "Success! URL: $result" >&2 + echo "$result" # Only this goes to stdout for capture + return + else + echo "Deployment failed on attempt $i: $output" >&2 + fi + [ $i -lt 3 ] && sleep 10 + i=$((i + 1)) + done + + echo "failed" +} + +# Post or update GitHub comment +post_comment() { + body="$1" + temp_file=$(mktemp) + echo "$body" > "$temp_file" + + if command -v gh > /dev/null 2>&1; then + # Find existing comment ID + existing=$(gh api "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \ + --jq ".[] | select(.body | contains(\"$COMMENT_MARKER\")) | .id" | head -1) + + if [ -n "$existing" ]; then + # Update specific comment by ID + gh api --method PATCH "repos/$GITHUB_REPOSITORY/issues/comments/$existing" \ + --field body="$(cat "$temp_file")" + else + # Create new comment + gh pr comment "$PR_NUMBER" --body-file "$temp_file" + fi + else + echo "GitHub CLI not available, outputting comment:" + cat "$temp_file" + fi + + rm -f "$temp_file" +} + +# Main execution +if [ "$STATUS" = "starting" ]; then + # Post starting comment + comment=$(cat < **Tests are starting...** + +⏰ Started at: $START_TIME UTC + +### 🚀 Running Tests +- 🧪 **chromium**: Running tests... +- 🧪 **chromium-0.5x**: Running tests... +- 🧪 **chromium-2x**: Running tests... +- 🧪 **mobile-chrome**: Running tests... + +--- +⏱️ Please wait while tests are running... +EOF +) + post_comment "$comment" + +else + # Deploy and post completion comment + # Convert branch name to Cloudflare-compatible format (lowercase, only alphanumeric and dashes) + cloudflare_branch=$(echo "$BRANCH_NAME" | tr '[:upper:]' '[:lower:]' | \ + sed 's/[^a-z0-9-]/-/g' | sed 's/--*/-/g' | sed 's/^-\|-$//g') + + echo "Looking for reports in: $(pwd)/reports" + echo "Available reports:" + ls -la reports/ 2>/dev/null || echo "Reports directory not found" + + # Deploy all reports in parallel and collect URLs + temp_dir=$(mktemp -d) + pids="" + i=0 + + # Start parallel deployments + for browser in $BROWSERS; do + if [ -d "reports/playwright-report-$browser" ]; then + echo "Found report for $browser, deploying in parallel..." + ( + url=$(deploy_report "reports/playwright-report-$browser" "$browser" "$cloudflare_branch") + echo "$url" > "$temp_dir/$i.url" + echo "Deployment result for $browser: $url" + ) & + pids="$pids $!" + else + echo "Report not found for $browser at reports/playwright-report-$browser" + echo "failed" > "$temp_dir/$i.url" + fi + i=$((i + 1)) + done + + # Wait for all deployments to complete + for pid in $pids; do + wait $pid + done + + # Collect URLs in order + urls="" + i=0 + for browser in $BROWSERS; do + if [ -f "$temp_dir/$i.url" ]; then + url=$(cat "$temp_dir/$i.url") + else + url="failed" + fi + if [ -z "$urls" ]; then + urls="$url" + else + urls="$urls $url" + fi + i=$((i + 1)) + done + + # Clean up temp directory + rm -rf "$temp_dir" + + # Generate completion comment + comment="$COMMENT_MARKER +## 🎭 Playwright Test Results + +✅ **Tests completed successfully!** + +⏰ Completed at: $(date -u '+%m/%d/%Y, %I:%M:%S %p') UTC + +### 📊 Test Reports by Browser" + + # Add browser results + i=0 + for browser in $BROWSERS; do + # Get URL at position i + url=$(echo "$urls" | cut -d' ' -f$((i + 1))) + + if [ "$url" != "failed" ] && [ -n "$url" ]; then + comment="$comment +- ✅ **${browser}**: [View Report](${url})" + else + comment="$comment +- ❌ **${browser}**: Deployment failed" + fi + i=$((i + 1)) + done + + comment="$comment + +--- +🎉 Click on the links above to view detailed test results for each browser configuration." + + post_comment "$comment" +fi \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 1a4068a27..5e183c430 100644 --- a/src/App.vue +++ b/src/App.vue @@ -15,10 +15,10 @@ import ProgressSpinner from 'primevue/progressspinner' import { computed, onMounted } from 'vue' import GlobalDialog from '@/components/dialog/GlobalDialog.vue' -import { useConflictDetection } from '@/composables/useConflictDetection' import config from '@/config' import { useWorkspaceStore } from '@/stores/workspaceStore' +import { useConflictDetection } from './composables/useConflictDetection' import { electronAPI, isElectron } from './utils/envUtil' const workspaceStore = useWorkspaceStore() diff --git a/src/assets/css/style.css b/src/assets/css/style.css index dcf8e55fe..3258cbba5 100644 --- a/src/assets/css/style.css +++ b/src/assets/css/style.css @@ -29,7 +29,7 @@ --content-fg: #000; --content-hover-bg: #adadad; --content-hover-fg: #000; - + /* Code styling colors for help menu*/ --code-text-color: rgba(0, 122, 255, 1); --code-bg-color: rgba(96, 165, 250, 0.2); @@ -47,6 +47,91 @@ } } +@theme { + --text-xxs: 0.625rem; + --text-xxs--line-height: calc(1 / 0.625); + + /* Palette Colors */ + --color-charcoal-100: #171718; + --color-charcoal-200: #202121; + --color-charcoal-300: #262729; + --color-charcoal-400: #2d2e32; + --color-charcoal-500: #313235; + --color-charcoal-600: #3c3d42; + --color-charcoal-700: #494a50; + --color-charcoal-800: #55565e; + + --color-stone-100: #444444; + --color-stone-200: #828282; + --color-stone-300: #bbbbbb; + + --color-ivory-100: #fdfbfa; + --color-ivory-200: #faf9f5; + --color-ivory-300: #f0eee6; + + --color-gray-100: #f3f3f3; + --color-gray-200: #e9e9e9; + --color-gray-300: #e1e1e1; + --color-gray-400: #d9d9d9; + --color-gray-500: #c5c5c5; + --color-gray-600: #b4b4b4; + --color-gray-700: #a0a0a0; + --color-gray-800: #8a8a8a; + + --color-sand-100: #e1ded5; + --color-sand-200: #d6cfc2; + --color-sand-300: #888682; + + --color-slate-100: #9c9eab; + --color-slate-200: #9fa2bd; + --color-slate-300: #5b5e7d; + + --color-brand-yellow: #f0ff41; + --color-brand-blue: #172dd7; + + --color-blue-100: #0b8ce9; + --color-blue-200: #31b9f4; + --color-success-100: #00cd72; + --color-success-200: #47e469; + --color-warning-100: #fd9903; + --color-warning-200: #fcbf64; + --color-danger-100: #c02323; + --color-danger-200: #d62952; + + --color-error: #962a2a; + + --color-blue-selection: rgb( from var(--color-blue-100) r g b / 0.3); + --color-node-hover-100: rgb( from var(--color-charcoal-800) r g b/ 0.15); + --color-node-hover-200: rgb(from var(--color-charcoal-800) r g b/ 0.1); + --color-modal-tag: rgb(from var(--color-gray-400) r g b/ 0.4); + + /* PrimeVue pulled colors */ + --color-muted: var(--p-text-muted-color); + --color-highlight: var(--p-primary-color); + + /* Special Colors (temporary) */ + --color-dark-elevation-1.5: rgba(from white r g b/ 0.015); + --color-dark-elevation-2: rgba(from white r g b / 0.03); +} + +@custom-variant dark-theme { + .dark-theme & { + @slot; + } +} + +@utility scrollbar-hide { + scrollbar-width: none; + &::-webkit-scrollbar { + width: 1px; + } + &::-webkit-scrollbar-thumb { + background-color: transparent; + } +} + +/* Everthing below here to be cleaned up over time. */ + body { width: 100vw; height: 100vh; @@ -136,6 +221,188 @@ body { border: thin solid; } +/* Shared markdown content styling for consistent rendering across components */ +.comfy-markdown-content { + /* Typography */ + font-size: 0.875rem; /* text-sm */ + line-height: 1.6; + word-wrap: break-word; +} + +/* Headings */ +.comfy-markdown-content h1 { + font-size: 22px; /* text-[22px] */ + font-weight: 700; /* font-bold */ + margin-top: 2rem; /* mt-8 */ + margin-bottom: 1rem; /* mb-4 */ +} + +.comfy-markdown-content h1:first-child { + margin-top: 0; /* first:mt-0 */ +} + +.comfy-markdown-content h2 { + font-size: 18px; /* text-[18px] */ + font-weight: 700; /* font-bold */ + margin-top: 2rem; /* mt-8 */ + margin-bottom: 1rem; /* mb-4 */ +} + +.comfy-markdown-content h2:first-child { + margin-top: 0; /* first:mt-0 */ +} + +.comfy-markdown-content h3 { + font-size: 16px; /* text-[16px] */ + font-weight: 700; /* font-bold */ + margin-top: 2rem; /* mt-8 */ + margin-bottom: 1rem; /* mb-4 */ +} + +.comfy-markdown-content h3:first-child { + margin-top: 0; /* first:mt-0 */ +} + +.comfy-markdown-content h4, +.comfy-markdown-content h5, +.comfy-markdown-content h6 { + margin-top: 2rem; /* mt-8 */ + margin-bottom: 1rem; /* mb-4 */ +} + +.comfy-markdown-content h4:first-child, +.comfy-markdown-content h5:first-child, +.comfy-markdown-content h6:first-child { + margin-top: 0; /* first:mt-0 */ +} + +/* Paragraphs */ +.comfy-markdown-content p { + margin: 0 0 0.5em; +} + +.comfy-markdown-content p:last-child { + margin-bottom: 0; +} + +/* First child reset */ +.comfy-markdown-content *:first-child { + margin-top: 0; /* mt-0 */ +} + +/* Lists */ +.comfy-markdown-content ul, +.comfy-markdown-content ol { + padding-left: 2rem; /* pl-8 */ + margin: 0.5rem 0; /* my-2 */ +} + +/* Nested lists */ +.comfy-markdown-content ul ul, +.comfy-markdown-content ol ol, +.comfy-markdown-content ul ol, +.comfy-markdown-content ol ul { + padding-left: 1.5rem; /* pl-6 */ + margin: 0.5rem 0; /* my-2 */ +} + +.comfy-markdown-content li { + margin: 0.5rem 0; /* my-2 */ +} + +/* Code */ +.comfy-markdown-content code { + color: var(--code-text-color); + background-color: var(--code-bg-color); + border-radius: 0.25rem; /* rounded */ + padding: 0.125rem 0.375rem; /* px-1.5 py-0.5 */ + font-family: monospace; +} + +.comfy-markdown-content pre { + background-color: var(--code-block-bg-color); + border-radius: 0.25rem; /* rounded */ + padding: 1rem; /* p-4 */ + margin: 1rem 0; /* my-4 */ + overflow-x: auto; /* overflow-x-auto */ +} + +.comfy-markdown-content pre code { + background-color: transparent; /* bg-transparent */ + padding: 0; /* p-0 */ + color: var(--p-text-color); +} + +/* Tables */ +.comfy-markdown-content table { + width: 100%; /* w-full */ + border-collapse: collapse; /* border-collapse */ +} + +.comfy-markdown-content th, +.comfy-markdown-content td { + padding: 0.5rem; /* px-2 py-2 */ +} + +.comfy-markdown-content th { + color: var(--fg-color); +} + +.comfy-markdown-content td { + color: var(--drag-text); +} + +.comfy-markdown-content tr { + border-bottom: 1px solid var(--content-bg); +} + +.comfy-markdown-content tr:last-child { + border-bottom: none; +} + +.comfy-markdown-content thead { + border-bottom: 1px solid var(--p-text-color); +} + +/* Links */ +.comfy-markdown-content a { + color: var(--drag-text); + text-decoration: underline; +} + +/* Media */ +.comfy-markdown-content img, +.comfy-markdown-content video { + max-width: 100%; /* max-w-full */ + height: auto; /* h-auto */ + display: block; /* block */ + margin-bottom: 1rem; /* mb-4 */ +} + +/* Blockquotes */ +.comfy-markdown-content blockquote { + border-left: 3px solid var(--p-primary-color, var(--primary-bg)); + padding-left: 0.75em; + margin: 0.5em 0; + opacity: 0.8; +} + +/* Horizontal rule */ +.comfy-markdown-content hr { + border: none; + border-top: 1px solid var(--p-border-color, var(--border-color)); + margin: 1em 0; +} + +/* Strong and emphasis */ +.comfy-markdown-content strong { + font-weight: bold; +} + +.comfy-markdown-content em { + font-style: italic; +} + .comfy-modal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ @@ -607,7 +874,7 @@ audio.comfy-audio.empty-audio-widget { .comfy-load-3d, .comfy-load-3d-animation, .comfy-preview-3d, -.comfy-preview-3d-animation{ +.comfy-preview-3d-animation { display: flex; flex-direction: column; background: transparent; @@ -620,7 +887,7 @@ audio.comfy-audio.empty-audio-widget { .comfy-load-3d-animation canvas, .comfy-preview-3d canvas, .comfy-preview-3d-animation canvas, -.comfy-load-3d-viewer canvas{ +.comfy-load-3d-viewer canvas { display: flex; width: 100% !important; height: 100% !important; @@ -641,3 +908,93 @@ audio.comfy-audio.empty-audio-widget { width: calc(100vw - env(titlebar-area-width, 100vw)); } /* End of [Desktop] Electron window specific styles */ + +/* Vue Node LOD (Level of Detail) System */ +/* These classes control rendering detail based on zoom level */ + +/* Minimal LOD (zoom <= 0.4) - Title only for performance */ +.lg-node--lod-minimal { + min-height: 32px; + transition: min-height 0.2s ease; + /* Performance optimizations */ + text-shadow: none; + backdrop-filter: none; +} + +.lg-node--lod-minimal .lg-node-body { + display: none !important; +} + +/* Reduced LOD (0.4 < zoom <= 0.8) - Essential widgets, simplified styling */ +.lg-node--lod-reduced { + transition: opacity 0.1s ease; + /* Performance optimizations */ + text-shadow: none; +} + +.lg-node--lod-reduced .lg-widget-label, +.lg-node--lod-reduced .lg-slot-label { + display: none; +} + +.lg-node--lod-reduced .lg-slot { + opacity: 0.6; + font-size: 0.75rem; +} + +.lg-node--lod-reduced .lg-widget { + margin: 2px 0; + font-size: 0.875rem; +} + +/* Full LOD (zoom > 0.8) - Complete detail rendering */ +.lg-node--lod-full { + /* Uses default styling - no overrides needed */ +} + +/* Smooth transitions between LOD levels */ +.lg-node { + transition: min-height 0.2s ease; + /* Disable text selection on all nodes */ + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; +} + +.lg-node .lg-slot, +.lg-node .lg-widget { + transition: + opacity 0.1s ease, + font-size 0.1s ease; +} + +/* Performance optimization during canvas interaction */ +.transform-pane--interacting .lg-node * { + transition: none !important; +} + +.transform-pane--interacting .lg-node { + will-change: transform; +} + +/* Global performance optimizations for LOD */ +.lg-node--lod-minimal, +.lg-node--lod-reduced { + /* Remove ALL expensive paint effects */ + box-shadow: none !important; + filter: none !important; + backdrop-filter: none !important; + text-shadow: none !important; + -webkit-mask-image: none !important; + mask-image: none !important; + clip-path: none !important; +} + +/* Reduce paint complexity for minimal LOD */ +.lg-node--lod-minimal { + /* Skip complex borders */ + border-radius: 0 !important; + /* Use solid colors only */ + background-image: none !important; +} diff --git a/src/components/breadcrumb/SubgraphBreadcrumb.vue b/src/components/breadcrumb/SubgraphBreadcrumb.vue index af6324aa9..e710f6c82 100644 --- a/src/components/breadcrumb/SubgraphBreadcrumb.vue +++ b/src/components/breadcrumb/SubgraphBreadcrumb.vue @@ -40,6 +40,7 @@ import SubgraphBreadcrumbItem from '@/components/breadcrumb/SubgraphBreadcrumbIt import { useOverflowObserver } from '@/composables/element/useOverflowObserver' import { useCanvasStore } from '@/stores/graphStore' import { useSubgraphNavigationStore } from '@/stores/subgraphNavigationStore' +import { useSubgraphStore } from '@/stores/subgraphStore' import { useWorkflowStore } from '@/stores/workflowStore' import { forEachSubgraphNode } from '@/utils/graphTraversalUtil' @@ -52,6 +53,9 @@ const workflowStore = useWorkflowStore() const navigationStore = useSubgraphNavigationStore() const breadcrumbRef = ref>() const workflowName = computed(() => workflowStore.activeWorkflow?.filename) +const isBlueprint = computed(() => + useSubgraphStore().isSubgraphBlueprint(workflowStore.activeWorkflow) +) const collapseTabs = ref(false) const overflowingTabs = ref(false) @@ -89,6 +93,7 @@ const home = computed(() => ({ label: workflowName.value, icon: 'pi pi-home', key: 'root', + isBlueprint: isBlueprint.value, command: () => { const canvas = useCanvasStore().getCanvas() if (!canvas.graph) throw new TypeError('Canvas has no graph') diff --git a/src/components/breadcrumb/SubgraphBreadcrumbItem.vue b/src/components/breadcrumb/SubgraphBreadcrumbItem.vue index b980c0e2d..eb688dff6 100644 --- a/src/components/breadcrumb/SubgraphBreadcrumbItem.vue +++ b/src/components/breadcrumb/SubgraphBreadcrumbItem.vue @@ -16,6 +16,7 @@ @click="handleClick" > {{ item.label }} + (() => { command: async () => { await workflowService.duplicateWorkflow(workflowStore.activeWorkflow!) }, - visible: isRoot + visible: isRoot && !props.item.isBlueprint }, { separator: true, @@ -153,12 +155,26 @@ const menuItems = computed(() => { await useCommandStore().execute('Comfy.ClearWorkflow') } }, + { + separator: true, + visible: props.item.key === 'root' && props.item.isBlueprint + }, + { + label: t('subgraphStore.publish'), + icon: 'pi pi-copy', + command: async () => { + await workflowService.saveWorkflowAs(workflowStore.activeWorkflow!) + }, + visible: props.item.key === 'root' && props.item.isBlueprint + }, { separator: true, visible: isRoot }, { - label: t('breadcrumbsMenu.deleteWorkflow'), + label: props.item.isBlueprint + ? t('breadcrumbsMenu.deleteBlueprint') + : t('breadcrumbsMenu.deleteWorkflow'), icon: 'pi pi-times', command: async () => { await workflowService.deleteWorkflow(workflowStore.activeWorkflow!) diff --git a/src/components/button/IconButton.stories.ts b/src/components/button/IconButton.stories.ts index 7caf298e9..d774c0e5b 100644 --- a/src/components/button/IconButton.stories.ts +++ b/src/components/button/IconButton.stories.ts @@ -1,5 +1,4 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite' -import { Bell, Download, Heart, Settings, Trophy, X } from 'lucide-vue-next' import IconButton from './IconButton.vue' @@ -33,13 +32,13 @@ type Story = StoryObj export const Primary: Story = { render: (args) => ({ - components: { IconButton, Trophy }, + components: { IconButton }, setup() { return { args } }, template: ` - + ` }), @@ -51,13 +50,13 @@ export const Primary: Story = { export const Secondary: Story = { render: (args) => ({ - components: { IconButton, Settings }, + components: { IconButton }, setup() { return { args } }, template: ` - + ` }), @@ -69,13 +68,13 @@ export const Secondary: Story = { export const Transparent: Story = { render: (args) => ({ - components: { IconButton, X }, + components: { IconButton }, setup() { return { args } }, template: ` - + ` }), @@ -87,13 +86,13 @@ export const Transparent: Story = { export const Small: Story = { render: (args) => ({ - components: { IconButton, Bell }, + components: { IconButton }, setup() { return { args } }, template: ` - + ` }), @@ -105,42 +104,42 @@ export const Small: Story = { export const AllVariants: Story = { render: () => ({ - components: { IconButton, Trophy, Settings, X, Bell, Heart, Download }, + components: { IconButton }, template: `
- + - +
- + - +
- + - +
- + - + - +
diff --git a/src/components/button/IconButton.vue b/src/components/button/IconButton.vue index 1f5b24bac..1038a82e4 100644 --- a/src/components/button/IconButton.vue +++ b/src/components/button/IconButton.vue @@ -1,5 +1,11 @@ @@ -20,6 +26,10 @@ interface IconButtonProps extends BaseButtonProps { onClick: (event: Event) => void } +defineOptions({ + inheritAttrs: false +}) + const { size = 'md', type = 'secondary', diff --git a/src/components/button/IconGroup.stories.ts b/src/components/button/IconGroup.stories.ts index 1eb0d6e0a..c2fa1b96d 100644 --- a/src/components/button/IconGroup.stories.ts +++ b/src/components/button/IconGroup.stories.ts @@ -1,5 +1,4 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite' -import { Download, ExternalLink, Heart } from 'lucide-vue-next' import IconButton from './IconButton.vue' import IconGroup from './IconGroup.vue' @@ -17,17 +16,17 @@ type Story = StoryObj export const Basic: Story = { render: () => ({ - components: { IconGroup, IconButton, Download, ExternalLink, Heart }, + components: { IconGroup, IconButton }, template: ` - + - + - + ` diff --git a/src/components/button/IconTextButton.stories.ts b/src/components/button/IconTextButton.stories.ts index da07d9a66..0139b9bd6 100644 --- a/src/components/button/IconTextButton.stories.ts +++ b/src/components/button/IconTextButton.stories.ts @@ -1,14 +1,4 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite' -import { - ChevronLeft, - ChevronRight, - Download, - Package, - Save, - Settings, - Trash2, - X -} from 'lucide-vue-next' import IconTextButton from './IconTextButton.vue' @@ -49,14 +39,14 @@ type Story = StoryObj export const Primary: Story = { render: (args) => ({ - components: { IconTextButton, Package }, + components: { IconTextButton }, setup() { return { args } }, template: ` ` @@ -70,14 +60,14 @@ export const Primary: Story = { export const Secondary: Story = { render: (args) => ({ - components: { IconTextButton, Settings }, + components: { IconTextButton }, setup() { return { args } }, template: ` ` @@ -91,14 +81,14 @@ export const Secondary: Story = { export const Transparent: Story = { render: (args) => ({ - components: { IconTextButton, X }, + components: { IconTextButton }, setup() { return { args } }, template: ` ` @@ -112,14 +102,14 @@ export const Transparent: Story = { export const WithIconRight: Story = { render: (args) => ({ - components: { IconTextButton, ChevronRight }, + components: { IconTextButton }, setup() { return { args } }, template: ` ` @@ -134,14 +124,14 @@ export const WithIconRight: Story = { export const Small: Story = { render: (args) => ({ - components: { IconTextButton, Save }, + components: { IconTextButton }, setup() { return { args } }, template: ` ` @@ -156,66 +146,60 @@ export const Small: Story = { export const AllVariants: Story = { render: () => ({ components: { - IconTextButton, - Download, - Settings, - Trash2, - ChevronRight, - ChevronLeft, - Save + IconTextButton }, template: `
diff --git a/src/components/button/IconTextButton.vue b/src/components/button/IconTextButton.vue index 656761757..bdf40d4ed 100644 --- a/src/components/button/IconTextButton.vue +++ b/src/components/button/IconTextButton.vue @@ -1,5 +1,11 @@ diff --git a/src/components/button/TextButton.vue b/src/components/button/TextButton.vue index a183ea788..14d32cc73 100644 --- a/src/components/button/TextButton.vue +++ b/src/components/button/TextButton.vue @@ -1,5 +1,11 @@ @@ -21,6 +27,10 @@ interface TextButtonProps extends BaseButtonProps { onClick: () => void } +defineOptions({ + inheritAttrs: false +}) + const { size = 'md', type = 'primary', diff --git a/src/components/card/Card.stories.ts b/src/components/card/Card.stories.ts index 0d8bf4385..923327a79 100644 --- a/src/components/card/Card.stories.ts +++ b/src/components/card/Card.stories.ts @@ -1,13 +1,4 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite' -import { - Download, - Folder, - Heart, - Info, - MoreVertical, - Star, - Upload -} from 'lucide-vue-next' import { ref } from 'vue' import IconButton from '../button/IconButton.vue' @@ -149,14 +140,7 @@ const createCardTemplate = (args: CardStoryArgs) => ({ CardTitle, CardDescription, IconButton, - SquareChip, - Info, - Folder, - Heart, - Download, - Star, - Upload, - MoreVertical + SquareChip }, setup() { const favorited = ref(false) @@ -202,14 +186,14 @@ const createCardTemplate = (args: CardStoryArgs) => ({ class="!bg-white/90 !text-neutral-900" @click="() => console.log('Info clicked')" > - + - + @@ -222,7 +206,7 @@ const createCardTemplate = (args: CardStoryArgs) => ({ @@ -409,11 +393,7 @@ export const GridOfCards: Story = { CardTitle, CardDescription, IconButton, - SquareChip, - Info, - Folder, - Heart, - Download + SquareChip }, setup() { const cards = ref([ @@ -500,7 +480,7 @@ export const GridOfCards: Story = { class="!bg-white/90 !text-neutral-900" @click="() => console.log('Info:', card.title)" > - + @@ -511,7 +491,7 @@ export const GridOfCards: Story = { :label="tag" > diff --git a/src/components/common/EditableText.spec.ts b/src/components/common/EditableText.spec.ts index 2e7b036b5..2d31123b9 100644 --- a/src/components/common/EditableText.spec.ts +++ b/src/components/common/EditableText.spec.ts @@ -68,4 +68,73 @@ describe('EditableText', () => { // @ts-expect-error fixme ts strict error expect(wrapper.emitted('edit')[0]).toEqual(['Test Text']) }) + + it('cancels editing on escape key', async () => { + const wrapper = mountComponent({ + modelValue: 'Original Text', + isEditing: true + }) + + // Change the input value + await wrapper.findComponent(InputText).setValue('Modified Text') + + // Press escape + await wrapper.findComponent(InputText).trigger('keyup.escape') + + // Should emit cancel event + expect(wrapper.emitted('cancel')).toBeTruthy() + + // Should NOT emit edit event + expect(wrapper.emitted('edit')).toBeFalsy() + + // Input value should be reset to original + expect(wrapper.findComponent(InputText).props()['modelValue']).toBe( + 'Original Text' + ) + }) + + it('does not save changes when escape is pressed and blur occurs', async () => { + const wrapper = mountComponent({ + modelValue: 'Original Text', + isEditing: true + }) + + // Change the input value + await wrapper.findComponent(InputText).setValue('Modified Text') + + // Press escape (which triggers blur internally) + await wrapper.findComponent(InputText).trigger('keyup.escape') + + // Manually trigger blur to simulate the blur that happens after escape + await wrapper.findComponent(InputText).trigger('blur') + + // Should emit cancel but not edit + expect(wrapper.emitted('cancel')).toBeTruthy() + expect(wrapper.emitted('edit')).toBeFalsy() + }) + + it('saves changes on enter but not on escape', async () => { + // Test Enter key saves changes + const enterWrapper = mountComponent({ + modelValue: 'Original Text', + isEditing: true + }) + await enterWrapper.findComponent(InputText).setValue('Saved Text') + await enterWrapper.findComponent(InputText).trigger('keyup.enter') + // Trigger blur that happens after enter + await enterWrapper.findComponent(InputText).trigger('blur') + expect(enterWrapper.emitted('edit')).toBeTruthy() + // @ts-expect-error fixme ts strict error + expect(enterWrapper.emitted('edit')[0]).toEqual(['Saved Text']) + + // Test Escape key cancels changes with a fresh wrapper + const escapeWrapper = mountComponent({ + modelValue: 'Original Text', + isEditing: true + }) + await escapeWrapper.findComponent(InputText).setValue('Cancelled Text') + await escapeWrapper.findComponent(InputText).trigger('keyup.escape') + expect(escapeWrapper.emitted('cancel')).toBeTruthy() + expect(escapeWrapper.emitted('edit')).toBeFalsy() + }) }) diff --git a/src/components/common/EditableText.vue b/src/components/common/EditableText.vue index 16510d3fd..c6fa18a8d 100644 --- a/src/components/common/EditableText.vue +++ b/src/components/common/EditableText.vue @@ -14,10 +14,12 @@ fluid :pt="{ root: { - onBlur: finishEditing + onBlur: finishEditing, + ...inputAttrs } }" @keyup.enter="blurInputElement" + @keyup.escape="cancelEditing" @click.stop />
@@ -27,21 +29,41 @@ import InputText from 'primevue/inputtext' import { nextTick, ref, watch } from 'vue' -const { modelValue, isEditing = false } = defineProps<{ +const { + modelValue, + isEditing = false, + inputAttrs = {} +} = defineProps<{ modelValue: string isEditing?: boolean + inputAttrs?: Record }>() -const emit = defineEmits(['update:modelValue', 'edit']) +const emit = defineEmits(['update:modelValue', 'edit', 'cancel']) const inputValue = ref(modelValue) const inputRef = ref | undefined>() +const isCanceling = ref(false) const blurInputElement = () => { // @ts-expect-error - $el is an internal property of the InputText component inputRef.value?.$el.blur() } const finishEditing = () => { - emit('edit', inputValue.value) + // Don't save if we're canceling + if (!isCanceling.value) { + emit('edit', inputValue.value) + } + isCanceling.value = false +} +const cancelEditing = () => { + // Set canceling flag to prevent blur from saving + isCanceling.value = true + // Reset to original value + inputValue.value = modelValue + // Emit cancel event + emit('cancel') + // Blur the input to exit edit mode + blurInputElement() } watch( () => isEditing, diff --git a/src/components/common/FormImageUpload.vue b/src/components/common/FormImageUpload.vue index 1515289cc..efb09c900 100644 --- a/src/components/common/FormImageUpload.vue +++ b/src/components/common/FormImageUpload.vue @@ -3,7 +3,7 @@
+
+ + +
+ + + + diff --git a/src/components/helpcenter/HelpCenterMenuContent.vue b/src/components/helpcenter/HelpCenterMenuContent.vue index 852b1b593..c91589407 100644 --- a/src/components/helpcenter/HelpCenterMenuContent.vue +++ b/src/components/helpcenter/HelpCenterMenuContent.vue @@ -142,11 +142,12 @@ import { useI18n } from 'vue-i18n' import PuzzleIcon from '@/components/icons/PuzzleIcon.vue' import { useConflictAcknowledgment } from '@/composables/useConflictAcknowledgment' -import { useDialogService } from '@/services/dialogService' +import { useManagerState } from '@/composables/useManagerState' import { type ReleaseNote } from '@/services/releaseService' import { useCommandStore } from '@/stores/commandStore' import { useReleaseStore } from '@/stores/releaseStore' import { useSettingStore } from '@/stores/settingStore' +import { ManagerTab } from '@/types/comfyManagerTypes' import { electronAPI, isElectron } from '@/utils/envUtil' import { formatVersionAnchor } from '@/utils/formatUtil' @@ -191,7 +192,6 @@ const { t, locale } = useI18n() const releaseStore = useReleaseStore() const commandStore = useCommandStore() const settingStore = useSettingStore() -const dialogService = useDialogService() // Emits const emit = defineEmits<{ @@ -313,8 +313,11 @@ const menuItems = computed(() => { icon: PuzzleIcon, label: t('helpCenter.managerExtension'), showRedDot: shouldShowManagerRedDot.value, - action: () => { - dialogService.showManagerDialog() + action: async () => { + await useManagerState().openManager({ + initialTab: ManagerTab.All, + showToastOnLegacyError: false + }) emit('close') } }, diff --git a/src/components/input/SingleSelect.stories.ts b/src/components/input/SingleSelect.stories.ts index c0a279822..a529a2fe1 100644 --- a/src/components/input/SingleSelect.stories.ts +++ b/src/components/input/SingleSelect.stories.ts @@ -1,5 +1,4 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite' -import { ArrowUpDown } from 'lucide-vue-next' import { ref } from 'vue' import SingleSelect from './SingleSelect.vue' @@ -57,7 +56,7 @@ export const Default: Story = { export const WithIcon: Story = { render: () => ({ - components: { SingleSelect, ArrowUpDown }, + components: { SingleSelect }, setup() { const selected = ref('popular') const options = sampleOptions @@ -67,7 +66,7 @@ export const WithIcon: Story = {
@@ -94,7 +93,7 @@ export const Preselected: Story = { export const AllVariants: Story = { render: () => ({ - components: { SingleSelect, ArrowUpDown }, + components: { SingleSelect }, setup() { const options = sampleOptions const a = ref(null) @@ -110,7 +109,7 @@ export const AllVariants: Story = {
diff --git a/src/components/sidebar/tabs/nodeLibrary/NodeTreeLeaf.vue b/src/components/sidebar/tabs/nodeLibrary/NodeTreeLeaf.vue index 1f1d782f3..2dc099c41 100644 --- a/src/components/sidebar/tabs/nodeLibrary/NodeTreeLeaf.vue +++ b/src/components/sidebar/tabs/nodeLibrary/NodeTreeLeaf.vue @@ -1,6 +1,6 @@