From edc95141f7f90a048d68db58d19f0b8836350999 Mon Sep 17 00:00:00 2001 From: Rohit Malhotra Date: Thu, 28 Aug 2025 23:38:42 -0400 Subject: [PATCH] Implement branch pagination for repository selection and improve UI async dropdown behaviour (#10588) Co-authored-by: openhands Co-authored-by: amanape <83104063+amanape@users.noreply.github.com> --- .../features/home/repo-connector.test.tsx | 79 +- .../home/repo-selection-form.test.tsx | 18 +- .../microagent-management.test.tsx | 26 +- .../__tests__/routes/home-screen.test.tsx | 31 +- frontend/package-lock.json | 1939 ++++++++++------- frontend/package.json | 2 +- frontend/src/api/open-hands.ts | 37 +- .../components/common/git-branch-dropdown.tsx | 69 - .../common/git-provider-dropdown.tsx | 65 - .../common/git-repository-dropdown.tsx | 208 -- .../common/react-select-async-dropdown.tsx | 79 - .../common/react-select-dropdown.tsx | 62 - .../components/common/react-select-styles.ts | 115 - .../branch-dropdown-menu.tsx | 86 + .../git-branch-dropdown.tsx | 236 ++ .../home/git-branch-dropdown/index.ts | 3 + .../git-provider-dropdown.tsx | 193 ++ .../home/git-provider-dropdown/index.ts | 2 + .../home/git-repo-dropdown/dropdown-menu.tsx | 79 + .../git-repo-dropdown/git-repo-dropdown.tsx | 243 +++ .../features/home/git-repo-dropdown/index.tsx | 10 + .../git-repo-dropdown/use-repository-data.tsx | 89 + .../home/git-repo-dropdown/use-url-search.tsx | 41 + .../features/home/repo-selection-form.tsx | 70 +- .../features/home/shared/clear-button.tsx | 45 + .../features/home/shared/dropdown-item.tsx | 44 + .../features/home/shared/empty-state.tsx | 24 + .../features/home/shared/error-message.tsx | 21 + .../home/shared/generic-dropdown-menu.tsx | 74 + .../components/features/home/shared/index.ts | 7 + .../features/home/shared/loading-spinner.tsx | 26 + .../features/home/shared/toggle-button.tsx | 45 + .../microagent-management-sidebar.tsx | 5 +- frontend/src/hooks/query/use-branch-data.ts | 126 ++ .../hooks/query/use-repository-branches.ts | 38 +- .../src/hooks/query/use-search-branches.ts | 35 + frontend/src/mocks/git-repository-handlers.ts | 170 +- frontend/src/types/git.d.ts | 9 + frontend/vitest.setup.ts | 1 + .../bitbucket/bitbucket_service.py | 78 + .../integrations/github/github_service.py | 106 + openhands/integrations/github/queries.py | 29 + .../integrations/gitlab/gitlab_service.py | 64 + openhands/integrations/provider.py | 73 +- openhands/integrations/service_types.py | 18 + openhands/server/routes/git.py | 60 +- .../bitbucket/test_bitbucket_branches.py | 84 + .../github/test_github_branches.py | 168 ++ .../gitlab/test_gitlab_branches.py | 119 + 49 files changed, 3661 insertions(+), 1590 deletions(-) delete mode 100644 frontend/src/components/common/git-branch-dropdown.tsx delete mode 100644 frontend/src/components/common/git-provider-dropdown.tsx delete mode 100644 frontend/src/components/common/git-repository-dropdown.tsx delete mode 100644 frontend/src/components/common/react-select-async-dropdown.tsx delete mode 100644 frontend/src/components/common/react-select-dropdown.tsx delete mode 100644 frontend/src/components/common/react-select-styles.ts create mode 100644 frontend/src/components/features/home/git-branch-dropdown/branch-dropdown-menu.tsx create mode 100644 frontend/src/components/features/home/git-branch-dropdown/git-branch-dropdown.tsx create mode 100644 frontend/src/components/features/home/git-branch-dropdown/index.ts create mode 100644 frontend/src/components/features/home/git-provider-dropdown/git-provider-dropdown.tsx create mode 100644 frontend/src/components/features/home/git-provider-dropdown/index.ts create mode 100644 frontend/src/components/features/home/git-repo-dropdown/dropdown-menu.tsx create mode 100644 frontend/src/components/features/home/git-repo-dropdown/git-repo-dropdown.tsx create mode 100644 frontend/src/components/features/home/git-repo-dropdown/index.tsx create mode 100644 frontend/src/components/features/home/git-repo-dropdown/use-repository-data.tsx create mode 100644 frontend/src/components/features/home/git-repo-dropdown/use-url-search.tsx create mode 100644 frontend/src/components/features/home/shared/clear-button.tsx create mode 100644 frontend/src/components/features/home/shared/dropdown-item.tsx create mode 100644 frontend/src/components/features/home/shared/empty-state.tsx create mode 100644 frontend/src/components/features/home/shared/error-message.tsx create mode 100644 frontend/src/components/features/home/shared/generic-dropdown-menu.tsx create mode 100644 frontend/src/components/features/home/shared/index.ts create mode 100644 frontend/src/components/features/home/shared/loading-spinner.tsx create mode 100644 frontend/src/components/features/home/shared/toggle-button.tsx create mode 100644 frontend/src/hooks/query/use-branch-data.ts create mode 100644 frontend/src/hooks/query/use-search-branches.ts create mode 100644 tests/unit/integrations/bitbucket/test_bitbucket_branches.py create mode 100644 tests/unit/integrations/github/test_github_branches.py create mode 100644 tests/unit/integrations/gitlab/test_gitlab_branches.py diff --git a/frontend/__tests__/components/features/home/repo-connector.test.tsx b/frontend/__tests__/components/features/home/repo-connector.test.tsx index 428911006d..25604416f8 100644 --- a/frontend/__tests__/components/features/home/repo-connector.test.tsx +++ b/frontend/__tests__/components/features/home/repo-connector.test.tsx @@ -54,12 +54,14 @@ const MOCK_RESPOSITORIES: GitRepository[] = [ full_name: "rbren/polaris", git_provider: "github", is_public: true, + main_branch: "main", }, { id: "2", full_name: "All-Hands-AI/OpenHands", git_provider: "github", is_public: true, + main_branch: "main", }, ]; @@ -99,16 +101,15 @@ describe("RepoConnector", () => { // First select the provider const providerDropdown = await waitFor(() => - screen.getByText("Select Provider"), + screen.getByTestId("git-provider-dropdown"), ); await userEvent.click(providerDropdown); - await userEvent.click(screen.getByText("Github")); + await userEvent.click(screen.getByText("GitHub")); // Then interact with the repository dropdown - const repoDropdown = await waitFor(() => - screen.getByTestId("repo-dropdown"), + const repoInput = await waitFor(() => + screen.getByTestId("git-repo-dropdown"), ); - const repoInput = within(repoDropdown).getByRole("combobox"); await userEvent.click(repoInput); // Wait for the options to be loaded and displayed @@ -134,23 +135,23 @@ describe("RepoConnector", () => { expect(launchButton).toBeDisabled(); // Mock the repository branches API call - vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue([ + vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue({ branches: [ { name: "main", commit_sha: "123", protected: false }, { name: "develop", commit_sha: "456", protected: false }, - ]); + ], has_next_page: false, current_page: 1, per_page: 30, total_count: 2 }); // First select the provider const providerDropdown = await waitFor(() => - screen.getByText("Select Provider"), + screen.getByTestId("git-provider-dropdown"), ); await userEvent.click(providerDropdown); - await userEvent.click(screen.getByText("Github")); + await userEvent.click(screen.getByText("GitHub")); // Then select the repository - const repoDropdown = await waitFor(() => - screen.getByTestId("repo-dropdown"), + const repoInput = await waitFor(() => + screen.getByTestId("git-repo-dropdown"), ); - const repoInput = within(repoDropdown).getByRole("combobox"); + await userEvent.click(repoInput); // Wait for the options to be loaded and displayed @@ -161,7 +162,8 @@ describe("RepoConnector", () => { // Wait for the branch to be auto-selected await waitFor(() => { - expect(screen.getByText("main")).toBeInTheDocument(); + const branchInput = screen.getByTestId("git-branch-dropdown-input"); + expect(branchInput).toHaveValue("main"); }); expect(launchButton).toBeEnabled(); @@ -224,6 +226,19 @@ describe("RepoConnector", () => { it("should create a conversation and redirect with the selected repo when pressing the launch button", async () => { const createConversationSpy = vi.spyOn(OpenHands, "createConversation"); + createConversationSpy.mockResolvedValue({ + conversation_id: "mock-conversation-id", + title: "Test Conversation", + selected_repository: "user/repo1", + selected_branch: "main", + git_provider: "github", + last_updated_at: "2023-01-01T00:00:00Z", + created_at: "2023-01-01T00:00:00Z", + status: "STARTING", + runtime_status: null, + url: null, + session_api_key: null, + }); const retrieveUserGitRepositoriesSpy = vi.spyOn( OpenHands, "retrieveUserGitRepositories", @@ -244,23 +259,23 @@ describe("RepoConnector", () => { expect(createConversationSpy).not.toHaveBeenCalled(); // Mock the repository branches API call - vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue([ + vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue({ branches: [ { name: "main", commit_sha: "123", protected: false }, { name: "develop", commit_sha: "456", protected: false }, - ]); + ], has_next_page: false, current_page: 1, per_page: 30, total_count: 2 }); // First select the provider const providerDropdown = await waitFor(() => - screen.getByText("Select Provider"), + screen.getByTestId("git-provider-dropdown"), ); await userEvent.click(providerDropdown); - await userEvent.click(screen.getByText("Github")); + await userEvent.click(screen.getByText("GitHub")); // Then select the repository - const repoDropdown = await waitFor(() => - within(repoConnector).getByTestId("repo-dropdown"), + const repoInput = await waitFor(() => + within(repoConnector).getByTestId("git-repo-dropdown"), ); - const repoInput = within(repoDropdown).getByRole("combobox"); + await userEvent.click(repoInput); // Wait for the options to be loaded and displayed @@ -271,7 +286,8 @@ describe("RepoConnector", () => { // Wait for the branch to be auto-selected await waitFor(() => { - expect(screen.getByText("main")).toBeInTheDocument(); + const branchInput = screen.getByTestId("git-branch-dropdown-input"); + expect(branchInput).toHaveValue("main"); }); await userEvent.click(launchButton); @@ -288,6 +304,8 @@ describe("RepoConnector", () => { }); it("should change the launch button text to 'Loading...' when creating a conversation", async () => { + const createConversationSpy = vi.spyOn(OpenHands, "createConversation"); + createConversationSpy.mockImplementation(() => new Promise(() => {})); // Never resolves to keep loading state const retrieveUserGitRepositoriesSpy = vi.spyOn( OpenHands, "retrieveUserGitRepositories", @@ -298,10 +316,10 @@ describe("RepoConnector", () => { }); // Mock the repository branches API call - vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue([ + vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue({ branches: [ { name: "main", commit_sha: "123", protected: false }, { name: "develop", commit_sha: "456", protected: false }, - ]); + ], has_next_page: false, current_page: 1, per_page: 30, total_count: 2 }); renderRepoConnector(); @@ -309,16 +327,16 @@ describe("RepoConnector", () => { // First select the provider const providerDropdown = await waitFor(() => - screen.getByText("Select Provider"), + screen.getByTestId("git-provider-dropdown"), ); await userEvent.click(providerDropdown); - await userEvent.click(screen.getByText("Github")); + await userEvent.click(screen.getByText("GitHub")); // Then select the repository - const repoDropdown = await waitFor(() => - screen.getByTestId("repo-dropdown"), + const repoInput = await waitFor(() => + screen.getByTestId("git-repo-dropdown"), ); - const repoInput = within(repoDropdown).getByRole("combobox"); + await userEvent.click(repoInput); // Wait for the options to be loaded and displayed @@ -329,7 +347,8 @@ describe("RepoConnector", () => { // Wait for the branch to be auto-selected await waitFor(() => { - expect(screen.getByText("main")).toBeInTheDocument(); + const branchInput = screen.getByTestId("git-branch-dropdown-input"); + expect(branchInput).toHaveValue("main"); }); await userEvent.click(launchButton); @@ -358,7 +377,7 @@ describe("RepoConnector", () => { const goToSettingsButton = await screen.findByTestId( "navigate-to-settings-button", ); - const dropdown = screen.queryByTestId("repo-dropdown"); + const dropdown = screen.queryByTestId("git-repo-dropdown"); const launchButton = screen.queryByTestId("repo-launch-button"); const providerLinks = screen.queryAllByText(/add git(hub|lab) repos/i); diff --git a/frontend/__tests__/components/features/home/repo-selection-form.test.tsx b/frontend/__tests__/components/features/home/repo-selection-form.test.tsx index a8c04b8966..e5baa5e823 100644 --- a/frontend/__tests__/components/features/home/repo-selection-form.test.tsx +++ b/frontend/__tests__/components/features/home/repo-selection-form.test.tsx @@ -151,7 +151,7 @@ describe("RepositorySelectionForm", () => { }); renderForm(); - expect(await screen.findByTestId("repo-dropdown")).toBeInTheDocument(); + expect(await screen.findByTestId("git-repo-dropdown")).toBeInTheDocument(); }); it("shows error message when repository fetch fails", async () => { @@ -168,10 +168,10 @@ describe("RepositorySelectionForm", () => { renderForm(); expect( - await screen.findByTestId("repo-dropdown-error"), + await screen.findByTestId("dropdown-error"), ).toBeInTheDocument(); expect( - screen.getByText("HOME$FAILED_TO_LOAD_REPOSITORIES"), + screen.getByText("Failed to load data"), ).toBeInTheDocument(); }); @@ -231,11 +231,7 @@ describe("RepositorySelectionForm", () => { renderForm(); - const dropdown = await screen.findByTestId("repo-dropdown"); - const input = dropdown.querySelector( - 'input[type="text"]', - ) as HTMLInputElement; - expect(input).toBeInTheDocument(); + const input = await screen.findByTestId("git-repo-dropdown"); await userEvent.type(input, "https://github.com/kubernetes/kubernetes"); expect(searchGitReposSpy).toHaveBeenLastCalledWith( @@ -270,11 +266,7 @@ describe("RepositorySelectionForm", () => { renderForm(); - const dropdown = await screen.findByTestId("repo-dropdown"); - const input = dropdown.querySelector( - 'input[type="text"]', - ) as HTMLInputElement; - expect(input).toBeInTheDocument(); + const input = await screen.findByTestId("git-repo-dropdown"); await userEvent.type(input, "https://github.com/kubernetes/kubernetes"); expect(searchGitReposSpy).toHaveBeenLastCalledWith( diff --git a/frontend/__tests__/components/features/microagent-management/microagent-management.test.tsx b/frontend/__tests__/components/features/microagent-management/microagent-management.test.tsx index c463030b1f..84b4f5c0cd 100644 --- a/frontend/__tests__/components/features/microagent-management/microagent-management.test.tsx +++ b/frontend/__tests__/components/features/microagent-management/microagent-management.test.tsx @@ -1272,9 +1272,11 @@ describe("MicroagentManagement", () => { // Add microagent integration tests describe("Add microagent functionality", () => { beforeEach(() => { - vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue([ + vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue(({ branches: [ { name: "main", commit_sha: "abc123", protected: false }, - ]); + ], has_next_page: false, current_page: 1, per_page: 30, total_count: [ + { name: "main", commit_sha: "abc123", protected: false }, + ].length }) ); }); it("should render add microagent button", async () => { @@ -1960,9 +1962,11 @@ describe("MicroagentManagement", () => { }; beforeEach(() => { - vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue([ + vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue(({ branches: [ { name: "main", commit_sha: "abc123", protected: false }, - ]); + ], has_next_page: false, current_page: 1, per_page: 30, total_count: [ + { name: "main", commit_sha: "abc123", protected: false }, + ].length }) ); }); it("should render update microagent modal when updateMicroagentModalVisible is true", async () => { @@ -2522,10 +2526,16 @@ describe("MicroagentManagement", () => { // Mock branch API const branchesSpy = vi .spyOn(OpenHands, "getRepositoryBranches") - .mockResolvedValue([ - { name: "main", commit_sha: "abc123", protected: false }, - { name: "develop", commit_sha: "def456", protected: false }, - ]); + .mockResolvedValue({ + branches: [ + { name: "main", commit_sha: "abc123", protected: false }, + { name: "develop", commit_sha: "def456", protected: false }, + ], + has_next_page: false, + current_page: 1, + per_page: 30, + total_count: 2, + }); // Mock other APIs const getRepositoryMicroagentsSpy = vi.spyOn( diff --git a/frontend/__tests__/routes/home-screen.test.tsx b/frontend/__tests__/routes/home-screen.test.tsx index 5f9515d577..daf8cd725f 100644 --- a/frontend/__tests__/routes/home-screen.test.tsx +++ b/frontend/__tests__/routes/home-screen.test.tsx @@ -37,34 +37,27 @@ const selectRepository = async (repoName: string) => { // First select the provider const providerDropdown = await waitFor(() => - screen.getByText("Select Provider"), + screen.getByTestId("git-provider-dropdown"), ); await userEvent.click(providerDropdown); - await userEvent.click(screen.getByText("Github")); + await userEvent.click(screen.getByText("GitHub")); // Then select the repository - const dropdown = within(repoConnector).getByTestId("repo-dropdown"); - const repoInput = within(dropdown).getByRole("combobox"); + const repoInput = within(repoConnector).getByTestId("git-repo-dropdown"); await userEvent.click(repoInput); // Wait for the options to be loaded and displayed await waitFor(() => { - const options = screen.getAllByText(repoName); - // Find the option in the dropdown (it will have role="option") - const dropdownOption = options.find( - (el) => el.getAttribute("role") === "option", - ); - expect(dropdownOption).toBeInTheDocument(); + const dropdownMenu = screen.getByTestId("git-repo-dropdown-menu"); + expect(within(dropdownMenu).getByText(repoName)).toBeInTheDocument(); }); - const options = screen.getAllByText(repoName); - const dropdownOption = options.find( - (el) => el.getAttribute("role") === "option", - ); - await userEvent.click(dropdownOption!); + const dropdownMenu = screen.getByTestId("git-repo-dropdown-menu"); + await userEvent.click(within(dropdownMenu).getByText(repoName)); // Wait for the branch to be auto-selected await waitFor(() => { - expect(screen.getByText("main")).toBeInTheDocument(); + const branchInput = screen.getByTestId("git-branch-dropdown-input"); + expect(branchInput).toHaveValue("main"); }); }; @@ -85,12 +78,14 @@ const MOCK_RESPOSITORIES: GitRepository[] = [ full_name: "octocat/hello-world", git_provider: "github", is_public: true, + main_branch: "main", }, { id: "2", full_name: "octocat/earth", git_provider: "github", is_public: true, + main_branch: "main", }, ]; @@ -140,10 +135,10 @@ describe("HomeScreen", () => { await screen.findAllByTestId("task-launch-button"); // Mock the repository branches API call - vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue([ + vi.spyOn(OpenHands, "getRepositoryBranches").mockResolvedValue({ branches: [ { name: "main", commit_sha: "123", protected: false }, { name: "develop", commit_sha: "456", protected: false }, - ]); + ], has_next_page: false, current_page: 1, per_page: 30, total_count: 2 }); // Select a repository to enable the repo launch button await selectRepository("octocat/hello-world"); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 0f83ba41ca..13b11935b7 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -28,6 +28,7 @@ "axios": "^1.11.0", "clsx": "^2.1.1", "date-fns": "^4.1.0", + "downshift": "^9.0.10", "eslint-config-airbnb-typescript": "^18.0.0", "framer-motion": "^12.23.12", "i18next": "^25.4.2", @@ -47,7 +48,6 @@ "react-markdown": "^10.1.0", "react-redux": "^9.2.0", "react-router": "^7.8.2", - "react-select": "^5.10.2", "react-syntax-highlighter": "^15.6.6", "react-textarea-autosize": "^8.5.9", "remark-breaks": "^4.0.0", @@ -111,9 +111,9 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.3.tgz", - "integrity": "sha512-VQKMkwriZbaOgVCby1UDY/LDk5fIjhQicCvVPFqfe+69fWaPWydbWJ3wRt59/YzIwda1I81loas3oCoHxnqvdA==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==", "dev": true, "license": "MIT" }, @@ -190,6 +190,7 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -228,6 +229,7 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "license": "MIT", "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", @@ -278,18 +280,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", - "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.27.1", + "@babel/traverse": "^7.28.3", "semver": "^6.3.1" }, "engines": { @@ -349,6 +351,7 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", @@ -446,6 +449,7 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", + "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.2" @@ -458,6 +462,7 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "license": "MIT", "dependencies": { "@babel/types": "^7.28.2" }, @@ -588,9 +593,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", - "integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", + "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -614,6 +619,7 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -708,9 +714,9 @@ } }, "node_modules/@csstools/color-helpers": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", - "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", "dev": true, "funding": [ { @@ -752,9 +758,9 @@ } }, "node_modules/@csstools/css-color-parser": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", - "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", "dev": true, "funding": [ { @@ -768,7 +774,7 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.0.2", + "@csstools/color-helpers": "^5.1.0", "@csstools/css-calc": "^2.1.4" }, "engines": { @@ -822,126 +828,6 @@ "node": ">=18" } }, - "node_modules/@emotion/babel-plugin": { - "version": "11.13.5", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", - "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/serialize": "^1.3.3", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "license": "MIT" - }, - "node_modules/@emotion/cache": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", - "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", - "license": "MIT", - "dependencies": { - "@emotion/memoize": "^0.9.0", - "@emotion/sheet": "^1.4.0", - "@emotion/utils": "^1.4.2", - "@emotion/weak-memoize": "^0.4.0", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/hash": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", - "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", - "license": "MIT" - }, - "node_modules/@emotion/memoize": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", - "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", - "license": "MIT" - }, - "node_modules/@emotion/react": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", - "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.13.5", - "@emotion/cache": "^11.14.0", - "@emotion/serialize": "^1.3.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", - "@emotion/utils": "^1.4.2", - "@emotion/weak-memoize": "^0.4.0", - "hoist-non-react-statics": "^3.3.1" - }, - "peerDependencies": { - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@emotion/serialize": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", - "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", - "license": "MIT", - "dependencies": { - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/unitless": "^0.10.0", - "@emotion/utils": "^1.4.2", - "csstype": "^3.0.2" - } - }, - "node_modules/@emotion/sheet": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", - "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", - "license": "MIT" - }, - "node_modules/@emotion/unitless": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", - "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", - "license": "MIT" - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", - "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", - "license": "MIT", - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@emotion/utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", - "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", - "license": "MIT" - }, - "node_modules/@emotion/weak-memoize": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", - "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", - "license": "MIT" - }, "node_modules/@epic-web/invariant": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", @@ -950,9 +836,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", - "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", "cpu": [ "ppc64" ], @@ -966,9 +852,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", - "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", "cpu": [ "arm" ], @@ -982,9 +868,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", - "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", "cpu": [ "arm64" ], @@ -998,9 +884,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", - "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", "cpu": [ "x64" ], @@ -1014,9 +900,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", - "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", "cpu": [ "arm64" ], @@ -1030,9 +916,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", - "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", "cpu": [ "x64" ], @@ -1046,9 +932,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", - "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", "cpu": [ "arm64" ], @@ -1062,9 +948,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", - "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", "cpu": [ "x64" ], @@ -1078,9 +964,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", - "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", "cpu": [ "arm" ], @@ -1094,9 +980,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", - "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", "cpu": [ "arm64" ], @@ -1110,9 +996,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", - "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", "cpu": [ "ia32" ], @@ -1126,9 +1012,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", - "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", "cpu": [ "loong64" ], @@ -1142,9 +1028,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", - "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", "cpu": [ "mips64el" ], @@ -1158,9 +1044,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", - "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", "cpu": [ "ppc64" ], @@ -1174,9 +1060,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", - "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", "cpu": [ "riscv64" ], @@ -1190,9 +1076,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", - "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", "cpu": [ "s390x" ], @@ -1206,9 +1092,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", - "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", "cpu": [ "x64" ], @@ -1222,9 +1108,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", - "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", "cpu": [ "arm64" ], @@ -1238,9 +1124,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", - "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", "cpu": [ "x64" ], @@ -1254,9 +1140,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", - "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", "cpu": [ "arm64" ], @@ -1270,9 +1156,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", - "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", "cpu": [ "x64" ], @@ -1286,9 +1172,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", - "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", "cpu": [ "arm64" ], @@ -1302,9 +1188,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", - "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", "cpu": [ "x64" ], @@ -1318,9 +1204,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", - "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", "cpu": [ "arm64" ], @@ -1334,9 +1220,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", - "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", "cpu": [ "ia32" ], @@ -1350,9 +1236,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", - "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", "cpu": [ "x64" ], @@ -1452,31 +1338,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@floating-ui/core": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", - "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.3.tgz", - "integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.3", - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", - "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", - "license": "MIT" - }, "node_modules/@formatjs/ecma402-abstract": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz", @@ -1560,6 +1421,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -1604,6 +1466,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -1643,6 +1506,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -1729,6 +1593,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -1771,6 +1636,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -1801,6 +1667,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -1835,6 +1702,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -1901,6 +1769,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -1940,6 +1809,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -1964,6 +1834,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2043,6 +1914,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2133,6 +2005,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2202,6 +2075,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2235,6 +2109,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2327,6 +2202,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2431,6 +2307,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2592,6 +2469,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2762,6 +2640,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2832,6 +2711,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2935,6 +2815,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2959,6 +2840,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -2983,6 +2865,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -3032,6 +2915,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -3056,6 +2940,7 @@ "version": "3.31.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.31.0.tgz", "integrity": "sha512-ua5U6V66gDcbLZe4P2QeyNgPp4YWD1ymGA6j3n+s8CGExtrCPe64v+g4mvpT8Bnb985R96e4zFT61+m0YCwqMg==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } @@ -3322,13 +3207,13 @@ "license": "BSD-3-Clause" }, "node_modules/@inquirer/confirm": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.14.tgz", - "integrity": "sha512-5yR4IBfe0kXe59r1YCTG8WXkUbl7Z35HK87Sw+WUyGD8wNUx7JvY7laahzeytyE1oLn74bQnL7hstctQxisQ8Q==", + "version": "5.1.16", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.16.tgz", + "integrity": "sha512-j1a5VstaK5KQy8Mu8cHmuQvN1Zc62TbLhjJxwHvKPPKEoowSF6h/0UdOpA9DNdWZ+9Inq73+puRq1df6OJ8Sag==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/type": "^3.0.8" }, "engines": { @@ -3344,9 +3229,9 @@ } }, "node_modules/@inquirer/core": { - "version": "10.1.15", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.15.tgz", - "integrity": "sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.2.0.tgz", + "integrity": "sha512-NyDSjPqhSvpZEMZrLCYUquWNl+XC/moEcVFqS55IEYIYsY0a1cUCevSqk7ctOlnm/RaSBU5psFryNlxcmGrjaA==", "dev": true, "license": "MIT", "dependencies": { @@ -3495,9 +3380,9 @@ } }, "node_modules/@internationalized/number": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.4.tgz", - "integrity": "sha512-P+/h+RDaiX8EGt3shB9AYM1+QgkvHmJ5rKi4/59k4sg9g58k9rqsRW0WxRO7jCoHyvVbFRRFKmVTdFYdehrxHg==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.5.tgz", + "integrity": "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -3531,9 +3416,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "dev": true, "license": "MIT", "engines": { @@ -3595,6 +3480,7 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -3673,9 +3559,9 @@ } }, "node_modules/@mswjs/interceptors": { - "version": "0.39.5", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.5.tgz", - "integrity": "sha512-B9nHSJYtsv79uo7QdkZ/b/WoKm20IkVSmTc/WCKarmDtFwM0dRx2ouEniqwNkzCSLn3fydzKmnMzjtfdOWt3VQ==", + "version": "0.39.6", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.6.tgz", + "integrity": "sha512-bndDP83naYYkfayr/qhBHMhk0YGwS1iv6vaEGcr0SQbO0IZtbOPqjKjds/WcG+bJA+1T5vCx6kprKOzn5Bg+Vw==", "dev": true, "license": "MIT", "dependencies": { @@ -3859,6 +3745,7 @@ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.0.tgz", "integrity": "sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "playwright": "1.55.0" }, @@ -3878,7 +3765,8 @@ "node_modules/@posthog/core": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.0.2.tgz", - "integrity": "sha512-hWk3rUtJl2crQK0WNmwg13n82hnTwB99BT99/XI5gZSvIlYZ1TPmMZE8H2dhJJ98J/rm9vYJ/UXNzw3RV5HTpQ==" + "integrity": "sha512-hWk3rUtJl2crQK0WNmwg13n82hnTwB99BT99/XI5gZSvIlYZ1TPmMZE8H2dhJJ98J/rm9vYJ/UXNzw3RV5HTpQ==", + "license": "MIT" }, "node_modules/@react-aria/breadcrumbs": { "version": "3.5.27", @@ -4073,23 +3961,23 @@ } }, "node_modules/@react-aria/grid": { - "version": "3.14.3", - "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.14.3.tgz", - "integrity": "sha512-O4Ius5tJqKcMGfQT6IXD4MnEOeq6f/59nKmfCLTXMREFac/oxafqanUx3zrEVYbaqLOjEmONcd8S61ptQM6aPg==", + "version": "3.14.4", + "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.14.4.tgz", + "integrity": "sha512-l1FLQNKnoHpY4UClUTPUV0AqJ5bfAULEE0ErY86KznWLd+Hqzo7mHLqqDV02CDa/8mIUcdoax/MrYYIbPDlOZA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.21.0", - "@react-aria/i18n": "^3.12.11", - "@react-aria/interactions": "^3.25.4", + "@react-aria/focus": "^3.21.1", + "@react-aria/i18n": "^3.12.12", + "@react-aria/interactions": "^3.25.5", "@react-aria/live-announcer": "^3.4.4", - "@react-aria/selection": "^3.25.0", - "@react-aria/utils": "^3.30.0", - "@react-stately/collections": "^3.12.6", - "@react-stately/grid": "^3.11.4", - "@react-stately/selection": "^3.20.4", - "@react-types/checkbox": "^3.10.0", - "@react-types/grid": "^3.3.4", - "@react-types/shared": "^3.31.0", + "@react-aria/selection": "^3.25.1", + "@react-aria/utils": "^3.30.1", + "@react-stately/collections": "^3.12.7", + "@react-stately/grid": "^3.11.5", + "@react-stately/selection": "^3.20.5", + "@react-types/checkbox": "^3.10.1", + "@react-types/grid": "^3.3.5", + "@react-types/shared": "^3.32.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4097,6 +3985,143 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@react-aria/grid/node_modules/@internationalized/date": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.9.0.tgz", + "integrity": "sha512-yaN3brAnHRD+4KyyOsJyk49XUvj2wtbNACSqg0bz3u8t2VuzhC8Q5dfRnrSxjnnbDb+ienBnkn1TzQfE154vyg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-aria/grid/node_modules/@react-aria/focus": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.1.tgz", + "integrity": "sha512-hmH1IhHlcQ2lSIxmki1biWzMbGgnhdxJUM0MFfzc71Rv6YAzhlx4kX3GYn4VNcjCeb6cdPv4RZ5vunV4kgMZYQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.25.5", + "@react-aria/utils": "^3.30.1", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/grid/node_modules/@react-aria/i18n": { + "version": "3.12.12", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.12.tgz", + "integrity": "sha512-JN6p+Xc6Pu/qddGRoeYY6ARsrk2Oz7UiQc9nLEPOt3Ch+blJZKWwDjcpo/p6/wVZdD/2BgXS7El6q6+eMg7ibw==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.9.0", + "@internationalized/message": "^3.1.8", + "@internationalized/number": "^3.6.5", + "@internationalized/string": "^3.2.7", + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.30.1", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/grid/node_modules/@react-aria/interactions": { + "version": "3.25.5", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.5.tgz", + "integrity": "sha512-EweYHOEvMwef/wsiEqV73KurX/OqnmbzKQa2fLxdULbec5+yDj6wVGaRHIzM4NiijIDe+bldEl5DG05CAKOAHA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.30.1", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/grid/node_modules/@react-aria/selection": { + "version": "3.25.1", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.25.1.tgz", + "integrity": "sha512-HG+k3rDjuhnXPdVyv9CKiebee2XNkFYeYZBxEGlK3/pFVBzndnc8BXNVrXSgtCHLs2d090JBVKl1k912BPbj0Q==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/focus": "^3.21.1", + "@react-aria/i18n": "^3.12.12", + "@react-aria/interactions": "^3.25.5", + "@react-aria/utils": "^3.30.1", + "@react-stately/selection": "^3.20.5", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/grid/node_modules/@react-aria/utils": { + "version": "3.30.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.30.1.tgz", + "integrity": "sha512-zETcbDd6Vf9GbLndO6RiWJadIZsBU2MMm23rBACXLmpRztkrIqPEb2RVdlLaq1+GklDx0Ii6PfveVjx+8S5U6A==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.8", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/grid/node_modules/@react-stately/collections": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.7.tgz", + "integrity": "sha512-0kQc0mI986GOCQHvRy4L0JQiotIK/KmEhR9Mu/6V0GoSdqg5QeUe4kyoNWj3bl03uQXme80v0L2jLHt+fOHHjA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/grid/node_modules/@react-types/checkbox": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.10.1.tgz", + "integrity": "sha512-8ZqBoGBxtn6U/znpmyutGtBBaafUzcZnbuvYjwyRSONTrqQ0IhUq6jI/jbnE9r9SslIkbMB8IS1xRh2e63qmEQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/grid/node_modules/@react-types/grid": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.3.5.tgz", + "integrity": "sha512-hG6J2KDfmOHitkWoCa/9DvY1nTO2wgMIApcFoqLv7AWJr9CzvVqo5tIhZZCXiT1AvU2kafJxu9e7sr5GxAT2YA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, "node_modules/@react-aria/i18n": { "version": "3.12.11", "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.11.tgz", @@ -4150,13 +4175,13 @@ } }, "node_modules/@react-aria/landmark": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@react-aria/landmark/-/landmark-3.0.5.tgz", - "integrity": "sha512-klUgRGQyTv5qWFQ0EMMLBOLa87qSTGjWoiMvytL9EgJCACkn/OzNMPbqVSkMADvadDyWCMWFYWvfweLxl3T5yw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@react-aria/landmark/-/landmark-3.0.6.tgz", + "integrity": "sha512-dMPBqJWTDAr3Lj5hA+XYDH2PWqtFghYy+y7iq7K5sK/96cub8hZEUjhwn+HGgHsLerPp0dWt293nKupAJnf4Vw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/utils": "^3.30.0", - "@react-types/shared": "^3.31.0", + "@react-aria/utils": "^3.30.1", + "@react-types/shared": "^3.32.0", "@swc/helpers": "^0.5.0", "use-sync-external-store": "^1.4.0" }, @@ -4165,16 +4190,34 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, - "node_modules/@react-aria/link": { - "version": "3.8.4", - "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.8.4.tgz", - "integrity": "sha512-7cPRGIo7x6ZZv1dhp2xGjqLR1snazSQgl7tThrBDL5E8f6Yr7SVpxOOK5/EBmfpFkhkmmXEO/Fgo/GPJdc6Vmw==", + "node_modules/@react-aria/landmark/node_modules/@react-aria/utils": { + "version": "3.30.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.30.1.tgz", + "integrity": "sha512-zETcbDd6Vf9GbLndO6RiWJadIZsBU2MMm23rBACXLmpRztkrIqPEb2RVdlLaq1+GklDx0Ii6PfveVjx+8S5U6A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.25.4", - "@react-aria/utils": "^3.30.0", - "@react-types/link": "^3.6.3", - "@react-types/shared": "^3.31.0", + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.8", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/link": { + "version": "3.8.5", + "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.8.5.tgz", + "integrity": "sha512-klhV4roPp5MLRXJv1N+7SXOj82vx4gzVpuwQa3vouA+YI1my46oNzwgtkLGSTvE9OvDqYzPDj2YxFYhMywrkuw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.25.5", + "@react-aria/utils": "^3.30.1", + "@react-types/link": "^3.6.4", + "@react-types/shared": "^3.32.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4182,6 +4225,53 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@react-aria/link/node_modules/@react-aria/interactions": { + "version": "3.25.5", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.5.tgz", + "integrity": "sha512-EweYHOEvMwef/wsiEqV73KurX/OqnmbzKQa2fLxdULbec5+yDj6wVGaRHIzM4NiijIDe+bldEl5DG05CAKOAHA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.30.1", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/link/node_modules/@react-aria/utils": { + "version": "3.30.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.30.1.tgz", + "integrity": "sha512-zETcbDd6Vf9GbLndO6RiWJadIZsBU2MMm23rBACXLmpRztkrIqPEb2RVdlLaq1+GklDx0Ii6PfveVjx+8S5U6A==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.8", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/link/node_modules/@react-types/link": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.6.4.tgz", + "integrity": "sha512-eLpIgOPf7GW4DpdMq8UqiRJkriend1kWglz5O9qU+/FM6COtvRnQkEeRhHICUaU2NZUvMRQ30KaGUo3eeZ6b+g==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, "node_modules/@react-aria/listbox": { "version": "3.14.7", "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.14.7.tgz", @@ -4364,16 +4454,16 @@ } }, "node_modules/@react-aria/spinbutton": { - "version": "3.6.17", - "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.17.tgz", - "integrity": "sha512-gdGc3kkqpvFUd9XsrhPwQHMrG2TY0LVuGGgjvaZwF/ONm9FMz393ogCM0P484HsjU50hClO+yiRRgNjdwDIzPQ==", + "version": "3.6.18", + "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.18.tgz", + "integrity": "sha512-dnmh7sNsprhYTpqCJhcuc9QJ9C/IG/o9TkgW5a9qcd2vS+dzEgqAiJKIMbJFG9kiJymv2NwIPysF12IWix+J3A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.11", + "@react-aria/i18n": "^3.12.12", "@react-aria/live-announcer": "^3.4.4", - "@react-aria/utils": "^3.30.0", - "@react-types/button": "^3.13.0", - "@react-types/shared": "^3.31.0", + "@react-aria/utils": "^3.30.1", + "@react-types/button": "^3.14.0", + "@react-types/shared": "^3.32.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4381,6 +4471,65 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@react-aria/spinbutton/node_modules/@internationalized/date": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.9.0.tgz", + "integrity": "sha512-yaN3brAnHRD+4KyyOsJyk49XUvj2wtbNACSqg0bz3u8t2VuzhC8Q5dfRnrSxjnnbDb+ienBnkn1TzQfE154vyg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-aria/spinbutton/node_modules/@react-aria/i18n": { + "version": "3.12.12", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.12.tgz", + "integrity": "sha512-JN6p+Xc6Pu/qddGRoeYY6ARsrk2Oz7UiQc9nLEPOt3Ch+blJZKWwDjcpo/p6/wVZdD/2BgXS7El6q6+eMg7ibw==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.9.0", + "@internationalized/message": "^3.1.8", + "@internationalized/number": "^3.6.5", + "@internationalized/string": "^3.2.7", + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.30.1", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/spinbutton/node_modules/@react-aria/utils": { + "version": "3.30.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.30.1.tgz", + "integrity": "sha512-zETcbDd6Vf9GbLndO6RiWJadIZsBU2MMm23rBACXLmpRztkrIqPEb2RVdlLaq1+GklDx0Ii6PfveVjx+8S5U6A==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.8", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/spinbutton/node_modules/@react-types/button": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.14.0.tgz", + "integrity": "sha512-pXt1a+ElxiZyWpX0uznyjy5Z6EHhYxPcaXpccZXyn6coUo9jmCbgg14xR7Odo+JcbfaaISzZTDO7oGLVTcHnpA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, "node_modules/@react-aria/ssr": { "version": "3.9.10", "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", @@ -4502,16 +4651,16 @@ } }, "node_modules/@react-aria/toggle": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.12.0.tgz", - "integrity": "sha512-JfcrF8xUEa2CbbUXp+WQiTBVwSM/dm21v5kueQlksvLfXG6DGE8/zjM6tJFErrFypAasc1JXyrI4dspLOWCfRA==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.12.1.tgz", + "integrity": "sha512-XaFiRs1KEcIT6bTtVY/KTQxw4kinemj/UwXw2iJTu9XS43hhJ/9cvj8KzNGrKGqaxTpOYj62TnSHZbSiFViHDA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.25.4", - "@react-aria/utils": "^3.30.0", - "@react-stately/toggle": "^3.9.0", - "@react-types/checkbox": "^3.10.0", - "@react-types/shared": "^3.31.0", + "@react-aria/interactions": "^3.25.5", + "@react-aria/utils": "^3.30.1", + "@react-stately/toggle": "^3.9.1", + "@react-types/checkbox": "^3.10.1", + "@react-types/shared": "^3.32.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4519,6 +4668,68 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@react-aria/toggle/node_modules/@react-aria/interactions": { + "version": "3.25.5", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.5.tgz", + "integrity": "sha512-EweYHOEvMwef/wsiEqV73KurX/OqnmbzKQa2fLxdULbec5+yDj6wVGaRHIzM4NiijIDe+bldEl5DG05CAKOAHA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.30.1", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/toggle/node_modules/@react-aria/utils": { + "version": "3.30.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.30.1.tgz", + "integrity": "sha512-zETcbDd6Vf9GbLndO6RiWJadIZsBU2MMm23rBACXLmpRztkrIqPEb2RVdlLaq1+GklDx0Ii6PfveVjx+8S5U6A==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.8", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/toggle/node_modules/@react-stately/toggle": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.9.1.tgz", + "integrity": "sha512-L6yUdE8xZfQhw4aEFZduF8u4v0VrpYrwWEA4Tu/4qwGIPukH0wd2W21Zpw+vAiLOaDKnxel1nXX68MWnm4QXpw==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/utils": "^3.10.8", + "@react-types/checkbox": "^3.10.1", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/toggle/node_modules/@react-types/checkbox": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.10.1.tgz", + "integrity": "sha512-8ZqBoGBxtn6U/znpmyutGtBBaafUzcZnbuvYjwyRSONTrqQ0IhUq6jI/jbnE9r9SslIkbMB8IS1xRh2e63qmEQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, "node_modules/@react-aria/toolbar": { "version": "3.0.0-beta.19", "resolved": "https://registry.npmjs.org/@react-aria/toolbar/-/toolbar-3.0.0-beta.19.tgz", @@ -4593,6 +4804,7 @@ "resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.8.2.tgz", "integrity": "sha512-9ilgQoNhvgvUyQKDapALt9qVO3GpSw9ng5X2BwIhLIwqh8CTyRM/jz5cK53p5yzGiVeyx9njXXfeuxUlvQgJuA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.27.7", "@babel/generator": "^7.27.5", @@ -4661,10 +4873,33 @@ "node": ">=6" } }, + "node_modules/@react-router/express": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/@react-router/express/-/express-7.8.2.tgz", + "integrity": "sha512-AJUNsE5Q+vD8TsNlKTw2MGUUnp/QJGlRV1jG2ItV30lwIx2wE7d4NHx/jWkGZIEblHQBTpodcp6MFirZXbisJw==", + "license": "MIT", + "dependencies": { + "@react-router/node": "7.8.2" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "express": "^4.17.1 || ^5", + "react-router": "7.8.2", + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@react-router/node": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/@react-router/node/-/node-7.8.2.tgz", "integrity": "sha512-FNepNg4Aya6V0ZxD/+uObtqxtMXcsBGa0ax9PznUh5qr8g4M6Xo9IN+soLb1tghz6iS/F9djFyhJ/lDkF77dEw==", + "license": "MIT", "dependencies": { "@mjackson/node-fetch-server": "^0.2.0" }, @@ -4685,6 +4920,7 @@ "version": "7.8.2", "resolved": "https://registry.npmjs.org/@react-router/serve/-/serve-7.8.2.tgz", "integrity": "sha512-1AwKjBWmyWWA7dGCRjn2glWwO6cA7dDX7roP1tosFi5cu1EvqHaqelRH6K6MZSV10Tv6oPtFG7rgV+rCafJvyw==", + "license": "MIT", "dependencies": { "@react-router/express": "7.8.2", "@react-router/node": "7.8.2", @@ -4704,27 +4940,6 @@ "react-router": "7.8.2" } }, - "node_modules/@react-router/serve/node_modules/@react-router/express": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/@react-router/express/-/express-7.8.2.tgz", - "integrity": "sha512-AJUNsE5Q+vD8TsNlKTw2MGUUnp/QJGlRV1jG2ItV30lwIx2wE7d4NHx/jWkGZIEblHQBTpodcp6MFirZXbisJw==", - "dependencies": { - "@react-router/node": "7.8.2" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "express": "^4.17.1 || ^5", - "react-router": "7.8.2", - "typescript": "^5.1.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@react-stately/calendar": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.8.3.tgz", @@ -4832,21 +5047,46 @@ } }, "node_modules/@react-stately/grid": { - "version": "3.11.4", - "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.11.4.tgz", - "integrity": "sha512-oaXFSk2eM0PJ0GVniGA0ZlTpAA0AL0O4MQ7V3cHqZAQbwSO0n2pT31GM0bSVnYP/qTF5lQHo3ECmRQCz0fVyMw==", + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.11.5.tgz", + "integrity": "sha512-4cNjGYaNkcVS2wZoNHUrMRICBpkHStYw57EVemP7MjiWEVu53kzPgR1Iwmti2WFCpi1Lwu0qWNeCfzKpXW4BTg==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.6", - "@react-stately/selection": "^3.20.4", - "@react-types/grid": "^3.3.4", - "@react-types/shared": "^3.31.0", + "@react-stately/collections": "^3.12.7", + "@react-stately/selection": "^3.20.5", + "@react-types/grid": "^3.3.5", + "@react-types/shared": "^3.32.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@react-stately/grid/node_modules/@react-stately/collections": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.7.tgz", + "integrity": "sha512-0kQc0mI986GOCQHvRy4L0JQiotIK/KmEhR9Mu/6V0GoSdqg5QeUe4kyoNWj3bl03uQXme80v0L2jLHt+fOHHjA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/grid/node_modules/@react-types/grid": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.3.5.tgz", + "integrity": "sha512-hG6J2KDfmOHitkWoCa/9DvY1nTO2wgMIApcFoqLv7AWJr9CzvVqo5tIhZZCXiT1AvU2kafJxu9e7sr5GxAT2YA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, "node_modules/@react-stately/list": { "version": "3.12.4", "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.12.4.tgz", @@ -4925,31 +5165,112 @@ } }, "node_modules/@react-stately/select": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.7.0.tgz", - "integrity": "sha512-OWLOCKBEj8/XI+vzBSSHQAJu0Hf9Xl/flMhYh47f2b45bO++DRLcVsi8nycPNisudvK6xMQ8a/h4FwjePrCXfg==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.7.1.tgz", + "integrity": "sha512-vZt4j9yVyOTWWJoP9plXmYaPZH2uMxbjcGMDbiShwsFiK8C2m9b3Cvy44TZehfzCWzpMVR/DYxEYuonEIGA82Q==", "license": "Apache-2.0", "dependencies": { - "@react-stately/form": "^3.2.0", - "@react-stately/list": "^3.12.4", - "@react-stately/overlays": "^3.6.18", - "@react-types/select": "^3.10.0", - "@react-types/shared": "^3.31.0", + "@react-stately/form": "^3.2.1", + "@react-stately/list": "^3.13.0", + "@react-stately/overlays": "^3.6.19", + "@react-types/select": "^3.10.1", + "@react-types/shared": "^3.32.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, - "node_modules/@react-stately/selection": { - "version": "3.20.4", - "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.20.4.tgz", - "integrity": "sha512-Hxmc6NtECStYo+Z2uBRhQ80KPhbSF7xXv9eb4qN8dhyuSnsD6c0wc6oAJsv18dldcFz8VrD48aP/uff9mj0hxQ==", + "node_modules/@react-stately/select/node_modules/@react-stately/collections": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.7.tgz", + "integrity": "sha512-0kQc0mI986GOCQHvRy4L0JQiotIK/KmEhR9Mu/6V0GoSdqg5QeUe4kyoNWj3bl03uQXme80v0L2jLHt+fOHHjA==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.6", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/select/node_modules/@react-stately/form": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.2.1.tgz", + "integrity": "sha512-btgOPXkwvd6fdWKoepy5Ue43o2932OSkQxozsR7US1ffFLcQc3SNlADHaRChIXSG8ffPo9t0/Sl4eRzaKu3RgQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/select/node_modules/@react-stately/list": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.13.0.tgz", + "integrity": "sha512-Panv8TmaY8lAl3R7CRhyUadhf2yid6VKsRDBCBB1FHQOOeL7lqIraz/oskvpabZincuaIUWqQhqYslC4a6dvuA==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.7", + "@react-stately/selection": "^3.20.5", "@react-stately/utils": "^3.10.8", - "@react-types/shared": "^3.31.0", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/select/node_modules/@react-stately/overlays": { + "version": "3.6.19", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.19.tgz", + "integrity": "sha512-swZXfDvxTYd7tKEpijEHBFFaEmbbnCvEhGlmrAz4K72cuRR9O5u+lcla8y1veGBbBSzrIdKNdBoIIJ+qQH+1TQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/utils": "^3.10.8", + "@react-types/overlays": "^3.9.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/select/node_modules/@react-types/overlays": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.9.1.tgz", + "integrity": "sha512-UCG3TOu8FLk4j0Pr1nlhv0opcwMoqbGEOUvsSr6ITN6Qs2y0j+KYSYQ7a4+04m3dN//8+9Wjkkid8k+V1dV2CA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/selection": { + "version": "3.20.5", + "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.20.5.tgz", + "integrity": "sha512-YezWUNEn2pz5mQlbhmngiX9HqQsruLSXlkrAzB1DD6aliGrUvPKufTTGCixOaB8KVeCamdiFAgx1WomNplzdQA==", + "license": "Apache-2.0", + "dependencies": { + "@react-stately/collections": "^3.12.7", + "@react-stately/utils": "^3.10.8", + "@react-types/shared": "^3.32.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/selection/node_modules/@react-stately/collections": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.7.tgz", + "integrity": "sha512-0kQc0mI986GOCQHvRy4L0JQiotIK/KmEhR9Mu/6V0GoSdqg5QeUe4kyoNWj3bl03uQXme80v0L2jLHt+fOHHjA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -5181,13 +5502,25 @@ } }, "node_modules/@react-types/dialog": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.20.tgz", - "integrity": "sha512-ebn8jW/xW/nmRATaWIPHVBIpIFWSaqjrAxa58f5TXer5FtCD9pUuzAQDmy/o22ucB0yvn6Kl+fjb3SMbMdALZQ==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.21.tgz", + "integrity": "sha512-jF1gN4bvwYamsLjefaFDnaSKxTa3Wtvn5f7WLjNVZ8ICVoiMBMdUJXTlPQHAL4YWqtCj4hK/3uimR1E+Pwd7Xw==", "license": "Apache-2.0", "dependencies": { - "@react-types/overlays": "^3.9.0", - "@react-types/shared": "^3.31.0" + "@react-types/overlays": "^3.9.1", + "@react-types/shared": "^3.32.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/dialog/node_modules/@react-types/overlays": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.9.1.tgz", + "integrity": "sha512-UCG3TOu8FLk4j0Pr1nlhv0opcwMoqbGEOUvsSr6ITN6Qs2y0j+KYSYQ7a4+04m3dN//8+9Wjkkid8k+V1dV2CA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.32.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5230,12 +5563,12 @@ } }, "node_modules/@react-types/listbox": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.7.2.tgz", - "integrity": "sha512-MRpBhApR1jJNASoVWsEvH5vf89TJw+l9Lt1ssawop0K2iYF5PmkthRdqcpYcTkFu5+f5QvFchVsNJ3TKD4cf2A==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.7.3.tgz", + "integrity": "sha512-ONgror9uyGmIer5XxpRRNcc8QFVWiOzINrMKyaS8G4l3aP52ZwYpRfwMAVtra8lkVNvXDmO7hthPZkB6RYdNOA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.31.0" + "@react-types/shared": "^3.32.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5303,12 +5636,12 @@ } }, "node_modules/@react-types/select": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.10.0.tgz", - "integrity": "sha512-+xJwYWJoJTCGsaiPAqb6QB79ub1WKIHSmOS9lh/fPUXfUszVs05jhajaN9KjrKmnXds5uh4u6l1JH5J1l2K5pw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.10.1.tgz", + "integrity": "sha512-teANUr1byOzGsS/r2j7PatV470JrOhKP8En9lscfnqW5CeUghr+0NxkALnPkiEhCObi/Vu8GIcPareD0HNhtFA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.31.0" + "@react-types/shared": "^3.32.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5318,29 +5651,30 @@ "version": "3.32.0", "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.0.tgz", "integrity": "sha512-t+cligIJsZYFMSPFMvsJMjzlzde06tZMOIOFa1OV5Z0BcMowrb2g4mB57j/9nP28iJIRYn10xCniQts+qadrqQ==", + "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/slider": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.8.0.tgz", - "integrity": "sha512-eN6Fd3YCPseGfvfOJDtn9Lh9CrAb8tF3cTAprEcpnGrsxmdW9JQpcuciYuLM871X5D2fYg4WaYMpZaiYssjxBQ==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.8.1.tgz", + "integrity": "sha512-WxiQWj6iQr5Uft0/KcB9XSr361XnyTmL6eREZZacngA9CjPhRWYP3BRDPcCTuP7fj9Yi4QKMrryyjHqMHP8OKQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.31.0" + "@react-types/shared": "^3.32.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/switch": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.13.tgz", - "integrity": "sha512-C2EhKBu7g7xhKboPPxhyKtROEti80Ck7TBnKclXt0D4LiwbzpR3qGfuzB+7YFItnhiauP7Uxe+bAfM5ojjtm9w==", + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.14.tgz", + "integrity": "sha512-M8kIv97i+ejCel4Ho+Y7tDbpOehymGwPA4ChxibeyD32+deyxu5B6BXxgKiL3l+oTLQ8ihLo3sRESdPFw8vpQg==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.31.0" + "@react-types/shared": "^3.32.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5360,12 +5694,12 @@ } }, "node_modules/@react-types/tabs": { - "version": "3.3.17", - "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.17.tgz", - "integrity": "sha512-cLcdxWNJe0Kf/pKuPQbEF9Fl+axiP4gB/WVjmAdhCgQ5LCJw2dGcy1LI1SXrlS3PVclbnujD1DJ8z1lIW4Tmww==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.18.tgz", + "integrity": "sha512-yX/AVlGS7VXCuy2LSm8y8nxUrKVBgnLv+FrtkLqf6jUMtD4KP3k1c4+GPHeScR0HcYzCQF7gCF3Skba1RdYoug==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.31.0" + "@react-types/shared": "^3.32.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -5425,7 +5759,8 @@ "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.34", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.34.tgz", - "integrity": "sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA==" + "integrity": "sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA==", + "license": "MIT" }, "node_modules/@rollup/pluginutils": { "version": "5.2.0", @@ -5471,9 +5806,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", - "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.49.0.tgz", + "integrity": "sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA==", "cpu": [ "arm" ], @@ -5484,9 +5819,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz", - "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.49.0.tgz", + "integrity": "sha512-cqPpZdKUSQYRtLLr6R4X3sD4jCBO1zUmeo3qrWBCqYIeH8Q3KRL4F3V7XJ2Rm8/RJOQBZuqzQGWPjjvFUcYa/w==", "cpu": [ "arm64" ], @@ -5497,9 +5832,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz", - "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.49.0.tgz", + "integrity": "sha512-99kMMSMQT7got6iYX3yyIiJfFndpojBmkHfTc1rIje8VbjhmqBXE+nb7ZZP3A5skLyujvT0eIUCUsxAe6NjWbw==", "cpu": [ "arm64" ], @@ -5510,9 +5845,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz", - "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.49.0.tgz", + "integrity": "sha512-y8cXoD3wdWUDpjOLMKLx6l+NFz3NlkWKcBCBfttUn+VGSfgsQ5o/yDUGtzE9HvsodkP0+16N0P4Ty1VuhtRUGg==", "cpu": [ "x64" ], @@ -5523,9 +5858,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz", - "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.49.0.tgz", + "integrity": "sha512-3mY5Pr7qv4GS4ZvWoSP8zha8YoiqrU+e0ViPvB549jvliBbdNLrg2ywPGkgLC3cmvN8ya3za+Q2xVyT6z+vZqA==", "cpu": [ "arm64" ], @@ -5536,9 +5871,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz", - "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.49.0.tgz", + "integrity": "sha512-C9KzzOAQU5gU4kG8DTk+tjdKjpWhVWd5uVkinCwwFub2m7cDYLOdtXoMrExfeBmeRy9kBQMkiyJ+HULyF1yj9w==", "cpu": [ "x64" ], @@ -5549,9 +5884,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz", - "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.49.0.tgz", + "integrity": "sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==", "cpu": [ "arm" ], @@ -5562,9 +5897,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz", - "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.49.0.tgz", + "integrity": "sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==", "cpu": [ "arm" ], @@ -5575,9 +5910,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz", - "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.49.0.tgz", + "integrity": "sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==", "cpu": [ "arm64" ], @@ -5588,9 +5923,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz", - "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.49.0.tgz", + "integrity": "sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==", "cpu": [ "arm64" ], @@ -5601,9 +5936,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz", - "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.49.0.tgz", + "integrity": "sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==", "cpu": [ "loong64" ], @@ -5614,9 +5949,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz", - "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.49.0.tgz", + "integrity": "sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==", "cpu": [ "ppc64" ], @@ -5627,9 +5962,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz", - "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.49.0.tgz", + "integrity": "sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==", "cpu": [ "riscv64" ], @@ -5640,9 +5975,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz", - "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.49.0.tgz", + "integrity": "sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==", "cpu": [ "riscv64" ], @@ -5653,9 +5988,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz", - "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.49.0.tgz", + "integrity": "sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==", "cpu": [ "s390x" ], @@ -5666,9 +6001,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz", - "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.49.0.tgz", + "integrity": "sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==", "cpu": [ "x64" ], @@ -5679,9 +6014,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz", - "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.49.0.tgz", + "integrity": "sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==", "cpu": [ "x64" ], @@ -5692,9 +6027,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz", - "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.49.0.tgz", + "integrity": "sha512-wkNRzfiIGaElC9kXUT+HLx17z7D0jl+9tGYRKwd8r7cUqTL7GYAvgUY++U2hK6Ar7z5Z6IRRoWC8kQxpmM7TDA==", "cpu": [ "arm64" ], @@ -5705,9 +6040,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz", - "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.49.0.tgz", + "integrity": "sha512-gq5aW/SyNpjp71AAzroH37DtINDcX1Qw2iv9Chyz49ZgdOP3NV8QCyKZUrGsYX9Yyggj5soFiRCgsL3HwD8TdA==", "cpu": [ "ia32" ], @@ -5718,9 +6053,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz", - "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.49.0.tgz", + "integrity": "sha512-gEtqFbzmZLFk2xKh7g0Rlo8xzho8KrEFEkzvHbfUGkrgXOpZ4XagQ6n+wIZFNh1nTb8UD16J4nFSFKXYgnbdBg==", "cpu": [ "x64" ], @@ -5759,6 +6094,7 @@ "version": "3.9.2", "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-3.9.2.tgz", "integrity": "sha512-urAZek4LrnHWfk4WYXItOiX+6xyxjcn0SkhBDoysXphLkUt92UWCd5+NlomhVqaLo98XiUQGZRiRcL8HOHZ8Jw==", + "license": "MIT", "dependencies": { "prop-types": "^15.7.2" }, @@ -5772,6 +6108,7 @@ "version": "7.9.0", "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.9.0.tgz", "integrity": "sha512-ggs5k+/0FUJcIgNY08aZTqpBTtbExkJMYMLSMwyucrhtWexVOEY1KJmhBsxf+E/Q15f5rbwBpj+t0t2AW2oCsQ==", + "license": "MIT", "engines": { "node": ">=12.16" } @@ -5960,33 +6297,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/core/node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@svgr/hast-util-to-babel-ast": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", @@ -6054,6 +6364,7 @@ "version": "4.1.12", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.12.tgz", "integrity": "sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==", + "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", @@ -6069,6 +6380,7 @@ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.12.tgz", "integrity": "sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==", "hasInstallScript": true, + "license": "MIT", "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" @@ -6098,6 +6410,7 @@ "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "android" @@ -6113,6 +6426,7 @@ "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -6128,6 +6442,7 @@ "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -6143,6 +6458,7 @@ "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -6158,6 +6474,7 @@ "cpu": [ "arm" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -6173,6 +6490,7 @@ "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -6188,6 +6506,7 @@ "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -6203,6 +6522,7 @@ "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -6218,6 +6538,7 @@ "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -6241,6 +6562,7 @@ "cpu": [ "wasm32" ], + "license": "MIT", "optional": true, "dependencies": { "@emnapi/core": "^1.4.5", @@ -6254,60 +6576,6 @@ "node": ">=14.0.0" } }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.4.5", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.0.4", - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.4.5", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.0.4", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { - "version": "2.8.0", - "inBundle": true, - "license": "0BSD", - "optional": true - }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.12.tgz", @@ -6315,6 +6583,7 @@ "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -6330,6 +6599,7 @@ "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -6342,6 +6612,7 @@ "version": "4.1.12", "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.12.tgz", "integrity": "sha512-5PpLYhCAwf9SJEeIsSmCDLgyVfdBhdBpzX1OJ87anT9IVR0Z9pjM0FNixCAUAHGnMBGB8K99SwAheXrT0Kh6QQ==", + "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.12", @@ -6370,6 +6641,7 @@ "version": "4.1.12", "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.12.tgz", "integrity": "sha512-4pt0AMFDx7gzIrAOIYgYP0KCBuKWqyW8ayrdiLEjoJTT4pKTjrzG/e4uzWtTLDziC+66R9wbUqZBccJalSE5vQ==", + "license": "MIT", "dependencies": { "@tailwindcss/node": "4.1.12", "@tailwindcss/oxide": "4.1.12", @@ -6400,6 +6672,7 @@ "version": "5.85.5", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.85.5.tgz", "integrity": "sha512-KO0WTob4JEApv69iYp1eGvfMSUkgw//IpMnq+//cORBzXf0smyRwPLrUvEe5qtAEGjwZTXrjxg+oJNP/C00t6w==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -6409,6 +6682,7 @@ "version": "5.85.5", "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.85.5.tgz", "integrity": "sha512-/X4EFNcnPiSs8wM2v+b6DqS5mmGeuJQvxBglmDxl6ZQb5V26ouD2SJYAcC3VjbNwqhY2zjxVD15rDA5nGbMn3A==", + "license": "MIT", "dependencies": { "@tanstack/query-core": "5.85.5" }, @@ -6472,6 +6746,7 @@ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.8.0.tgz", "integrity": "sha512-WgXcWzVM6idy5JaftTVC8Vs83NKRmGJz4Hqs4oyOuO2J4r/y79vvKZsb+CaGyCSEbUPI6OsewfPd0G1A0/TUZQ==", "dev": true, + "license": "MIT", "dependencies": { "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", @@ -6679,20 +6954,16 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", "devOptional": true, + "license": "MIT", "dependencies": { "undici-types": "~7.10.0" } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "license": "MIT" - }, "node_modules/@types/react": { "version": "19.1.12", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.12.tgz", "integrity": "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==", + "license": "MIT", "dependencies": { "csstype": "^3.0.2" } @@ -6702,6 +6973,7 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz", "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", "dev": true, + "license": "MIT", "peerDependencies": { "@types/react": "^19.0.0" } @@ -6726,15 +6998,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-transition-group": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", - "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*" - } - }, "node_modules/@types/statuses": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz", @@ -6858,14 +7121,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", - "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.41.0.tgz", + "integrity": "sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.39.1", - "@typescript-eslint/types": "^8.39.1", + "@typescript-eslint/tsconfig-utils": "^8.41.0", + "@typescript-eslint/types": "^8.41.0", "debug": "^4.3.4" }, "engines": { @@ -6880,9 +7143,9 @@ } }, "node_modules/@typescript-eslint/project-service/node_modules/@typescript-eslint/types": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.41.0.tgz", + "integrity": "sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==", "dev": true, "license": "MIT", "engines": { @@ -6912,9 +7175,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", - "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.41.0.tgz", + "integrity": "sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw==", "dev": true, "license": "MIT", "engines": { @@ -7023,16 +7286,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", - "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.41.0.tgz", + "integrity": "sha512-udbCVstxZ5jiPIXrdH+BZWnPatjlYwJuJkDA4Tbo3WyYLh8NvB+h/bKeSZHDOFKfphsZYJQqaFtLeXEqurQn1A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1" + "@typescript-eslint/scope-manager": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/typescript-estree": "8.41.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7047,14 +7310,14 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", - "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.41.0.tgz", + "integrity": "sha512-n6m05bXn/Cd6DZDGyrpXrELCPVaTnLdPToyhBoFkLIMznRUQUEQdSp96s/pcWSQdqOhrgR1mzJ+yItK7T+WPMQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1" + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7065,9 +7328,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.41.0.tgz", + "integrity": "sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==", "dev": true, "license": "MIT", "engines": { @@ -7079,16 +7342,16 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", - "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.41.0.tgz", + "integrity": "sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.39.1", - "@typescript-eslint/tsconfig-utils": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", + "@typescript-eslint/project-service": "8.41.0", + "@typescript-eslint/tsconfig-utils": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7108,13 +7371,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", - "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.41.0.tgz", + "integrity": "sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/types": "8.41.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -7192,6 +7455,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.2.tgz", "integrity": "sha512-tmyFgixPZCx2+e6VO9TNITWcCQl8+Nl/E8YbAyPVv85QCc7/A3JrdfG2A8gIzvVhWuzMOVrFW1aReaNxrI6tbw==", + "license": "MIT", "dependencies": { "@babel/core": "^7.28.3", "@babel/plugin-transform-react-jsx-self": "^7.27.1", @@ -7426,6 +7690,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -7438,6 +7703,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7578,7 +7844,8 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/array-includes": { "version": "3.1.9", @@ -7883,21 +8150,6 @@ "@babel/types": "^7.23.6" } }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - } - }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -7943,6 +8195,7 @@ "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -7966,6 +8219,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -7973,7 +8227,8 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/brace-expansion": { "version": "2.0.2", @@ -7999,9 +8254,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz", - "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", + "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", "funding": [ { "type": "opencollective", @@ -8018,8 +8273,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001733", - "electron-to-chromium": "^1.5.199", + "caniuse-lite": "^1.0.30001737", + "electron-to-chromium": "^1.5.211", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -8107,6 +8362,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8126,9 +8382,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001734", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001734.tgz", - "integrity": "sha512-uhE1Ye5vgqju6OI71HTQqcBCZrvHugk0MjLak7Q+HfoBgoq5Bi+5YnwjP4fjDgrtYr/l8MVRBvzz9dPD4KyK0A==", + "version": "1.0.30001737", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz", + "integrity": "sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==", "funding": [ { "type": "opencollective", @@ -8156,9 +8412,9 @@ } }, "node_modules/chai": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.1.tgz", - "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", "dev": true, "license": "MIT", "dependencies": { @@ -8298,9 +8554,9 @@ } }, "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "dev": true, "license": "MIT", "engines": { @@ -8311,9 +8567,9 @@ } }, "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", "dev": true, "license": "MIT" }, @@ -8599,6 +8855,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -8610,6 +8867,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8624,6 +8882,7 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8631,12 +8890,13 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/core-js": { - "version": "3.45.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.0.tgz", - "integrity": "sha512-c2KZL9lP4DjkN3hk/an4pWn5b5ZefhRJnAc42n6LJ19kSnbeRbdQZE5dSeE2LBol1OwJD3X1BQvFTAsa8ReeDA==", + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.1.tgz", + "integrity": "sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -8645,28 +8905,30 @@ } }, "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/cosmiconfig/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "license": "ISC", - "engines": { - "node": ">= 6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/cross-env": { @@ -8996,6 +9258,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -9056,16 +9319,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", @@ -9077,6 +9330,22 @@ "tslib": "^2.0.3" } }, + "node_modules/downshift": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-9.0.10.tgz", + "integrity": "sha512-TP/iqV6bBok6eGD5tZ8boM8Xt7/+DZvnVNr8cNIhbAm2oUBd79Tudiccs2hbcV9p7xAgS/ozE7Hxy3a9QqS6Mw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.5", + "compute-scroll-into-view": "^3.1.0", + "prop-types": "^15.8.1", + "react-is": "18.2.0", + "tslib": "^2.6.2" + }, + "peerDependencies": { + "react": ">=16.12.0" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -9105,9 +9374,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.200", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.200.tgz", - "integrity": "sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==", + "version": "1.5.211", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.211.tgz", + "integrity": "sha512-IGBvimJkotaLzFnwIVgW9/UD/AOJ2tByUmeOrtqBfACSbAw5b1G0XpvdaieKyc7ULmbwXVx+4e4Be8pOPBrYkw==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -9121,6 +9390,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -9235,11 +9505,19 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, + "node_modules/error-ex/node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, "node_modules/es-abstract": { "version": "1.24.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", @@ -9421,9 +9699,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", - "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -9433,32 +9711,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.8", - "@esbuild/android-arm": "0.25.8", - "@esbuild/android-arm64": "0.25.8", - "@esbuild/android-x64": "0.25.8", - "@esbuild/darwin-arm64": "0.25.8", - "@esbuild/darwin-x64": "0.25.8", - "@esbuild/freebsd-arm64": "0.25.8", - "@esbuild/freebsd-x64": "0.25.8", - "@esbuild/linux-arm": "0.25.8", - "@esbuild/linux-arm64": "0.25.8", - "@esbuild/linux-ia32": "0.25.8", - "@esbuild/linux-loong64": "0.25.8", - "@esbuild/linux-mips64el": "0.25.8", - "@esbuild/linux-ppc64": "0.25.8", - "@esbuild/linux-riscv64": "0.25.8", - "@esbuild/linux-s390x": "0.25.8", - "@esbuild/linux-x64": "0.25.8", - "@esbuild/netbsd-arm64": "0.25.8", - "@esbuild/netbsd-x64": "0.25.8", - "@esbuild/openbsd-arm64": "0.25.8", - "@esbuild/openbsd-x64": "0.25.8", - "@esbuild/openharmony-arm64": "0.25.8", - "@esbuild/sunos-x64": "0.25.8", - "@esbuild/win32-arm64": "0.25.8", - "@esbuild/win32-ia32": "0.25.8", - "@esbuild/win32-x64": "0.25.8" + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" } }, "node_modules/escalade": { @@ -9473,12 +9751,14 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -9993,6 +10273,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.2.0.tgz", "integrity": "sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w==", "dev": true, + "license": "MIT", "peerDependencies": { "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", "eslint": "^9.0.0 || ^8.0.0" @@ -10145,6 +10426,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10183,6 +10465,7 @@ "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -10228,6 +10511,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -10235,7 +10519,8 @@ "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/extend": { "version": "3.0.2", @@ -10360,6 +10645,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", @@ -10377,6 +10663,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -10384,12 +10671,7 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/find-up": { @@ -10521,6 +10803,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -10570,6 +10853,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -11101,21 +11385,6 @@ "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", "license": "CC0-1.0" }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "license": "BSD-3-Clause", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" - }, "node_modules/hosted-git-info": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.3.tgz", @@ -11182,6 +11451,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -11255,6 +11525,7 @@ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" } ], + "license": "MIT", "dependencies": { "@babel/runtime": "^7.27.6" }, @@ -11289,6 +11560,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -11320,6 +11592,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -11417,6 +11690,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -11464,9 +11738,9 @@ } }, "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", "license": "MIT" }, "node_modules/is-async-function": { @@ -11539,6 +11813,7 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -11931,6 +12206,7 @@ "version": "5.1.30", "resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.30.tgz", "integrity": "sha512-3wVJEonAns1OETX83uWsk5IAne2S5zfDcntD2hbtU23LelSqNXzXs9zKjMPOLMzroCgIjCfjYAEHrd2D6FOkiA==", + "license": "Unlicense", "engines": { "node": ">=18" } @@ -11983,9 +12259,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -12043,6 +12319,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.0.tgz", "integrity": "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -12475,6 +12752,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, "license": "MIT" }, "node_modules/lint-staged": { @@ -12506,9 +12784,9 @@ } }, "node_modules/lint-staged/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "dev": true, "license": "MIT", "engines": { @@ -12519,9 +12797,9 @@ } }, "node_modules/listr2": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.1.tgz", - "integrity": "sha512-SL0JY3DaxylDuo/MecFeiC+7pedM0zia33zl0vcjgwcq1q1FWWF1To9EIauPbl8GbMCU0R2e0uJ8bZunhYKD2g==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.2.tgz", + "integrity": "sha512-VVd7cS6W+vLJu2wmq4QmfVj14Iep7cz4r/OWNk36Aq5ZOY7G8/BfCrQFexcwB1OIxB3yERiePfE/REBjEFulag==", "dev": true, "license": "MIT", "dependencies": { @@ -12537,9 +12815,9 @@ } }, "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "dev": true, "license": "MIT", "engines": { @@ -12563,9 +12841,9 @@ } }, "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", "dev": true, "license": "MIT" }, @@ -12701,9 +12979,9 @@ } }, "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "dev": true, "license": "MIT", "engines": { @@ -12727,9 +13005,9 @@ } }, "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", "dev": true, "license": "MIT" }, @@ -12841,9 +13119,9 @@ } }, "node_modules/loupe": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.0.tgz", - "integrity": "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", "dev": true, "license": "MIT" }, @@ -12884,6 +13162,7 @@ "version": "0.542.0", "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.542.0.tgz", "integrity": "sha512-w3hD8/SQB7+lzU2r4VdFyzzOzKnUjTZIF/MQJGSSvni7Llewni4vuViRppfRAa2guOsY5k4jZyxw/i9DQHv+dw==", + "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } @@ -12899,12 +13178,12 @@ } }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "version": "0.30.18", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", + "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/magicast": { @@ -13254,20 +13533,16 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/memoize-one": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", - "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", - "license": "MIT" - }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -13286,6 +13561,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -13871,6 +14147,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -14082,9 +14359,9 @@ "license": "MIT" }, "node_modules/msw": { - "version": "2.10.4", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.10.4.tgz", - "integrity": "sha512-6R1or/qyele7q3RyPwNuvc0IxO8L8/Aim6Sz5ncXEgcWUNxSKE+udriTOWHtpMwmfkLYlacA2y7TIx4cL5lgHA==", + "version": "2.10.5", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.10.5.tgz", + "integrity": "sha512-0EsQCrCI1HbhpBWd89DvmxY6plmvrM96b0sCIztnvcNHQbXn5vqwm1KlXslo6u4wN9LFGLC1WFjjgljcQhe40A==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -14475,6 +14752,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -14603,6 +14881,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -14640,6 +14919,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", @@ -14658,6 +14938,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, "license": "MIT" }, "node_modules/parse5": { @@ -14677,6 +14958,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -14715,6 +14997,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, "license": "MIT" }, "node_modules/path-scurry": { @@ -14744,12 +15027,14 @@ "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -14821,6 +15106,7 @@ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.0.tgz", "integrity": "sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "playwright-core": "1.55.0" }, @@ -14839,6 +15125,7 @@ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.0.tgz", "integrity": "sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==", "dev": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -14909,6 +15196,7 @@ "version": "1.261.0", "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.261.0.tgz", "integrity": "sha512-jyiXqyrCU+VlpbNNVRA6OQYAVut0XZMYNELCZH+XvTd981VqbE4jXn4XCBreo7XCL2gdPgDVxUVOuzNvEuKcmw==", + "license": "SEE LICENSE IN LICENSE", "dependencies": { "@posthog/core": "1.0.2", "core-js": "^3.38.1", @@ -14936,9 +15224,9 @@ "license": "Apache-2.0" }, "node_modules/preact": { - "version": "10.27.0", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.0.tgz", - "integrity": "sha512-/DTYoB6mwwgPytiqQTh/7SFRL98ZdiD8Sk8zIUVOxtwq4oWcwrcd1uno9fE/zZmUaUrFNYzbH14CPebOz9tZQw==", + "version": "10.27.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.1.tgz", + "integrity": "sha512-V79raXEWch/rbqoNc7nT9E4ep7lu+mI3+sBmfRD4i1M73R3WLYcCtdI0ibxGVf4eQL8ZIz2nFacqEC+rmnOORQ==", "license": "MIT", "funding": { "type": "opencollective", @@ -15012,6 +15300,13 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT" + }, "node_modules/prismjs": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", @@ -15083,6 +15378,7 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -15167,6 +15463,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -15175,6 +15472,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -15259,6 +15557,7 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==", + "license": "MIT", "dependencies": { "csstype": "^3.1.3", "goober": "^2.1.16" @@ -15272,9 +15571,10 @@ } }, "node_modules/react-i18next": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.7.2.tgz", - "integrity": "sha512-xJxq7ibnhUlMvd82lNC4te1GxGUMoM1A05KKyqoqsBXVZtEvZg/fz/fnVzdlY/hhQ3SpP/79qCocZOtICGhd3g==", + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.7.3.tgz", + "integrity": "sha512-AANws4tOE+QSq/IeMF/ncoHlMNZaVLxpa5uUGW1wjike68elVYr0018L9xYoqBr1OFO7G7boDPrbn0HpMCJxTw==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.27.6", "html-parse-stringify": "^3.0.1" @@ -15306,10 +15606,9 @@ } }, "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true, + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "license": "MIT" }, "node_modules/react-lifecycles-compat": { @@ -15382,6 +15681,7 @@ "version": "7.8.2", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.2.tgz", "integrity": "sha512-7M2fR1JbIZ/jFWqelpvSZx+7vd7UlBTfdZqf6OSdF9g6+sfdqJDAWcak6ervbHph200ePlu+7G8LdoiC3ReyAQ==", + "license": "MIT", "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" @@ -15408,31 +15708,11 @@ "node": ">=18" } }, - "node_modules/react-select": { - "version": "5.10.2", - "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.2.tgz", - "integrity": "sha512-Z33nHdEFWq9tfnfVXaiM12rbJmk+QjFEztWLtmXqQhz6Al4UZZ9xc0wiatmGtUOCCnHN0WizL3tCMYRENX4rVQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.0", - "@emotion/cache": "^11.4.0", - "@emotion/react": "^11.8.1", - "@floating-ui/dom": "^1.0.1", - "@types/react-transition-group": "^4.4.0", - "memoize-one": "^6.0.0", - "prop-types": "^15.6.0", - "react-transition-group": "^4.3.0", - "use-isomorphic-layout-effect": "^1.2.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/react-syntax-highlighter": { "version": "15.6.6", "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz", "integrity": "sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.3.1", "highlight.js": "^10.4.1", @@ -15462,22 +15742,6 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "license": "BSD-3-Clause", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" - } - }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -15799,6 +16063,7 @@ "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -15819,6 +16084,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -15933,9 +16199,9 @@ } }, "node_modules/rollup": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", - "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.49.0.tgz", + "integrity": "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -15948,26 +16214,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.46.2", - "@rollup/rollup-android-arm64": "4.46.2", - "@rollup/rollup-darwin-arm64": "4.46.2", - "@rollup/rollup-darwin-x64": "4.46.2", - "@rollup/rollup-freebsd-arm64": "4.46.2", - "@rollup/rollup-freebsd-x64": "4.46.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", - "@rollup/rollup-linux-arm-musleabihf": "4.46.2", - "@rollup/rollup-linux-arm64-gnu": "4.46.2", - "@rollup/rollup-linux-arm64-musl": "4.46.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", - "@rollup/rollup-linux-ppc64-gnu": "4.46.2", - "@rollup/rollup-linux-riscv64-gnu": "4.46.2", - "@rollup/rollup-linux-riscv64-musl": "4.46.2", - "@rollup/rollup-linux-s390x-gnu": "4.46.2", - "@rollup/rollup-linux-x64-gnu": "4.46.2", - "@rollup/rollup-linux-x64-musl": "4.46.2", - "@rollup/rollup-win32-arm64-msvc": "4.46.2", - "@rollup/rollup-win32-ia32-msvc": "4.46.2", - "@rollup/rollup-win32-x64-msvc": "4.46.2", + "@rollup/rollup-android-arm-eabi": "4.49.0", + "@rollup/rollup-android-arm64": "4.49.0", + "@rollup/rollup-darwin-arm64": "4.49.0", + "@rollup/rollup-darwin-x64": "4.49.0", + "@rollup/rollup-freebsd-arm64": "4.49.0", + "@rollup/rollup-freebsd-x64": "4.49.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", + "@rollup/rollup-linux-arm-musleabihf": "4.49.0", + "@rollup/rollup-linux-arm64-gnu": "4.49.0", + "@rollup/rollup-linux-arm64-musl": "4.49.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", + "@rollup/rollup-linux-ppc64-gnu": "4.49.0", + "@rollup/rollup-linux-riscv64-gnu": "4.49.0", + "@rollup/rollup-linux-riscv64-musl": "4.49.0", + "@rollup/rollup-linux-s390x-gnu": "4.49.0", + "@rollup/rollup-linux-x64-gnu": "4.49.0", + "@rollup/rollup-linux-x64-musl": "4.49.0", + "@rollup/rollup-win32-arm64-msvc": "4.49.0", + "@rollup/rollup-win32-ia32-msvc": "4.49.0", + "@rollup/rollup-win32-x64-msvc": "4.49.0", "fsevents": "~2.3.2" } }, @@ -16149,6 +16415,7 @@ "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -16172,6 +16439,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -16179,12 +16447,14 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/send/node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -16193,6 +16463,7 @@ "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", @@ -16261,7 +16532,8 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", @@ -16387,12 +16659,6 @@ "is-arrayish": "^0.3.1" } }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "license": "MIT" - }, "node_modules/sirv": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", @@ -16543,9 +16809,9 @@ } }, "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -16570,15 +16836,6 @@ "source-map": "^0.6.0" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -16737,9 +16994,9 @@ } }, "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "dev": true, "license": "MIT", "engines": { @@ -16980,6 +17237,7 @@ "resolved": "https://registry.npmjs.org/stripe/-/stripe-18.5.0.tgz", "integrity": "sha512-Hp+wFiEQtCB0LlNgcFh5uVyKznpDjzyUZ+CNVEf+I3fhlYvh7rZruIg+jOwzJRCpy0ZTPMjlzm7J2/M2N6d+DA==", "dev": true, + "license": "MIT", "dependencies": { "qs": "^6.11.0" }, @@ -17013,12 +17271,6 @@ "inline-style-parser": "0.2.4" } }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", - "license": "MIT" - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -17036,6 +17288,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -17106,15 +17359,20 @@ "node_modules/tailwindcss": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.12.tgz", - "integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==" + "integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==", + "license": "MIT" }, "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", + "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/tar": { @@ -17205,10 +17463,13 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -17297,6 +17558,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -17459,6 +17721,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -17686,6 +17949,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -17806,6 +18070,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -17887,6 +18152,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz", "integrity": "sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==", + "license": "MIT", "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -17991,6 +18257,7 @@ "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.5.0.tgz", "integrity": "sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==", "dev": true, + "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.2.0", "@svgr/core": "^8.1.0", @@ -18024,6 +18291,7 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", "engines": { "node": ">=12.0.0" }, @@ -18054,6 +18322,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -18464,9 +18733,9 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "dev": true, "license": "MIT", "engines": { @@ -18671,9 +18940,9 @@ } }, "node_modules/yoctocolors-cjs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", - "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", "dev": true, "license": "MIT", "engines": { diff --git a/frontend/package.json b/frontend/package.json index 25d98523f3..0fafb82cf8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,6 +27,7 @@ "axios": "^1.11.0", "clsx": "^2.1.1", "date-fns": "^4.1.0", + "downshift": "^9.0.10", "eslint-config-airbnb-typescript": "^18.0.0", "framer-motion": "^12.23.12", "i18next": "^25.4.2", @@ -46,7 +47,6 @@ "react-markdown": "^10.1.0", "react-redux": "^9.2.0", "react-router": "^7.8.2", - "react-select": "^5.10.2", "react-syntax-highlighter": "^15.6.6", "react-textarea-autosize": "^8.5.9", "remark-breaks": "^4.0.0", diff --git a/frontend/src/api/open-hands.ts b/frontend/src/api/open-hands.ts index 1984d841c0..8cd11d3df1 100644 --- a/frontend/src/api/open-hands.ts +++ b/frontend/src/api/open-hands.ts @@ -21,7 +21,12 @@ import { } from "./open-hands.types"; import { openHands } from "./open-hands-axios"; import { ApiSettings, PostApiSettings, Provider } from "#/types/settings"; -import { GitUser, GitRepository, Branch } from "#/types/git"; +import { + GitUser, + GitRepository, + PaginatedBranchesResponse, + Branch, +} from "#/types/git"; import { SuggestedTask } from "#/components/features/home/tasks/task.types"; import { extractNextPageFromLink } from "#/utils/extract-next-page-from-link"; import { RepositoryMicroagent } from "#/types/microagent-management"; @@ -567,14 +572,38 @@ class OpenHands { }; } - static async getRepositoryBranches(repository: string): Promise { - const { data } = await openHands.get( - `/api/user/repository/branches?repository=${encodeURIComponent(repository)}`, + static async getRepositoryBranches( + repository: string, + page: number = 1, + perPage: number = 30, + ): Promise { + const { data } = await openHands.get( + `/api/user/repository/branches?repository=${encodeURIComponent(repository)}&page=${page}&per_page=${perPage}`, ); return data; } + static async searchRepositoryBranches( + repository: string, + query: string, + perPage: number = 30, + selectedProvider?: Provider, + ): Promise { + const { data } = await openHands.get( + `/api/user/search/branches`, + { + params: { + repository, + query, + per_page: perPage, + selected_provider: selectedProvider, + }, + }, + ); + return data; + } + /** * Get the available microagents associated with a conversation * @param conversationId The ID of the conversation diff --git a/frontend/src/components/common/git-branch-dropdown.tsx b/frontend/src/components/common/git-branch-dropdown.tsx deleted file mode 100644 index 3625ee076b..0000000000 --- a/frontend/src/components/common/git-branch-dropdown.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { useMemo } from "react"; -import { useRepositoryBranches } from "../../hooks/query/use-repository-branches"; -import { ReactSelectDropdown, SelectOption } from "./react-select-dropdown"; - -export interface GitBranchDropdownProps { - repositoryName?: string | null; - value?: string | null; - placeholder?: string; - className?: string; - errorMessage?: string; - disabled?: boolean; - onChange?: (branchName: string | null) => void; -} - -export function GitBranchDropdown({ - repositoryName, - value, - placeholder = "Select branch...", - className, - errorMessage, - disabled = false, - onChange, -}: GitBranchDropdownProps) { - const { data: branches, isLoading } = useRepositoryBranches( - repositoryName || null, - ); - - const options: SelectOption[] = useMemo( - () => - branches?.map((branch) => ({ - value: branch.name, - label: branch.name, - })) || [], - [branches], - ); - - const hasNoBranches = !isLoading && branches && branches.length === 0; - - const selectedOption = useMemo( - () => options.find((option) => option.value === value) || null, - [options, value], - ); - - const handleChange = (option: SelectOption | null) => { - onChange?.(option?.value || null); - }; - - const isDisabled = disabled || !repositoryName || isLoading || hasNoBranches; - - const displayPlaceholder = hasNoBranches ? "No branches found" : placeholder; - const displayErrorMessage = hasNoBranches - ? "This repository has no branches" - : errorMessage; - - return ( - - ); -} diff --git a/frontend/src/components/common/git-provider-dropdown.tsx b/frontend/src/components/common/git-provider-dropdown.tsx deleted file mode 100644 index a488d11120..0000000000 --- a/frontend/src/components/common/git-provider-dropdown.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useMemo } from "react"; -import { StylesConfig } from "react-select"; -import { Provider } from "../../types/settings"; -import { ReactSelectDropdown, SelectOption } from "./react-select-dropdown"; - -export interface GitProviderDropdownProps { - providers: Provider[]; - value?: Provider | null; - placeholder?: string; - className?: string; - errorMessage?: string; - disabled?: boolean; - isLoading?: boolean; - onChange?: (provider: Provider | null) => void; - classNamePrefix?: string; - styles?: StylesConfig; -} - -export function GitProviderDropdown({ - providers, - value, - placeholder = "Select Provider", - className, - errorMessage, - disabled = false, - isLoading = false, - onChange, - classNamePrefix, - styles, -}: GitProviderDropdownProps) { - const options: SelectOption[] = useMemo( - () => - providers.map((provider) => ({ - value: provider, - label: provider.charAt(0).toUpperCase() + provider.slice(1), - })), - [providers], - ); - - const selectedOption = useMemo( - () => options.find((option) => option.value === value) || null, - [options, value], - ); - - const handleChange = (option: SelectOption | null) => { - onChange?.(option?.value as Provider | null); - }; - - return ( - - ); -} diff --git a/frontend/src/components/common/git-repository-dropdown.tsx b/frontend/src/components/common/git-repository-dropdown.tsx deleted file mode 100644 index ecbd19d522..0000000000 --- a/frontend/src/components/common/git-repository-dropdown.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import { useCallback, useMemo, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { Provider } from "../../types/settings"; -import { useGitRepositories } from "../../hooks/query/use-git-repositories"; -import { useSearchRepositories } from "../../hooks/query/use-search-repositories"; -import { useDebounce } from "../../hooks/use-debounce"; -import OpenHands from "../../api/open-hands"; -import { GitRepository } from "../../types/git"; -import { - ReactSelectAsyncDropdown, - AsyncSelectOption, -} from "./react-select-async-dropdown"; - -export interface GitRepositoryDropdownProps { - provider: Provider; - value?: string | null; - placeholder?: string; - className?: string; - errorMessage?: string; - disabled?: boolean; - onChange?: (repository?: GitRepository) => void; -} - -export function GitRepositoryDropdown({ - provider, - value, - placeholder = "Search repositories...", - className, - errorMessage, - disabled = false, - onChange, -}: GitRepositoryDropdownProps) { - const { t } = useTranslation(); - const [searchInput, setSearchInput] = useState(""); - const debouncedSearchInput = useDebounce(searchInput, 300); - - // Process search input to handle URLs - const processedSearchInput = useMemo(() => { - if (debouncedSearchInput.startsWith("https://")) { - const match = debouncedSearchInput.match( - /https:\/\/[^/]+\/([^/]+\/[^/]+)/, - ); - return match ? match[1] : debouncedSearchInput; - } - return debouncedSearchInput; - }, [debouncedSearchInput]); - - const { - data, - fetchNextPage, - hasNextPage, - isLoading, - isFetchingNextPage, - isError, - } = useGitRepositories({ - provider, - enabled: !disabled, - }); - - // Search query for processed input (handles URLs) - const { data: searchData, isLoading: isSearchLoading } = - useSearchRepositories(processedSearchInput, provider); - - const allOptions: AsyncSelectOption[] = useMemo( - () => - data?.pages - ? data.pages.flatMap((page) => - page.data.map((repo) => ({ - value: repo.id, - label: repo.full_name, - })), - ) - : [], - [data], - ); - - const searchOptions: AsyncSelectOption[] = useMemo( - () => - searchData - ? searchData.map((repo) => ({ - value: repo.id, - label: repo.full_name, - })) - : [], - [searchData], - ); - - const selectedOption = useMemo(() => { - // First check in loaded pages - const option = allOptions.find((opt) => opt.value === value); - if (option) return option; - - // If not found, check in search results - const searchOption = searchOptions.find((opt) => opt.value === value); - if (searchOption) return searchOption; - - return null; - }, [allOptions, searchOptions, value]); - - const loadOptions = useCallback( - async (inputValue: string): Promise => { - // Update search input to trigger debounced search - setSearchInput(inputValue); - - // If empty input, show all loaded options - if (!inputValue.trim()) { - return allOptions; - } - - // For very short inputs, do local filtering - if (inputValue.length < 2) { - return allOptions.filter((option) => - option.label.toLowerCase().includes(inputValue.toLowerCase()), - ); - } - - // Handle URL inputs by performing direct search - if (inputValue.startsWith("https://")) { - const match = inputValue.match(/https:\/\/[^/]+\/([^/]+\/[^/]+)/); - if (match) { - const repoName = match[1]; - try { - // Perform direct search for URL-based inputs - const repositories = await OpenHands.searchGitRepositories( - repoName, - 3, - provider, - ); - return repositories.map((repo) => ({ - value: repo.full_name, - label: repo.full_name, - data: repo, - })); - } catch (error) { - // Fall back to local filtering if search fails - return allOptions.filter((option) => - option.label.toLowerCase().includes(repoName.toLowerCase()), - ); - } - } - } - - // For regular text inputs, use hook-based search results if available - if (searchOptions.length > 0 && processedSearchInput === inputValue) { - return searchOptions; - } - - // Fallback to local filtering while search is loading - return allOptions.filter((option) => - option.label.toLowerCase().includes(inputValue.toLowerCase()), - ); - }, - [allOptions, searchOptions, processedSearchInput, provider], - ); - - const handleChange = (option: AsyncSelectOption | null) => { - if (!option) { - onChange?.(undefined); - return; - } - - // First check in loaded pages - let repo = data?.pages - ?.flatMap((p) => p.data) - .find((r) => r.id === option.value); - - // If not found, check in search results - if (!repo) { - repo = searchData?.find((r) => r.id === option.value); - } - - onChange?.(repo); - }; - - const handleMenuScrollToBottom = useCallback(() => { - if (hasNextPage && !isFetchingNextPage && !isLoading) { - fetchNextPage(); - } - }, [hasNextPage, isFetchingNextPage, isLoading, fetchNextPage]); - - return ( - <> - - {isError && ( -
- {t("HOME$FAILED_TO_LOAD_REPOSITORIES")} -
- )} - - ); -} diff --git a/frontend/src/components/common/react-select-async-dropdown.tsx b/frontend/src/components/common/react-select-async-dropdown.tsx deleted file mode 100644 index 8bd540d727..0000000000 --- a/frontend/src/components/common/react-select-async-dropdown.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { useCallback, useMemo } from "react"; -import AsyncSelect from "react-select/async"; -import { cn } from "#/utils/utils"; -import { SelectOptionBase, getCustomStyles } from "./react-select-styles"; - -export type AsyncSelectOption = SelectOptionBase; - -export interface ReactSelectAsyncDropdownProps { - loadOptions: (inputValue: string) => Promise; - testId?: string; - placeholder?: string; - value?: AsyncSelectOption | null; - defaultValue?: AsyncSelectOption | null; - className?: string; - errorMessage?: string; - disabled?: boolean; - isClearable?: boolean; - isLoading?: boolean; - cacheOptions?: boolean; - defaultOptions?: boolean | AsyncSelectOption[]; - onChange?: (option: AsyncSelectOption | null) => void; - onMenuScrollToBottom?: () => void; -} - -export function ReactSelectAsyncDropdown({ - loadOptions, - testId, - placeholder = "Search...", - value, - defaultValue, - className, - errorMessage, - disabled = false, - isClearable = false, - isLoading = false, - cacheOptions = true, - defaultOptions = true, - onChange, - onMenuScrollToBottom, -}: ReactSelectAsyncDropdownProps) { - const customStyles = useMemo(() => getCustomStyles(), []); - - const handleLoadOptions = useCallback( - (inputValue: string, callback: (options: AsyncSelectOption[]) => void) => { - loadOptions(inputValue) - .then((options) => callback(options)) - .catch(() => callback([])); - }, - [loadOptions], - ); - - return ( -
- - {errorMessage && ( -

- {errorMessage} -

- )} -
- ); -} diff --git a/frontend/src/components/common/react-select-dropdown.tsx b/frontend/src/components/common/react-select-dropdown.tsx deleted file mode 100644 index 1b033a5875..0000000000 --- a/frontend/src/components/common/react-select-dropdown.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { useMemo } from "react"; -import Select, { StylesConfig } from "react-select"; -import { cn } from "#/utils/utils"; -import { SelectOptionBase, getCustomStyles } from "./react-select-styles"; - -export type SelectOption = SelectOptionBase; - -export interface ReactSelectDropdownProps { - options: SelectOption[]; - placeholder?: string; - value?: SelectOption | null; - defaultValue?: SelectOption | null; - className?: string; - errorMessage?: string; - disabled?: boolean; - isClearable?: boolean; - isSearchable?: boolean; - isLoading?: boolean; - onChange?: (option: SelectOption | null) => void; - classNamePrefix?: string; - styles?: StylesConfig; -} - -export function ReactSelectDropdown({ - options, - placeholder = "Select option...", - value, - defaultValue, - className, - errorMessage, - disabled = false, - isClearable = false, - isSearchable = true, - isLoading = false, - onChange, - classNamePrefix, - styles, -}: ReactSelectDropdownProps) { - const customStyles = useMemo(() => getCustomStyles(), []); - - return ( -
- + +
+ {selectedBranch && ( + + )} + + +
+ + {isLoadingState && } +
+ + + + + + ); +} diff --git a/frontend/src/components/features/home/git-branch-dropdown/index.ts b/frontend/src/components/features/home/git-branch-dropdown/index.ts new file mode 100644 index 0000000000..e72b5504c7 --- /dev/null +++ b/frontend/src/components/features/home/git-branch-dropdown/index.ts @@ -0,0 +1,3 @@ +export { GitBranchDropdown } from "./git-branch-dropdown"; +export { BranchDropdownMenu } from "./branch-dropdown-menu"; +export type { GitBranchDropdownProps } from "./git-branch-dropdown"; diff --git a/frontend/src/components/features/home/git-provider-dropdown/git-provider-dropdown.tsx b/frontend/src/components/features/home/git-provider-dropdown/git-provider-dropdown.tsx new file mode 100644 index 0000000000..1123f7e022 --- /dev/null +++ b/frontend/src/components/features/home/git-provider-dropdown/git-provider-dropdown.tsx @@ -0,0 +1,193 @@ +import React, { useState, useMemo, useEffect } from "react"; +import { useCombobox } from "downshift"; +import { Provider } from "#/types/settings"; +import { cn } from "#/utils/utils"; +import { DropdownItem } from "../shared/dropdown-item"; +import { GenericDropdownMenu } from "../shared/generic-dropdown-menu"; +import { ToggleButton } from "../shared/toggle-button"; +import { LoadingSpinner } from "../shared/loading-spinner"; +import { ErrorMessage } from "../shared/error-message"; +import { EmptyState } from "../shared/empty-state"; + +export interface GitProviderDropdownProps { + providers: Provider[]; + value?: Provider | null; + placeholder?: string; + className?: string; + errorMessage?: string; + disabled?: boolean; + isLoading?: boolean; + onChange?: (provider: Provider | null) => void; +} + +export function GitProviderDropdown({ + providers, + value, + placeholder = "Select Provider", + className, + errorMessage, + disabled = false, + isLoading = false, + onChange, +}: GitProviderDropdownProps) { + const [inputValue, setInputValue] = useState(""); + const [localSelectedItem, setLocalSelectedItem] = useState( + value || null, + ); + + // Format provider names for display + const formatProviderName = (provider: Provider): string => { + switch (provider) { + case "github": + return "GitHub"; + case "gitlab": + return "GitLab"; + case "bitbucket": + return "Bitbucket"; + case "enterprise_sso": + return "Enterprise SSO"; + default: + // Fallback for any future provider types + return ( + (provider as string).charAt(0).toUpperCase() + + (provider as string).slice(1) + ); + } + }; + + // Filter providers based on input value + const filteredProviders = useMemo(() => { + // If we have a selected provider and the input matches it exactly, show all providers + if ( + localSelectedItem && + inputValue === formatProviderName(localSelectedItem) + ) { + return providers; + } + + // If no input value, show all providers + if (!inputValue || !inputValue.trim()) { + return providers; + } + + // Filter providers based on input + return providers.filter((provider) => + formatProviderName(provider) + .toLowerCase() + .includes(inputValue.toLowerCase()), + ); + }, [providers, inputValue, localSelectedItem]); + + const { + isOpen, + getToggleButtonProps, + getMenuProps, + getInputProps, + highlightedIndex, + getItemProps, + selectedItem, + } = useCombobox({ + items: filteredProviders, + itemToString: (item) => (item ? formatProviderName(item) : ""), + selectedItem: localSelectedItem, + onSelectedItemChange: ({ selectedItem: newSelectedItem }) => { + setLocalSelectedItem(newSelectedItem || null); + onChange?.(newSelectedItem || null); + }, + onInputValueChange: ({ inputValue: newInputValue }) => { + setInputValue(newInputValue || ""); + }, + inputValue, + }); + + // Sync with external value prop + useEffect(() => { + if (value !== localSelectedItem) { + setLocalSelectedItem(value || null); + } + }, [value, localSelectedItem]); + + // Update input value when selection changes (but not when user is typing) + useEffect(() => { + if (selectedItem && !isOpen) { + setInputValue(formatProviderName(selectedItem)); + } else if (!selectedItem) { + setInputValue(""); + } + }, [selectedItem, isOpen]); + + const renderItem = ( + item: Provider, + index: number, + currentHighlightedIndex: number, + currentSelectedItem: Provider | null, + currentGetItemProps: any, // eslint-disable-line @typescript-eslint/no-explicit-any + ) => ( + provider} + /> + ); + + const renderEmptyState = (currentInputValue: string) => ( + + ); + + return ( +
+
+ + +
+ +
+ + {isLoading && } +
+ + + + +
+ ); +} diff --git a/frontend/src/components/features/home/git-provider-dropdown/index.ts b/frontend/src/components/features/home/git-provider-dropdown/index.ts new file mode 100644 index 0000000000..422b8fa73f --- /dev/null +++ b/frontend/src/components/features/home/git-provider-dropdown/index.ts @@ -0,0 +1,2 @@ +export { GitProviderDropdown } from "./git-provider-dropdown"; +export type { GitProviderDropdownProps } from "./git-provider-dropdown"; diff --git a/frontend/src/components/features/home/git-repo-dropdown/dropdown-menu.tsx b/frontend/src/components/features/home/git-repo-dropdown/dropdown-menu.tsx new file mode 100644 index 0000000000..bee4b5e45e --- /dev/null +++ b/frontend/src/components/features/home/git-repo-dropdown/dropdown-menu.tsx @@ -0,0 +1,79 @@ +import React from "react"; +import { + UseComboboxGetMenuPropsOptions, + UseComboboxGetItemPropsOptions, +} from "downshift"; +import { GitRepository } from "#/types/git"; +import { DropdownItem } from "../shared/dropdown-item"; +import { GenericDropdownMenu, EmptyState } from "../shared"; + +interface DropdownMenuProps { + isOpen: boolean; + filteredRepositories: GitRepository[]; + inputValue: string; + highlightedIndex: number; + selectedItem: GitRepository | null; + getMenuProps: ( + options?: UseComboboxGetMenuPropsOptions & Options, + ) => any; // eslint-disable-line @typescript-eslint/no-explicit-any + getItemProps: ( + options: UseComboboxGetItemPropsOptions & Options, + ) => any; // eslint-disable-line @typescript-eslint/no-explicit-any + onScroll: (event: React.UIEvent) => void; + menuRef: React.RefObject; +} + +export function DropdownMenu({ + isOpen, + filteredRepositories, + inputValue, + highlightedIndex, + selectedItem, + getMenuProps, + getItemProps, + onScroll, + menuRef, +}: DropdownMenuProps) { + const renderItem = ( + repository: GitRepository, + index: number, + currentHighlightedIndex: number, + currentSelectedItem: GitRepository | null, + currentGetItemProps: ( + options: UseComboboxGetItemPropsOptions & Options, + ) => any, // eslint-disable-line @typescript-eslint/no-explicit-any + ) => ( + repo.full_name} + getItemKey={(repo) => repo.id.toString()} + /> + ); + + const renderEmptyState = (currentInputValue: string) => ( + + ); + + return ( +
+ +
+ ); +} diff --git a/frontend/src/components/features/home/git-repo-dropdown/git-repo-dropdown.tsx b/frontend/src/components/features/home/git-repo-dropdown/git-repo-dropdown.tsx new file mode 100644 index 0000000000..cc75148818 --- /dev/null +++ b/frontend/src/components/features/home/git-repo-dropdown/git-repo-dropdown.tsx @@ -0,0 +1,243 @@ +import React, { + useState, + useMemo, + useCallback, + useRef, + useEffect, +} from "react"; +import { useCombobox } from "downshift"; +import { Provider } from "#/types/settings"; +import { GitRepository } from "#/types/git"; +import { useDebounce } from "#/hooks/use-debounce"; +import { cn } from "#/utils/utils"; +import { LoadingSpinner } from "../shared/loading-spinner"; +import { ClearButton } from "../shared/clear-button"; +import { ToggleButton } from "../shared/toggle-button"; +import { ErrorMessage } from "../shared/error-message"; +import { useUrlSearch } from "./use-url-search"; +import { useRepositoryData } from "./use-repository-data"; +import { DropdownMenu } from "./dropdown-menu"; + +export interface GitRepoDropdownProps { + provider: Provider; + value?: string | null; + placeholder?: string; + className?: string; + disabled?: boolean; + onChange?: (repository?: GitRepository) => void; +} + +export function GitRepoDropdown({ + provider, + value, + placeholder = "Search repositories...", + className, + disabled = false, + onChange, +}: GitRepoDropdownProps) { + const [inputValue, setInputValue] = useState(""); + const [localSelectedItem, setLocalSelectedItem] = + useState(null); + const debouncedInputValue = useDebounce(inputValue, 300); + const menuRef = useRef(null); + + // Process search input to handle URLs + const processedSearchInput = useMemo(() => { + if (debouncedInputValue.startsWith("https://")) { + const match = debouncedInputValue.match( + /https:\/\/[^/]+\/([^/]+\/[^/]+)/, + ); + return match ? match[1] : debouncedInputValue; + } + return debouncedInputValue; + }, [debouncedInputValue]); + + // URL search functionality + const { urlSearchResults, isUrlSearchLoading } = useUrlSearch( + inputValue, + provider, + ); + + // Repository data management + const { + repositories, + selectedRepository, + fetchNextPage, + hasNextPage, + isLoading, + isFetchingNextPage, + isError, + isSearchLoading, + } = useRepositoryData( + provider, + disabled, + processedSearchInput, + urlSearchResults, + inputValue, + value, + ); + + // Filter repositories based on input value + const filteredRepositories = useMemo(() => { + // If we have URL search results, show them directly (no filtering needed) + if (urlSearchResults.length > 0) { + return repositories; + } + + // If we have a selected repository and the input matches it exactly, show all repositories + if (selectedRepository && inputValue === selectedRepository.full_name) { + return repositories; + } + + // If no input value, show all repositories + if (!inputValue || !inputValue.trim()) { + return repositories; + } + + // For URL inputs, use the processed search input for filtering + const filterText = inputValue.startsWith("https://") + ? processedSearchInput + : inputValue; + + return repositories.filter((repo) => + repo.full_name.toLowerCase().includes(filterText.toLowerCase()), + ); + }, [ + repositories, + inputValue, + selectedRepository, + urlSearchResults, + processedSearchInput, + ]); + + // Handle selection + const handleSelectionChange = useCallback( + (selectedItem: GitRepository | null) => { + setLocalSelectedItem(selectedItem); + onChange?.(selectedItem || undefined); + // Update input value to show selected item + if (selectedItem) { + setInputValue(selectedItem.full_name); + } + }, + [onChange], + ); + + // Handle clear selection + const handleClear = useCallback(() => { + setLocalSelectedItem(null); + handleSelectionChange(null); + setInputValue(""); + }, [handleSelectionChange]); + + // Handle input value change + const handleInputValueChange = useCallback( + ({ inputValue: newInputValue }: { inputValue?: string }) => { + setInputValue(newInputValue || ""); + }, + [], + ); + + // Handle scroll to bottom for pagination + const handleMenuScroll = useCallback( + (event: React.UIEvent) => { + const { scrollTop, scrollHeight, clientHeight } = event.currentTarget; + const isNearBottom = scrollTop + clientHeight >= scrollHeight - 10; + + if (isNearBottom && hasNextPage && !isFetchingNextPage) { + fetchNextPage(); + } + }, + [hasNextPage, isFetchingNextPage, fetchNextPage], + ); + + const { + isOpen, + getToggleButtonProps, + getMenuProps, + getInputProps, + highlightedIndex, + getItemProps, + selectedItem, + } = useCombobox({ + items: filteredRepositories, + itemToString: (item) => item?.full_name || "", + selectedItem: localSelectedItem, + onSelectedItemChange: ({ selectedItem: newSelectedItem }) => { + handleSelectionChange(newSelectedItem); + }, + onInputValueChange: handleInputValueChange, + inputValue, + }); + + // Sync localSelectedItem with external value prop + useEffect(() => { + if (selectedRepository) { + setLocalSelectedItem(selectedRepository); + } else if (value === null) { + setLocalSelectedItem(null); + } + }, [selectedRepository, value]); + + // Initialize input value when selectedRepository changes (but not when user is typing) + useEffect(() => { + if (selectedRepository && !isOpen) { + setInputValue(selectedRepository.full_name); + } + }, [selectedRepository, isOpen]); + + const isLoadingState = + isLoading || isSearchLoading || isFetchingNextPage || isUrlSearchLoading; + + return ( +
+
+ + +
+ {selectedRepository && ( + + )} + + +
+ + {isLoadingState && ( + + )} +
+ + + + +
+ ); +} diff --git a/frontend/src/components/features/home/git-repo-dropdown/index.tsx b/frontend/src/components/features/home/git-repo-dropdown/index.tsx new file mode 100644 index 0000000000..5322bbede8 --- /dev/null +++ b/frontend/src/components/features/home/git-repo-dropdown/index.tsx @@ -0,0 +1,10 @@ +// Main component +export { GitRepoDropdown } from "./git-repo-dropdown"; +export type { GitRepoDropdownProps } from "./git-repo-dropdown"; + +// Repository-specific UI Components +export { DropdownMenu } from "./dropdown-menu"; + +// Repository-specific Custom Hooks +export { useUrlSearch } from "./use-url-search"; +export { useRepositoryData } from "./use-repository-data"; diff --git a/frontend/src/components/features/home/git-repo-dropdown/use-repository-data.tsx b/frontend/src/components/features/home/git-repo-dropdown/use-repository-data.tsx new file mode 100644 index 0000000000..0ee7344f45 --- /dev/null +++ b/frontend/src/components/features/home/git-repo-dropdown/use-repository-data.tsx @@ -0,0 +1,89 @@ +import { useMemo } from "react"; +import { Provider } from "#/types/settings"; +import { GitRepository } from "#/types/git"; +import { useGitRepositories } from "#/hooks/query/use-git-repositories"; +import { useSearchRepositories } from "#/hooks/query/use-search-repositories"; + +export function useRepositoryData( + provider: Provider, + disabled: boolean, + processedSearchInput: string, + urlSearchResults: GitRepository[], + inputValue: string, + value?: string | null, +) { + // Fetch user repositories with pagination + const { + data: repoData, + fetchNextPage, + hasNextPage, + isLoading, + isFetchingNextPage, + isError, + } = useGitRepositories({ + provider, + enabled: !disabled, + }); + + // Search repositories when user types + const { data: searchData, isLoading: isSearchLoading } = + useSearchRepositories(processedSearchInput, provider); + + // Combine all repositories from paginated data + const allRepositories = useMemo( + () => repoData?.pages?.flatMap((page) => page.data) || [], + [repoData], + ); + + // Find selected repository from all possible sources + const selectedRepository = useMemo(() => { + if (!value) return null; + + // Search in all possible repository sources + const allPossibleRepos = [ + ...allRepositories, + ...urlSearchResults, + ...(searchData || []), + ]; + + return allPossibleRepos.find((repo) => repo.id === value) || null; + }, [allRepositories, urlSearchResults, searchData, value]); + + // Get repositories to display (URL search, regular search, or all repos) + const repositories = useMemo(() => { + // Prioritize URL search results when available + if (urlSearchResults.length > 0) { + return urlSearchResults; + } + + // Don't use search results if input exactly matches selected repository + const shouldUseSearch = + processedSearchInput && + searchData && + !(selectedRepository && inputValue === selectedRepository.full_name); + + if (shouldUseSearch) { + return searchData; + } + return allRepositories; + }, [ + urlSearchResults, + processedSearchInput, + searchData, + allRepositories, + selectedRepository, + inputValue, + ]); + + return { + repositories, + allRepositories, + selectedRepository, + fetchNextPage, + hasNextPage, + isLoading, + isFetchingNextPage, + isError, + isSearchLoading, + }; +} diff --git a/frontend/src/components/features/home/git-repo-dropdown/use-url-search.tsx b/frontend/src/components/features/home/git-repo-dropdown/use-url-search.tsx new file mode 100644 index 0000000000..82cb6d27f2 --- /dev/null +++ b/frontend/src/components/features/home/git-repo-dropdown/use-url-search.tsx @@ -0,0 +1,41 @@ +import { useState, useEffect } from "react"; +import { Provider } from "#/types/settings"; +import { GitRepository } from "#/types/git"; +import OpenHands from "#/api/open-hands"; + +export function useUrlSearch(inputValue: string, provider: Provider) { + const [urlSearchResults, setUrlSearchResults] = useState([]); + const [isUrlSearchLoading, setIsUrlSearchLoading] = useState(false); + + useEffect(() => { + const handleUrlSearch = async () => { + if (inputValue.startsWith("https://")) { + const match = inputValue.match(/https:\/\/[^/]+\/([^/]+\/[^/]+)/); + if (match) { + const repoName = match[1]; + + setIsUrlSearchLoading(true); + try { + const repositories = await OpenHands.searchGitRepositories( + repoName, + 3, + provider, + ); + + setUrlSearchResults(repositories); + } catch (error) { + setUrlSearchResults([]); + } finally { + setIsUrlSearchLoading(false); + } + } + } else { + setUrlSearchResults([]); + } + }; + + handleUrlSearch(); + }, [inputValue, provider]); + + return { urlSearchResults, isUrlSearchLoading }; +} diff --git a/frontend/src/components/features/home/repo-selection-form.tsx b/frontend/src/components/features/home/repo-selection-form.tsx index c7835f8e86..ce8a007f73 100644 --- a/frontend/src/components/features/home/repo-selection-form.tsx +++ b/frontend/src/components/features/home/repo-selection-form.tsx @@ -2,15 +2,15 @@ import React from "react"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router"; import { useCreateConversation } from "#/hooks/mutation/use-create-conversation"; -import { useRepositoryBranches } from "#/hooks/query/use-repository-branches"; +// Removed useRepositoryBranches import - GitBranchDropdown manages its own data import { useIsCreatingConversation } from "#/hooks/use-is-creating-conversation"; import { Branch, GitRepository } from "#/types/git"; import { BrandButton } from "../settings/brand-button"; import { useUserProviders } from "#/hooks/use-user-providers"; import { Provider } from "#/types/settings"; -import { GitProviderDropdown } from "../../common/git-provider-dropdown"; -import { GitRepositoryDropdown } from "../../common/git-repository-dropdown"; -import { GitBranchDropdown } from "../../common/git-branch-dropdown"; +import { GitProviderDropdown } from "./git-provider-dropdown"; +import { GitBranchDropdown } from "./git-branch-dropdown"; +import { GitRepoDropdown } from "./git-repo-dropdown"; interface RepositorySelectionFormProps { onRepoSelection: (repo: GitRepository | null) => void; @@ -28,8 +28,6 @@ export function RepositorySelectionForm({ const [selectedProvider, setSelectedProvider] = React.useState(null); const { providers } = useUserProviders(); - const { data: branches, isLoading: isLoadingBranches } = - useRepositoryBranches(selectedRepository?.full_name || null); const { mutate: createConversation, isPending, @@ -50,8 +48,7 @@ export function RepositorySelectionForm({ const isCreatingConversation = isPending || isSuccess || isCreatingConversationElsewhere; - // Check if repository has no branches (empty array after loading completes) - const hasNoBranches = !isLoadingBranches && branches && branches.length === 0; + // Branch selection is now handled by GitBranchDropdown component const handleProviderSelection = (provider: Provider | null) => { setSelectedProvider(provider); @@ -60,14 +57,9 @@ export function RepositorySelectionForm({ onRepoSelection(null); // Reset parent component's selected repo }; - const handleBranchSelection = (branchName: string | null) => { - const selectedBranchObj = branches?.find( - (branch) => branch.name === branchName, - ); - if (selectedBranchObj) { - setSelectedBranch(selectedBranchObj); - } - }; + const handleBranchSelection = React.useCallback((branch: Branch | null) => { + setSelectedBranch(branch); + }, []); // Render the provider dropdown const renderProviderSelector = () => { @@ -87,19 +79,6 @@ export function RepositorySelectionForm({ ); }; - // Effect to auto-select main/master branch when branches are loaded - React.useEffect(() => { - if (branches?.length) { - // Look for main or master branch - const defaultBranch = branches.find( - (branch) => branch.name === "main" || branch.name === "master", - ); - - // If found, select it, otherwise select the first branch - setSelectedBranch(defaultBranch || branches[0]); - } - }, [branches]); - // Render the repository selector using our new component const renderRepositorySelector = () => { const handleRepoSelection = (repository?: GitRepository) => { @@ -107,13 +86,14 @@ export function RepositorySelectionForm({ onRepoSelection(repository); setSelectedRepository(repository); } else { + onRepoSelection(null); // Notify parent component that repo was cleared setSelectedRepository(null); setSelectedBranch(null); } }; return ( - ( - - ); + const renderBranchSelector = () => { + const defaultBranch = selectedRepository?.main_branch || null; + return ( + + ); + }; return (
@@ -148,8 +133,7 @@ export function RepositorySelectionForm({ type="button" isDisabled={ !selectedRepository || - (!selectedBranch && !hasNoBranches) || - isLoadingBranches || + !selectedBranch || isCreatingConversation || (providers.length > 1 && !selectedProvider) } @@ -159,7 +143,7 @@ export function RepositorySelectionForm({ repository: { name: selectedRepository?.full_name || "", gitProvider: selectedRepository?.git_provider || "github", - branch: selectedBranch?.name || (hasNoBranches ? "" : "main"), + branch: selectedBranch?.name || "main", }, }, { diff --git a/frontend/src/components/features/home/shared/clear-button.tsx b/frontend/src/components/features/home/shared/clear-button.tsx new file mode 100644 index 0000000000..db2206b866 --- /dev/null +++ b/frontend/src/components/features/home/shared/clear-button.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import { cn } from "#/utils/utils"; + +interface ClearButtonProps { + disabled: boolean; + onClear: () => void; + testId?: string; +} + +export function ClearButton({ + disabled, + onClear, + testId = "dropdown-clear", +}: ClearButtonProps) { + return ( + + ); +} diff --git a/frontend/src/components/features/home/shared/dropdown-item.tsx b/frontend/src/components/features/home/shared/dropdown-item.tsx new file mode 100644 index 0000000000..df3830963a --- /dev/null +++ b/frontend/src/components/features/home/shared/dropdown-item.tsx @@ -0,0 +1,44 @@ +import React from "react"; +import { cn } from "#/utils/utils"; + +interface DropdownItemProps { + item: T; + index: number; + isHighlighted: boolean; + isSelected: boolean; + getItemProps: (options: any & Options) => any; // eslint-disable-line @typescript-eslint/no-explicit-any + getDisplayText: (item: T) => string; + getItemKey: (item: T) => string; +} + +export function DropdownItem({ + item, + index, + isHighlighted, + isSelected, + getItemProps, + getDisplayText, + getItemKey, +}: DropdownItemProps) { + const itemProps = getItemProps({ + index, + item, + className: cn( + "px-3 py-2 cursor-pointer text-sm rounded-lg mx-0.5 my-0.5", + "text-[#ECEDEE] focus:outline-none", + { + "bg-[#24272E]": isHighlighted && !isSelected, + "bg-[#C9B974] text-black": isSelected, + "hover:bg-[#24272E]": !isSelected, + "hover:bg-[#C9B974] hover:text-black": isSelected, + }, + ), + }); + + return ( + // eslint-disable-next-line react/jsx-props-no-spreading +
  • + {getDisplayText(item)} +
  • + ); +} diff --git a/frontend/src/components/features/home/shared/empty-state.tsx b/frontend/src/components/features/home/shared/empty-state.tsx new file mode 100644 index 0000000000..9e65d23fe3 --- /dev/null +++ b/frontend/src/components/features/home/shared/empty-state.tsx @@ -0,0 +1,24 @@ +import React from "react"; + +interface EmptyStateProps { + inputValue: string; + searchMessage?: string; + emptyMessage?: string; + testId?: string; +} + +export function EmptyState({ + inputValue, + searchMessage = "No items found", + emptyMessage = "No items available", + testId = "dropdown-empty", +}: EmptyStateProps) { + return ( +
  • + {inputValue ? searchMessage : emptyMessage} +
  • + ); +} diff --git a/frontend/src/components/features/home/shared/error-message.tsx b/frontend/src/components/features/home/shared/error-message.tsx new file mode 100644 index 0000000000..df4cc05e99 --- /dev/null +++ b/frontend/src/components/features/home/shared/error-message.tsx @@ -0,0 +1,21 @@ +import React from "react"; + +interface ErrorMessageProps { + isError: boolean; + message?: string; + testId?: string; +} + +export function ErrorMessage({ + isError, + message = "Failed to load data", + testId = "dropdown-error", +}: ErrorMessageProps) { + if (!isError) return null; + + return ( +
    + {message} +
    + ); +} diff --git a/frontend/src/components/features/home/shared/generic-dropdown-menu.tsx b/frontend/src/components/features/home/shared/generic-dropdown-menu.tsx new file mode 100644 index 0000000000..65e11f8eff --- /dev/null +++ b/frontend/src/components/features/home/shared/generic-dropdown-menu.tsx @@ -0,0 +1,74 @@ +import React from "react"; +import { + UseComboboxGetMenuPropsOptions, + UseComboboxGetItemPropsOptions, +} from "downshift"; +import { cn } from "#/utils/utils"; + +export interface GenericDropdownMenuProps { + isOpen: boolean; + filteredItems: T[]; + inputValue: string; + highlightedIndex: number; + selectedItem: T | null; + getMenuProps: ( + options?: UseComboboxGetMenuPropsOptions & Options, + ) => any; // eslint-disable-line @typescript-eslint/no-explicit-any + getItemProps: ( + options: UseComboboxGetItemPropsOptions & Options, + ) => any; // eslint-disable-line @typescript-eslint/no-explicit-any + onScroll?: (event: React.UIEvent) => void; + menuRef?: React.RefObject; + renderItem: ( + item: T, + index: number, + highlightedIndex: number, + selectedItem: T | null, + getItemProps: ( + options: UseComboboxGetItemPropsOptions & Options, + ) => any, // eslint-disable-line @typescript-eslint/no-explicit-any + ) => React.ReactNode; + renderEmptyState: (inputValue: string) => React.ReactNode; +} + +export function GenericDropdownMenu({ + isOpen, + filteredItems, + inputValue, + highlightedIndex, + selectedItem, + getMenuProps, + getItemProps, + onScroll, + menuRef, + renderItem, + renderEmptyState, +}: GenericDropdownMenuProps) { + if (!isOpen) return null; + + return ( +
      + {filteredItems.length === 0 + ? renderEmptyState(inputValue) + : filteredItems.map((item, index) => + renderItem( + item, + index, + highlightedIndex, + selectedItem, + getItemProps, + ), + )} +
    + ); +} diff --git a/frontend/src/components/features/home/shared/index.ts b/frontend/src/components/features/home/shared/index.ts new file mode 100644 index 0000000000..4c92cb75b5 --- /dev/null +++ b/frontend/src/components/features/home/shared/index.ts @@ -0,0 +1,7 @@ +export { GenericDropdownMenu } from "./generic-dropdown-menu"; +export { EmptyState } from "./empty-state"; +export { ErrorMessage } from "./error-message"; +export { LoadingSpinner } from "./loading-spinner"; +export { ClearButton } from "./clear-button"; +export { ToggleButton } from "./toggle-button"; +export type { GenericDropdownMenuProps } from "./generic-dropdown-menu"; diff --git a/frontend/src/components/features/home/shared/loading-spinner.tsx b/frontend/src/components/features/home/shared/loading-spinner.tsx new file mode 100644 index 0000000000..5d9af18e93 --- /dev/null +++ b/frontend/src/components/features/home/shared/loading-spinner.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import { cn } from "#/utils/utils"; + +interface LoadingSpinnerProps { + hasSelection: boolean; + testId?: string; +} + +export function LoadingSpinner({ + hasSelection, + testId = "dropdown-loading", +}: LoadingSpinnerProps) { + return ( +
    +
    +
    + ); +} diff --git a/frontend/src/components/features/home/shared/toggle-button.tsx b/frontend/src/components/features/home/shared/toggle-button.tsx new file mode 100644 index 0000000000..2905043ca4 --- /dev/null +++ b/frontend/src/components/features/home/shared/toggle-button.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import { cn } from "#/utils/utils"; + +interface ToggleButtonProps { + isOpen: boolean; + disabled: boolean; + getToggleButtonProps: ( + props?: Record, + ) => Record; +} + +export function ToggleButton({ + isOpen, + disabled, + getToggleButtonProps, +}: ToggleButtonProps) { + return ( + + ); +} diff --git a/frontend/src/components/features/microagent-management/microagent-management-sidebar.tsx b/frontend/src/components/features/microagent-management/microagent-management-sidebar.tsx index f05343fd51..a7decafc83 100644 --- a/frontend/src/components/features/microagent-management/microagent-management-sidebar.tsx +++ b/frontend/src/components/features/microagent-management/microagent-management-sidebar.tsx @@ -5,7 +5,7 @@ import { Spinner } from "@heroui/react"; import { MicroagentManagementSidebarHeader } from "./microagent-management-sidebar-header"; import { MicroagentManagementSidebarTabs } from "./microagent-management-sidebar-tabs"; import { useGitRepositories } from "#/hooks/query/use-git-repositories"; -import { GitProviderDropdown } from "#/components/common/git-provider-dropdown"; +import { GitProviderDropdown } from "#/components/features/home/git-provider-dropdown"; import { setPersonalRepositories, setOrganizationRepositories, @@ -16,7 +16,6 @@ import { Provider } from "#/types/settings"; import { cn } from "#/utils/utils"; import { sanitizeQuery } from "#/utils/sanitize-query"; import { I18nKey } from "#/i18n/declaration"; -import { getGitProviderMicroagentManagementCustomStyles } from "#/components/common/react-select-styles"; interface MicroagentManagementSidebarProps { isSmallerScreen?: boolean; @@ -123,8 +122,6 @@ export function MicroagentManagementSidebar({ placeholder="Select Provider" onChange={handleProviderChange} className="w-full" - classNamePrefix="git-provider-dropdown" - styles={getGitProviderMicroagentManagementCustomStyles()} />
    )} diff --git a/frontend/src/hooks/query/use-branch-data.ts b/frontend/src/hooks/query/use-branch-data.ts new file mode 100644 index 0000000000..2173cf4c6e --- /dev/null +++ b/frontend/src/hooks/query/use-branch-data.ts @@ -0,0 +1,126 @@ +import { useMemo } from "react"; +import { useRepositoryBranchesPaginated } from "./use-repository-branches"; +import { useSearchBranches } from "./use-search-branches"; +import { Branch } from "#/types/git"; +import { Provider } from "#/types/settings"; + +export function useBranchData( + repository: string | null, + provider: Provider, + defaultBranch: string | null, + processedSearchInput: string, + inputValue: string, + selectedBranch?: Branch | null, +) { + // Fetch branches with pagination + const { + data: branchData, + fetchNextPage, + hasNextPage, + isLoading, + isFetchingNextPage, + isError, + } = useRepositoryBranchesPaginated(repository); + + // Search branches when user types + const { data: searchData, isLoading: isSearchLoading } = useSearchBranches( + repository, + processedSearchInput, + 30, + provider, + ); + + // Combine all branches from paginated data + const allBranches = useMemo( + () => branchData?.pages?.flatMap((page) => page.branches) || [], + [branchData], + ); + + // Check if default branch is in the loaded branches + const defaultBranchInLoaded = useMemo( + () => + defaultBranch + ? allBranches.find((branch) => branch.name === defaultBranch) + : null, + [allBranches, defaultBranch], + ); + + // Only search for default branch if it's not already in the loaded branches + // and we have loaded some branches (to avoid searching immediately on mount) + const shouldSearchDefaultBranch = + defaultBranch && + !defaultBranchInLoaded && + allBranches.length > 0 && + !processedSearchInput; // Don't search for default branch when user is searching + + const { data: defaultBranchData, isLoading: isDefaultBranchLoading } = + useSearchBranches( + repository, + shouldSearchDefaultBranch ? defaultBranch : "", + 30, + provider, + ); + + // Get branches to display with default branch prioritized + const branches = useMemo(() => { + // Don't use search results if input exactly matches selected branch + const shouldUseSearch = + processedSearchInput && + searchData && + !(selectedBranch && inputValue === selectedBranch.name); + + let branchesToUse = shouldUseSearch ? searchData : allBranches; + + // If we have a default branch, ensure it's at the top of the list + if (defaultBranch) { + // Use the already computed defaultBranchInLoaded or check in current branches + let defaultBranchObj = shouldUseSearch + ? branchesToUse.find((branch) => branch.name === defaultBranch) + : defaultBranchInLoaded; + + // If not found in current branches, check if we have it from the default branch search + if ( + !defaultBranchObj && + defaultBranchData && + defaultBranchData.length > 0 + ) { + defaultBranchObj = defaultBranchData.find( + (branch) => branch.name === defaultBranch, + ); + + // Add the default branch to the beginning of the list + if (defaultBranchObj) { + branchesToUse = [defaultBranchObj, ...branchesToUse]; + } + } else if (defaultBranchObj) { + // If found in current branches, move it to the front + const otherBranches = branchesToUse.filter( + (branch) => branch.name !== defaultBranch, + ); + branchesToUse = [defaultBranchObj, ...otherBranches]; + } + } + + return branchesToUse; + }, [ + processedSearchInput, + searchData, + allBranches, + selectedBranch, + inputValue, + defaultBranch, + defaultBranchInLoaded, + defaultBranchData, + ]); + + return { + branches, + allBranches, + fetchNextPage, + hasNextPage, + isLoading: isLoading || isDefaultBranchLoading, + isFetchingNextPage, + isError, + isSearchLoading, + }; +} diff --git a/frontend/src/hooks/query/use-repository-branches.ts b/frontend/src/hooks/query/use-repository-branches.ts index 64d80d6f62..de78556fc4 100644 --- a/frontend/src/hooks/query/use-repository-branches.ts +++ b/frontend/src/hooks/query/use-repository-branches.ts @@ -1,14 +1,46 @@ -import { useQuery } from "@tanstack/react-query"; +import { useQuery, useInfiniteQuery } from "@tanstack/react-query"; import OpenHands from "#/api/open-hands"; -import { Branch } from "#/types/git"; +import { Branch, PaginatedBranchesResponse } from "#/types/git"; export const useRepositoryBranches = (repository: string | null) => useQuery({ queryKey: ["repository", repository, "branches"], queryFn: async () => { if (!repository) return []; - return OpenHands.getRepositoryBranches(repository); + const response = await OpenHands.getRepositoryBranches(repository); + // Ensure we return an array even if the response is malformed + return Array.isArray(response.branches) ? response.branches : []; }, enabled: !!repository, staleTime: 1000 * 60 * 5, // 5 minutes }); + +export const useRepositoryBranchesPaginated = ( + repository: string | null, + perPage: number = 30, +) => + useInfiniteQuery({ + queryKey: ["repository", repository, "branches", "paginated", perPage], + queryFn: async ({ pageParam = 1 }) => { + if (!repository) { + return { + branches: [], + has_next_page: false, + current_page: 1, + per_page: perPage, + total_count: 0, + }; + } + return OpenHands.getRepositoryBranches( + repository, + pageParam as number, + perPage, + ); + }, + enabled: !!repository, + staleTime: 1000 * 60 * 5, // 5 minutes + getNextPageParam: (lastPage) => + // Use the has_next_page flag from the API response + lastPage.has_next_page ? lastPage.current_page + 1 : undefined, + initialPageParam: 1, + }); diff --git a/frontend/src/hooks/query/use-search-branches.ts b/frontend/src/hooks/query/use-search-branches.ts new file mode 100644 index 0000000000..b2ce4af078 --- /dev/null +++ b/frontend/src/hooks/query/use-search-branches.ts @@ -0,0 +1,35 @@ +import { useQuery } from "@tanstack/react-query"; +import OpenHands from "#/api/open-hands"; +import { Branch } from "#/types/git"; +import { Provider } from "#/types/settings"; + +export function useSearchBranches( + repository: string | null, + query: string, + perPage: number = 30, + selectedProvider?: Provider, +) { + return useQuery({ + queryKey: [ + "repository", + repository, + "branches", + "search", + query, + perPage, + selectedProvider, + ], + queryFn: async () => { + if (!repository || !query) return []; + return OpenHands.searchRepositoryBranches( + repository, + query, + perPage, + selectedProvider, + ); + }, + enabled: !!repository && !!query, + staleTime: 1000 * 60 * 5, + gcTime: 1000 * 60 * 15, + }); +} diff --git a/frontend/src/mocks/git-repository-handlers.ts b/frontend/src/mocks/git-repository-handlers.ts index 9f8d74bff4..ef836a8346 100644 --- a/frontend/src/mocks/git-repository-handlers.ts +++ b/frontend/src/mocks/git-repository-handlers.ts @@ -1,6 +1,8 @@ import { delay, http, HttpResponse } from "msw"; -import { GitRepository } from "#/types/git"; +import { GitRepository, Branch, PaginatedBranchesResponse } from "#/types/git"; import { Provider } from "#/types/settings"; +import { RepositoryMicroagent } from "#/types/microagent-management"; +import { MicroagentContentResponse } from "#/api/open-hands.types"; // Generate a list of mock repositories with realistic data const generateMockRepositories = ( @@ -19,6 +21,32 @@ const generateMockRepositories = ( owner_type: Math.random() > 0.7 ? "organization" : "user", // 30% chance of being organization })); +// Generate mock branches for a repository +const generateMockBranches = (count: number): Branch[] => + Array.from({ length: count }, (_, i) => ({ + name: (() => { + if (i === 0) return "main"; + if (i === 1) return "develop"; + return `feature/branch-${i}`; + })(), + commit_sha: `abc123${i.toString().padStart(3, "0")}`, + protected: i === 0, // main branch is protected + last_push_date: new Date( + Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000, + ).toISOString(), + })); + +// Generate mock microagents for a repository +const generateMockMicroagents = (count: number): RepositoryMicroagent[] => + Array.from({ length: count }, (_, i) => ({ + name: `microagent-${i + 1}`, + path: `.openhands/microagents/microagent-${i + 1}.md`, + created_at: new Date( + Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000, + ).toISOString(), + git_provider: "github", + })); + // Mock repositories for each provider const MOCK_REPOSITORIES = { github: generateMockRepositories(120, "github"), @@ -26,6 +54,12 @@ const MOCK_REPOSITORIES = { bitbucket: generateMockRepositories(120, "bitbucket"), }; +// Mock branches (same for all repos for simplicity) +const MOCK_BRANCHES = generateMockBranches(25); + +// Mock microagents (same for all repos for simplicity) +const MOCK_MICROAGENTS = generateMockMicroagents(5); + export const GIT_REPOSITORY_HANDLERS = [ http.get("/api/user/repositories", async ({ request }) => { await delay(500); // Simulate network delay @@ -154,4 +188,138 @@ export const GIT_REPOSITORY_HANDLERS = [ return HttpResponse.json(limitedRepos); }), + + // Repository branches endpoint + http.get("/api/user/repository/branches", async ({ request }) => { + await delay(300); + + const url = new URL(request.url); + const repository = url.searchParams.get("repository"); + const page = parseInt(url.searchParams.get("page") || "1", 10); + const perPage = parseInt(url.searchParams.get("per_page") || "30", 10); + + if (!repository) { + return HttpResponse.json("Repository parameter is required", { + status: 400, + }); + } + + // Calculate pagination + const startIndex = (page - 1) * perPage; + const endIndex = startIndex + perPage; + const paginatedBranches = MOCK_BRANCHES.slice(startIndex, endIndex); + const hasNextPage = endIndex < MOCK_BRANCHES.length; + + const response: PaginatedBranchesResponse = { + branches: paginatedBranches, + has_next_page: hasNextPage, + current_page: page, + per_page: perPage, + total_count: MOCK_BRANCHES.length, + }; + + return HttpResponse.json(response); + }), + + // Search repository branches endpoint + http.get("/api/user/search/branches", async ({ request }) => { + await delay(200); + + const url = new URL(request.url); + const repository = url.searchParams.get("repository"); + const query = url.searchParams.get("query") || ""; + const perPage = parseInt(url.searchParams.get("per_page") || "30", 10); + + if (!repository) { + return HttpResponse.json("Repository parameter is required", { + status: 400, + }); + } + + // Filter branches by search query + const filteredBranches = MOCK_BRANCHES.filter((branch) => + branch.name.toLowerCase().includes(query.toLowerCase()), + ); + + // Limit results + const limitedBranches = filteredBranches.slice(0, perPage); + + return HttpResponse.json(limitedBranches); + }), + + // Repository microagents endpoint + http.get( + "/api/user/repository/:owner/:repo/microagents", + async ({ params }) => { + await delay(400); + + const { owner, repo } = params; + + if (!owner || !repo) { + return HttpResponse.json("Owner and repo parameters are required", { + status: 400, + }); + } + + return HttpResponse.json(MOCK_MICROAGENTS); + }, + ), + + // Repository microagent content endpoint + http.get( + "/api/user/repository/:owner/:repo/microagents/content", + async ({ request, params }) => { + await delay(300); + + const { owner, repo } = params; + const url = new URL(request.url); + const filePath = url.searchParams.get("file_path"); + + if (!owner || !repo || !filePath) { + return HttpResponse.json( + "Owner, repo, and file_path parameters are required", + { status: 400 }, + ); + } + + // Find the microagent by path + const microagent = MOCK_MICROAGENTS.find((m) => m.path === filePath); + + if (!microagent) { + return HttpResponse.json("Microagent not found", { status: 404 }); + } + + const response: MicroagentContentResponse = { + content: `# ${microagent.name} + +A helpful microagent for repository tasks. + +## Instructions + +This microagent helps with specific tasks related to the repository. + +### Usage + +1. Describe your task clearly +2. The microagent will analyze the context +3. Follow the provided recommendations + +### Capabilities + +- Code analysis +- Task automation +- Best practice recommendations +- Error detection and resolution + +--- + +*Generated mock content for ${microagent.name}*`, + path: microagent.path, + git_provider: "github", + triggers: ["code review", "bug fix", "feature development"], + }; + + return HttpResponse.json(response); + }, + ), ]; diff --git a/frontend/src/types/git.d.ts b/frontend/src/types/git.d.ts index a5f1daa483..9a5eb62ee5 100644 --- a/frontend/src/types/git.d.ts +++ b/frontend/src/types/git.d.ts @@ -22,6 +22,14 @@ interface Branch { last_push_date?: string; } +interface PaginatedBranchesResponse { + branches: Branch[]; + has_next_page: boolean; + current_page: number; + per_page: number; + total_count?: number; +} + interface GitRepository { id: string; full_name: string; @@ -31,6 +39,7 @@ interface GitRepository { link_header?: string; pushed_at?: string; owner_type?: "user" | "organization"; + main_branch?: string; } interface GitHubCommit { diff --git a/frontend/vitest.setup.ts b/frontend/vitest.setup.ts index f42e34a555..c40437f430 100644 --- a/frontend/vitest.setup.ts +++ b/frontend/vitest.setup.ts @@ -5,6 +5,7 @@ import "@testing-library/jest-dom/vitest"; HTMLCanvasElement.prototype.getContext = vi.fn(); HTMLElement.prototype.scrollTo = vi.fn(); +window.scrollTo = vi.fn(); // Mock the i18n provider vi.mock("react-i18next", async (importOriginal) => ({ diff --git a/openhands/integrations/bitbucket/bitbucket_service.py b/openhands/integrations/bitbucket/bitbucket_service.py index d536892db1..d2f5908566 100644 --- a/openhands/integrations/bitbucket/bitbucket_service.py +++ b/openhands/integrations/bitbucket/bitbucket_service.py @@ -13,6 +13,7 @@ from openhands.integrations.service_types import ( GitService, InstallationsService, OwnerType, + PaginatedBranchesResponse, ProviderType, Repository, RequestMethod, @@ -551,6 +552,83 @@ class BitBucketService(BaseGitService, GitService, InstallationsService): return branches + async def get_paginated_branches( + self, repository: str, page: int = 1, per_page: int = 30 + ) -> PaginatedBranchesResponse: + """Get branches for a repository with pagination.""" + # Extract owner and repo from the repository string (e.g., "owner/repo") + parts = repository.split('/') + if len(parts) < 2: + raise ValueError(f'Invalid repository name: {repository}') + + owner = parts[-2] + repo = parts[-1] + + url = f'{self.BASE_URL}/repositories/{owner}/{repo}/refs/branches' + + params = { + 'pagelen': per_page, + 'page': page, + 'sort': '-target.date', # Sort by most recent commit date, descending + } + + response, _ = await self._make_request(url, params) + + branches = [] + for branch in response.get('values', []): + branches.append( + Branch( + name=branch.get('name', ''), + commit_sha=branch.get('target', {}).get('hash', ''), + protected=False, # Bitbucket doesn't expose this in the API + last_push_date=branch.get('target', {}).get('date', None), + ) + ) + + # Bitbucket provides pagination info in the response + has_next_page = response.get('next') is not None + total_count = response.get('size') # Total number of items + + return PaginatedBranchesResponse( + branches=branches, + has_next_page=has_next_page, + current_page=page, + per_page=per_page, + total_count=total_count, + ) + + async def search_branches( + self, repository: str, query: str, per_page: int = 30 + ) -> list[Branch]: + """Search branches by name using Bitbucket API with `q` param.""" + parts = repository.split('/') + if len(parts) < 2: + raise ValueError(f'Invalid repository name: {repository}') + + owner = parts[-2] + repo = parts[-1] + + url = f'{self.BASE_URL}/repositories/{owner}/{repo}/refs/branches' + # Bitbucket filtering: name ~ "query" + params = { + 'pagelen': per_page, + 'q': f'name~"{query}"', + 'sort': '-target.date', + } + response, _ = await self._make_request(url, params) + + branches: list[Branch] = [] + for branch in response.get('values', []): + branches.append( + Branch( + name=branch.get('name', ''), + commit_sha=branch.get('target', {}).get('hash', ''), + protected=False, + last_push_date=branch.get('target', {}).get('date', None), + ) + ) + return branches + async def create_pr( self, repo_name: str, diff --git a/openhands/integrations/github/github_service.py b/openhands/integrations/github/github_service.py index d613dd9acc..4c00ca1c5b 100644 --- a/openhands/integrations/github/github_service.py +++ b/openhands/integrations/github/github_service.py @@ -12,6 +12,7 @@ from openhands.integrations.github.queries import ( get_review_threads_graphql_query, get_thread_comments_graphql_query, get_thread_from_comment_graphql_query, + search_branches_graphql_query, suggested_task_issue_graphql_query, suggested_task_pr_graphql_query, ) @@ -22,6 +23,7 @@ from openhands.integrations.service_types import ( GitService, InstallationsService, OwnerType, + PaginatedBranchesResponse, ProviderType, Repository, RequestMethod, @@ -252,6 +254,7 @@ class GitHubService(BaseGitService, GitService, InstallationsService): else OwnerType.USER ), link_header=link_header, + main_branch=repo.get('default_branch'), ) async def get_paginated_repos( @@ -619,6 +622,109 @@ class GitHubService(BaseGitService, GitService, InstallationsService): return all_branches + async def get_paginated_branches( + self, repository: str, page: int = 1, per_page: int = 30 + ) -> PaginatedBranchesResponse: + """Get branches for a repository with pagination""" + url = f'{self.BASE_URL}/repos/{repository}/branches' + + params = {'per_page': str(per_page), 'page': str(page)} + response, headers = await self._make_request(url, params) + + branches: list[Branch] = [] + for branch_data in response: + # Extract the last commit date if available + last_push_date = None + if branch_data.get('commit') and branch_data['commit'].get('commit'): + commit_info = branch_data['commit']['commit'] + if commit_info.get('committer') and commit_info['committer'].get( + 'date' + ): + last_push_date = commit_info['committer']['date'] + + branch = Branch( + name=branch_data.get('name'), + commit_sha=branch_data.get('commit', {}).get('sha', ''), + protected=branch_data.get('protected', False), + last_push_date=last_push_date, + ) + branches.append(branch) + + # Parse Link header to determine if there's a next page + has_next_page = False + if 'Link' in headers: + link_header = headers['Link'] + has_next_page = 'rel="next"' in link_header + + return PaginatedBranchesResponse( + branches=branches, + has_next_page=has_next_page, + current_page=page, + per_page=per_page, + total_count=None, # GitHub doesn't provide total count in branch API + ) + + async def search_branches( + self, repository: str, query: str, per_page: int = 30 + ) -> list[Branch]: + """Search branches by name using GitHub GraphQL with a partial query.""" + # Require a non-empty query + if not query: + return [] + + # Clamp per_page to GitHub GraphQL limits + per_page = min(max(per_page, 1), 100) + + # Extract owner and repo name from the repository string + parts = repository.split('/') + if len(parts) < 2: + return [] + owner, name = parts[-2], parts[-1] + + variables = { + 'owner': owner, + 'name': name, + 'query': query or '', + 'perPage': per_page, + } + + try: + result = await self.execute_graphql_query( + search_branches_graphql_query, variables + ) + except Exception as e: + logger.warning(f'Failed to search for branches: {e}') + # Fallback to empty result on any GraphQL error + return [] + + repo = result.get('data', {}).get('repository') + if not repo or not repo.get('refs'): + return [] + + branches: list[Branch] = [] + for node in repo['refs'].get('nodes', []): + bname = node.get('name') or '' + target = node.get('target') or {} + typename = target.get('__typename') + commit_sha = '' + last_push_date = None + if typename == 'Commit': + commit_sha = target.get('oid', '') or '' + last_push_date = target.get('committedDate') + + protected = node.get('branchProtectionRule') is not None + + branches.append( + Branch( + name=bname, + commit_sha=commit_sha, + protected=protected, + last_push_date=last_push_date, + ) + ) + + return branches + async def create_pr( self, repo_name: str, diff --git a/openhands/integrations/github/queries.py b/openhands/integrations/github/queries.py index a8b2739846..ffa6596b5e 100644 --- a/openhands/integrations/github/queries.py +++ b/openhands/integrations/github/queries.py @@ -122,3 +122,32 @@ query ($threadId: ID!, $page: Int = 50, $after: String) { } } """ + +# Search branches in a repository by partial name using GitHub GraphQL. +# This leverages the `refs` connection with: +# - refPrefix: "refs/heads/" to restrict to branches +# - query: partial branch name provided by the user +# - first: pagination size (clamped by caller to GitHub limits) +search_branches_graphql_query = """ + query SearchBranches($owner: String!, $name: String!, $query: String!, $perPage: Int!) { + repository(owner: $owner, name: $name) { + refs( + refPrefix: "refs/heads/", + query: $query, + first: $perPage, + orderBy: { field: ALPHABETICAL, direction: ASC } + ) { + nodes { + name + target { + __typename + ... on Commit { + oid + committedDate + } + } + } + } + } + } +""" diff --git a/openhands/integrations/gitlab/gitlab_service.py b/openhands/integrations/gitlab/gitlab_service.py index 2e4c6328f7..485cf37a08 100644 --- a/openhands/integrations/gitlab/gitlab_service.py +++ b/openhands/integrations/gitlab/gitlab_service.py @@ -12,6 +12,7 @@ from openhands.integrations.service_types import ( Comment, GitService, OwnerType, + PaginatedBranchesResponse, ProviderType, Repository, RequestMethod, @@ -265,6 +266,7 @@ class GitLabService(BaseGitService, GitService): else OwnerType.USER ), link_header=link_header, + main_branch=repo.get('default_branch'), ) def _parse_gitlab_url(self, url: str) -> str | None: @@ -577,6 +579,68 @@ class GitLabService(BaseGitService, GitService): return all_branches + async def get_paginated_branches( + self, repository: str, page: int = 1, per_page: int = 30 + ) -> PaginatedBranchesResponse: + """Get branches for a repository with pagination""" + encoded_name = repository.replace('/', '%2F') + url = f'{self.BASE_URL}/projects/{encoded_name}/repository/branches' + + params = {'per_page': str(per_page), 'page': str(page)} + response, headers = await self._make_request(url, params) + + branches: list[Branch] = [] + for branch_data in response: + branch = Branch( + name=branch_data.get('name'), + commit_sha=branch_data.get('commit', {}).get('id', ''), + protected=branch_data.get('protected', False), + last_push_date=branch_data.get('commit', {}).get('committed_date'), + ) + branches.append(branch) + + # Parse pagination headers + has_next_page = False + total_count = None + + if 'X-Next-Page' in headers and headers['X-Next-Page']: + has_next_page = True + if 'X-Total' in headers: + try: + total_count = int(headers['X-Total']) + except (ValueError, TypeError): + pass + + return PaginatedBranchesResponse( + branches=branches, + has_next_page=has_next_page, + current_page=page, + per_page=per_page, + total_count=total_count, + ) + + async def search_branches( + self, repository: str, query: str, per_page: int = 30 + ) -> list[Branch]: + """Search branches using GitLab API which supports `search` param.""" + encoded_name = repository.replace('/', '%2F') + url = f'{self.BASE_URL}/projects/{encoded_name}/repository/branches' + + params = {'per_page': str(per_page), 'search': query} + response, _ = await self._make_request(url, params) + + branches: list[Branch] = [] + for branch_data in response: + branches.append( + Branch( + name=branch_data.get('name'), + commit_sha=branch_data.get('commit', {}).get('id', ''), + protected=branch_data.get('protected', False), + last_push_date=branch_data.get('commit', {}).get('committed_date'), + ) + ) + return branches + async def create_mr( self, id: int | str, diff --git a/openhands/integrations/provider.py b/openhands/integrations/provider.py index c0bff80581..b25530dcbc 100644 --- a/openhands/integrations/provider.py +++ b/openhands/integrations/provider.py @@ -26,6 +26,7 @@ from openhands.integrations.service_types import ( GitService, InstallationsService, MicroagentParseError, + PaginatedBranchesResponse, ProviderType, Repository, ResourceNotFoundError, @@ -256,6 +257,33 @@ class ProviderHandler: return tasks + async def search_branches( + self, + selected_provider: ProviderType | None, + repository: str, + query: str, + per_page: int = 30, + ) -> list[Branch]: + """Search for branches within a repository using the appropriate provider service.""" + if selected_provider: + service = self._get_service(selected_provider) + try: + return await service.search_branches(repository, query, per_page) + except Exception as e: + logger.warning( + f'Error searching branches from selected provider {selected_provider}: {e}' + ) + return [] + + # If provider not specified, determine provider by verifying repository access + try: + repo_details = await self.verify_repo_provider(repository) + service = self._get_service(repo_details.git_provider) + return await service.search_branches(repository, query, per_page) + except Exception as e: + logger.warning(f'Error searching branches for {repository}: {e}') + return [] + async def search_repositories( self, selected_provider: ProviderType | None, @@ -442,24 +470,27 @@ class ProviderHandler: raise AuthenticationError(f'Unable to access repo {repository}') async def get_branches( - self, repository: str, specified_provider: ProviderType | None = None - ) -> list[Branch]: + self, + repository: str, + specified_provider: ProviderType | None = None, + page: int = 1, + per_page: int = 30, + ) -> PaginatedBranchesResponse: """Get branches for a repository Args: repository: The repository name specified_provider: Optional provider type to use + page: Page number for pagination (default: 1) + per_page: Number of branches per page (default: 30) Returns: - A list of branches for the repository + A paginated response with branches for the repository """ - all_branches: list[Branch] = [] - if specified_provider: try: service = self._get_service(specified_provider) - branches = await service.get_branches(repository) - return branches + return await service.get_paginated_branches(repository, page, per_page) except Exception as e: logger.warning( f'Error fetching branches from {specified_provider}: {e}' @@ -468,31 +499,19 @@ class ProviderHandler: for provider in self.provider_tokens: try: service = self._get_service(provider) - branches = await service.get_branches(repository) - all_branches.extend(branches) - # If we found branches, no need to check other providers - if all_branches: - break + return await service.get_paginated_branches(repository, page, per_page) except Exception as e: logger.warning(f'Error fetching branches from {provider}: {e}') - # Sort branches by last push date (newest first) - all_branches.sort( - key=lambda b: b.last_push_date if b.last_push_date else '', reverse=True + # Return empty response if no provider worked + return PaginatedBranchesResponse( + branches=[], + has_next_page=False, + current_page=page, + per_page=per_page, + total_count=0, ) - # Move main/master branch to the top if it exists - main_branches = [] - other_branches = [] - - for branch in all_branches: - if branch.name.lower() in ['main', 'master']: - main_branches.append(branch) - else: - other_branches.append(branch) - - return main_branches + other_branches - async def get_microagents(self, repository: str) -> list[MicroagentResponse]: """Get microagents from a repository using the appropriate service. diff --git a/openhands/integrations/service_types.py b/openhands/integrations/service_types.py index 8020c88e97..669f70258f 100644 --- a/openhands/integrations/service_types.py +++ b/openhands/integrations/service_types.py @@ -130,6 +130,14 @@ class Branch(BaseModel): last_push_date: str | None = None # ISO 8601 format date string +class PaginatedBranchesResponse(BaseModel): + branches: list[Branch] + has_next_page: bool + current_page: int + per_page: int + total_count: int | None = None # Some APIs don't provide total count + + class Repository(BaseModel): id: str full_name: str @@ -511,6 +519,16 @@ class GitService(Protocol): async def get_branches(self, repository: str) -> list[Branch]: """Get branches for a repository""" + async def get_paginated_branches( + self, repository: str, page: int = 1, per_page: int = 30 + ) -> PaginatedBranchesResponse: + """Get branches for a repository with pagination""" + + async def search_branches( + self, repository: str, query: str, per_page: int = 30 + ) -> list[Branch]: + """Search for branches within a repository""" + async def get_microagents(self, repository: str) -> list[MicroagentResponse]: """Get microagents from a repository""" ... diff --git a/openhands/server/routes/git.py b/openhands/server/routes/git.py index 024190c88c..db0f0255b4 100644 --- a/openhands/server/routes/git.py +++ b/openhands/server/routes/git.py @@ -13,6 +13,7 @@ from openhands.integrations.provider import ( from openhands.integrations.service_types import ( AuthenticationError, Branch, + PaginatedBranchesResponse, ProviderType, Repository, SuggestedTask, @@ -163,6 +164,49 @@ async def search_repositories( raise AuthenticationError('Git provider token required.') +@app.get('/search/branches', response_model=list[Branch]) +async def search_branches( + repository: str, + query: str, + per_page: int = 30, + selected_provider: ProviderType | None = None, + provider_tokens: PROVIDER_TOKEN_TYPE | None = Depends(get_provider_tokens), + access_token: SecretStr | None = Depends(get_access_token), + user_id: str | None = Depends(get_user_id), +) -> list[Branch] | JSONResponse: + if provider_tokens: + client = ProviderHandler( + provider_tokens=provider_tokens, + external_auth_token=access_token, + external_auth_id=user_id, + ) + try: + branches: list[Branch] = await client.search_branches( + selected_provider, repository, query, per_page + ) + return branches + + except AuthenticationError as e: + return JSONResponse( + content=str(e), + status_code=status.HTTP_401_UNAUTHORIZED, + ) + + except UnknownException as e: + return JSONResponse( + content=str(e), + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) + + logger.info( + f'Returning 401 Unauthorized - Git provider token required for user_id: {user_id}' + ) + return JSONResponse( + content='Git provider token required.', + status_code=status.HTTP_401_UNAUTHORIZED, + ) + + @app.get('/suggested-tasks', response_model=list[SuggestedTask]) async def get_suggested_tasks( provider_tokens: PROVIDER_TOKEN_TYPE | None = Depends(get_provider_tokens), @@ -192,28 +236,34 @@ async def get_suggested_tasks( raise AuthenticationError('No providers set.') -@app.get('/repository/branches', response_model=list[Branch]) +@app.get('/repository/branches', response_model=PaginatedBranchesResponse) async def get_repository_branches( repository: str, + page: int = 1, + per_page: int = 30, provider_tokens: PROVIDER_TOKEN_TYPE | None = Depends(get_provider_tokens), access_token: SecretStr | None = Depends(get_access_token), user_id: str | None = Depends(get_user_id), -) -> list[Branch] | JSONResponse: +) -> PaginatedBranchesResponse | JSONResponse: """Get branches for a repository. Args: repository: The repository name in the format 'owner/repo' + page: Page number for pagination (default: 1) + per_page: Number of branches per page (default: 30) Returns: - A list of branches for the repository + A paginated response with branches for the repository """ if provider_tokens: client = ProviderHandler( provider_tokens=provider_tokens, external_auth_token=access_token ) try: - branches: list[Branch] = await client.get_branches(repository) - return branches + branches_response: PaginatedBranchesResponse = await client.get_branches( + repository, page=page, per_page=per_page + ) + return branches_response except UnknownException as e: return JSONResponse( diff --git a/tests/unit/integrations/bitbucket/test_bitbucket_branches.py b/tests/unit/integrations/bitbucket/test_bitbucket_branches.py new file mode 100644 index 0000000000..61574aa324 --- /dev/null +++ b/tests/unit/integrations/bitbucket/test_bitbucket_branches.py @@ -0,0 +1,84 @@ +from unittest.mock import patch + +import pytest +from pydantic import SecretStr + +from openhands.integrations.bitbucket.bitbucket_service import BitBucketService +from openhands.integrations.service_types import Branch, PaginatedBranchesResponse + + +@pytest.mark.asyncio +async def test_get_paginated_branches_bitbucket_parsing_and_pagination(): + service = BitBucketService(token=SecretStr('t')) + + mock_response = { + 'values': [ + { + 'name': 'main', + 'target': {'hash': 'abc', 'date': '2024-01-01T00:00:00Z'}, + }, + { + 'name': 'feature/x', + 'target': {'hash': 'def', 'date': '2024-01-02T00:00:00Z'}, + }, + ], + 'next': 'https://api.bitbucket.org/2.0/repositories/w/r/refs/branches?page=3', + 'size': 123, + } + + with patch.object(service, '_make_request', return_value=(mock_response, {})): + res = await service.get_paginated_branches('w/r', page=2, per_page=2) + + assert isinstance(res, PaginatedBranchesResponse) + assert res.has_next_page is True + assert res.current_page == 2 + assert res.per_page == 2 + assert res.total_count == 123 + assert res.branches == [ + Branch( + name='main', + commit_sha='abc', + protected=False, + last_push_date='2024-01-01T00:00:00Z', + ), + Branch( + name='feature/x', + commit_sha='def', + protected=False, + last_push_date='2024-01-02T00:00:00Z', + ), + ] + + +@pytest.mark.asyncio +async def test_search_branches_bitbucket_filters_by_name_contains(): + service = BitBucketService(token=SecretStr('t')) + + mock_response = { + 'values': [ + { + 'name': 'bugfix/issue-1', + 'target': {'hash': 'hhh', 'date': '2024-01-10T10:00:00Z'}, + } + ] + } + + with patch.object(service, '_make_request', return_value=(mock_response, {})) as m: + branches = await service.search_branches('w/r', query='bugfix', per_page=15) + + args, kwargs = m.call_args + url = args[0] + params = args[1] + assert 'refs/branches' in url + assert params['pagelen'] == 15 + assert params['q'] == 'name~"bugfix"' + assert params['sort'] == '-target.date' + + assert branches == [ + Branch( + name='bugfix/issue-1', + commit_sha='hhh', + protected=False, + last_push_date='2024-01-10T10:00:00Z', + ) + ] diff --git a/tests/unit/integrations/github/test_github_branches.py b/tests/unit/integrations/github/test_github_branches.py new file mode 100644 index 0000000000..7aa010016f --- /dev/null +++ b/tests/unit/integrations/github/test_github_branches.py @@ -0,0 +1,168 @@ +from unittest.mock import AsyncMock, patch + +import pytest +from pydantic import SecretStr + +from openhands.integrations.github.github_service import GitHubService +from openhands.integrations.service_types import Branch, PaginatedBranchesResponse + + +@pytest.mark.asyncio +async def test_get_paginated_branches_github_basic_next_page(): + service = GitHubService(token=SecretStr('t')) + + mock_response = [ + { + 'name': 'main', + 'commit': { + 'sha': 'abc123', + 'commit': {'committer': {'date': '2024-01-01T12:00:00Z'}}, + }, + 'protected': True, + }, + { + 'name': 'feature/foo', + 'commit': { + 'sha': 'def456', + 'commit': {'committer': {'date': '2024-01-02T15:30:00Z'}}, + }, + 'protected': False, + }, + ] + headers = { + # Include rel="next" to indicate there is another page + 'Link': '; rel="next"' + } + + with patch.object(service, '_make_request', return_value=(mock_response, headers)): + result = await service.get_paginated_branches('owner/repo', page=2, per_page=2) + + assert isinstance(result, PaginatedBranchesResponse) + assert result.current_page == 2 + assert result.per_page == 2 + assert result.has_next_page is True + assert result.total_count is None # GitHub does not provide total count + assert len(result.branches) == 2 + + b0, b1 = result.branches + assert isinstance(b0, Branch) and isinstance(b1, Branch) + assert b0.name == 'main' + assert b0.commit_sha == 'abc123' + assert b0.protected is True + assert b0.last_push_date == '2024-01-01T12:00:00Z' + assert b1.name == 'feature/foo' + assert b1.commit_sha == 'def456' + assert b1.protected is False + assert b1.last_push_date == '2024-01-02T15:30:00Z' + + +@pytest.mark.asyncio +async def test_get_paginated_branches_github_no_next_page(): + service = GitHubService(token=SecretStr('t')) + + mock_response = [ + { + 'name': 'dev', + 'commit': { + 'sha': 'zzz999', + 'commit': {'committer': {'date': '2024-01-03T00:00:00Z'}}, + }, + 'protected': False, + } + ] + headers = { + # No rel="next" – should be treated as last page + 'Link': '; rel="prev"' + } + + with patch.object(service, '_make_request', return_value=(mock_response, headers)): + result = await service.get_paginated_branches('owner/repo', page=1, per_page=1) + assert result.has_next_page is False + assert len(result.branches) == 1 + assert result.branches[0].name == 'dev' + + +@pytest.mark.asyncio +async def test_search_branches_github_success_and_variables(): + service = GitHubService(token=SecretStr('t')) + + # Prepare a fake GraphQL response structure + graphql_result = { + 'data': { + 'repository': { + 'refs': { + 'nodes': [ + { + 'name': 'feature/bar', + 'target': { + '__typename': 'Commit', + 'oid': 'aaa111', + 'committedDate': '2024-01-05T10:00:00Z', + }, + 'branchProtectionRule': {}, # indicates protected + }, + { + 'name': 'chore/update', + 'target': { + '__typename': 'Tag', + 'oid': 'should_be_ignored_for_commit', + }, + 'branchProtectionRule': None, + }, + ] + } + } + } + } + + exec_mock = AsyncMock(return_value=graphql_result) + with patch.object(service, 'execute_graphql_query', exec_mock) as mock_exec: + branches = await service.search_branches('foo/bar', query='fe', per_page=999) + + # per_page should be clamped to <= 100 when passed to GraphQL variables + args, kwargs = mock_exec.call_args + _query = args[0] + variables = args[1] + assert variables['owner'] == 'foo' + assert variables['name'] == 'bar' + assert variables['query'] == 'fe' + assert 1 <= variables['perPage'] <= 100 + + assert len(branches) == 2 + b0, b1 = branches + assert b0.name == 'feature/bar' + assert b0.commit_sha == 'aaa111' + assert b0.protected is True + assert b0.last_push_date == '2024-01-05T10:00:00Z' + + # Non-commit target results in empty sha and no date + assert b1.name == 'chore/update' + assert b1.commit_sha == '' + assert b1.last_push_date is None + assert b1.protected is False + + +@pytest.mark.asyncio +async def test_search_branches_github_edge_cases(): + service = GitHubService(token=SecretStr('t')) + + # Empty query should return [] without issuing a GraphQL call + branches = await service.search_branches('foo/bar', query='') + assert branches == [] + + # Invalid repository string should return [] without calling GraphQL + exec_mock = AsyncMock() + with patch.object(service, 'execute_graphql_query', exec_mock): + branches = await service.search_branches('invalidrepo', query='q') + assert branches == [] + exec_mock.assert_not_called() + + +@pytest.mark.asyncio +async def test_search_branches_github_graphql_error_returns_empty(): + service = GitHubService(token=SecretStr('t')) + + exec_mock = AsyncMock(side_effect=Exception('Boom')) + with patch.object(service, 'execute_graphql_query', exec_mock): + branches = await service.search_branches('foo/bar', query='q') + assert branches == [] diff --git a/tests/unit/integrations/gitlab/test_gitlab_branches.py b/tests/unit/integrations/gitlab/test_gitlab_branches.py new file mode 100644 index 0000000000..e903aef3fd --- /dev/null +++ b/tests/unit/integrations/gitlab/test_gitlab_branches.py @@ -0,0 +1,119 @@ +from unittest.mock import patch + +import pytest +from pydantic import SecretStr + +from openhands.integrations.gitlab.gitlab_service import GitLabService +from openhands.integrations.service_types import Branch, PaginatedBranchesResponse + + +@pytest.mark.asyncio +async def test_get_paginated_branches_gitlab_headers_and_parsing(): + service = GitLabService(token=SecretStr('t')) + + mock_response = [ + { + 'name': 'main', + 'commit': {'id': 'abc', 'committed_date': '2024-01-01T00:00:00Z'}, + 'protected': True, + }, + { + 'name': 'dev', + 'commit': {'id': 'def', 'committed_date': '2024-01-02T00:00:00Z'}, + 'protected': False, + }, + ] + + headers = { + 'X-Next-Page': '3', # indicates has next page + 'X-Total': '42', + } + + with patch.object(service, '_make_request', return_value=(mock_response, headers)): + res = await service.get_paginated_branches('group/repo', page=2, per_page=2) + + assert isinstance(res, PaginatedBranchesResponse) + assert res.has_next_page is True + assert res.current_page == 2 + assert res.per_page == 2 + assert res.total_count == 42 + assert len(res.branches) == 2 + assert res.branches[0] == Branch( + name='main', + commit_sha='abc', + protected=True, + last_push_date='2024-01-01T00:00:00Z', + ) + assert res.branches[1] == Branch( + name='dev', + commit_sha='def', + protected=False, + last_push_date='2024-01-02T00:00:00Z', + ) + + +@pytest.mark.asyncio +async def test_get_paginated_branches_gitlab_no_next_or_total(): + service = GitLabService(token=SecretStr('t')) + + mock_response = [ + { + 'name': 'fix', + 'commit': {'id': 'zzz', 'committed_date': '2024-01-03T00:00:00Z'}, + 'protected': False, + } + ] + + headers = {} # No pagination headers; should be has_next_page False + + with patch.object(service, '_make_request', return_value=(mock_response, headers)): + res = await service.get_paginated_branches('group/repo', page=1, per_page=1) + assert res.has_next_page is False + assert res.total_count is None + assert len(res.branches) == 1 + assert res.branches[0].name == 'fix' + + +@pytest.mark.asyncio +async def test_search_branches_gitlab_uses_search_param(): + service = GitLabService(token=SecretStr('t')) + + mock_response = [ + { + 'name': 'feat/new', + 'commit': {'id': '111', 'committed_date': '2024-01-04T00:00:00Z'}, + 'protected': False, + }, + { + 'name': 'feature/xyz', + 'commit': {'id': '222', 'committed_date': '2024-01-05T00:00:00Z'}, + 'protected': True, + }, + ] + + with patch.object(service, '_make_request', return_value=(mock_response, {})) as m: + branches = await service.search_branches( + 'group/repo', query='feat', per_page=50 + ) + + # Verify parameters + args, kwargs = m.call_args + url = args[0] + params = args[1] + assert 'repository/branches' in url + assert params['per_page'] == '50' + assert params['search'] == 'feat' + + assert len(branches) == 2 + assert branches[0] == Branch( + name='feat/new', + commit_sha='111', + protected=False, + last_push_date='2024-01-04T00:00:00Z', + ) + assert branches[1] == Branch( + name='feature/xyz', + commit_sha='222', + protected=True, + last_push_date='2024-01-05T00:00:00Z', + )